aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlistair Strachan <astrachan@google.com>2018-11-27 10:53:02 -0800
committerAmit Pundir <amit.pundir@linaro.org>2019-02-15 12:34:40 +0530
commit7edf3e102504cd7b5ec91d6eab6f797ee8eddabf (patch)
tree89f351e6b68a357aa030af3bbc4e3bb0ab4f5cff
parent31eb28c81eba1542d906a47ef0a08a79a878b4ac (diff)
downloadkernel_replicant_linux-7edf3e102504cd7b5ec91d6eab6f797ee8eddabf.tar.gz
kernel_replicant_linux-7edf3e102504cd7b5ec91d6eab6f797ee8eddabf.tar.bz2
kernel_replicant_linux-7edf3e102504cd7b5ec91d6eab6f797ee8eddabf.zip
Revert "proc: Convert proc_mount to use mount_ns."
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> [AmitP: TODO] Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
-rw-r--r--fs/proc/inode.c8
-rw-r--r--fs/proc/internal.h3
-rw-r--r--fs/proc/root.c54
3 files changed, 53 insertions, 12 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index da649ccd6804..81412ec2328a 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -489,17 +489,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;
+ 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..146f6f51ed87 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -24,8 +24,25 @@
#include <linux/parser.h>
#include <linux/cred.h>
+#include <uapi/linux/mount.h>
+
#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 +53,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 +106,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 |= 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)