Skip to content

Instantly share code, notes, and snippets.

@stgraber
Created April 2, 2022 16:10
Show Gist options
  • Save stgraber/5c76aefcc8643e37a3e1b81a7a37a6f9 to your computer and use it in GitHub Desktop.
Save stgraber/5c76aefcc8643e37a3e1b81a7a37a6f9 to your computer and use it in GitHub Desktop.
diff --git a/.gitignore b/.gitignore
index fbe965b04..cd78e21cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -126,6 +126,7 @@ config/bash/lxc
config/init/common/lxc-containers
config/init/common/lxc-net
config/init/systemd/lxc-autostart-helper
+config/init/systemd/lxc-monitord.service
config/init/systemd/lxc-net.service
config/init/systemd/lxc.service
config/init/systemd/lxc@.service
diff --git a/config/init/systemd/Makefile.am b/config/init/systemd/Makefile.am
index c448850d1..4a4fde5e7 100644
--- a/config/init/systemd/Makefile.am
+++ b/config/init/systemd/Makefile.am
@@ -2,19 +2,21 @@ EXTRA_DIST = \
lxc-apparmor-load \
lxc.service.in \
lxc@.service.in \
- lxc-net.service.in
+ lxc-net.service.in \
+ lxc-monitord.service.in
if INIT_SCRIPT_SYSTEMD
-BUILT_SOURCES = lxc.service lxc@.service lxc-net.service
+BUILT_SOURCES = lxc.service lxc@.service lxc-net.service lxc-monitord.service
-install-systemd: lxc.service lxc@.service lxc-net.service lxc-apparmor-load
+install-systemd: lxc.service lxc@.service lxc-net.service lxc-monitord.service lxc-apparmor-load
$(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
- $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
+ $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service lxc-monitord.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
uninstall-systemd:
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc.service
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc@.service
rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-net.service
+ rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-monitord.service
rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || :
pkglibexec_SCRIPTS = lxc-apparmor-load
diff --git a/config/init/systemd/lxc-net.service.in b/config/init/systemd/lxc-net.service.in
index 6ed8cd82b..a615d8b2d 100644
--- a/config/init/systemd/lxc-net.service.in
+++ b/config/init/systemd/lxc-net.service.in
@@ -3,6 +3,7 @@ Description=LXC network bridge setup
After=network-online.target
Before=lxc.service
Documentation=man:lxc
+ConditionVirtualization=!lxc
[Service]
Type=oneshot
diff --git a/configure.ac b/configure.ac
index f9fbd7273..581f0d7d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,9 @@
AC_PREREQ([2.69])
-m4_define([lxc_devel], 0)
+m4_define([lxc_devel], 1)
m4_define([lxc_version_major], 4)
m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 12)
+m4_define([lxc_version_micro], 0)
m4_define([lxc_version_beta], [])
m4_define([lxc_abi_major], 1)
@@ -908,6 +908,7 @@ AC_CONFIG_FILES([
config/init/systemd/lxc.service
config/init/systemd/lxc@.service
config/init/systemd/lxc-net.service
+ config/init/systemd/lxc-monitord.service
config/init/sysvinit/Makefile
config/init/sysvinit/lxc-containers
config/init/sysvinit/lxc-net
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 98686f9ed..0e9c724e8 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -119,6 +119,15 @@ This adds a new API function `init_pidfd()` which allows one to retrieve a pidfd
When running on kernels that support pidfds LXC will rely on them for most operations. This makes interacting with containers not just more reliable it also makes it significantly safer and eliminates various races inherent to PID-based kernel APIs. LXC will require that the running kernel at least support `pidfd_send_signal()`, `CLONE_PIDFD`, `P_PIDFD`, and pidfd polling support. Any kernel starting with `Linux 5.4` should have full support for pidfds.
+## cgroup\_advanced\_isolation
+
+Privileged containers will usually be able to override the cgroup limits given to them. This introduces three new configuration keys `lxc.cgroup.dir.monitor`, `lxc.cgroup.dir.container`, and `lxc.cgroup.dir.container.inner`. The `lxc.cgroup.dir.monitor` and `lxc.cgroup.dir.container` keys can be used to set to place the `monitor` and the `container` into different cgroups. The `lxc.cgroup.dir.container.inner` key can be set to a cgroup that is concatenated with `lxc.cgroup.dir.container`. When `lxc.cgroup.dir.container.inner` is set the container will be placed into the `lxc.cgroup.dir.container.inner` cgroup but the limits will be set in the `lxc.cgroup.dir.container` cgroup. This way privileged containers cannot escape their cgroup limits.
+
+
+## time\_namespace
+
+This adds time namespace support to LXC.
+
## seccomp\_allow\_deny\_syntax
This adds the ability to use "denylist" and "allowlist" in seccomp v2 policies.
diff --git a/doc/ja/lxc.container.conf.sgml.in b/doc/ja/lxc.container.conf.sgml.in
index c4d6c962e..9b0b01ba1 100644
--- a/doc/ja/lxc.container.conf.sgml.in
+++ b/doc/ja/lxc.container.conf.sgml.in
@@ -657,6 +657,12 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<option>lxc.net.[i].veth.ipv6.route</option> options.
Several lines specify several routes.
The route is in format x.y.z.t/m, eg. 192.168.1.0/24.
+
+ In <option>bridge</option> mode untagged VLAN membership can be set with the
+ <option>lxc.net.[i].veth.vlan.id</option> option. It accepts a special value of 'none' indicating
+ that the container port should be removed from the bridge's default untagged VLAN.
+ The <option>lxc.net.[i].veth.vlan.tagged.id</option> option can be specified multiple times to set
+ the container's bridge port membership to one or more tagged VLANs.
-->
<option>veth:</option> 一方がコンテナに、もう一方がホストに接続されるペアの仮想イーサネットデバイスを作成します。
<option>lxc.net.[i].veth.mode</option> は、veth の親(ホスト側)がホスト上で使うモードを指定します。
@@ -674,6 +680,8 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<option>lxc.net.[i].veth.ipv4.route</option>、<option>lxc.net.[i].veth.ipv6.route</option> オプションを使って、静的ルーティングをコンテナを指し示すホスト上に追加できます。
複数のルートがある場合は複数の設定を指定します。
ルートは x.y.z.t/m の形式です。例: 192.168.1.0/24
+
+ <option>bridge</option> モードでは、タグなし VLAN は <option>lxc.net.[i].veth.vlan.id</option> で設定できます。このオプションでは、コンテナポートをブリッジのデフォルトのタグなし VLAN から削除するための特別な値 'none' が指定できます。コンテナのブリッジポートを複数のタグ付き VLAN に所属させるために、<option>lxc.net.[i].veth.vlan.tagged.id</option> を複数回指定できます。
</para>
<para>
@@ -922,8 +930,13 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
Specify the ipv4 address to assign to the virtualized interface.
Several lines specify several ipv4 addresses. The address is in
format x.y.z.t/m, eg. 192.168.1.123/24.
+ You can optionally specify the broadcast address after the IP adress,
+ e.g. 192.168.1.123/24 255.255.255.255.
+ Otherwise it is automatically calculated from the IP address.
-->
仮想インターフェースに割り当てる ipv4 アドレスを指定します。複数行により複数の ipv4 アドレスを指定します。このアドレスは x.y.z.t/m というフォーマットで指定します。例) 192.168.1.123/24
+ IP アドレスのあとにオプションでブロードキャストアドレスを指定できます。例)192.168.1.123/24 255.255.255.255
+ 指定しなければ IP アドレスから自動的に計算されます。
</para>
</listitem>
</varlistentry>
@@ -2204,7 +2217,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<listitem>
<para>
<!--
- A allowlist device rule
+ A denylist device rule
<programlisting>
lxc.cgroup2.devices.deny = a
</programlisting>
@@ -2213,7 +2226,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
must be added via the <option>lxc.cgroup2.devices.allow</option>
key. This is referred to as a "allowlist" device program.
-->
- 許可リスト(allowlist)のデバイスルール
+ 拒否リスト(denylist)のデバイスルール
<programlisting>
lxc.cgroup2.devices.deny = a
</programlisting>
@@ -2225,7 +2238,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
<listitem>
<para>
<!--
- A denylist device rule
+ An allowlist device rule
<programlisting>
lxc.cgroup2.devices.allow = a
</programlisting>
@@ -2234,7 +2247,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
must be added via <option>lxc.cgroup2.devices.deny</option> key.
This is referred to as a "denylist" device program.
-->
- 拒否リスト(denylist)のデバイスルール
+ 許可リスト(allowlist)のデバイスルール
<programlisting>
lxc.cgroup2.devices.allow = a
</programlisting>
@@ -2355,7 +2368,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
</programlisting>
<!--
instead then the last line will cause LXC to reset the device list and
- switch from a allowlist program to a denylist program.
+ switch from an allowlist program to a denylist program.
-->
前の例と違って最後の行によって、LXC はデバイスリストをリセットし、許可リスト(allowlist)から拒否リスト(denylist)にプログラムを変更してしまいます。
</para>
@@ -2425,6 +2438,79 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.container</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ This is similar to <option>lxc.cgroup.dir</option>, but must be
+ used together with <option>lxc.cgroup.dir.monitor</option> and
+ affects only the container's cgroup path. This option is mutually
+ exclusive with <option>lxc.cgroup.dir</option>.
+ Note that the final path the container attaches to may be
+ extended further by the
+ <option>lxc.cgroup.dir.container.inner</option> option.
+ -->
+ これは <option>lxc.cgroup.dir</option> と同様の設定ですが、かならず <option>lxc.cgroup.dir.monitor</option> と同時に使わなければなりません。そして、設定はコンテナの cgroup パスにのみ影響を与えます。このオプションは <option>lxc.cgroup.dir</option> と同時に設定できません。コンテナがアタッチされる最終的なパスは <option>lxc.cgroup.dir.container.inner</option> オプションによりさらに変更される可能性があります。
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.monitor</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ This is the monitor process counterpart to
+ <option>lxc.cgroup.dir.container</option>.
+ -->
+ このオプションは、モニタプロセスに対して<option>lxc.cgroup.dir.container</option> と同様の働きをします。
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.monitor.pivot</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ On container termination the PID of the monitor process is attached to this cgroup.
+ This path should not be a subpath of any other configured cgroup dir to ensure
+ proper removal of other cgroup paths on container termination.
+ -->
+ コンテナ終了時に、モニタープロセスの PID がここで指定した cgroup にアタッチされます。
+ コンテナ終了時に、他の cgroup パスが確実に適切に削除されるように、ここに設定するパスは他で設定した cgroup ディレクトリのサブパスにすべきではありません。
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.container.inner</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ Specify an additional subdirectory where the cgroup namespace
+ will be created. With this option, the cgroup limits will be
+ applied to the outer path specified in
+ <option>lxc.cgroup.dir.container</option>, which is not accessible
+ from within the container, making it possible to better enforce
+ limits for privileged containers in a way they cannot override
+ them.
+ This only works in conjunction with the
+ <option>lxc.cgroup.dir.container</option> and
+ <option>lxc.cgroup.dir.monitor</option> options and has otherwise
+ no effect.
+ -->
+ cgroup 名前空間が作られる追加のサブディレクトリを指定します。このオプションを使うと、cgroup の制限は <option>lxc.cgroup.dir.container</option> で指定した外部パスに適用されます。<option>lxc.cgroup.dir.container</option> はコンテナ内部からアクセスできないため、特権コンテナに対する制限を上書きできない方法でよりよい方法で強制できます。
+ このオプションは <option>lxc.cgroup.dir.container</option> と <option>lxc.cgroup.dir.monitor</option> と同時に指定したときのみ機能し、それ以外の場合は効果がありません。
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup.relative</option>
@@ -2678,6 +2764,39 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>lxc.time.offset.boot</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ Specify a positive or negative offset for the boottime clock. The
+ format accepts hours (h), minutes (m), seconds (s),
+ milliseconds (ms), microseconds (us), and nanoseconds (ns).
+ -->
+ ブートタイム(boottime)クロックの正または負のオフセット値を指定します。フォーマットは、時(h)、分(m)、秒(s)、ミリ秒(ms)、マイクロ秒(us)、ナノ秒(ns)を指定できます。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>lxc.time.offset.monotonic</option>
+ </term>
+ <listitem>
+ <para>
+ <!--
+ Specify a positive or negative offset for the montonic clock. The
+ format accepts hours (h), minutes (m), seconds (s),
+ milliseconds (ms), microseconds (us), and nanoseconds (ns).
+ -->
+ monotonicクロックの正または負のオフセット値を指定します。フォーマットは、時(h)、分(m)、秒(s)、ミリ秒(ms)、マイクロ秒(us)、ナノ秒(ns)を指定できます。
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index c1054ddbc..9c5db9ba1 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -502,6 +502,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<option>lxc.net.[i].veth.ipv6.route</option> options.
Several lines specify several routes.
The route is in format x.y.z.t/m, eg. 192.168.1.0/24.
+
+ In <option>bridge</option> mode untagged VLAN membership can be set with the
+ <option>lxc.net.[i].veth.vlan.id</option> option. It accepts a special value of 'none' indicating
+ that the container port should be removed from the bridge's default untagged VLAN.
+ The <option>lxc.net.[i].veth.vlan.tagged.id</option> option can be specified multiple times to set
+ the container's bridge port membership to one or more tagged VLANs.
</para>
<para>
@@ -1646,7 +1652,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<itemizedlist>
<listitem>
<para>
- A allowlist device rule
+ A denylist device rule
<programlisting>
lxc.cgroup2.devices.deny = a
</programlisting>
@@ -1659,7 +1665,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<listitem>
<para>
- A denylist device rule
+ An allowlist device rule
<programlisting>
lxc.cgroup2.devices.allow = a
</programlisting>
@@ -1749,7 +1755,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
lxc.cgroup2.devices.deny = a
</programlisting>
instead then the last line will cause LXC to reset the device list and
- switch from a allowlist program to a denylist program.
+ switch from an allowlist program to a denylist program.
</para>
<variablelist>
<varlistentry>
@@ -1801,6 +1807,65 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.container</option>
+ </term>
+ <listitem>
+ <para>
+ This is similar to <option>lxc.cgroup.dir</option>, but must be
+ used together with <option>lxc.cgroup.dir.monitor</option> and
+ affects only the container's cgroup path. This option is mutually
+ exclusive with <option>lxc.cgroup.dir</option>.
+ Note that the final path the container attaches to may be
+ extended further by the
+ <option>lxc.cgroup.dir.container.inner</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.monitor</option>
+ </term>
+ <listitem>
+ <para>
+ This is the monitor process counterpart to
+ <option>lxc.cgroup.dir.container</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.monitor.pivot</option>
+ </term>
+ <listitem>
+ <para>
+ On container termination the PID of the monitor process is attached to this cgroup.
+ This path should not be a subpath of any other configured cgroup dir to ensure
+ proper removal of other cgroup paths on container termination.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>lxc.cgroup.dir.container.inner</option>
+ </term>
+ <listitem>
+ <para>
+ Specify an additional subdirectory where the cgroup namespace
+ will be created. With this option, the cgroup limits will be
+ applied to the outer path specified in
+ <option>lxc.cgroup.dir.container</option>, which is not accessible
+ from within the container, making it possible to better enforce
+ limits for privileged containers in a way they cannot override
+ them.
+ This only works in conjunction with the
+ <option>lxc.cgroup.dir.container</option> and
+ <option>lxc.cgroup.dir.monitor</option> options and has otherwise
+ no effect.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup.relative</option>
@@ -1983,6 +2048,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>lxc.time.offset.boot</option>
+ </term>
+ <listitem>
+ <para>
+ Specify a positive or negative offset for the boottime clock. The
+ format accepts hours (h), minutes (m), seconds (s),
+ milliseconds (ms), microseconds (us), and nanoseconds (ns).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>lxc.time.offset.monotonic</option>
+ </term>
+ <listitem>
+ <para>
+ Specify a positive or negative offset for the monotonic clock. The
+ format accepts hours (h), minutes (m), seconds (s),
+ milliseconds (ms), microseconds (us), and nanoseconds (ns).
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
diff --git a/lxc.spec.in b/lxc.spec.in
index a7ce2601c..7ed9685bd 100644
--- a/lxc.spec.in
+++ b/lxc.spec.in
@@ -255,6 +255,7 @@ fi
%{_unitdir}/lxc-net.service
%{_unitdir}/lxc.service
%{_unitdir}/lxc@.service
+%{_unitdir}/lxc-monitord.service
%else
%{_sysconfdir}/rc.d/init.d/lxc
%{_sysconfdir}/rc.d/init.d/lxc-net
diff --git a/meson.build b/meson.build
index 8f8331a3d..c19b768f3 100644
--- a/meson.build
+++ b/meson.build
@@ -61,6 +61,7 @@ lxcpathprefix = get_option('config-path')
rootfsmount = get_option('rootfs-mount-dir')
runtimepath = join_paths(prefixdir, get_option('runtime-path'))
wants_io_uring = get_option('io-uring-event-loop')
+want_tests = get_option('tests')
conf.set_quoted('BINDIR', bindir)
conf.set_quoted('DATADIR', datadir)
@@ -428,6 +429,9 @@ subdir('hooks')
template_scripts = []
subdir('templates')
+test_programs = []
+subdir('src/tests')
+
cmd_programs = []
subdir('src/lxc/cmd')
diff --git a/src/lxc/api_extensions.h b/src/lxc/api_extensions.h
index d99adacbe..6a0b9fe98 100644
--- a/src/lxc/api_extensions.h
+++ b/src/lxc/api_extensions.h
@@ -39,6 +39,9 @@ static char *api_extensions[] = {
"cgroup2_devices",
"cgroup2",
"pidfd",
+ "cgroup_advanced_isolation",
+ "network_bridge_vlan",
+ "time_namespace",
"seccomp_allow_deny_syntax",
"devpts_fd",
#ifdef HAVE_DECL_SECCOMP_NOTIFY_FD
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index e82b56902..e39bde8df 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -727,6 +727,7 @@ static int __cgroup_tree_create(int dfd_base, const char *path, mode_t mode,
* it will be automatically zapped if we return early.
*/
dfd_cur = dfd_final;
+ TRACE("Opened%s cgroup %s as %d", !ret ? " newly created" : "", cur, dfd_cur);
}
/* The final cgroup must be succesfully creatd by us. */
@@ -2143,7 +2144,7 @@ static int cgroup_attach_leaf(const struct lxc_conf *conf, int unified_fd, pid_t
}
static int cgroup_attach_create_leaf(const struct lxc_conf *conf,
- int unified_fd, int *sk_fd)
+ int unified_fd, int *sk_fd, bool unprivileged)
{
__do_close int sk = *sk_fd, target_fd0 = -EBADF, target_fd1 = -EBADF;
int target_fds[2];
@@ -2152,37 +2153,66 @@ static int cgroup_attach_create_leaf(const struct lxc_conf *conf,
/* Create leaf cgroup. */
ret = mkdirat(unified_fd, ".lxc", 0755);
if (ret < 0 && errno != EEXIST)
- return log_error_errno(-1, errno, "Failed to create leaf cgroup \".lxc\"");
+ return syserror("Failed to create leaf cgroup \".lxc\"");
- target_fd0 = open_at(unified_fd, ".lxc/cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
- if (target_fd0 < 0)
- return log_error_errno(-errno, errno, "Failed to open \".lxc/cgroup.procs\"");
- target_fds[0] = target_fd0;
+ if (unprivileged) {
+ target_fd0 = open_at(unified_fd, ".lxc/cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
+ if (target_fd0 < 0)
+ return syserror("Failed to open \".lxc/cgroup.procs\"");
+ target_fds[0] = target_fd0;
- target_fd1 = open_at(unified_fd, "cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
- if (target_fd1 < 0)
- return log_error_errno(-errno, errno, "Failed to open \".lxc/cgroup.procs\"");
- target_fds[1] = target_fd1;
+ target_fd1 = open_at(unified_fd, "cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
+ if (target_fd1 < 0)
+ return syserror("Failed to open \".lxc/cgroup.procs\"");
+ target_fds[1] = target_fd1;
- ret = lxc_abstract_unix_send_fds(sk, target_fds, 2, NULL, 0);
- if (ret <= 0)
- return log_error_errno(-errno, errno, "Failed to send \".lxc/cgroup.procs\" fds %d and %d",
- target_fd0, target_fd1);
+ ret = lxc_abstract_unix_send_fds(sk, target_fds, 2, NULL, 0);
+ if (ret <= 0)
+ return syserror("Failed to send \".lxc/cgroup.procs\" fds %d and %d",
+ target_fd0, target_fd1);
- return log_debug(0, "Sent target cgroup fds %d and %d", target_fd0, target_fd1);
+ TRACE("Sent cgroup file descriptors %d and %d", target_fd0, target_fd1);
+ } else {
+ ret = lxc_abstract_unix_send_credential(sk, NULL, 0);
+ if (ret < 0)
+ return syserror("Failed to inform parent that we are done setting up mounts");
+
+ TRACE("Informed parent process that cgroup has been created");
+ }
+
+ return 0;
}
static int cgroup_attach_move_into_leaf(const struct lxc_conf *conf,
- int *sk_fd, pid_t pid)
+ int unified_fd, int *sk_fd, pid_t pid,
+ bool unprivileged)
{
__do_close int sk = *sk_fd, target_fd0 = -EBADF, target_fd1 = -EBADF;
char pidstr[INTTYPE_TO_STRLEN(int64_t) + 1];
size_t pidstr_len;
ssize_t ret;
- ret = lxc_abstract_unix_recv_two_fds(sk, &target_fd0, &target_fd1);
- if (ret < 0)
- return log_error_errno(-1, errno, "Failed to receive target cgroup fd");
+ if (unprivileged) {
+ ret = lxc_abstract_unix_recv_two_fds(sk, &target_fd0, &target_fd1);
+ if (ret < 0)
+ return log_error_errno(-1, errno, "Failed to receive target cgroup fd");
+ } else {
+ ret = lxc_abstract_unix_rcv_credential(sk, NULL, 0);
+ if (ret < 0)
+ return syserror("Failed to receive notification from parent process");
+
+ TRACE("Child process informed us that cgroup has been created");
+
+ target_fd0 = open_at(unified_fd, ".lxc/cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
+ if (target_fd0 < 0)
+ return syserror("Failed to open \".lxc/cgroup.procs\"");
+
+ target_fd1 = open_at(unified_fd, "cgroup.procs", PROTECT_OPEN_W, PROTECT_LOOKUP_BENEATH, 0);
+ if (target_fd1 < 0)
+ return syserror("Failed to open \".lxc/cgroup.procs\"");
+
+ TRACE("Opened target cgroup file descriptors %d and %d", target_fd0, target_fd1);
+ }
pidstr_len = sprintf(pidstr, INT64_FMT, (int64_t)pid);
@@ -2194,8 +2224,7 @@ static int cgroup_attach_move_into_leaf(const struct lxc_conf *conf,
if (ret > 0 && (size_t)ret == pidstr_len)
return log_debug(0, "Moved process into target cgroup via fd %d", target_fd1);
- return log_debug_errno(-1, errno, "Failed to move process into target cgroup via fd %d and %d",
- target_fd0, target_fd1);
+ return syserror("Failed to move process into target cgroup via fd %d and %d", target_fd0, target_fd1);
}
struct userns_exec_unified_attach_data {
@@ -2203,6 +2232,7 @@ struct userns_exec_unified_attach_data {
int unified_fd;
int sk_pair[2];
pid_t pid;
+ bool unprivileged;
};
static int cgroup_unified_attach_child_wrapper(void *data)
@@ -2215,7 +2245,7 @@ static int cgroup_unified_attach_child_wrapper(void *data)
close_prot_errno_disarm(args->sk_pair[0]);
return cgroup_attach_create_leaf(args->conf, args->unified_fd,
- &args->sk_pair[1]);
+ &args->sk_pair[1], args->unprivileged);
}
static int cgroup_unified_attach_parent_wrapper(void *data)
@@ -2227,8 +2257,9 @@ static int cgroup_unified_attach_parent_wrapper(void *data)
return ret_errno(EINVAL);
close_prot_errno_disarm(args->sk_pair[1]);
- return cgroup_attach_move_into_leaf(args->conf, &args->sk_pair[0],
- args->pid);
+ return cgroup_attach_move_into_leaf(args->conf, args->unified_fd,
+ &args->sk_pair[0], args->pid,
+ args->unprivileged);
}
/* Technically, we're always at a delegation boundary here (This is especially
@@ -2275,6 +2306,7 @@ static int __cg_unified_attach(const struct hierarchy *h,
.conf = conf,
.unified_fd = unified_fd,
.pid = pid,
+ .unprivileged = am_guest_unpriv(),
};
ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, args.sk_pair);
@@ -3174,6 +3206,12 @@ static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
SYSTRACE("Unified cgroup not mounted");
continue;
}
+
+ if (!fhas_fs_type(dfd_mnt, CGROUP2_SUPER_MAGIC)) {
+ SYSTRACE("Opened file descriptor %d is not a cgroup2 mountpoint", dfd_mnt);
+ continue;
+ }
+
dfd = dfd_mnt;
if (!is_empty_string(current_cgroup)) {
@@ -3239,6 +3277,12 @@ static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
SYSTRACE("%s not mounted", controllers);
continue;
}
+
+ if (!fhas_fs_type(dfd_mnt, CGROUP_SUPER_MAGIC)) {
+ SYSTRACE("Opened file descriptor %d is not a cgroup mountpoint", dfd_mnt);
+ continue;
+ }
+
dfd = dfd_mnt;
if (!abspath(__current_cgroup))
@@ -3467,6 +3511,7 @@ static int __unified_attach_fd(const struct lxc_conf *conf, int fd_unified, pid_
.conf = conf,
.unified_fd = fd_unified,
.pid = pid,
+ .unprivileged = am_guest_unpriv(),
};
ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, args.sk_pair);
diff --git a/src/lxc/cmd/lxc-checkconfig.in b/src/lxc/cmd/lxc-checkconfig.in
index 1061b062f..8dc620076 100755
--- a/src/lxc/cmd/lxc-checkconfig.in
+++ b/src/lxc/cmd/lxc-checkconfig.in
@@ -58,6 +58,9 @@ has_cgroup_ns() {
}
is_probed() {
+ if [ ! -f /proc/modules ]; then
+ return
+ fi
lsmod | grep $1 > /dev/null
if [ $? -eq 0 ]; then
echo -n ", loaded"
@@ -111,7 +114,8 @@ KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
fi
if [ -z "${KVER_MAJOR}" ]; then
- echo "WARNING: Unable to detect version from configuration, assuming latest\n"
+ echo "WARNING: Unable to detect version from configuration, assuming latest"
+ echo ""
KVER_MAJOR="100"
KVER_MINOR="0"
fi
diff --git a/src/lxc/cmd/lxc_monitord.c b/src/lxc/cmd/lxc_monitord.c
index 2b0895fc6..a194fbea8 100644
--- a/src/lxc/cmd/lxc_monitord.c
+++ b/src/lxc/cmd/lxc_monitord.c
@@ -327,41 +327,46 @@ static void lxc_monitord_sig_handler(int sig)
int main(int argc, char *argv[])
{
- int ret, pipefd;
- char logpath[PATH_MAX];
+ int ret, pipefd = -1;
sigset_t mask;
- char *lxcpath = argv[1];
+ const char *lxcpath = NULL;
bool mainloop_opened = false;
bool monitord_created = false;
- struct lxc_log log;
+ bool persistent = false;
- if (argc != 3) {
- fprintf(stderr,
- "Usage: lxc-monitord lxcpath sync-pipe-fd\n\n"
- "NOTE: lxc-monitord is intended for use by lxc internally\n"
- " and does not need to be run by hand\n\n");
- exit(EXIT_FAILURE);
+ if (argc > 1 && !strcmp(argv[1], "--daemon")) {
+ persistent = true;
+ --argc;
+ ++argv;
}
- ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log",
- (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH));
- if (ret < 0 || (size_t)ret >= sizeof(logpath))
- exit(EXIT_FAILURE);
-
- log.name = NULL;
- log.file = logpath;
- log.level = "DEBUG";
- log.prefix = "lxc-monitord";
- log.quiet = 0;
- log.lxcpath = lxcpath;
+ if (argc > 1) {
+ lxcpath = argv[1];
+ --argc;
+ ++argv;
+ } else {
+ lxcpath = lxc_global_config_value("lxc.lxcpath");
+ if (!lxcpath) {
+ ERROR("Failed to get default lxcpath");
+ exit(EXIT_FAILURE);
+ }
+ }
- ret = lxc_log_init(&log);
- if (ret)
- INFO("Failed to open log file %s, log will be lost", lxcpath);
- lxc_log_options_no_override();
+ if (argc > 1) {
+ if (lxc_safe_int(argv[1], &pipefd) < 0)
+ exit(EXIT_FAILURE);
+ --argc;
+ ++argv;
+ }
- if (lxc_safe_int(argv[2], &pipefd) < 0)
+ if (argc != 1 || (persistent != (pipefd == -1))) {
+ fprintf(stderr,
+ "Usage: lxc-monitord lxcpath sync-pipe-fd\n"
+ " lxc-monitord --daemon lxcpath\n\n"
+ "NOTE: lxc-monitord is intended for use by lxc internally\n"
+ " and does not need to be run by hand\n\n");
exit(EXIT_FAILURE);
+ }
if (sigfillset(&mask) ||
sigdelset(&mask, SIGILL) ||
@@ -417,7 +422,7 @@ int main(int argc, char *argv[])
lxc_raw_getpid(), monitor.lxcpath);
for (;;) {
- ret = lxc_mainloop(&monitor.descr, 1000 * 30);
+ ret = lxc_mainloop(&monitor.descr, persistent ? -1 : 1000 * 30);
if (ret) {
ERROR("mainloop returned an error");
break;
diff --git a/src/lxc/cmd/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c
index 83e79cd1e..a91e2259d 100644
--- a/src/lxc/cmd/lxc_user_nic.c
+++ b/src/lxc/cmd/lxc_user_nic.c
@@ -469,7 +469,7 @@ static int instantiate_veth(char *veth1, char *veth2, pid_t pid, unsigned int mt
{
int ret;
- ret = lxc_veth_create(veth1, veth2, pid, mtu);
+ ret = lxc_veth_create(veth1, veth2, pid, mtu, -1, -1);
if (ret < 0) {
CMD_SYSERROR("Failed to create %s-%s\n", veth1, veth2);
return ret_errno(-ret);
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index e656f63bb..c1ce717bf 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1089,17 +1089,20 @@ static int lxc_allocate_ttys(struct lxc_conf *conf)
return -ENOMEM;
for (size_t i = 0; i < conf->ttys.max; i++) {
- int pty_nr = -1;
struct lxc_terminal_info *tty = &ttys->tty[i];
ret = lxc_devpts_terminal(conf->devpts_fd, &tty->ptx,
- &tty->pty, &pty_nr, false);
+ &tty->pty, &tty->pty_nr, false);
if (ret < 0) {
conf->ttys.max = i;
return syserror_set(-ENOTTY, "Failed to create tty %zu", i);
}
+ ret = strnprintf(tty->name, sizeof(tty->name), "pts/%d", tty->pty_nr);
+ if (ret < 0)
+ return syserror("Failed to create tty %zu", i);
+
DEBUG("Created tty with ptx fd %d and pty fd %d and index %d",
- tty->ptx, tty->pty, pty_nr);
+ tty->ptx, tty->pty, tty->pty_nr);
tty->busy = -1;
}
@@ -1180,6 +1183,7 @@ static int lxc_create_ttys(struct lxc_handler *handler)
SYSERROR("Failed to set \"container_ttys=%s\"", conf->ttys.tty_names);
goto on_error;
}
+ TRACE("Set \"container_ttys=%s\"", conf->ttys.tty_names);
}
return 0;
@@ -4163,6 +4167,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
for (size_t i = 0; i < ttys_max; i++) {
terminal_info = &info_new->tty[i];
terminal_info->busy = -1;
+ terminal_info->pty_nr = -1;
terminal_info->ptx = -EBADF;
terminal_info->pty = -EBADF;
}
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 5cb3ecfac..40f34af45 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -29,6 +29,7 @@
#include "netns_ifaddrs.h"
#include "log.h"
#include "lxcseccomp.h"
+#include "macro.h"
#include "memory_utils.h"
#include "network.h"
#include "parse.h"
@@ -67,6 +68,10 @@ lxc_config_define(cap_keep);
lxc_config_define(cgroup_controller);
lxc_config_define(cgroup2_controller);
lxc_config_define(cgroup_dir);
+lxc_config_define(cgroup_monitor_dir);
+lxc_config_define(cgroup_monitor_pivot_dir);
+lxc_config_define(cgroup_container_dir);
+lxc_config_define(cgroup_container_inner_dir);
lxc_config_define(cgroup_relative);
lxc_config_define(console_buffer_size);
lxc_config_define(console_logfile);
@@ -99,6 +104,8 @@ lxc_config_define(mount_auto);
lxc_config_define(mount_fstab);
lxc_config_define(namespace_clone);
lxc_config_define(namespace_keep);
+lxc_config_define(time_offset_boot);
+lxc_config_define(time_offset_monotonic);
lxc_config_define(namespace_share);
lxc_config_define(net);
lxc_config_define(net_flags);
@@ -118,9 +125,13 @@ lxc_config_define(net_script_down);
lxc_config_define(net_script_up);
lxc_config_define(net_type);
lxc_config_define(net_veth_mode);
+lxc_config_define(net_veth_n_rxqueues);
+lxc_config_define(net_veth_n_txqueues);
lxc_config_define(net_veth_pair);
lxc_config_define(net_veth_ipv4_route);
lxc_config_define(net_veth_ipv6_route);
+lxc_config_define(net_veth_vlan_id);
+lxc_config_define(net_veth_vlan_tagged_id);
lxc_config_define(net_vlan_id);
lxc_config_define(no_new_privs);
lxc_config_define(personality);
@@ -187,6 +198,10 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.cap.drop", true, set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
{ "lxc.cap.keep", true, set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
{ "lxc.cgroup2", false, set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, },
+ { "lxc.cgroup.dir.monitor.pivot", true, set_config_cgroup_monitor_pivot_dir, get_config_cgroup_monitor_pivot_dir, clr_config_cgroup_monitor_pivot_dir, },
+ { "lxc.cgroup.dir.monitor", true, set_config_cgroup_monitor_dir, get_config_cgroup_monitor_dir, clr_config_cgroup_monitor_dir, },
+ { "lxc.cgroup.dir.container.inner", true, set_config_cgroup_container_inner_dir, get_config_cgroup_container_inner_dir, clr_config_cgroup_container_inner_dir, },
+ { "lxc.cgroup.dir.container", true, set_config_cgroup_container_dir, get_config_cgroup_container_dir, clr_config_cgroup_container_dir, },
{ "lxc.cgroup.dir", true, set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, },
{ "lxc.cgroup.relative", true, set_config_cgroup_relative, get_config_cgroup_relative, clr_config_cgroup_relative, },
{ "lxc.cgroup", false, set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, },
@@ -231,6 +246,8 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.namespace.clone", true, set_config_namespace_clone, get_config_namespace_clone, clr_config_namespace_clone, },
{ "lxc.namespace.keep", true, set_config_namespace_keep, get_config_namespace_keep, clr_config_namespace_keep, },
{ "lxc.namespace.share.", false, set_config_namespace_share, get_config_namespace_share, clr_config_namespace_share, },
+ { "lxc.time.offset.boot", true, set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
+ { "lxc.time.offset.monotonic", true, set_config_time_offset_monotonic, get_config_time_offset_monotonic, clr_config_time_offset_monotonic, },
{ "lxc.net.", false, set_config_jump_table_net, get_config_jump_table_net, clr_config_jump_table_net, },
{ "lxc.net", true, set_config_net, get_config_net, clr_config_net, },
{ "lxc.no_new_privs", true, set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
@@ -292,9 +309,13 @@ static struct lxc_config_net_t config_jump_table_net[] = {
{ "type", true, set_config_net_type, get_config_net_type, clr_config_net_type, },
{ "vlan.id", true, set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, },
{ "veth.mode", true, set_config_net_veth_mode, get_config_net_veth_mode, clr_config_net_veth_mode, },
+ { "veth.n_rxqueues", true, set_config_net_veth_n_rxqueues, get_config_net_veth_n_rxqueues, clr_config_net_veth_n_rxqueues, },
+ { "veth.n_txqueues", true, set_config_net_veth_n_txqueues, get_config_net_veth_n_txqueues, clr_config_net_veth_n_txqueues, },
{ "veth.pair", true, set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, },
{ "veth.ipv4.route", true, set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, },
{ "veth.ipv6.route", true, set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, },
+ { "veth.vlan.id", true, set_config_net_veth_vlan_id, get_config_net_veth_vlan_id, clr_config_net_veth_vlan_id, },
+ { "veth.vlan.tagged.id", true, set_config_net_veth_vlan_tagged_id, get_config_net_veth_vlan_tagged_id, clr_config_net_veth_vlan_tagged_id, },
};
static struct lxc_config_net_t unsupported_config_net_key = {
@@ -570,6 +591,56 @@ static int set_config_net_veth_mode(const char *key, const char *value,
return lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, value);
}
+static int set_config_net_veth_n_rxqueues(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int n_rxqueues;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_n_rxqueues(key, lxc_conf, data);
+
+ if (lxc_safe_int(value, &n_rxqueues))
+ return ret_errno(EINVAL);
+
+ if (n_rxqueues <= 0)
+ return ret_errno(EINVAL);
+
+ netdev->priv.veth_attr.n_rxqueues = n_rxqueues;
+ return 0;
+}
+
+static int set_config_net_veth_n_txqueues(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int n_txqueues;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_n_txqueues(key, lxc_conf, data);
+
+ if (lxc_safe_int(value, &n_txqueues))
+ return ret_errno(EINVAL);
+
+ if (n_txqueues <= 0)
+ return ret_errno(EINVAL);
+
+ netdev->priv.veth_attr.n_txqueues = n_txqueues;
+ return 0;
+}
+
static int set_config_net_veth_pair(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -588,6 +659,76 @@ static int set_config_net_veth_pair(const char *key, const char *value,
sizeof(netdev->priv.veth_attr.pair));
}
+static int set_config_net_veth_vlan_id(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_vlan_id(key, lxc_conf, data);
+
+ if (strequal(value, "none")) {
+ netdev->priv.veth_attr.vlan_id = BRIDGE_VLAN_NONE;
+ } else {
+ unsigned short vlan_id;
+
+ ret = get_u16(&vlan_id, value, 0);
+ if (ret < 0)
+ return ret_errno(EINVAL);
+
+ if (vlan_id > BRIDGE_VLAN_ID_MAX)
+ return ret_errno(EINVAL);
+
+ netdev->priv.veth_attr.vlan_id = vlan_id;
+ }
+
+ netdev->priv.veth_attr.vlan_id_set = true;
+ return 0;
+}
+
+static int set_config_net_veth_vlan_tagged_id(const char *key, const char *value,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ __do_free struct lxc_list *list = NULL;
+ int ret;
+ unsigned short vlan_id;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_vlan_tagged_id(key, lxc_conf, data);
+
+ ret = get_u16(&vlan_id, value, 0);
+ if (ret < 0)
+ return ret_errno(EINVAL);
+
+ if (vlan_id > BRIDGE_VLAN_ID_MAX)
+ return ret_errno(EINVAL);
+
+ list = lxc_list_new();
+ if (!list)
+ return ret_errno(ENOMEM);
+
+ list->elem = UINT_TO_PTR(vlan_id);
+
+ lxc_list_add_tail(&netdev->priv.veth_attr.vlan_tagged_ids, move_ptr(list));
+
+ return 0;
+}
+
static int set_config_net_macvlan_mode(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -1501,8 +1642,7 @@ static int set_config_apparmor_profile(const char *key, const char *value,
#if HAVE_APPARMOR
return set_config_string_item(&lxc_conf->lsm_aa_profile, value);
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -1528,8 +1668,7 @@ static int set_config_apparmor_allow_incomplete(const char *key,
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -1553,8 +1692,7 @@ static int set_config_apparmor_allow_nesting(const char *key,
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -1584,8 +1722,7 @@ static int set_config_apparmor_raw(const char *key,
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -1595,8 +1732,7 @@ static int set_config_selinux_context(const char *key, const char *value,
#if HAVE_SELINUX
return set_config_string_item(&lxc_conf->lsm_se_context, value);
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -1606,8 +1742,7 @@ static int set_config_selinux_context_keyring(const char *key, const char *value
#if HAVE_SELINUX
return set_config_string_item(&lxc_conf->lsm_se_keyring_context, value);
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -1840,6 +1975,69 @@ static int set_config_cgroup_dir(const char *key, const char *value,
return set_config_path_item(&lxc_conf->cgroup_meta.dir, value);
}
+static int set_config_cgroup_monitor_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_monitor_dir(key, lxc_conf, NULL);
+
+ if (abspath(value))
+ return syserror_set(-EINVAL, "%s paths may not be absolute", key);
+
+ if (dotdot(value))
+ return syserror_set(-EINVAL, "%s paths may not walk upwards via \"../\"", key);
+
+ return set_config_path_item(&lxc_conf->cgroup_meta.monitor_dir, value);
+}
+
+static int set_config_cgroup_monitor_pivot_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_monitor_pivot_dir(key, lxc_conf, NULL);
+
+ if (abspath(value))
+ return syserror_set(-EINVAL, "%s paths may not be absolute", key);
+
+ if (dotdot(value))
+ return syserror_set(-EINVAL, "%s paths may not walk upwards via \"../\"", key);
+
+ return set_config_path_item(&lxc_conf->cgroup_meta.monitor_pivot_dir, value);
+}
+
+static int set_config_cgroup_container_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_container_dir(key, lxc_conf, NULL);
+
+ if (abspath(value))
+ return syserror_set(-EINVAL, "%s paths may not be absolute", key);
+
+ if (dotdot(value))
+ return syserror_set(-EINVAL, "%s paths may not walk upwards via \"../\"", key);
+
+ return set_config_path_item(&lxc_conf->cgroup_meta.container_dir, value);
+}
+
+static int set_config_cgroup_container_inner_dir(const char *key,
+ const char *value,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_container_inner_dir(key, lxc_conf, NULL);
+
+ if (abspath(value))
+ return syserror_set(-EINVAL, "%s paths may not be absolute", key);
+
+ if (strchr(value, '/') || strequal(value, ".") || strequal(value, ".."))
+ return log_error_errno(-EINVAL, EINVAL, "lxc.cgroup.dir.container.inner must be a single directory name");
+
+ return set_config_string_item(&lxc_conf->cgroup_meta.namespace_dir, value);
+}
+
static int set_config_cgroup_relative(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -2742,6 +2940,84 @@ static int set_config_namespace_keep(const char *key, const char *value,
return 0;
}
+static int set_config_time_offset_boot(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ char *unit;
+ int64_t offset = 0;
+ char buf[STRLITERALLEN("ms") + 1];
+
+ if (lxc_config_value_empty(value))
+ return clr_config_time_offset_boot(key, lxc_conf, data);
+
+ ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ unit = lxc_trim_whitespace_in_place(buf);
+ if (strequal(unit, "h")) {
+ if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "m")) {
+ if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "s")) {
+ lxc_conf->timens.s_boot = offset;
+ } else if (strequal(unit, "ms")) {
+ if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "us")) {
+ if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "ns")) {
+ lxc_conf->timens.ns_boot = offset;
+ } else {
+ return ret_errno(EINVAL);
+ }
+
+ return 0;
+}
+
+static int set_config_time_offset_monotonic(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ char *unit;
+ int64_t offset = 0;
+ char buf[STRLITERALLEN("ms") + 1];
+
+ if (lxc_config_value_empty(value))
+ return clr_config_time_offset_monotonic(key, lxc_conf, data);
+
+ ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ unit = lxc_trim_whitespace_in_place(buf);
+ if (strequal(unit, "h")) {
+ if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "m")) {
+ if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "s")) {
+ lxc_conf->timens.s_monotonic = offset;
+ } else if (strequal(unit, "ms")) {
+ if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "us")) {
+ if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strequal(unit, "ns")) {
+ lxc_conf->timens.ns_monotonic = offset;
+ } else {
+ return ret_errno(EINVAL);
+ }
+
+ return 0;
+}
+
static int set_config_namespace_share(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -3534,8 +3810,7 @@ static int get_config_apparmor_profile(const char *key, char *retv, int inlen,
#if HAVE_APPARMOR
return lxc_get_conf_str(retv, inlen, c->lsm_aa_profile);
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -3546,8 +3821,7 @@ static int get_config_apparmor_allow_incomplete(const char *key, char *retv,
#if HAVE_APPARMOR
return lxc_get_conf_int(c, retv, inlen, c->lsm_aa_allow_incomplete);
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -3558,8 +3832,7 @@ static int get_config_apparmor_allow_nesting(const char *key, char *retv,
#if HAVE_APPARMOR
return lxc_get_conf_int(c, retv, inlen, c->lsm_aa_allow_nesting);
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -3583,8 +3856,7 @@ static int get_config_apparmor_raw(const char *key, char *retv,
return fulllen;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -3594,8 +3866,7 @@ static int get_config_selinux_context(const char *key, char *retv, int inlen,
#if HAVE_SELINUX
return lxc_get_conf_str(retv, inlen, c->lsm_se_context);
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -3605,8 +3876,7 @@ static int get_config_selinux_context_keyring(const char *key, char *retv, int i
#if HAVE_SELINUX
return lxc_get_conf_str(retv, inlen, c->lsm_se_keyring_context);
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -3711,6 +3981,74 @@ static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_cgroup_monitor_dir(const char *key, char *retv, int inlen,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.monitor_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_monitor_pivot_dir(const char *key, char *retv, int inlen,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.monitor_pivot_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_container_dir(const char *key, char *retv,
+ int inlen,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.container_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_container_inner_dir(const char *key, char *retv,
+ int inlen,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.namespace_dir);
+
+ return fulllen;
+}
+
static inline int get_config_cgroup_relative(const char *key, char *retv,
int inlen, struct lxc_conf *lxc_conf,
void *data)
@@ -4413,6 +4751,46 @@ static int get_config_namespace_keep(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_time_offset_boot(const char *key, char *retv, int inlen, struct lxc_conf *c,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (c->timens.s_boot) {
+ strprint(retv, inlen, "%" PRId64 " s\n", c->timens.s_boot);
+ } else {
+ strprint(retv, inlen, "%" PRId64 " ns\n", c->timens.ns_boot);
+ }
+
+ return fulllen;
+}
+
+static int get_config_time_offset_monotonic(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (c->timens.s_monotonic) {
+ strprint(retv, inlen, "%" PRId64 "s\n", c->timens.s_monotonic);
+ } else {
+ strprint(retv, inlen, "%" PRId64 "ns\n", c->timens.ns_monotonic);
+ }
+
+ return fulllen;
+}
+
static int get_config_namespace_share(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
@@ -4474,8 +4852,7 @@ static inline int clr_config_apparmor_profile(const char *key,
free_disarm(c->lsm_aa_profile);
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -4487,8 +4864,7 @@ static inline int clr_config_apparmor_allow_incomplete(const char *key,
c->lsm_aa_allow_incomplete = 0;
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -4500,8 +4876,7 @@ static inline int clr_config_apparmor_allow_nesting(const char *key,
c->lsm_aa_allow_nesting = 0;
return 0;
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -4512,8 +4887,7 @@ static inline int clr_config_apparmor_raw(const char *key,
#if HAVE_APPARMOR
return lxc_clear_apparmor_raw(c);
#else
- SYSWARN("Built without AppArmor support");
- return 0;
+ return syserror_set(-EINVAL, "Built without AppArmor support");
#endif
}
@@ -4524,8 +4898,7 @@ static inline int clr_config_selinux_context(const char *key,
free_disarm(c->lsm_se_context);
return 0;
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -4536,8 +4909,7 @@ static inline int clr_config_selinux_context_keyring(const char *key,
free_disarm(c->lsm_se_keyring_context);
return 0;
#else
- SYSWARN("Built without SELinux support");
- return 0;
+ return syserror_set(-EINVAL, "Built without SELinux support");
#endif
}
@@ -4572,6 +4944,38 @@ static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,
return 0;
}
+static int clr_config_cgroup_monitor_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.monitor_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_monitor_pivot_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.monitor_pivot_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_container_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.container_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_container_inner_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.namespace_dir);
+ return 0;
+}
+
static inline int clr_config_cgroup_relative(const char *key,
struct lxc_conf *lxc_conf,
void *data)
@@ -4941,6 +5345,20 @@ static int clr_config_namespace_keep(const char *key, struct lxc_conf *lxc_conf,
return 0;
}
+static int clr_config_time_offset_boot(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+ lxc_conf->timens.s_boot = 0;
+ lxc_conf->timens.ns_boot = 0;
+ return 0;
+}
+
+static int clr_config_time_offset_monotonic(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+ lxc_conf->timens.s_monotonic = 0;
+ lxc_conf->timens.ns_monotonic = 0;
+ return 0;
+}
+
static int clr_config_namespace_share(const char *key,
struct lxc_conf *lxc_conf, void *data)
{
@@ -5213,6 +5631,39 @@ static int clr_config_net_veth_mode(const char *key,
return 0;
}
+static int clr_config_net_veth_n_rxqueues(const char *key, struct lxc_conf *lxc_conf,
+ void *data)
+{
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ netdev->priv.veth_attr.n_rxqueues = -1;
+
+ return 0;
+}
+
+static int clr_config_net_veth_n_txqueues(const char *key, struct lxc_conf *lxc_conf,
+ void *data)
+{
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ netdev->priv.veth_attr.n_txqueues = -1;
+
+ return 0;
+}
+
+
static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
@@ -5229,6 +5680,44 @@ static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf,
return 0;
}
+static int clr_config_net_veth_vlan_id(const char *key, struct lxc_conf *lxc_conf,
+ void *data)
+{
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ netdev->priv.veth_attr.vlan_id = 0;
+ netdev->priv.veth_attr.vlan_id_set = false;
+
+ return 0;
+}
+
+static int clr_config_net_veth_vlan_tagged_id(const char *key,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ struct lxc_netdev *netdev = data;
+ struct lxc_list *cur, *next;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.vlan_tagged_ids, next) {
+ lxc_list_del(cur);
+ free(cur);
+ }
+
+ return 0;
+}
+
+
static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
@@ -5665,6 +6154,54 @@ static int get_config_net_veth_mode(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_net_veth_n_rxqueues(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (netdev->priv.veth_attr.n_rxqueues > 0)
+ strprint(retv, inlen, "%d", netdev->priv.veth_attr.n_rxqueues);
+
+ return fulllen;
+}
+
+static int get_config_net_veth_n_txqueues(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (netdev->priv.veth_attr.n_txqueues > 0)
+ strprint(retv, inlen, "%d", netdev->priv.veth_attr.n_txqueues);
+
+ return fulllen;
+}
+
static int get_config_net_veth_pair(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
@@ -5691,6 +6228,60 @@ static int get_config_net_veth_pair(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_net_veth_vlan_id(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%d", netdev->priv.veth_attr.vlan_id);
+
+ return fulllen;
+}
+
+static int get_config_net_veth_vlan_tagged_id(const char *key, char *retv,
+ int inlen, struct lxc_conf *c,
+ void *data)
+{
+ int len;
+ size_t listlen;
+ struct lxc_list *it;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return ret_errno(EINVAL);
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ listlen = lxc_list_len(&netdev->priv.veth_attr.vlan_tagged_ids);
+
+ lxc_list_for_each(it, &netdev->priv.veth_attr.vlan_tagged_ids) {
+ unsigned short i = PTR_TO_USHORT(it->elem);
+ strprint(retv, inlen, "%u%s", i, (listlen-- > 1) ? "\n" : "");
+ }
+
+ return fulllen;
+}
+
static int get_config_net_script_up(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
@@ -6117,6 +6708,7 @@ int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen)
strprint(retv, inlen, "veth.pair\n");
strprint(retv, inlen, "veth.ipv4.route\n");
strprint(retv, inlen, "veth.ipv6.route\n");
+ strprint(retv, inlen, "veth.vlan.id\n");
break;
case LXC_NET_MACVLAN:
strprint(retv, inlen, "macvlan.mode\n");
diff --git a/src/lxc/network.c b/src/lxc/network.c
index ad43694f2..81efc8a7a 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -656,7 +656,8 @@ static int netdev_configure_server_veth(struct lxc_handler *handler, struct lxc_
}
}
- err = lxc_veth_create(veth1, veth2, handler->pid, mtu);
+ err = lxc_veth_create(veth1, veth2, handler->pid, mtu,
+ netdev->priv.veth_attr.n_rxqueues, netdev->priv.veth_attr.n_txqueues);
if (err)
return log_error_errno(-1, -err, "Failed to create veth pair \"%s\" and \"%s\"", veth1, veth2);
@@ -2070,7 +2071,8 @@ int lxc_netdev_down(const char *name)
return netdev_set_flag(name, 0);
}
-int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu)
+int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu,
+ int n_rxqueues, int n_txqueues)
{
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
@@ -2130,6 +2132,12 @@ int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned in
if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
return ret_errno(ENOMEM);
+ if (n_rxqueues > 0 && nla_put_u32(nlmsg, IFLA_NUM_RX_QUEUES, (unsigned int)n_rxqueues))
+ return ret_errno(ENOMEM);
+
+ if (n_txqueues > 0 && nla_put_u32(nlmsg, IFLA_NUM_TX_QUEUES, (unsigned int)n_txqueues))
+ return ret_errno(ENOMEM);
+
if (mtu > 0 && nla_put_u32(nlmsg, IFLA_MTU, mtu))
return ret_errno(ENOMEM);
@@ -2143,6 +2151,12 @@ int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned in
if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
return ret_errno(ENOMEM);
+ if (n_txqueues > 0 && nla_put_u32(nlmsg, IFLA_NUM_RX_QUEUES, (unsigned int)n_txqueues))
+ return ret_errno(ENOMEM);
+
+ if (n_rxqueues > 0 && nla_put_u32(nlmsg, IFLA_NUM_TX_QUEUES, (unsigned int)n_rxqueues))
+ return ret_errno(ENOMEM);
+
return netlink_transaction(nlh_ptr, nlmsg, answer);
}
diff --git a/src/lxc/network.h b/src/lxc/network.h
index d5d3d54b6..fd93242be 100644
--- a/src/lxc/network.h
+++ b/src/lxc/network.h
@@ -77,6 +77,8 @@ struct ifla_veth {
struct list_head ipv4_routes;
struct list_head ipv6_routes;
int mode; /* bridge, router */
+ int n_rxqueues;
+ int n_txqueues;
short vlan_id;
bool vlan_id_set;
struct lxc_list vlan_tagged_ids;
@@ -207,7 +209,7 @@ __hidden extern int lxc_netdev_set_mtu(const char *name, int mtu);
/* Create a virtual network devices. */
__hidden extern int lxc_veth_create(const char *name1, const char *name2, pid_t pid,
- unsigned int mtu);
+ unsigned int mtu, int n_rxqueues, int n_txqueues);
__hidden extern int lxc_macvlan_create(const char *parent, const char *name, int mode);
__hidden extern int lxc_vlan_create(const char *parent, const char *name, unsigned short vid);
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index c5bf8cdfe..38ba5c14d 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -1371,6 +1371,7 @@ void lxc_terminal_info_init(struct lxc_terminal_info *terminal)
terminal->ptx = -EBADF;
terminal->pty = -EBADF;
terminal->busy = -1;
+ terminal->pty_nr = -1;
}
void lxc_terminal_init(struct lxc_terminal *terminal)
diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h
index 45d6a18cc..d8e0f5c11 100644
--- a/src/lxc/terminal.h
+++ b/src/lxc/terminal.h
@@ -29,6 +29,9 @@ struct lxc_terminal_info {
/* whether the terminal is currently used */
int busy;
+
+ /* the number of the terminal */
+ int pty_nr;
};
struct lxc_terminal_state {
diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index 91596d4f6..062135d40 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -282,6 +282,11 @@ static int cmporder(const void *p1, const void *p2)
return (c1_order - c2_order);
}
+static int cmporder_reverse(const void *p1, const void *p2)
+{
+ return -1 * cmporder(p1, p2);
+}
+
static int toss_list(struct lxc_list *c_groups_list)
{
struct lxc_list *it, *next;
@@ -332,7 +337,8 @@ int main(int argc, char *argv[])
if (!my_args.all)
c_groups_lists = calloc( count, sizeof( struct lxc_list * ) );
- qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder);
+ qsort(&containers[0], count, sizeof(struct lxc_container *),
+ (my_args.shutdown || my_args.hardstop) ? cmporder_reverse : cmporder);
if (cmd_groups_list && my_args.all)
ERROR("Specifying -a (all) with -g (groups) doesn't make sense. All option overrides");
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index b2cfb865d..4acb10585 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -218,6 +218,9 @@ int mkdir_p(const char *dir, mode_t mode)
const char *tmp = dir;
const char *orig = dir;
+ if (access(dir, F_OK) != -1)
+ return 0;
+
do {
__do_free char *makeme = NULL;
int ret;
diff --git a/src/tests/aa.c b/src/tests/aa.c
index e288b46df..417f3fc23 100644
--- a/src/tests/aa.c
+++ b/src/tests/aa.c
@@ -21,7 +21,7 @@
/* Test apparmor rules */
#include <lxc/lxccontainer.h>
-#include "lxc/utils.h"
+#include "utils.h"
#include <fcntl.h>
#include <unistd.h>
diff --git a/src/tests/config_jump_table.c b/src/tests/config_jump_table.c
index a0b966b3c..cc975a625 100644
--- a/src/tests/config_jump_table.c
+++ b/src/tests/config_jump_table.c
@@ -33,7 +33,7 @@
#include <string.h>
#include "confile.h"
-#include "lxc/state.h"
+#include "state.h"
#include "lxctest.h"
int main(int argc, char *argv[])
diff --git a/src/tests/containertests.c b/src/tests/containertests.c
index 7bd5e92ef..6da622f77 100644
--- a/src/tests/containertests.c
+++ b/src/tests/containertests.c
@@ -29,7 +29,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
-#include "lxc/state.h"
+#include "state.h"
#define MYNAME "lxctest1"
diff --git a/src/tests/get_item.c b/src/tests/get_item.c
index d9cf1e7b2..8ad53c437 100644
--- a/src/tests/get_item.c
+++ b/src/tests/get_item.c
@@ -30,7 +30,7 @@
#include <errno.h>
#include <string.h>
-#include "lxc/state.h"
+#include "state.h"
#include "lxctest.h"
#include "utils.h"
@@ -42,10 +42,28 @@
int main(int argc, char *argv[])
{
- int ret;
- struct lxc_container *c;
+ int fd_log, ret;
+ struct lxc_container *c = NULL;
int fret = EXIT_FAILURE;
char v1[2], v2[256], v3[2048];
+ struct lxc_log log = {};
+ char template[sizeof(P_tmpdir"/attach_XXXXXX")];
+
+ (void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template));
+
+ fd_log = lxc_make_tmpfile(template, false);
+ if (fd_log < 0) {
+ lxc_error("Failed to create temporary log file for container %s\n", MYNAME);
+ exit(EXIT_FAILURE);
+ }
+ log.name = MYNAME;
+ log.file = template;
+ log.level = "TRACE";
+ log.prefix = "get_item";
+ log.quiet = false;
+ log.lxcpath = NULL;
+ if (lxc_log_init(&log))
+ goto out;
if ((c = lxc_container_new("testxyz", NULL)) == NULL) {
fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
@@ -144,6 +162,59 @@ int main(int argc, char *argv[])
}
printf("lxc.init_gid returned %d %s\n", ret, v2);
+ if (c->set_config_item(c, "lxc.init.groups", "10,20,foo,40")) {
+ fprintf(stderr, "%d: managed to set lxc.init.groups to '10,20,foo,40'\n", __LINE__);
+ goto out;
+ }
+
+ if (!c->set_config_item(c, "lxc.init.groups", "10,20,30,40")) {
+ fprintf(stderr, "%d: managed to set lxc.init.groups to '10,20,30,40'\n", __LINE__);
+ goto out;
+ }
+
+ ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
+ if (ret < 0) {
+ fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
+ goto out;
+ }
+ ret = strcmp("10,20,30,40", v2);
+ printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (!c->set_config_item(c, "lxc.init.groups", "50,60,70,80")) {
+ fprintf(stderr, "%d: failed to set lxc.init.groups to '50,60,70,80'\n", __LINE__);
+ goto out;
+ }
+
+ ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
+ if (ret < 0) {
+ fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
+ goto out;
+ }
+ ret = strcmp("10,20,30,40,50,60,70,80", v2);
+ printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (!c->set_config_item(c, "lxc.init.groups", "")) {
+ fprintf(stderr, "%d: failed to set lxc.init.groups to ''\n", __LINE__);
+ goto out;
+ }
+
+ ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
+ if (ret < 0) {
+ fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
+ goto out;
+ }
+ ret = strcmp("", v2);
+ printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
+ if (ret != 0) {
+ goto out;
+ }
+
#define HNAME "hostname1"
// demonstrate proper usage:
char *alloced;
@@ -410,7 +481,6 @@ int main(int argc, char *argv[])
}
printf("lxc.proc returned %d %s\n", ret, v3);
-#if HAVE_APPARMOR
if (!c->set_config_item(c, "lxc.apparmor.profile", "unconfined")) {
fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__);
goto out;
@@ -422,7 +492,6 @@ int main(int argc, char *argv[])
goto out;
}
printf("lxc.aa_profile returned %d %s\n", ret, v2);
-#endif
lxc_container_put(c);
@@ -629,6 +698,17 @@ out:
c->destroy(c);
lxc_container_put(c);
}
+ if (fret != EXIT_SUCCESS) {
+ char buf[4096];
+ ssize_t buflen;
+ while ((buflen = read(fd_log, buf, 1024)) > 0) {
+ buflen = write(STDERR_FILENO, buf, buflen);
+ if (buflen <= 0)
+ break;
+ }
+ close(fd_log);
+ }
+ (void)unlink(template);
exit(fret);
}
diff --git a/src/tests/getkeys.c b/src/tests/getkeys.c
index 4768b9ebd..f718fe99e 100644
--- a/src/tests/getkeys.c
+++ b/src/tests/getkeys.c
@@ -29,7 +29,7 @@
#include <sys/wait.h>
#include <lxc/lxccontainer.h>
-#include "lxc/state.h"
+#include "state.h"
#define MYNAME "lxctest1"
diff --git a/src/tests/locktests.c b/src/tests/locktests.c
index 4836d46df..f7eb3ad5c 100644
--- a/src/tests/locktests.c
+++ b/src/tests/locktests.c
@@ -19,7 +19,7 @@
#include "config.h"
-#include "lxc/lxclock.h"
+#include "lxclock.h"
#include "config.h"
#include <unistd.h>
#include <signal.h>
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index f10c1eba8..e23ac729c 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -254,13 +254,13 @@ void test_lxc_safe_uint(void)
lxc_test_assert_abort((-EINVAL == lxc_safe_uint("-123", &n)));
ret = snprintf(numstr, sizeof(numstr), "%" PRIu64, (uint64_t)UINT_MAX);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((0 == lxc_safe_uint(numstr, &n)) && n == UINT_MAX);
ret = snprintf(numstr, sizeof(numstr), "%" PRIu64, (uint64_t)UINT_MAX + 1);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((-ERANGE == lxc_safe_uint(numstr, &n)));
@@ -287,25 +287,25 @@ void test_lxc_safe_int(void)
char numstr[INTTYPE_TO_STRLEN(uint64_t)];
ret = snprintf(numstr, sizeof(numstr), "%" PRIu64, (uint64_t)INT_MAX);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((0 == lxc_safe_int(numstr, &n)) && n == INT_MAX);
ret = snprintf(numstr, sizeof(numstr), "%" PRIu64, (uint64_t)INT_MAX + 1);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((-ERANGE == lxc_safe_int(numstr, &n)));
ret = snprintf(numstr, sizeof(numstr), "%" PRId64, (int64_t)INT_MIN);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((0 == lxc_safe_int(numstr, &n)) && n == INT_MIN);
ret = snprintf(numstr, sizeof(numstr), "%" PRId64, (int64_t)INT_MIN - 1);
- if (ret < 0 || ret >= sizeof(numstr))
+ if (ret < 0 || (size_t)ret >= sizeof(numstr))
exit(EXIT_FAILURE);
lxc_test_assert_abort((-ERANGE == lxc_safe_int(numstr, &n)));
@@ -551,7 +551,7 @@ void test_task_blocks_signal(void)
sigemptyset(&mask);
- for (i = 0; i < (sizeof(signals) / sizeof(signals[0])); i++) {
+ for (i = 0; (size_t)i < (sizeof(signals) / sizeof(signals[0])); i++) {
ret = sigaddset(&mask, signals[i]);
if (ret < 0)
_exit(EXIT_FAILURE);
@@ -563,7 +563,7 @@ void test_task_blocks_signal(void)
_exit(EXIT_FAILURE);
}
- for (i = 0; i < (sizeof(signals) / sizeof(signals[0])); i++) {
+ for (i = 0; (size_t)i < (sizeof(signals) / sizeof(signals[0])); i++) {
if (!task_blocks_signal(getpid(), signals[i])) {
lxc_error("Failed to detect blocked signal "
"(idx = %d, signal number = %d)\n",
diff --git a/src/tests/meson.build b/src/tests/meson.build
new file mode 100644
index 000000000..0e0abdebd
--- /dev/null
+++ b/src/tests/meson.build
@@ -0,0 +1,534 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+tests_liblxc_includes = include_directories(
+ '.',
+ '../lxc/',
+ '../lxc/cgroups',
+ '../lxc/lsm',
+ '../lxc/storage',
+ '../include',
+ '../../')
+
+tests_common_sources = files(
+ '../lxc/af_unix.c',
+ '../lxc/af_unix.h',
+ '../lxc/attach_options.h',
+ '../lxc/caps.c',
+ '../lxc/caps.h',
+ '../lxc/commands.c',
+ '../lxc/commands.h',
+ '../lxc/commands_utils.c',
+ '../lxc/commands_utils.h',
+ '../lxc/compiler.h',
+ '../lxc/conf.c',
+ '../lxc/conf.h',
+ '../lxc/confile.c',
+ '../lxc/confile.h',
+ '../lxc/confile_utils.c',
+ '../lxc/confile_utils.h',
+ '../lxc/cgroups/cgfsng.c',
+ '../lxc/cgroups/cgroup.c',
+ '../lxc/cgroups/cgroup.h',
+ '../lxc/cgroups/cgroup2_devices.c',
+ '../lxc/cgroups/cgroup2_devices.h',
+ '../lxc/cgroups/cgroup_utils.c',
+ '../lxc/cgroups/cgroup_utils.h',
+ '../lxc/error.c',
+ '../lxc/error.h',
+ '../lxc/initutils.c',
+ '../lxc/initutils.h',
+ '../lxc/file_utils.c',
+ '../lxc/file_utils.h',
+ '../lxc/lsm/apparmor.c',
+ '../lxc/lsm/lsm.c',
+ '../lxc/lsm/lsm.h',
+ '../lxc/lsm/nop.c',
+ '../lxc/lsm/selinux.c',
+ '../lxc/lxcseccomp.h',
+ '../lxc/lxclock.c',
+ '../lxc/lxclock.h',
+ '../lxc/macro.h',
+ '../lxc/mainloop.c',
+ '../lxc/mainloop.h',
+ '../lxc/memory_utils.h',
+ '../lxc/monitor.c',
+ '../lxc/monitor.h',
+ '../lxc/mount_utils.c',
+ '../lxc/mount_utils.h',
+ '../lxc/namespace.c',
+ '../lxc/namespace.h',
+ '../lxc/network.c',
+ '../lxc/network.h',
+ '../lxc/nl.c',
+ '../lxc/nl.h',
+ '../lxc/parse.c',
+ '../lxc/parse.h',
+ '../lxc/process_utils.c',
+ '../lxc/process_utils.h',
+ '../lxc/ringbuf.c',
+ '../lxc/ringbuf.h',
+ '../lxc/seccomp.c',
+ '../lxc/start.c',
+ '../lxc/start.h',
+ '../lxc/state.c',
+ '../lxc/state.h',
+ '../lxc/storage/btrfs.c',
+ '../lxc/storage/btrfs.h',
+ '../lxc/storage/dir.c',
+ '../lxc/storage/dir.h',
+ '../lxc/storage/loop.c',
+ '../lxc/storage/loop.h',
+ '../lxc/storage/lvm.c',
+ '../lxc/storage/lvm.h',
+ '../lxc/storage/nbd.c',
+ '../lxc/storage/nbd.h',
+ '../lxc/storage/overlay.c',
+ '../lxc/storage/overlay.h',
+ '../lxc/storage/rbd.c',
+ '../lxc/storage/rbd.h',
+ '../lxc/storage/rsync.c',
+ '../lxc/storage/rsync.h',
+ '../lxc/storage/storage.c',
+ '../lxc/storage/storage.h',
+ '../lxc/storage/storage_utils.c',
+ '../lxc/storage/storage_utils.h',
+ '../lxc/storage/zfs.c',
+ '../lxc/storage/zfs.h',
+ '../lxc/string_utils.c',
+ '../lxc/string_utils.h',
+ '../lxc/sync.c',
+ '../lxc/sync.h',
+ '../lxc/terminal.c',
+ '../lxc/terminal.h',
+ '../lxc/utils.c',
+ '../lxc/utils.h',
+ '../lxc/uuid.c',
+ '../lxc/uuid.h',
+ '../lxc/log.h',
+ '../lxc/log.c') + include_sources + netns_ifaddrs_sources
+
+test_programs += executable(
+ 'lxc-test-arch-parse',
+ files('arch_parse.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-apparmor',
+ files('aa.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-api-reboot',
+ files('api_reboot.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-attach',
+ files('attach.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-basic',
+ files('basic.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-capabilities',
+ files('capabilities.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-cgpath',
+ files('cgpath.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-clonetest',
+ files('clonetest.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-concurrent',
+ files('concurrent.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-config-jump-table',
+ files('config_jump_table.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-console',
+ files('console.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-console-log',
+ files('console_log.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-containertests',
+ files('containertests.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-createtest',
+ files('createtest.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-criu-check-feature',
+ files('criu_check_feature.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-cve-2019-5736',
+ files('cve-2019-5736.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-destroytest',
+ files('destroytest.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-device-add-remove',
+ files('device_add_remove.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-get-item',
+ files('get_item.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-getkeys',
+ files('getkeys.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-list',
+ files('list.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-locktests',
+ files('locktests.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-lxc-test-utils',
+ files('lxc-test-utils.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-lxc-raw-clone',
+ files('lxc_raw_clone.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-lxcpath',
+ files('lxcpath.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-may-control',
+ files('may_control.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-mount-injection',
+ files('mount_injection.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-parse-config-file',
+ files('parse_config_file.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-personality',
+ files('personality.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-proc-pid',
+ files('proc_pid.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-reboot',
+ files('reboot.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-rootfs-options',
+ files('rootfs_options.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-rootfs-overmounted',
+ files('rootfs_overmounted.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-saveconfig',
+ files('saveconfig.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-share-ns',
+ files('share_ns.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-shortlived',
+ files('shortlived.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-shutdowntest',
+ files('shutdowntest.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-snapshot',
+ files('snapshot.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-startone',
+ files('startone.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-state-server',
+ files('state_server.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-sys-mixed',
+ files('sys_mixed.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += executable(
+ 'lxc-test-sysctls',
+ files('sysctls.c') + tests_common_sources,
+ include_directories : tests_liblxc_includes,
+ dependencies : liblxc_dep,
+ install: false,
+ build_by_default: want_tests != false)
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-apparmor-generated',
+ output : 'lxc-test-apparmor-generated')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-apparmor-mount',
+ output : 'lxc-test-apparmor-mount')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-automount',
+ output : 'lxc-test-automount')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-autostart',
+ output : 'lxc-test-autostart')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-checkpoint-restore',
+ output : 'lxc-test-checkpoint-restore')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-cloneconfig',
+ output : 'lxc-test-cloneconfig')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-createconfig',
+ output : 'lxc-test-createconfig')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-exit-code',
+ output : 'lxc-test-exit-code')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-fuzzers',
+ output : 'lxc-test-fuzzers')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-lxc-attach',
+ output : 'lxc-test-lxc-attach')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-no-new-privs',
+ output : 'lxc-test-no-new-privs')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-procsys',
+ output : 'lxc-test-procsys')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-rootfs',
+ output : 'lxc-test-rootfs')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-snapdeps',
+ output : 'lxc-test-snapdeps')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-symlink',
+ output : 'lxc-test-symlink')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-unpriv',
+ output : 'lxc-test-unpriv')
+
+test_programs += configure_file(
+ configuration : conf,
+ input : 'lxc-test-usernic.in',
+ output : 'lxc-test-usernic')
+
+test_programs += configure_file(
+ configuration : dummy_config_data,
+ input : 'lxc-test-usernsexec',
+ output : 'lxc-test-usernsexec')
diff --git a/src/tests/mount_injection.c b/src/tests/mount_injection.c
index 64b1cb253..f98370b4c 100644
--- a/src/tests/mount_injection.c
+++ b/src/tests/mount_injection.c
@@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <lxc/lxccontainer.h>
-#include <lxc/list.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
@@ -32,6 +31,7 @@
#include "config.h"
#include "lxctest.h"
+#include "list.h"
#include "utils.h"
#define NAME "mount_injection_test-"
diff --git a/src/tests/parse_config_file.c b/src/tests/parse_config_file.c
index ec37e3165..1444799ca 100644
--- a/src/tests/parse_config_file.c
+++ b/src/tests/parse_config_file.c
@@ -33,7 +33,7 @@
#include "conf.h"
#include "confile_utils.h"
-#include "lxc/state.h"
+#include "state.h"
#include "lxctest.h"
#include "utils.h"
@@ -797,6 +797,21 @@ int main(int argc, char *argv[])
return -1;
}
+ if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.vlan.id", "none", tmpf, false, "veth")) {
+ lxc_error("%s\n", "lxc.net.0.veth.vlan.id");
+ return -1;
+ }
+
+ if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.vlan.id", "2", tmpf, true, "veth")) {
+ lxc_error("%s\n", "lxc.net.0.veth.vlan.id");
+ return -1;
+ }
+
+ if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.vlan.tagged.id", "2", tmpf, true, "veth")) {
+ lxc_error("%s\n", "lxc.net.0.veth.vlan.tagged.id");
+ return -1;
+ }
+
if (set_get_compare_clear_save_load(c, "lxc.net.0.script.up", "/some/up/path", tmpf, true)) {
lxc_error("%s\n", "lxc.net.0.script.up");
goto non_test_error;
diff --git a/src/tests/reboot.c b/src/tests/reboot.c
index e16aabe2c..0a07bf467 100644
--- a/src/tests/reboot.c
+++ b/src/tests/reboot.c
@@ -30,7 +30,7 @@
#include <sys/types.h>
#include <sys/wait.h>
-#include "lxc/namespace.h"
+#include "namespace.h"
#include <sched.h>
#include <linux/sched.h>
diff --git a/src/tests/share_ns.c b/src/tests/share_ns.c
index c46023f01..fd070adad 100644
--- a/src/tests/share_ns.c
+++ b/src/tests/share_ns.c
@@ -288,7 +288,7 @@ int main(int argc, char *argv[])
lxc_debug("Starting namespace sharing test iteration %d\n", j);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; (size_t)i < nthreads; i++) {
memset(&args[i], 0, sizeof(struct thread_args));
memset(&threads[i], 0, sizeof(pthread_t));
@@ -303,7 +303,7 @@ int main(int argc, char *argv[])
goto on_error_stop;
}
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; (size_t)i < nthreads; i++) {
ret = pthread_join(threads[i], NULL);
if (ret != 0)
goto on_error_stop;
diff --git a/src/tests/snapshot.c b/src/tests/snapshot.c
index 62440fe28..dfbf78e45 100644
--- a/src/tests/snapshot.c
+++ b/src/tests/snapshot.c
@@ -26,7 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
-#include "lxc/lxc.h"
+#include "lxc.h"
#define MYNAME "snapxxx1"
#define MYNAME2 "snapxxx3"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment