diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2012-02-29 21:53:22 +0900 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-03-01 10:23:19 +1100 |
commit | df91e49477a9be15921cb2854e1d12a3bdb5e425 (patch) | |
tree | 8408a7d2a432a206070ac01b2939fefcdce9ca13 | |
parent | a69f15890292b5449f9056b4bb322b044e6ce0c6 (diff) |
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>
-rw-r--r-- | security/tomoyo/mount.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index bee09d062057..fe00cdfd0267 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, if (flags & MS_REMOUNT) { type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]; flags &= ~MS_REMOUNT; - } - if (flags & MS_MOVE) { - type = tomoyo_mounts[TOMOYO_MOUNT_MOVE]; - flags &= ~MS_MOVE; - } - if (flags & MS_BIND) { + } else if (flags & MS_BIND) { type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; flags &= ~MS_BIND; - } - if (flags & MS_UNBINDABLE) { - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; - flags &= ~MS_UNBINDABLE; - } - if (flags & MS_PRIVATE) { + } else if (flags & MS_SHARED) { + if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) + return -EINVAL; + type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; + flags &= ~MS_SHARED; + } else if (flags & MS_PRIVATE) { + if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE)) + return -EINVAL; type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; flags &= ~MS_PRIVATE; - } - if (flags & MS_SLAVE) { + } else if (flags & MS_SLAVE) { + if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE)) + return -EINVAL; type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; flags &= ~MS_SLAVE; - } - if (flags & MS_SHARED) { - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; - flags &= ~MS_SHARED; + } else if (flags & MS_UNBINDABLE) { + if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) + return -EINVAL; + type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; + flags &= ~MS_UNBINDABLE; + } else if (flags & MS_MOVE) { + type = tomoyo_mounts[TOMOYO_MOUNT_MOVE]; + flags &= ~MS_MOVE; } if (!type) type = "<NULL>"; |