diff options
Diffstat (limited to 'fs/coredump.c')
-rw-r--r-- | fs/coredump.c | 30 |
1 files changed, 26 insertions, 4 deletions
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 | ||