Loading fs/proc/inode.c +2 −7 Original line number Diff line number Diff line Loading @@ -456,17 +456,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; Loading fs/proc/internal.h +1 −2 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ extern const struct file_operations proc_reclaim_operations; extern void proc_init_inodecache(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 *); /* Loading Loading @@ -278,7 +278,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 *); Loading fs/proc/root.c +48 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,21 @@ #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, }; Loading @@ -33,7 +48,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]; Loading Loading @@ -85,16 +100,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) Loading Loading
fs/proc/inode.c +2 −7 Original line number Diff line number Diff line Loading @@ -456,17 +456,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; Loading
fs/proc/internal.h +1 −2 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ extern const struct file_operations proc_reclaim_operations; extern void proc_init_inodecache(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 *); /* Loading Loading @@ -278,7 +278,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 *); Loading
fs/proc/root.c +48 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,21 @@ #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, }; Loading @@ -33,7 +48,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]; Loading Loading @@ -85,16 +100,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) Loading