userns: have ext3 use fsuserns to read userns xattrs, and add groups to userns Signed-off-by: Serge Hallyn <serue@xxxxxxxxxx> --- fs/ext3/super.c | 11 +++++++++-- fs/ext3/xattr.c | 19 ++++++++++++++++++- fs/ext3/xattr.h | 3 ++- include/linux/fs.h | 2 +- lib/fsuserns.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 3458d25..37c8404 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -723,11 +723,18 @@ static struct quotactl_ops ext3_qctl_operations = { extern int fsuserns_add_userns(struct super_block *sb, struct user *user, void *data); extern int fsuserns_convert_uid_gid(struct user_namespace *ns, - struct inode *inode, uid_t *retuid, gid_t *retgid); + struct inode *inode, uid_t *retuid, gid_t *retgid, + int (*xattrget)(struct inode *, const void *, size_t)); extern int fsuserns_is_capable(struct user_namespace *ns, struct inode *inode, int cap); #endif +int ext3_convert_uid_gid(struct user_namespace *ns, struct inode *inode, + uid_t *retuid, gid_t *retgid) +{ + return fsuserns_convert_uid_gid(ns, inode, retuid, retgid, ext3_xattr_get_userns); +} + static const struct super_operations ext3_sops = { .alloc_inode = ext3_alloc_inode, .destroy_inode = ext3_destroy_inode, @@ -750,7 +757,7 @@ static const struct super_operations ext3_sops = { #ifdef CONFIG_USER_NS .add_userns = fsuserns_add_userns, .is_capable = fsuserns_is_capable, - .convert_uid_gid = fsuserns_convert_uid_gid, + .convert_uid_gid = ext3_convert_uid_gid, #endif }; diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index da47c35..500fec7 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -331,6 +331,23 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name, return error; } +int +ext3_xattr_get_userns(struct inode *inode, void *value, size_t value_size) +{ + int error; + int name_index = EXT3_XATTR_INDEX_SECURITY; + char *name = "userns"; + + down_read(&EXT3_I(inode)->xattr_sem); + error = ext3_xattr_ibody_get(inode, name_index, name, value, + value_size); + if (error == -ENODATA) + error = ext3_xattr_block_get(inode, name_index, name, value, + value_size); + up_read(&EXT3_I(inode)->xattr_sem); + return error; +} + static int ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry, char *buffer, size_t buffer_size) @@ -1087,7 +1104,7 @@ retry: int error2; error = ext3_xattr_set_handle(handle, inode, name_index, name, - value, value_len, flags); + value, value_len, 0); error2 = ext3_journal_stop(handle); if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 8a523de..8c5b982 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -70,7 +70,8 @@ extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); -extern int ext3_xattr_set_userns(struct inode *inode, const void *value, size_t value_len, int flags); +extern int ext3_xattr_get_userns(struct inode *inode, void *value, size_t value_len); +extern int ext3_xattr_set_userns(struct inode *inode, const void *value, size_t value_len); extern void ext3_xattr_delete_inode(handle_t *, struct inode *); extern void ext3_xattr_put_super(struct super_block *); diff --git a/include/linux/fs.h b/include/linux/fs.h index 492abef..9ec6dac 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1329,7 +1329,7 @@ struct super_operations { void (*umount_begin) (struct super_block *); int (*add_userns) (struct super_block *, struct user_struct *, void *); int (*is_capable) (struct user_namespace *, struct inode *, int); - uid_t (*convert_uid_gid)(struct user_namespace *, struct inode *, + int (*convert_uid_gid)(struct user_namespace *, struct inode *, uid_t *, gid_t *); int (*show_options)(struct seq_file *, struct vfsmount *); diff --git a/lib/fsuserns.c b/lib/fsuserns.c index db70970..ac0ca99 100644 --- a/lib/fsuserns.c +++ b/lib/fsuserns.c @@ -59,6 +59,12 @@ struct fsuserns_conversion_table { LIST_HEAD(fsuserns_tables); +struct unsstore { + int ns; + uid_t uid; + gid_t gid; +}; + struct fsuserns_conversion_table *find_table_locked( struct super_block *sb) { @@ -166,11 +172,15 @@ skip: * return 1 if we got a translation, 0 otherwise */ int fsuserns_convert_uid_gid(struct user_namespace *ns, struct inode *inode, - uid_t *retuid, gid_t *retgid) + uid_t *retuid, gid_t *retgid, + int (*xattrget)(struct inode *inode, void *value, size_t value_len)) { struct super_block *sb = inode->i_sb; struct fsuserns_conversion_table *t; struct fsuserns_table_entries *ep; + size_t valuelen; + struct unsstore *unsstore; + int i, ret; t = find_table(sb); if (!t) @@ -186,6 +196,23 @@ int fsuserns_convert_uid_gid(struct user_namespace *ns, struct inode *inode, convert: mutex_unlock(&fsuserns_table_mutex); + /* look for an xattr */ + /* yes, 3 needs to be made adjustable */ + valuelen = 3; + unsstore = kzalloc(3*sizeof(struct unsstore), GFP_KERNEL); + ret = xattrget(inode, unsstore, valuelen); + if (ret < 0) + return ret; + for (i=0; i<3; i++) + if (unsstore[i].ns == ep->userns_id) + break; + if (i==3) + goto out; + *retuid = unsstore[i].uid; + *retgid = unsstore[i].gid; + return 1; + +out: /* The following is BAD CODE. IT's for testing only */ if (current->uid == 0) { if (inode->i_uid == ns->creator->uid) { @@ -264,11 +291,6 @@ found: } -struct unsstore { - int ns; - uid_t uid; -}; - int fsuserns_store_creds(struct inode *inode, struct user_struct *user, int (*xattrset)(struct inode *inode, const void *value, size_t value_len)) { @@ -290,11 +312,23 @@ int fsuserns_store_creds(struct inode *inode, struct user_struct *user, size = depth * sizeof(struct unsstore); unsstore = kmalloc(size, GFP_KERNEL); ns = user->user_ns; + lastns = NULL; for (i=0; ns != &init_user_ns; i++) { unsstore[i].ns = find_ns_id(inode, ns); unsstore[i].uid = user->uid; + /* + * this is too bad. But putting grp on user_struct wouldn't work + * (think about if i do + * clone(CLONE_NEWUSER); + * change grp, + * clone(CLONE_NEWUSER) + * */ + if (!lastns) + unsstore[i].gid = current->gid; + else + unsstore[i].gid = lastns->creator_grp; printk(KERN_NOTICE "%s: setting xattr with ns=%d,uid=%d\n", __func__, - unsstore[i].ns, unsstore[i].uid); + unsstore[i].ns, unsstore[i].uid, unsstore[i].gid); user = ns->creator; lastns = ns; ns = user->user_ns; -- 1.5.4.3 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers