TOMOYO: Fix mount flags checking order.
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Wed, 11 Apr 2012 01:54:43 +0000 (20:54 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Apr 2012 15:14:08 +0000 (08:14 -0700)
commit df91e49477a9be15921cb2854e1d12a3bdb5e425 upstream.

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>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
security/tomoyo/mount.c

index 9fc2e15841c96f54edbefb24a96c40405d06bedd..892494ac58e2250c7a7af100cb4113d30d82d3dc 100644 (file)
@@ -205,30 +205,32 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
        if (flags & MS_REMOUNT) {
                type = TOMOYO_MOUNT_REMOUNT_KEYWORD;
                flags &= ~MS_REMOUNT;
-       }
-       if (flags & MS_MOVE) {
-               type = TOMOYO_MOUNT_MOVE_KEYWORD;
-               flags &= ~MS_MOVE;
-       }
-       if (flags & MS_BIND) {
+       } else if (flags & MS_BIND) {
                type = TOMOYO_MOUNT_BIND_KEYWORD;
                flags &= ~MS_BIND;
-       }
-       if (flags & MS_UNBINDABLE) {
-               type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
-               flags &= ~MS_UNBINDABLE;
-       }
-       if (flags & MS_PRIVATE) {
+       } else if (flags & MS_SHARED) {
+               if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+                       return -EINVAL;
+               type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
+               flags &= ~MS_SHARED;
+       } else if (flags & MS_PRIVATE) {
+               if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
+                       return -EINVAL;
                type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD;
                flags &= ~MS_PRIVATE;
-       }
-       if (flags & MS_SLAVE) {
+       } else if (flags & MS_SLAVE) {
+               if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
+                       return -EINVAL;
                type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD;
                flags &= ~MS_SLAVE;
-       }
-       if (flags & MS_SHARED) {
-               type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
-               flags &= ~MS_SHARED;
+       } else if (flags & MS_UNBINDABLE) {
+               if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
+                       return -EINVAL;
+               type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
+               flags &= ~MS_UNBINDABLE;
+       } else if (flags & MS_MOVE) {
+               type = TOMOYO_MOUNT_MOVE_KEYWORD;
+               flags &= ~MS_MOVE;
        }
        if (!type)
                type = "<NULL>";