aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa2012-02-29 06:53:22 -0600
committerJames Morris2012-02-29 17:23:19 -0600
commitdf91e49477a9be15921cb2854e1d12a3bdb5e425 (patch)
tree8408a7d2a432a206070ac01b2939fefcdce9ca13 /security/tomoyo
parenta69f15890292b5449f9056b4bb322b044e6ce0c6 (diff)
downloadkernel-common-df91e49477a9be15921cb2854e1d12a3bdb5e425.tar.gz
kernel-common-df91e49477a9be15921cb2854e1d12a3bdb5e425.tar.xz
kernel-common-df91e49477a9be15921cb2854e1d12a3bdb5e425.zip
TOMOYO: Fix mount flags checking order.
Userspace can pass in arbitrary combinations of MS_* flags to mount(). If both MS_BIND and one of MS_SHARED/MS_PRIVATE/MS_SLAVE/MS_UNBINDABLE are passed, device name which should be checked for MS_BIND was not checked because MS_SHARED/MS_PRIVATE/MS_SLAVE/MS_UNBINDABLE had higher priority than MS_BIND. If both one of MS_BIND/MS_MOVE and MS_REMOUNT are passed, device name which should not be checked for MS_REMOUNT was checked because MS_BIND/MS_MOVE had higher priority than MS_REMOUNT. Fix these bugs by changing priority to MS_REMOUNT -> MS_BIND -> MS_SHARED/MS_PRIVATE/MS_SLAVE/MS_UNBINDABLE -> MS_MOVE as with do_mount() does. Also, unconditionally return -EINVAL if more than one of MS_SHARED/MS_PRIVATE/MS_SLAVE/MS_UNBINDABLE is passed so that TOMOYO will not generate inaccurate audit logs, for commit 7a2e8a8f "VFS: Sanity check mount flags passed to change_mnt_propagation()" clarified that these flags must be exclusively passed. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/mount.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index bee09d06205..fe00cdfd026 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -199,30 +199,32 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
199 if (flags & MS_REMOUNT) { 199 if (flags & MS_REMOUNT) {
200 type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]; 200 type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
201 flags &= ~MS_REMOUNT; 201 flags &= ~MS_REMOUNT;
202 } 202 } else if (flags & MS_BIND) {
203 if (flags & MS_MOVE) {
204 type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
205 flags &= ~MS_MOVE;
206 }
207 if (flags & MS_BIND) {
208 type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; 203 type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
209 flags &= ~MS_BIND; 204 flags &= ~MS_BIND;
210 } 205 } else if (flags & MS_SHARED) {
211 if (flags & MS_UNBINDABLE) { 206 if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
212 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; 207 return -EINVAL;
213 flags &= ~MS_UNBINDABLE; 208 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
214 } 209 flags &= ~MS_SHARED;
215 if (flags & MS_PRIVATE) { 210 } else if (flags & MS_PRIVATE) {
211 if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
212 return -EINVAL;
216 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; 213 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
217 flags &= ~MS_PRIVATE; 214 flags &= ~MS_PRIVATE;
218 } 215 } else if (flags & MS_SLAVE) {
219 if (flags & MS_SLAVE) { 216 if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
217 return -EINVAL;
220 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; 218 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
221 flags &= ~MS_SLAVE; 219 flags &= ~MS_SLAVE;
222 } 220 } else if (flags & MS_UNBINDABLE) {
223 if (flags & MS_SHARED) { 221 if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
224 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; 222 return -EINVAL;
225 flags &= ~MS_SHARED; 223 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
224 flags &= ~MS_UNBINDABLE;
225 } else if (flags & MS_MOVE) {
226 type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
227 flags &= ~MS_MOVE;
226 } 228 }
227 if (!type) 229 if (!type)
228 type = "<NULL>"; 230 type = "<NULL>";