This is a preparation patch to allow to set and get hidepid and gid mount options correctly Signed-off-by: Djalal Harouni <tixxdz@xxxxxxxxx> --- fs/proc/base.c | 15 +++++++++------ fs/proc/generic.c | 37 +++++++++++++++++++++++++++++++++++++ fs/proc/inode.c | 5 +++-- fs/proc/internal.h | 2 +- fs/proc/root.c | 13 ++++++++----- include/linux/proc_fs.h | 35 ++++++++++++++++++++++++++++++++--- 6 files changed, 90 insertions(+), 17 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index cd16979..fd16566 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -681,13 +681,16 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) * May current process learn task's sched/cmdline info (for hide_pid_min=1) * or euid/egid (for hide_pid_min=2)? */ -static bool has_pid_permissions(struct pid_namespace *pid, +static bool has_pid_permissions(struct proc_fs_info *fs_info, struct task_struct *task, int hide_pid_min) { - if (pid->hide_pid < hide_pid_min) + int hide_pid = proc_fs_get_hide_pid(fs_info); + kgid_t gid = proc_fs_get_pid_gid(fs_info); + + if (hide_pid < hide_pid_min) return true; - if (in_group_p(pid->pid_gid)) + if (in_group_p(gid)) return true; return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); } @@ -703,7 +706,7 @@ static int proc_pid_permission(struct inode *inode, int mask) task = get_proc_task(inode); if (!task) return -ESRCH; - has_perms = has_pid_permissions(pid, task, HIDEPID_NO_ACCESS); + has_perms = has_pid_permissions(fs_info, task, HIDEPID_NO_ACCESS); put_task_struct(task); if (!has_perms) { @@ -1745,7 +1748,7 @@ int pid_getattr(const struct path *path, struct kstat *stat, stat->gid = GLOBAL_ROOT_GID; task = pid_task(proc_pid(inode), PIDTYPE_PID); if (task) { - if (!has_pid_permissions(pid, task, HIDEPID_INVISIBLE)) { + if (!has_pid_permissions(fs_info, task, HIDEPID_INVISIBLE)) { rcu_read_unlock(); /* * This doesn't prevent learning whether PID exists, @@ -3179,7 +3182,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx) int len; cond_resched(); - if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE)) + if (!has_pid_permissions(fs_info, iter.task, HIDEPID_INVISIBLE)) continue; len = snprintf(name, sizeof(name), "%d", iter.tgid); diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 49c8cb9..7e5e419 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/printk.h> +#include <linux/pid_namespace.h> #include <linux/mount.h> #include <linux/init.h> #include <linux/idr.h> @@ -33,6 +34,42 @@ struct proc_fs_info *proc_sb(struct super_block *sb) return sb->s_fs_info; } +void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_pid) +{ + /* For backward compatibility */ + if (fs_info->version == PROC_FS_V1) + fs_info->pid_ns->hide_pid = hide_pid; + else if (fs_info->version == PROC_FS_V2) + fs_info->hide_pid = hide_pid; +} + +void proc_fs_set_pid_gid(struct proc_fs_info *fs_info, kgid_t gid) +{ + /* For backward compatibility */ + if (fs_info->version == PROC_FS_V1) + fs_info->pid_ns->pid_gid = gid; + else if (fs_info->version == PROC_FS_V2) + fs_info->pid_gid = gid; +} + +int proc_fs_get_hide_pid(struct proc_fs_info *fs_info) +{ + /* For backward compatibility */ + if (fs_info->version == PROC_FS_V1) + return fs_info->pid_ns->hide_pid; + + return fs_info->hide_pid; +} + +kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info) +{ + /* For backward compatibility */ + if (fs_info->version == PROC_FS_V1) + return fs_info->pid_ns->pid_gid; + + return fs_info->pid_gid; +} + static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) { if (len < de->namelen) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index e708288..ca47a0a 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -475,11 +475,12 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) int proc_fill_super(struct super_block *s, void *data, int silent) { struct proc_fs_info *fs_info = proc_sb(s); - struct pid_namespace *ns = get_pid_ns(fs_info->pid_ns); struct inode *root_inode; int ret; - if (!proc_parse_options(data, ns)) + get_pid_ns(fs_info->pid_ns); + + if (!proc_parse_options(data, fs_info)) return -EINVAL; /* User space would break if executables or devices appear on proc */ diff --git a/fs/proc/internal.h b/fs/proc/internal.h index c5ae09b..126fa31 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -261,7 +261,7 @@ 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 int proc_parse_options(char *options, struct proc_fs_info *fs_info); 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 a683e93..6a96c02 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -36,11 +36,12 @@ static const match_table_t tokens = { {Opt_err, NULL}, }; -int proc_parse_options(char *options, struct pid_namespace *pid) +int proc_parse_options(char *options, struct proc_fs_info *fs_info) { char *p; substring_t args[MAX_OPT_ARGS]; int option; + kgid_t gid; if (!options) return 1; @@ -56,7 +57,8 @@ int proc_parse_options(char *options, struct pid_namespace *pid) case Opt_gid: if (match_int(&args[0], &option)) return 0; - pid->pid_gid = make_kgid(current_user_ns(), option); + gid = make_kgid(current_user_ns(), option); + proc_fs_set_pid_gid(fs_info, gid); break; case Opt_hidepid: if (match_int(&args[0], &option)) @@ -66,7 +68,7 @@ int proc_parse_options(char *options, struct pid_namespace *pid) pr_err("proc: hidepid value must be between 0 and 2.\n"); return 0; } - pid->hide_pid = option; + proc_fs_set_hide_pid(fs_info, option); break; default: pr_err("proc: unrecognized mount option \"%s\" " @@ -81,10 +83,9 @@ int proc_parse_options(char *options, struct pid_namespace *pid) int proc_remount(struct super_block *sb, int *flags, char *data) { struct proc_fs_info *fs_info = proc_sb(sb); - struct pid_namespace *pid = fs_info->pid_ns; sync_filesystem(sb); - return !proc_parse_options(data, pid); + return !proc_parse_options(data, fs_info); } static int proc_test_super(struct super_block *s, void *data) @@ -130,6 +131,8 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, fs_info->pid_ns = ns; fs_info->version = PROC_FS_V1; + fs_info->hide_pid = HIDEPID_OFF; + fs_info->pid_gid = GLOBAL_ROOT_GID; refcount_set(&fs_info->users, 1); sb = sget_userns(fs_type, proc_test_super, proc_set_super, flags, diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index e1cb9c3..c23299d 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -9,8 +9,8 @@ #include <linux/refcount.h> enum { - PROC_FS_V1 = 1, - PROC_FS_V2 = 2, + PROC_FS_V1 = 1, /* Inside same pidns procfs mounts are shared */ + PROC_FS_V2 = 2, /* New procfs mounts are separated by default */ }; struct proc_fs_info { @@ -27,6 +27,13 @@ struct proc_dir_entry; extern struct proc_fs_info *proc_sb(struct super_block *sb); +extern void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_pid); + +extern void proc_fs_set_pid_gid(struct proc_fs_info *fs_info, kgid_t gid); + +extern int proc_fs_get_hide_pid(struct proc_fs_info *fs_info); +extern kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info); + extern void proc_root_init(void); extern void proc_flush_task(struct task_struct *); @@ -38,7 +45,7 @@ extern struct proc_dir_entry *proc_mkdir_data(const char *, umode_t, extern struct proc_dir_entry *proc_mkdir_mode(const char *, umode_t, struct proc_dir_entry *); struct proc_dir_entry *proc_create_mount_point(const char *name); - + extern struct proc_dir_entry *proc_create_data(const char *, umode_t, struct proc_dir_entry *, const struct file_operations *, @@ -69,6 +76,28 @@ static inline void proc_flush_task(struct task_struct *task) { } +static inline void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_pid) +{ +} + +static inline void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_pid) +{ +} + +static inline void proc_fs_set_pid_gid(struct proc_info_fs *fs_info, kgid_t gid) +{ +} + +static inline int proc_fs_get_hide_pid(struct proc_fs_info *fs_info) +{ + return 0; +} + +extern kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info) +{ + return GLOBAL_ROOT_GID; +} + extern inline struct proc_fs_info *proc_sb(struct super_block *sb) { return NULL;} static inline struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent,const char *dest) { return NULL;} -- 2.10.2 -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html