ARM: dts: dra7xx: Correct mcasp8_ahclkx_mux name
[deliverable/linux.git] / fs / coredump.c
index b3c153ca435d24fdbdfcb909228b6b4787bb63f2..47c32c3bfa1d90c10ce6ade45fc7829a39345fcc 100644 (file)
@@ -32,6 +32,9 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
 #include <linux/compat.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/path.h>
 #include <linux/timekeeping.h>
 
 #include <asm/uaccess.h>
@@ -118,6 +121,26 @@ int cn_esc_printf(struct core_name *cn, const char *fmt, ...)
        ret = cn_vprintf(cn, fmt, arg);
        va_end(arg);
 
+       if (ret == 0) {
+               /*
+                * Ensure that this coredump name component can't cause the
+                * resulting corefile path to consist of a ".." or ".".
+                */
+               if ((cn->used - cur == 1 && cn->corename[cur] == '.') ||
+                               (cn->used - cur == 2 && cn->corename[cur] == '.'
+                               && cn->corename[cur+1] == '.'))
+                       cn->corename[cur] = '!';
+
+               /*
+                * Empty names are fishy and could be used to create a "//" in a
+                * corefile name, causing the coredump to happen one directory
+                * level too high. Enforce that all components of the core
+                * pattern are at least one character long.
+                */
+               if (cn->used == cur)
+                       ret = cn_printf(cn, "!");
+       }
+
        for (; cur < cn->used; ++cur) {
                if (cn->corename[cur] == '/')
                        cn->corename[cur] = '!';
@@ -629,6 +652,8 @@ void do_coredump(const siginfo_t *siginfo)
                }
        } else {
                struct inode *inode;
+               int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW |
+                                O_LARGEFILE | O_EXCL;
 
                if (cprm.limit < binfmt->min_coredump)
                        goto fail_unlock;
@@ -667,10 +692,27 @@ void do_coredump(const siginfo_t *siginfo)
                 * what matters is that at least one of the two processes
                 * writes its coredump successfully, not which one.
                 */
-               cprm.file = filp_open(cn.corename,
-                                O_CREAT | 2 | O_NOFOLLOW |
-                                O_LARGEFILE | O_EXCL,
-                                0600);
+               if (need_suid_safe) {
+                       /*
+                        * Using user namespaces, normal user tasks can change
+                        * their current->fs->root to point to arbitrary
+                        * directories. Since the intention of the "only dump
+                        * with a fully qualified path" rule is to control where
+                        * coredumps may be placed using root privileges,
+                        * current->fs->root must not be used. Instead, use the
+                        * root directory of init_task.
+                        */
+                       struct path root;
+
+                       task_lock(&init_task);
+                       get_fs_root(init_task.fs, &root);
+                       task_unlock(&init_task);
+                       cprm.file = file_open_root(root.dentry, root.mnt,
+                               cn.corename, open_flags, 0600);
+                       path_put(&root);
+               } else {
+                       cprm.file = filp_open(cn.corename, open_flags, 0600);
+               }
                if (IS_ERR(cprm.file))
                        goto fail_unlock;
 
This page took 0.032988 seconds and 5 git commands to generate.