[PATCH OpenHarmony-4.19] Revert "proc: Convert proc_mount to use mount_ns."

ohos inclusion category: bugfix issue: #I46HO0 CVE: NA ------------------------------------------ This reverts commit e94591d0d90c13166cb6eb54ce5f96ed13d81b55. Original patch was a minor cleanup, but the parsing of procfs mount parameters was broken by moving proc_parse_options() to proc_fill_super(). Kernel calls proc_fill_super as the first mount referrence in start_kernel -> alloc_pid -> pid_ns_prepare_proc -> mount_ns -> proc_fill_super with SB_KERNMOUNT. Then userspace mount procfs will just return root dentry by ignoring parsing options. Upstream 5.x fix the issue after refactoring vfs/procfs(introducing fs_context) and support multiple mount instances. fa10fed30f25 proc: allow to mount many instances of proc in one pid namespace 69879c01a0c3 proc: Remove the now unnecessary internal mount of proc 66f592e2ece0 proc: Add fs_context support to procfs 60a3c3a58e2e procfs: Move proc_fill_super() to fs/proc/root.c cb50b348c71f convenience helpers: vfs_get_super() and sget_fc() 3e1aeb00e6d1 vfs: Implement a filesystem superblock creation/configuration context ...... It is a little complicated and no need to do the backport. Just revert it to hornor the option of 'hidepid=2' for init. Signed-off-by: Yu Changchun <yuchangchun1@huawei.com> --- fs/proc/inode.c | 10 +++------ fs/proc/internal.h | 3 +-- fs/proc/root.c | 52 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 31bf3bb8ddae..fd6a01a9629a 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -491,17 +491,13 @@ 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; + /* User space would break if devices appear on proc */ + s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NODEV; s->s_flags |= SB_NODIRATIME | SB_NOSUID | SB_NOEXEC; s->s_blocksize = 1024; s->s_blocksize_bits = 10; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 95b14196f284..6e64cac02829 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -212,7 +212,7 @@ extern const struct inode_operations proc_pid_link_inode_operations; void proc_init_kmemcache(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 *); diff --git a/fs/proc/root.c b/fs/proc/root.c index f4b1a9d2eca6..c4e76846033e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -26,6 +26,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, }; @@ -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 & SB_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 |= SB_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) -- 2.22.0
participants (1)
-
Yu Changchun