summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/mconsole_kern.c2
-rw-r--r--fs/coredump.c30
-rw-r--r--fs/fhandle.c2
-rw-r--r--fs/open.c6
-rw-r--r--include/linux/fs.h2
-rw-r--r--kernel/sysctl_binary.c2
6 files changed, 32 insertions, 12 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index b821b13d343a..8a6b57108ac2 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -133,7 +133,7 @@ void mconsole_proc(struct mc_request *req)
133 ptr += strlen("proc"); 133 ptr += strlen("proc");
134 ptr = skip_spaces(ptr); 134 ptr = skip_spaces(ptr);
135 135
136 file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); 136 file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0);
137 if (IS_ERR(file)) { 137 if (IS_ERR(file)) {
138 mconsole_reply(req, "Failed to open file", 1, 0); 138 mconsole_reply(req, "Failed to open file", 1, 0);
139 printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); 139 printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
diff --git a/fs/coredump.c b/fs/coredump.c
index 9ea87e9fdccf..47c32c3bfa1d 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -32,6 +32,9 @@
32#include <linux/pipe_fs_i.h> 32#include <linux/pipe_fs_i.h>
33#include <linux/oom.h> 33#include <linux/oom.h>
34#include <linux/compat.h> 34#include <linux/compat.h>
35#include <linux/sched.h>
36#include <linux/fs.h>
37#include <linux/path.h>
35#include <linux/timekeeping.h> 38#include <linux/timekeeping.h>
36 39
37#include <asm/uaccess.h> 40#include <asm/uaccess.h>
@@ -649,6 +652,8 @@ void do_coredump(const siginfo_t *siginfo)
649 } 652 }
650 } else { 653 } else {
651 struct inode *inode; 654 struct inode *inode;
655 int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW |
656 O_LARGEFILE | O_EXCL;
652 657
653 if (cprm.limit < binfmt->min_coredump) 658 if (cprm.limit < binfmt->min_coredump)
654 goto fail_unlock; 659 goto fail_unlock;
@@ -687,10 +692,27 @@ void do_coredump(const siginfo_t *siginfo)
687 * what matters is that at least one of the two processes 692 * what matters is that at least one of the two processes
688 * writes its coredump successfully, not which one. 693 * writes its coredump successfully, not which one.
689 */ 694 */
690 cprm.file = filp_open(cn.corename, 695 if (need_suid_safe) {
691 O_CREAT | 2 | O_NOFOLLOW | 696 /*
692 O_LARGEFILE | O_EXCL, 697 * Using user namespaces, normal user tasks can change
693 0600); 698 * their current->fs->root to point to arbitrary
699 * directories. Since the intention of the "only dump
700 * with a fully qualified path" rule is to control where
701 * coredumps may be placed using root privileges,
702 * current->fs->root must not be used. Instead, use the
703 * root directory of init_task.
704 */
705 struct path root;
706
707 task_lock(&init_task);
708 get_fs_root(init_task.fs, &root);
709 task_unlock(&init_task);
710 cprm.file = file_open_root(root.dentry, root.mnt,
711 cn.corename, open_flags, 0600);
712 path_put(&root);
713 } else {
714 cprm.file = filp_open(cn.corename, open_flags, 0600);
715 }
694 if (IS_ERR(cprm.file)) 716 if (IS_ERR(cprm.file))
695 goto fail_unlock; 717 goto fail_unlock;
696 718
diff --git a/fs/fhandle.c b/fs/fhandle.c
index d59712dfa3e7..ca3c3dd01789 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -228,7 +228,7 @@ long do_handle_open(int mountdirfd,
228 path_put(&path); 228 path_put(&path);
229 return fd; 229 return fd;
230 } 230 }
231 file = file_open_root(path.dentry, path.mnt, "", open_flag); 231 file = file_open_root(path.dentry, path.mnt, "", open_flag, 0);
232 if (IS_ERR(file)) { 232 if (IS_ERR(file)) {
233 put_unused_fd(fd); 233 put_unused_fd(fd);
234 retval = PTR_ERR(file); 234 retval = PTR_ERR(file);
diff --git a/fs/open.c b/fs/open.c
index 55bdc75e2172..17cb6b1dab75 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -992,14 +992,12 @@ struct file *filp_open(const char *filename, int flags, umode_t mode)
992EXPORT_SYMBOL(filp_open); 992EXPORT_SYMBOL(filp_open);
993 993
994struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, 994struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
995 const char *filename, int flags) 995 const char *filename, int flags, umode_t mode)
996{ 996{
997 struct open_flags op; 997 struct open_flags op;
998 int err = build_open_flags(flags, 0, &op); 998 int err = build_open_flags(flags, mode, &op);
999 if (err) 999 if (err)
1000 return ERR_PTR(err); 1000 return ERR_PTR(err);
1001 if (flags & O_CREAT)
1002 return ERR_PTR(-EINVAL);
1003 return do_file_open_root(dentry, mnt, filename, &op); 1001 return do_file_open_root(dentry, mnt, filename, &op);
1004} 1002}
1005EXPORT_SYMBOL(file_open_root); 1003EXPORT_SYMBOL(file_open_root);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 35d99266ca9a..14a97194b34b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2263,7 +2263,7 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags,
2263extern struct file *file_open_name(struct filename *, int, umode_t); 2263extern struct file *file_open_name(struct filename *, int, umode_t);
2264extern struct file *filp_open(const char *, int, umode_t); 2264extern struct file *filp_open(const char *, int, umode_t);
2265extern struct file *file_open_root(struct dentry *, struct vfsmount *, 2265extern struct file *file_open_root(struct dentry *, struct vfsmount *,
2266 const char *, int); 2266 const char *, int, umode_t);
2267extern struct file * dentry_open(const struct path *, int, const struct cred *); 2267extern struct file * dentry_open(const struct path *, int, const struct cred *);
2268extern int filp_close(struct file *, fl_owner_t id); 2268extern int filp_close(struct file *, fl_owner_t id);
2269 2269
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 7e7746a42a62..10a1d7dc9313 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1321,7 +1321,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
1321 } 1321 }
1322 1322
1323 mnt = task_active_pid_ns(current)->proc_mnt; 1323 mnt = task_active_pid_ns(current)->proc_mnt;
1324 file = file_open_root(mnt->mnt_root, mnt, pathname, flags); 1324 file = file_open_root(mnt->mnt_root, mnt, pathname, flags, 0);
1325 result = PTR_ERR(file); 1325 result = PTR_ERR(file);
1326 if (IS_ERR(file)) 1326 if (IS_ERR(file))
1327 goto out_putname; 1327 goto out_putname;