diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-22 06:32:06 +0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-27 05:09:59 +0400 |
commit | c3c073f808b22dfae15ef8412b6f7b998644139a (patch) | |
tree | 3369bcbe414738d90e6ccfe257f6ce3e72f6a5ae /security/selinux/hooks.c | |
parent | ad47bd7252bf402fe7dba92f5240b5ed16832ae7 (diff) | |
download | linux-c3c073f808b22dfae15ef8412b6f7b998644139a.tar.xz |
new helper: iterate_fd()
iterates through the opened files in given descriptor table,
calling a supplied function; we stop once non-zero is returned.
Callback gets struct file *, descriptor number and const void *
argument passed to iterator. It is called with files->file_lock
held, so it is not allowed to block.
tty_io, netprio_cgroup and selinux flush_unauthorized_files()
converted to its use.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 57 |
1 files changed, 22 insertions, 35 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 00b50113642d..4dfbcea10eb7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2088,15 +2088,19 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) return (atsecure || cap_bprm_secureexec(bprm)); } +static int match_file(const void *p, struct file *file, unsigned fd) +{ + return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0; +} + /* Derived from fs/exec.c:flush_old_files. */ static inline void flush_unauthorized_files(const struct cred *cred, struct files_struct *files) { struct file *file, *devnull = NULL; struct tty_struct *tty; - struct fdtable *fdt; - long j = -1; int drop_tty = 0; + unsigned n; tty = get_current_tty(); if (tty) { @@ -2123,41 +2127,24 @@ static inline void flush_unauthorized_files(const struct cred *cred, no_tty(); /* Revalidate access to inherited open files. */ - spin_lock(&files->file_lock); - for (;;) { - unsigned long set, i; - j++; - i = j * BITS_PER_LONG; - fdt = files_fdtable(files); - if (i >= fdt->max_fds) - break; - set = fdt->open_fds[j]; - if (!set) - continue; - spin_unlock(&files->file_lock); - for ( ; set ; i++, set >>= 1) { - if (!(set & 1)) - continue; - file = fget(i); - if (!file) - continue; - if (file_has_perm(cred, file, file_to_av(file))) { - if (devnull) { - get_file(devnull); - } else { - devnull = dentry_open(&selinux_null, - O_RDWR, cred); - if (IS_ERR(devnull)) - devnull = NULL; - } - replace_fd(i, devnull, 0); - } - fput(file); - } - spin_lock(&files->file_lock); + n = iterate_fd(files, 0, match_file, cred); + if (!n) /* none found? */ + return; + devnull = dentry_open(&selinux_null, O_RDWR, cred); + if (!IS_ERR(devnull)) { + /* replace all the matching ones with this */ + do { + get_file(devnull); + replace_fd(n - 1, devnull, 0); + } while ((n = iterate_fd(files, n, match_file, cred)) != 0); + fput(devnull); + } else { + /* just close all the matching ones */ + do { + replace_fd(n - 1, NULL, 0); + } while ((n = iterate_fd(files, n, match_file, cred)) != 0); } - spin_unlock(&files->file_lock); } /* |