Revert "proc: Convert proc_mount to use mount_ns."
authorAlistair Strachan <astrachan@google.com>
Wed, 6 Jun 2018 20:46:44 +0000 (13:46 -0700)
committerAlistair Strachan <astrachan@google.com>
Tue, 27 Nov 2018 18:58:12 +0000 (10:58 -0800)
This reverts commit e94591d0d90c13166cb6eb54ce5f96ed13d81b55.

This cleanup broke the parsing of procfs mount parameters.

Bug: 79705088
Change-Id: I0f07180ef9a994c884abfa269ffb273ee0bcbc0d
Signed-off-by: Alistair Strachan <astrachan@google.com>
fs/proc/inode.c
fs/proc/internal.h
fs/proc/root.c

index 225f541f7078c937c6a4c25264069700025a0582..c5f154be0ab29e2041d851c306b24c5bde3a41a6 100644 (file)
@@ -472,17 +472,12 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
        return inode;
 }
 
-int proc_fill_super(struct super_block *s, void *data, int silent)
+int proc_fill_super(struct super_block *s)
 {
-       struct pid_namespace *ns = get_pid_ns(s->s_fs_info);
        struct inode *root_inode;
        int ret;
 
-       if (!proc_parse_options(data, ns))
-               return -EINVAL;
-
-       /* User space would break if executables or devices appear on proc */
-       s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
+       s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NODEV;
        s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
        s->s_blocksize = 1024;
        s->s_blocksize_bits = 10;
index 5e55186858c962ebde07bce79e5478b799d41c43..02e0d9e9b3fed2e338492515f034a20c76606ebe 100644 (file)
@@ -203,7 +203,7 @@ extern const struct inode_operations proc_pid_link_inode_operations;
 extern void proc_init_inodecache(void);
 void set_proc_pid_nlink(void);
 extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
-extern int proc_fill_super(struct super_block *, void *data, int flags);
+extern int proc_fill_super(struct super_block *);
 extern void proc_entry_rundown(struct proc_dir_entry *);
 
 /*
@@ -270,7 +270,6 @@ static inline void proc_tty_init(void) {}
  * root.c
  */
 extern struct proc_dir_entry proc_root;
-extern int proc_parse_options(char *options, struct pid_namespace *pid);
 
 extern void proc_self_init(void);
 extern int proc_remount(struct super_block *, int *, char *);
index eafe87e010eca52e516d75d360e0cc9b822d82a9..ef6840c64e95a0690a1abe1ba5a52614f4ab4deb 100644 (file)
 
 #include "internal.h"
 
+static int proc_test_super(struct super_block *sb, void *data)
+{
+       return sb->s_fs_info == data;
+}
+
+static int proc_set_super(struct super_block *sb, void *data)
+{
+       int err = set_anon_super(sb, NULL);
+       if (!err) {
+               struct pid_namespace *ns = (struct pid_namespace *)data;
+               sb->s_fs_info = get_pid_ns(ns);
+       }
+       return err;
+}
+
 enum {
        Opt_gid, Opt_hidepid, Opt_err,
 };
@@ -36,7 +51,7 @@ static const match_table_t tokens = {
        {Opt_err, NULL},
 };
 
-int proc_parse_options(char *options, struct pid_namespace *pid)
+static int proc_parse_options(char *options, struct pid_namespace *pid)
 {
        char *p;
        substring_t args[MAX_OPT_ARGS];
@@ -89,16 +104,45 @@ int proc_remount(struct super_block *sb, int *flags, char *data)
 static struct dentry *proc_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
+       int err;
+       struct super_block *sb;
        struct pid_namespace *ns;
+       char *options;
 
        if (flags & MS_KERNMOUNT) {
-               ns = data;
-               data = NULL;
+               ns = (struct pid_namespace *)data;
+               options = NULL;
        } else {
                ns = task_active_pid_ns(current);
+               options = data;
+
+               /* Does the mounter have privilege over the pid namespace? */
+               if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+                       return ERR_PTR(-EPERM);
+       }
+
+       sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
+       if (IS_ERR(sb))
+               return ERR_CAST(sb);
+
+       if (!proc_parse_options(options, ns)) {
+               deactivate_locked_super(sb);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!sb->s_root) {
+               err = proc_fill_super(sb);
+               if (err) {
+                       deactivate_locked_super(sb);
+                       return ERR_PTR(err);
+               }
+
+               sb->s_flags |= MS_ACTIVE;
+               /* User space would break if executables appear on proc */
+               sb->s_iflags |= SB_I_NOEXEC;
        }
 
-       return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super);
+       return dget(sb->s_root);
 }
 
 static void proc_kill_sb(struct super_block *sb)