summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2012-04-10 20:54:43 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-13 08:14:08 -0700
commitd5748309bb8d75852c92966477277d4572d8920a (patch)
tree348be52d97e998fde2273175d23ffce693d1f187 /security
parent1a92416a1d37fd96427bd8d8a5fb52b54429c26f (diff)
TOMOYO: Fix mount flags checking order.
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>
Diffstat (limited to 'security')
-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 9fc2e15841c9..892494ac58e2 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -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>";