summaryrefslogtreecommitdiff
path: root/fs/open.c
diff options
context:
space:
mode:
authorJann Horn <jann@thejh.net>2016-03-23 00:25:36 +0300
committerBen Hutchings <ben@decadent.org.uk>2016-05-01 01:05:20 +0300
commitb1bf6857ac304ee1c05cb3d804f70312e947887c (patch)
tree10dd2aeba52f5a2dde64ffe2f9981dd5d1e1801a /fs/open.c
parentdf79c015fd0655b0ff4f429c89654b47367285b4 (diff)
downloadlinux-b1bf6857ac304ee1c05cb3d804f70312e947887c.tar.xz
fs/coredump: prevent fsuid=0 dumps into user-controlled directories
commit 378c6520e7d29280f400ef2ceaf155c86f05a71a upstream. This commit fixes the following security hole affecting systems where all of the following conditions are fulfilled: - The fs.suid_dumpable sysctl is set to 2. - The kernel.core_pattern sysctl's value starts with "/". (Systems where kernel.core_pattern starts with "|/" are not affected.) - Unprivileged user namespace creation is permitted. (This is true on Linux >=3.8, but some distributions disallow it by default using a distro patch.) Under these conditions, if a program executes under secure exec rules, causing it to run with the SUID_DUMP_ROOT flag, then unshares its user namespace, changes its root directory and crashes, the coredump will be written using fsuid=0 and a path derived from kernel.core_pattern - but this path is interpreted relative to the root directory of the process, allowing the attacker to control where a coredump will be written with root privileges. To fix the security issue, always interpret core_pattern for dumps that are written under SUID_DUMP_ROOT relative to the root directory of init. Signed-off-by: Jann Horn <jann@thejh.net> Acked-by: Kees Cook <keescook@chromium.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> [bwh: Backported to 3.2: adjust filename, context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/fs/open.c b/fs/open.c
index b8485d3cef97..ca155d4f23d3 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -958,12 +958,10 @@ struct file *filp_open(const char *filename, int flags, int mode)
EXPORT_SYMBOL(filp_open);
struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
- const char *filename, int flags)
+ const char *filename, int flags, umode_t mode)
{
struct open_flags op;
- int lookup = build_open_flags(flags, 0, &op);
- if (flags & O_CREAT)
- return ERR_PTR(-EINVAL);
+ int lookup = build_open_flags(flags, mode, &op);
if (!filename && (flags & O_DIRECTORY))
if (!dentry->d_inode->i_op->lookup)
return ERR_PTR(-ENOTDIR);