|
32 | 32 | #include <linux/pipe_fs_i.h> |
33 | 33 | #include <linux/oom.h> |
34 | 34 | #include <linux/compat.h> |
| 35 | +#include <linux/sched.h> |
| 36 | +#include <linux/fs.h> |
| 37 | +#include <linux/path.h> |
35 | 38 | #include <linux/timekeeping.h> |
36 | 39 |
|
37 | 40 | #include <asm/uaccess.h> |
@@ -649,6 +652,8 @@ void do_coredump(const siginfo_t *siginfo) |
649 | 652 | } |
650 | 653 | } else { |
651 | 654 | struct inode *inode; |
| 655 | + int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW | |
| 656 | + O_LARGEFILE | O_EXCL; |
652 | 657 |
|
653 | 658 | if (cprm.limit < binfmt->min_coredump) |
654 | 659 | goto fail_unlock; |
@@ -687,10 +692,27 @@ void do_coredump(const siginfo_t *siginfo) |
687 | 692 | * what matters is that at least one of the two processes |
688 | 693 | * writes its coredump successfully, not which one. |
689 | 694 | */ |
690 | | - cprm.file = filp_open(cn.corename, |
691 | | - O_CREAT | 2 | O_NOFOLLOW | |
692 | | - O_LARGEFILE | O_EXCL, |
693 | | - 0600); |
| 695 | + if (need_suid_safe) { |
| 696 | + /* |
| 697 | + * Using user namespaces, normal user tasks can change |
| 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 | 716 | if (IS_ERR(cprm.file)) |
695 | 717 | goto fail_unlock; |
696 | 718 |
|
|
0 commit comments