|
@@ -18,6 +18,7 @@
|
|
#include <linux/bitops.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/pid_namespace.h>
|
|
#include <linux/pid_namespace.h>
|
|
|
|
+#include <linux/parser.h>
|
|
|
|
|
|
#include "internal.h"
|
|
#include "internal.h"
|
|
|
|
|
|
@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data)
|
|
return err;
|
|
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,
|
|
static struct dentry *proc_mount(struct file_system_type *fs_type,
|
|
int flags, const char *dev_name, void *data)
|
|
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 super_block *sb;
|
|
struct pid_namespace *ns;
|
|
struct pid_namespace *ns;
|
|
struct proc_inode *ei;
|
|
struct proc_inode *ei;
|
|
|
|
+ char *options;
|
|
|
|
|
|
- if (flags & MS_KERNMOUNT)
|
|
|
|
|
|
+ if (flags & MS_KERNMOUNT) {
|
|
ns = (struct pid_namespace *)data;
|
|
ns = (struct pid_namespace *)data;
|
|
- else
|
|
|
|
|
|
+ options = NULL;
|
|
|
|
+ } else {
|
|
ns = current->nsproxy->pid_ns;
|
|
ns = current->nsproxy->pid_ns;
|
|
|
|
+ options = data;
|
|
|
|
+ }
|
|
|
|
|
|
sb = sget(fs_type, proc_test_super, proc_set_super, ns);
|
|
sb = sget(fs_type, proc_test_super, proc_set_super, ns);
|
|
if (IS_ERR(sb))
|
|
if (IS_ERR(sb))
|
|
@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
|
|
|
|
|
|
if (!sb->s_root) {
|
|
if (!sb->s_root) {
|
|
sb->s_flags = flags;
|
|
sb->s_flags = flags;
|
|
|
|
+ if (!proc_parse_options(options, ns)) {
|
|
|
|
+ deactivate_locked_super(sb);
|
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
|
+ }
|
|
err = proc_fill_super(sb);
|
|
err = proc_fill_super(sb);
|
|
if (err) {
|
|
if (err) {
|
|
deactivate_locked_super(sb);
|
|
deactivate_locked_super(sb);
|