[Devel] [PATCH RH7 22/22] draft/ext4: add option to set userns of superblock
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Mar 10 08:32:15 PST 2016
* these one is TEMPORARY and for testing only, as changing
userns of sb is not safe!
We need it as NOW ploop device for VZCT can be mounted long
before the container userns is created so we can't be satisfied
with just setting userns on sb creation, we need to change it later.
Show userns inum of superblock as fd has no real use in
/proc/pid/mountinfo
Howto use:
Allow s_user_ns_ino mount option for /vz/root/101 disk:
echo "0 $major:$minor;1 s_user_ns_fd" >
/sys/fs/cgroup/ve/101/ve.mount_opts
Remount disk with new option(e.g. open ns at fd 101):
mount -t ext4 -oremount,s_user_ns_fd=101 /dev/ploop21845p1 /vz/root/101
101>/proc/10392/ns/user
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
fs/ext4/super.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------
fs/proc/namespaces.c | 2 ++
2 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 78fcdbc..4a5fed4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -40,6 +40,9 @@
#include <linux/crc16.h>
#include <linux/cleancache.h>
#include <linux/ve.h>
+#include <linux/user_namespace.h>
+#include <linux/proc_ns.h>
+#include <linux/file.h>
#include <asm/uaccess.h>
#include <linux/kthread.h>
@@ -1177,7 +1180,8 @@ enum {
Opt_inode_readahead_blks, Opt_journal_ioprio,
Opt_dioread_nolock, Opt_dioread_lock,
Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
- Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_balloon_ino,
+ Opt_max_dir_size_kb, Opt_nojournal_checksum,
+ Opt_s_user_ns_fd, Opt_balloon_ino,
Opt_pfcache_csum, Opt_nopfcache_csum,
Opt_pfcache, Opt_nopfcache,
};
@@ -1258,6 +1262,7 @@ static const match_table_t tokens = {
{Opt_init_itable, "init_itable"},
{Opt_noinit_itable, "noinit_itable"},
{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ {Opt_s_user_ns_fd, "s_user_ns_fd=%u"},
{Opt_balloon_ino, "balloon_ino=%u"},
{Opt_pfcache_csum, "pfcache_csum"},
{Opt_nopfcache_csum, "nopfcache_csum"},
@@ -1464,6 +1469,7 @@ static const struct mount_opts {
{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
{Opt_max_dir_size_kb, 0, MOPT_GTE0},
+ {Opt_s_user_ns_fd, 0, 0},
{Opt_balloon_ino, 0, 0},
{Opt_pfcache_csum, 0, 0},
{Opt_nopfcache_csum, 0, 0},
@@ -1472,7 +1478,7 @@ static const struct mount_opts {
static int handle_mount_opt(struct super_block *sb, char *opt, int token,
substring_t *args, unsigned long *journal_devnum,
- unsigned int *journal_ioprio,
+ unsigned int *journal_ioprio, unsigned long *s_user_ns_fd,
unsigned long *balloon_ino, int is_remount)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -1664,6 +1670,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
} else if (token == Opt_balloon_ino) {
*balloon_ino = arg;
+ } else if (token == Opt_s_user_ns_fd) {
+ *s_user_ns_fd = arg;
} else if (token == Opt_pfcache_csum) {
if (capable(CAP_SYS_ADMIN))
set_opt2(sb, PFCACHE_CSUM);
@@ -1722,6 +1730,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
static int parse_options(char *options, struct super_block *sb,
unsigned long *journal_devnum,
unsigned int *journal_ioprio,
+ unsigned long *s_user_ns_fd,
unsigned long *balloon_ino,
int is_remount)
{
@@ -1743,7 +1752,7 @@ static int parse_options(char *options, struct super_block *sb,
args[0].to = args[0].from = NULL;
token = match_token(p, tokens, args);
if (handle_mount_opt(sb, p, token, args, journal_devnum,
- journal_ioprio, balloon_ino,
+ journal_ioprio, s_user_ns_fd, balloon_ino,
is_remount) < 0)
return 0;
}
@@ -1914,6 +1923,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
if (sbi->s_balloon_ino)
SEQ_OPTS_PRINT("balloon_ino=%ld", sbi->s_balloon_ino->i_ino);
+ if (sb->s_user_ns)
+ SEQ_OPTS_PRINT("s_user_ns_ino=%u", sb->s_user_ns->proc_inum);
if (ve_is_super(get_exec_env())) {
if (test_opt2(sb, PFCACHE_CSUM))
@@ -2861,6 +2872,44 @@ static struct kobj_type ext4_ktype = {
.release = ext4_sb_release,
};
+static void ext4_load_s_user_ns(struct super_block *sb, unsigned long fd)
+{
+ const struct proc_ns_operations *ops;
+ struct proc_ns *ei;
+ struct file *file;
+ struct user_namespace *old_ns;
+ int err;
+
+ if (!fd)
+ return;
+
+ /* need to check ns inode number is valid */
+
+ file = proc_ns_fget(fd);
+ if (IS_ERR(file)) {
+ printk("%s: There is no %lu is open file table", __func__, fd);
+ return;
+ }
+
+ err = -EINVAL;
+ ei = get_proc_ns(file_inode(file));
+ ops = ei->ns_ops;
+ if (ops->type != CLONE_NEWUSER) {
+ fput(file);
+ printk("%s: %lu is not fd of userns", __func__, fd);
+ return;
+ }
+
+ /* might need some locking here */
+ old_ns = sb->s_user_ns;
+ sb->s_user_ns = get_user_ns(ei->ns);
+ /* unlock */
+ ops->put(old_ns);
+
+ fput(file);
+ return;
+}
+
static void ext4_load_balloon(struct super_block *sb, unsigned long ino)
{
struct inode *inode;
@@ -3600,6 +3649,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
__u64 blocks_count;
int err = 0;
unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+ unsigned long s_user_ns_fd = 0;
unsigned long balloon_ino = 0;
ext4_group_t first_not_zeroed;
@@ -3763,15 +3813,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
- &journal_devnum, &journal_ioprio, &balloon_ino,
- 0)) {
+ &journal_devnum, &journal_ioprio, &s_user_ns_fd,
+ &balloon_ino, 0)) {
ext4_msg(sb, KERN_WARNING,
"failed to parse options in superblock: %s",
sbi->s_es->s_mount_opts);
}
sbi->s_def_mount_opt = sbi->s_mount_opt;
if (!parse_options((char *) data, sb, &journal_devnum,
- &journal_ioprio, &balloon_ino, 0))
+ &journal_ioprio, &s_user_ns_fd, &balloon_ino, 0))
goto failed_mount;
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
@@ -4407,6 +4457,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
"the device does not support discard");
}
+ ext4_load_s_user_ns(sb, s_user_ns_fd);
ext4_load_balloon(sb, balloon_ino);
ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
@@ -5043,6 +5094,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
int i, j;
#endif
char *orig_data = kstrdup(data, GFP_KERNEL);
+ unsigned long s_user_ns_fd = 0;
unsigned long balloon_ino = -1;
/* Store the original options */
@@ -5072,7 +5124,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
if (sbi->s_journal && sbi->s_journal->j_task->io_context)
journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
- if (!parse_options(data, sb, NULL, &journal_ioprio, &balloon_ino, 1)) {
+ if (!parse_options(data, sb, NULL, &journal_ioprio, &s_user_ns_fd, &balloon_ino, 1)) {
err = -EINVAL;
goto restore_opts;
}
@@ -5216,6 +5268,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY))
ext4_commit_super(sb, 1);
+ if (s_user_ns_fd)
+ ext4_load_s_user_ns(sb, s_user_ns_fd);
if (balloon_ino != -1)
ext4_load_balloon(sb, balloon_ino);
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 54bdc67..927d6ff1 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -336,11 +336,13 @@ struct file *proc_ns_fget(int fd)
fput(file);
return ERR_PTR(-EINVAL);
}
+EXPORT_SYMBOL(proc_ns_fget);
struct proc_ns *get_proc_ns(struct inode *inode)
{
return &PROC_I(inode)->ns;
}
+EXPORT_SYMBOL(get_proc_ns);
bool proc_ns_inode(struct inode *inode)
{
--
1.9.3
More information about the Devel
mailing list