diff options
| author | Josh Boyer <jwboyer@redhat.com> | 2012-01-18 13:22:40 -0500 |
|---|---|---|
| committer | Josh Boyer <jwboyer@redhat.com> | 2012-01-18 13:26:41 -0500 |
| commit | 42c018e91790cc78b38a6cdbd97a0e25f4dff975 (patch) | |
| tree | d011bd9708f32061bb391348732b03c8951e221c /procfs-parse-mount-options.patch | |
| parent | ac03f32d0673c08a2df2372c602c04035db66d19 (diff) | |
/proc/pid/* information leak (rhbz 782686)
Diffstat (limited to 'procfs-parse-mount-options.patch')
| -rw-r--r-- | procfs-parse-mount-options.patch | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch new file mode 100644 index 00000000..99684c4b --- /dev/null +++ b/procfs-parse-mount-options.patch @@ -0,0 +1,173 @@ +From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kulikov <segooon@gmail.com> +Date: Tue, 10 Jan 2012 15:11:27 -0800 +Subject: [PATCH] procfs: parse mount options + +Add support for procfs mount options. Actual mount options are coming in +the next patches. + +Signed-off-by: Vasiliy Kulikov <segoon@openwall.com> +Cc: Alexey Dobriyan <adobriyan@gmail.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Cc: Randy Dunlap <rdunlap@xenotime.net> +Cc: "H. Peter Anvin" <hpa@zytor.com> +Cc: Greg KH <greg@kroah.com> +Cc: Theodore Tso <tytso@MIT.EDU> +Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> +Cc: James Morris <jmorris@namei.org> +Cc: Oleg Nesterov <oleg@redhat.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + fs/proc/inode.c | 10 +++++++++ + fs/proc/internal.h | 1 + + fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 51a1766..27c762f 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -7,6 +7,7 @@ + #include <linux/time.h> + #include <linux/proc_fs.h> + #include <linux/kernel.h> ++#include <linux/pid_namespace.h> + #include <linux/mm.h> + #include <linux/string.h> + #include <linux/stat.h> +@@ -17,7 +18,9 @@ + #include <linux/init.h> + #include <linux/module.h> + #include <linux/sysctl.h> ++#include <linux/seq_file.h> + #include <linux/slab.h> ++#include <linux/mount.h> + + #include <asm/system.h> + #include <asm/uaccess.h> +@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void) + init_once); + } + ++static int proc_show_options(struct seq_file *seq, struct dentry *root) ++{ ++ return 0; ++} ++ + static const struct super_operations proc_sops = { + .alloc_inode = proc_alloc_inode, + .destroy_inode = proc_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = proc_evict_inode, + .statfs = simple_statfs, ++ .remount_fs = proc_remount, ++ .show_options = proc_show_options, + }; + + static void __pde_users_dec(struct proc_dir_entry *pde) +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 7838e5c..2925775 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); + + int proc_fill_super(struct super_block *); + struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); ++int proc_remount(struct super_block *sb, int *flags, char *data); + + /* + * These are generic /proc routines that use the internal +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 03102d9..6a8ac1d 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -18,6 +18,7 @@ + #include <linux/bitops.h> + #include <linux/mount.h> + #include <linux/pid_namespace.h> ++#include <linux/parser.h> + + #include "internal.h" + +@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data) + return err; + } + ++enum { ++ Opt_err, ++}; ++ ++static const match_table_t tokens = { ++ {Opt_err, NULL}, ++}; ++ ++static int proc_parse_options(char *options, struct pid_namespace *pid) ++{ ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ pr_debug("proc: options = %s\n", options); ++ ++ if (!options) ++ return 1; ++ ++ while ((p = strsep(&options, ",")) != NULL) { ++ int token; ++ if (!*p) ++ continue; ++ ++ args[0].to = args[0].from = 0; ++ token = match_token(p, tokens, args); ++ switch (token) { ++ default: ++ pr_err("proc: unrecognized mount option \"%s\" " ++ "or missing value\n", p); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++int proc_remount(struct super_block *sb, int *flags, char *data) ++{ ++ struct pid_namespace *pid = sb->s_fs_info; ++ return !proc_parse_options(data, pid); ++} ++ + static struct dentry *proc_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -43,11 +86,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + struct super_block *sb; + struct pid_namespace *ns; + struct proc_inode *ei; ++ char *options; + +- if (flags & MS_KERNMOUNT) ++ if (flags & MS_KERNMOUNT) { + ns = (struct pid_namespace *)data; +- else ++ options = NULL; ++ } else { + ns = current->nsproxy->pid_ns; ++ options = data; ++ } + + sb = sget(fs_type, proc_test_super, proc_set_super, ns); + if (IS_ERR(sb)) +@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + + if (!sb->s_root) { + sb->s_flags = flags; ++ if (!proc_parse_options(options, ns)) { ++ deactivate_locked_super(sb); ++ return ERR_PTR(-EINVAL); ++ } + err = proc_fill_super(sb); + if (err) { + deactivate_locked_super(sb); +-- +1.7.7.5 + |
