]> git.proxmox.com Git - lxc.git/blob - debian/patches/extra/0004-apparmor-generate-ro-bind-remount-rule-list.patch
merge new apparmor profile update
[lxc.git] / debian / patches / extra / 0004-apparmor-generate-ro-bind-remount-rule-list.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Fri, 2 Aug 2019 12:57:42 +0200
4 Subject: [PATCH] apparmor: generate ro,bind,remount rule list
5
6 initially based on changes to lxd
7
8 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
9 ---
10 src/lxc/lsm/apparmor.c | 156 ++++++++++++++++++++++++++++++++++++-----
11 1 file changed, 140 insertions(+), 16 deletions(-)
12
13 diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c
14 index e32b12531..08966a246 100644
15 --- a/src/lxc/lsm/apparmor.c
16 +++ b/src/lxc/lsm/apparmor.c
17 @@ -149,6 +149,16 @@ static const char AA_PROFILE_BASE[] =
18 "# mount options=(rw,make-unbindable) -> **,\n"
19 "# mount options=(rw,make-runbindable) -> **,\n"
20 "\n"
21 +"# Allow limited modification of mount propagation\n"
22 +" mount options=(rw,make-slave) -> /,\n"
23 +" mount options=(rw,make-rslave) -> /,\n"
24 +" mount options=(rw,make-shared) -> /,\n"
25 +" mount options=(rw,make-rshared) -> /,\n"
26 +" mount options=(rw,make-private) -> /,\n"
27 +" mount options=(rw,make-rprivate) -> /,\n"
28 +" mount options=(rw,make-unbindable) -> /,\n"
29 +" mount options=(rw,make-runbindable) -> /,\n"
30 +"\n"
31 " # allow bind-mounts of anything except /proc, /sys and /dev\n"
32 " mount options=(rw,bind) /[^spd]*{,/**},\n"
33 " mount options=(rw,bind) /d[^e]*{,/**},\n"
34 @@ -167,15 +177,18 @@ static const char AA_PROFILE_BASE[] =
35 " mount options=(rw,bind) /sy[^s]*{,/**},\n"
36 " mount options=(rw,bind) /sys?*{,/**},\n"
37 "\n"
38 -" # allow various ro-bind-*re*-mounts\n"
39 -" mount options=(ro,remount,bind),\n"
40 -" mount options=(ro,remount,bind,nosuid),\n"
41 -" mount options=(ro,remount,bind,noexec),\n"
42 -" mount options=(ro,remount,bind,nodev),\n"
43 -" mount options=(ro,remount,bind,nosuid,noexec),\n"
44 -" mount options=(ro,remount,bind,noexec,nodev),\n"
45 -" mount options=(ro,remount,bind,nodev,nosuid),\n"
46 -" mount options=(ro,remount,bind,nosuid,noexec,nodev),\n"
47 +" # Allow rbind-mounts of anything except /, /dev, /proc and /sys\n"
48 +" mount options=(rw,rbind) /[^spd]*{,/**},\n"
49 +" mount options=(rw,rbind) /d[^e]*{,/**},\n"
50 +" mount options=(rw,rbind) /de[^v]*{,/**},\n"
51 +" mount options=(rw,rbind) /dev?*{,/**},\n"
52 +" mount options=(rw,rbind) /p[^r]*{,/**},\n"
53 +" mount options=(rw,rbind) /pr[^o]*{,/**},\n"
54 +" mount options=(rw,rbind) /pro[^c]*{,/**},\n"
55 +" mount options=(rw,rbind) /proc?*{,/**},\n"
56 +" mount options=(rw,rbind) /s[^y]*{,/**},\n"
57 +" mount options=(rw,rbind) /sy[^s]*{,/**},\n"
58 +" mount options=(rw,rbind) /sys?*{,/**},\n"
59 "\n"
60 " # allow moving mounts except for /proc, /sys and /dev\n"
61 " mount options=(rw,move) /[^spd]*{,/**},\n"
62 @@ -339,18 +352,57 @@ static const char AA_PROFILE_NESTING_BASE[] =
63 " deny /dev/.lxc/proc/** rw,\n"
64 " deny /dev/.lxc/sys/** rw,\n"
65 "\n"
66 +" # Allow modifying mount propagation\n"
67 +" mount options=(rw,make-slave) -> **,\n"
68 +" mount options=(rw,make-rslave) -> **,\n"
69 +" mount options=(rw,make-shared) -> **,\n"
70 +" mount options=(rw,make-rshared) -> **,\n"
71 +" mount options=(rw,make-private) -> **,\n"
72 +" mount options=(rw,make-rprivate) -> **,\n"
73 +" mount options=(rw,make-unbindable) -> **,\n"
74 +" mount options=(rw,make-runbindable) -> **,\n"
75 +"\n"
76 " mount fstype=proc -> /usr/lib/*/lxc/**,\n"
77 " mount fstype=sysfs -> /usr/lib/*/lxc/**,\n"
78 " mount options=(rw,bind),\n"
79 " mount options=(rw,rbind),\n"
80 -" mount options=(rw,make-rshared),\n"
81 "\n"
82 - /* FIXME: What's the state here on apparmor's side? */
83 -" # there doesn't seem to be a way to ask for:\n"
84 -" # mount options=(ro,nosuid,nodev,noexec,remount,bind),\n"
85 -" # as we always get mount to $cdir/proc/sys with those flags denied\n"
86 -" # So allow all mounts until that is straightened out:\n"
87 -" mount,\n"
88 +" # Allow common combinations of bind/remount\n"
89 +" # NOTE: AppArmor bug effectively turns those into wildcards mount allow\n"
90 +" mount options=(ro,remount,bind),\n"
91 +" mount options=(ro,remount,bind,nodev),\n"
92 +" mount options=(ro,remount,bind,nodev,nosuid),\n"
93 +" mount options=(ro,remount,bind,noexec),\n"
94 +" mount options=(ro,remount,bind,noexec,nodev),\n"
95 +" mount options=(ro,remount,bind,nosuid),\n"
96 +" mount options=(ro,remount,bind,nosuid,nodev),\n"
97 +" mount options=(ro,remount,bind,nosuid,noexec),\n"
98 +" mount options=(ro,remount,bind,nosuid,noexec,nodev),\n"
99 +
100 +" mount options=(ro,remount,bind,strictatime),\n"
101 +" mount options=(ro,remount,bind,strictatime,nodev),\n"
102 +" mount options=(ro,remount,bind,strictatime,nodev,nosuid),\n"
103 +" mount options=(ro,remount,bind,strictatime,noexec),\n"
104 +" mount options=(ro,remount,bind,strictatime,noexec,nodev),\n"
105 +" mount options=(ro,remount,bind,strictatime,nosuid),\n"
106 +" mount options=(ro,remount,bind,strictatime,nosuid,nodev),\n"
107 +" mount options=(ro,remount,bind,strictatime,nosuid,noexec),\n"
108 +" mount options=(ro,remount,bind,strictatime,nosuid,noexec,nodev),\n"
109 +
110 +" mount options=(ro,remount,bind,noatime),\n"
111 +" mount options=(ro,remount,bind,noatime,nodev),\n"
112 +" mount options=(ro,remount,bind,noatime,nodev,nosuid),\n"
113 +" mount options=(ro,remount,bind,noatime,noexec),\n"
114 +" mount options=(ro,remount,bind,noatime,noexec,nodev),\n"
115 +" mount options=(ro,remount,bind,noatime,nosuid),\n"
116 +" mount options=(ro,remount,bind,noatime,nosuid,nodev),\n"
117 +" mount options=(ro,remount,bind,noatime,nosuid,noexec),\n"
118 +" mount options=(ro,remount,bind,noatime,nosuid,noexec,nodev),\n"
119 +
120 +"\n"
121 +" # Allow remounting things read-only\n"
122 +" mount options=(ro,remount) /,\n"
123 +" mount options=(ro,remount) /**,\n"
124 ;
125
126 static const char AA_PROFILE_UNPRIVILEGED[] =
127 @@ -648,6 +700,76 @@ static bool is_privileged(struct lxc_conf *conf)
128 return lxc_list_empty(&conf->id_map);
129 }
130
131 +static const char* AA_ALL_DEST_PATH_LIST[] = {
132 + " -> /[^spd]*{,/**},\n",
133 + " -> /d[^e]*{,/**},\n",
134 + " -> /de[^v]*{,/**},\n",
135 + " -> /dev/.[^l]*{,/**},\n",
136 + " -> /dev/.l[^x]*{,/**},\n",
137 + " -> /dev/.lx[^c]*{,/**},\n",
138 + " -> /dev/.lxc?*{,/**},\n",
139 + " -> /dev/[^.]*{,/**},\n",
140 + " -> /dev?*{,/**},\n",
141 + " -> /p[^r]*{,/**},\n",
142 + " -> /pr[^o]*{,/**},\n",
143 + " -> /pro[^c]*{,/**},\n",
144 + " -> /proc?*{,/**},\n",
145 + " -> /s[^y]*{,/**},\n",
146 + " -> /sy[^s]*{,/**},\n",
147 + " -> /sys?*{,/**},\n",
148 + NULL,
149 +};
150 +
151 +static void append_remount_rule(char **profile, size_t *size, const char *rule)
152 +{
153 + size_t rule_len = strlen(rule);
154 +
155 + for (const char **dest = AA_ALL_DEST_PATH_LIST; *dest; ++dest) {
156 + must_append_sized(profile, size, rule, rule_len);
157 + must_append_sized(profile, size, *dest, strlen(*dest));
158 + }
159 +}
160 +
161 +static void append_all_remount_rules(char **profile, size_t *size)
162 +{
163 + must_append_sized(profile, size,
164 + "# allow various ro-bind-*re*mounts\n",
165 + sizeof("# allow various ro-bind-*re*mounts\n")-1);
166 +
167 + static struct mntopt_t {
168 + const char *opt;
169 + size_t len;
170 + } mnt_opt_list[] = {
171 + { ",nodev", sizeof(",nodev")-1 },
172 + { ",nosuid", sizeof(",nosuid")-1 },
173 + { ",noexec", sizeof(",noexec")-1 },
174 + };
175 +
176 + const size_t opt_count = sizeof(mnt_opt_list) / sizeof(mnt_opt_list[0]);
177 +
178 + char buf[128] = "mount options=(ro,remount,bind";
179 + const size_t start = strlen(buf);
180 + for (size_t i = 0; i != 1 << opt_count; ++i) {
181 + size_t at = start;
182 + unsigned opt_bit = 1;
183 +
184 + for (size_t o = 0; o != opt_count; ++o, opt_bit <<= 1) {
185 + if (i & opt_bit) {
186 + struct mntopt_t *opt = &mnt_opt_list[o];
187 + memcpy(&buf[at], opt->opt, opt->len);
188 + at += opt->len;
189 + }
190 + }
191 +
192 + memcpy(&buf[at], ")", sizeof(")"));
193 + append_remount_rule(profile, size, buf);
194 + memcpy(&buf[at], ",noatime)", sizeof(",noatime)"));
195 + append_remount_rule(profile, size, buf);
196 + memcpy(&buf[at], ",strictatime)", sizeof(",strictatime)"));
197 + append_remount_rule(profile, size, buf);
198 + }
199 +}
200 +
201 static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxcpath)
202 {
203 char *profile, *profile_name_full;
204 @@ -665,6 +787,8 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc
205 must_append_sized(&profile, &size, AA_PROFILE_BASE,
206 STRARRAYLEN(AA_PROFILE_BASE));
207
208 + append_all_remount_rules(&profile, &size);
209 +
210 if (aa_supports_unix)
211 must_append_sized(&profile, &size, AA_PROFILE_UNIX_SOCKETS,
212 STRARRAYLEN(AA_PROFILE_UNIX_SOCKETS));
213 --
214 2.20.1
215