]>
Commit | Line | Data |
---|---|---|
87c39e90 WB |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Fri, 3 Dec 2021 09:13:11 +0100 | |
4 | Subject: [PATCH lxc] use 2 sysfs instances for sys:mixed | |
5 | ||
6 | In order to facilitate this, the default mount list's | |
7 | 'destination' may now be NULL to mean that the source should | |
8 | be unmounted instead. | |
9 | ||
10 | Here's what we need to do: | |
11 | ||
12 | 1) Ensure the first sysfs mount point is writable. | |
13 | 2) Mount a read-only sysfs on /sys | |
14 | 3) Bind devices/virtual/net *writably* into /sys | |
15 | ||
16 | We use /proc/sys as a staging directory for the first sysfs | |
17 | mount in read-write mode, then mount /sys r/o. Afterwards we | |
18 | bind the r/w devices/virtual/net and unmount the staging | |
19 | /proc/sys mount point. | |
20 | ||
21 | The staging directory would not be required with the new | |
22 | mount API, but this way we can support the old API and keep | |
23 | the general workflow in the `default_mounts`. | |
24 | ||
25 | Once we drop support for the old mount API, the | |
26 | default_mounts table could just get a subdirectory field to | |
27 | mount subdirectories directly. | |
28 | ||
29 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
30 | --- | |
31 | src/lxc/conf.c | 19 ++++++++++++++----- | |
32 | 1 file changed, 14 insertions(+), 5 deletions(-) | |
33 | ||
34 | diff --git a/src/lxc/conf.c b/src/lxc/conf.c | |
35 | index 8e068b8ac..c9ab285d8 100644 | |
36 | --- a/src/lxc/conf.c | |
37 | +++ b/src/lxc/conf.c | |
38 | @@ -708,9 +708,11 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags) | |
39 | { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL, false }, | |
40 | { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW, "sysfs", "%r/sys", "sysfs", 0, NULL, false }, | |
41 | { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO, "sysfs", "%r/sys", "sysfs", MS_RDONLY, NULL, false }, | |
42 | + /* /proc/sys is used as a temporary staging directory for the read-write sysfs mount and unmounted after binding net */ | |
43 | + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/proc/sys", "sysfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL, false }, | |
44 | { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL, false }, | |
45 | - { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "%r/sys/devices/virtual/net", "%r/sys/devices/virtual/net", NULL, MS_BIND, NULL, false }, | |
46 | - { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys/devices/virtual/net", NULL, MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL, false }, | |
47 | + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "%r/proc/sys/devices/virtual/net", "%r/sys/devices/virtual/net", NULL, MS_BIND, NULL, false }, | |
48 | + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "%r/proc/sys", NULL, NULL, 0, NULL, false }, | |
49 | { 0, 0, NULL, NULL, NULL, 0, NULL, false } | |
50 | }; | |
51 | struct lxc_conf *conf = handler->conf; | |
52 | @@ -778,14 +780,21 @@ static int lxc_mount_auto_mounts(struct lxc_handler *handler, int flags) | |
53 | return syserror_set(-ENOMEM, "Failed to create source path"); | |
54 | } | |
55 | ||
56 | - if (!default_mounts[i].destination) | |
57 | - return syserror_set(-EINVAL, "BUG: auto mounts destination %d was NULL", i); | |
58 | - | |
59 | if (!has_cap_net_admin && default_mounts[i].requires_cap_net_admin) { | |
60 | TRACE("Container does not have CAP_NET_ADMIN. Skipping \"%s\" mount", default_mounts[i].source ?: "(null)"); | |
61 | continue; | |
62 | } | |
63 | ||
64 | + if (!default_mounts[i].destination) { | |
65 | + ret = umount2(source, MNT_DETACH); | |
66 | + if (ret < 0) | |
67 | + return log_error_errno(-1, errno, | |
68 | + "Failed to unmount \"%s\"", | |
69 | + source); | |
70 | + TRACE("Unmounted automount \"%s\"", source); | |
71 | + continue; | |
72 | + } | |
73 | + | |
74 | /* will act like strdup if %r is not present */ | |
75 | destination = lxc_string_replace("%r", rootfs->path ? rootfs->mount : "", default_mounts[i].destination); | |
76 | if (!destination) |