Final userns conversions
Subsystems (11)
cover Final userns conversions
This patchset contain the basic user namespace changes for filesystems that have needed nontrivial work. Along with the 2 patches that depend on these changes.
I belive these patches to be correct for allowing the remaining filesystems to work in the presence of user namespaces. At the same time I would like to give all of these much deeper scrutiny, just because there is so much going on. Unfortunately these patches individually are not obviously correct.
Since I won't have much time until after Thanksgiving and because the merge window is looming I figure I will put these changes out there and let people see I am looking at these changes, and see if anyone happens to spot anything.
If I can figure out how to responsibly get these changes into linux-next I want to get these changes into linux-next so that user namespace bugs show up in allyesconfig builds.
For people who want to see what else I am cooking my git tree is at:git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git
Eric W. Biederman (12):
userns: Support 9p interacting with multiple user namespaces
userns: Convert afs to use kuid/kgid where appropriate
userns: Convert ceph to use kuid/kgid where appropriate
userns: Convert cifs to use kuid/kgid where appropriate
userns: Convert coda's to use kuid/kgid where appropriate
userns: Convert gfs2 to use kuid/kgid where appropriate
userns: Convert ncpfs to use kuid and kgid where appropriate
userns: Convert nfs and nfsd to use kuid/kgid where appropriate
userns: Convert ocfs2 to use kuid and kgid where appropriate
userns: Convert xfs to use kuid/kgid/kprojid where appropriate
userns: Now that everything has been converted remove the unnecessary infrastructure
userns: Remove the EXPERMINTAL kconfig tag
fs/9p/fid.c | 17 +++-- fs/9p/v9fs.c | 34 ++++++++-- fs/9p/v9fs.h | 10 ++-- fs/9p/vfs_inode.c | 8 +- fs/9p/vfs_inode_dotl.c | 22 +++--- fs/afs/afs.h | 4 +- fs/afs/fsclient.c | 14 +++- fs/afs/inode.c | 6 +- fs/ceph/caps.c | 16 ++-- fs/ceph/inode.c | 18 +++--- fs/ceph/mds_client.c | 4 +- fs/ceph/super.h | 4 +- fs/cifs/cifs_fs_sb.h | 8 +- fs/cifs/cifs_spnego.c | 4 +- fs/cifs/cifsacl.c | 115 +++++++++++++++++++++++++-------- fs/cifs/cifsacl.h | 16 ++++- fs/cifs/cifsfs.c | 12 ++- fs/cifs/cifsglob.h | 22 +++--- fs/cifs/cifspdu.h | 2 + fs/cifs/cifsproto.h | 9 ++- fs/cifs/cifssmb.c | 11 +++- fs/cifs/connect.c | 58 +++++++++++++---- fs/cifs/dir.c | 18 +++--- fs/cifs/file.c | 8 +- fs/cifs/inode.c | 28 ++++---- fs/cifs/misc.c | 2 +- fs/coda/cache.c | 4 +- fs/coda/coda_fs_i.h | 2 +- fs/coda/coda_linux.c | 8 +- fs/coda/inode.c | 2 +- fs/coda/upcall.c | 6 +- fs/gfs2/acl.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/glops.c | 4 +- fs/gfs2/incore.h | 3 +- fs/gfs2/inode.c | 36 ++++++----- fs/gfs2/quota.c | 128 ++++++++++++++++--------------------- fs/gfs2/quota.h | 15 ++-- fs/gfs2/super.c | 6 +- fs/gfs2/sys.c | 14 ++++- fs/gfs2/xattr.c | 4 +- fs/ncpfs/inode.c | 55 ++++++++++------ fs/ncpfs/ioctl.c | 25 ++++--- fs/ncpfs/ncp_fs_sb.h | 6 +- fs/nfs/idmap.c | 45 ++++++++----- fs/nfs/inode.c | 12 ++-- fs/nfs/nfs2xdr.c | 8 +- fs/nfs/nfs3xdr.c | 8 +- fs/nfs/nfs4xdr.c | 16 ++-- fs/nfs_common/nfsacl.c | 37 ++++++---- fs/nfsd/acl.h | 2 - fs/nfsd/auth.c | 12 ++-- fs/nfsd/export.c | 22 ++++-- fs/nfsd/idmap.h | 8 +- fs/nfsd/nfs3xdr.c | 9 ++- fs/nfsd/nfs4acl.c | 63 +++++++++++++----- fs/nfsd/nfs4idmap.c | 34 ++++++---- fs/nfsd/nfs4recover.c | 4 +- fs/nfsd/nfs4state.c | 6 +- fs/nfsd/nfs4xdr.c | 42 ++++++++----- fs/nfsd/nfsxdr.c | 9 ++- fs/nfsd/vfs.c | 8 +- fs/ocfs2/acl.c | 31 ++++++++- fs/ocfs2/dlmglue.c | 8 +- fs/ocfs2/file.c | 11 ++-- fs/ocfs2/inode.c | 12 ++-- fs/ocfs2/namei.c | 4 +- fs/ocfs2/refcounttree.c | 2 +- fs/xfs/xfs_acl.c | 23 ++++++- fs/xfs/xfs_dquot.c | 36 +++++++---- fs/xfs/xfs_dquot.h | 5 +- fs/xfs/xfs_inode.c | 33 ++++++---- fs/xfs/xfs_inode.h | 32 ++-------- fs/xfs/xfs_ioctl.c | 23 +++++-- fs/xfs/xfs_iops.c | 18 +++--- fs/xfs/xfs_itable.c | 8 +- fs/xfs/xfs_qm.c | 87 +++++++++++++------------ fs/xfs/xfs_qm.h | 4 +- fs/xfs/xfs_qm_bhv.c | 3 +- fs/xfs/xfs_qm_syscalls.c | 24 ++++--- fs/xfs/xfs_quota.h | 4 +- fs/xfs/xfs_quotaops.c | 20 +----- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_trans_dquot.c | 6 +-- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- fs/xfs/xfs_vnodeops.c | 14 ++-- include/linux/coda_psdev.h | 2 +- include/linux/nfs4.h | 6 ++- include/linux/nfs_idmap.h | 10 ++-- include/linux/nfs_xdr.h | 4 +- include/linux/nfsd/export.h | 4 +- include/linux/posix_acl.h | 3 - include/linux/projid.h | 15 ---- include/linux/sunrpc/auth.h | 7 +- include/linux/sunrpc/svcauth.h | 4 +- include/linux/uidgid.h | 22 ------ include/net/9p/client.h | 12 ++-- init/Kconfig | 40 +----------- net/9p/client.c | 28 +++++---- net/sunrpc/auth.c | 6 +- net/sunrpc/auth_generic.c | 16 +++-- net/sunrpc/auth_gss/auth_gss.c | 33 ++++++---- net/sunrpc/auth_gss/svcauth_gss.c | 14 ++++- net/sunrpc/auth_unix.c | 36 ++++------ net/sunrpc/svcauth_unix.c | 40 +++++++----- 107 files changed, 1035 insertions(+), 820 deletions(-)
RFC PATCH 1/12 userns: Support 9p interacting with multiple user namespaces
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Use kuid_t and kgid_t in struct v9fs_session_info and struct 9p_fid.
--- fs/9p/fid.c | 17 +++++++++-------- fs/9p/v9fs.c | 34 +++++++++++++++++++++++++++------- fs/9p/v9fs.h | 10 +++++----- fs/9p/vfs_inode.c | 8 ++++---- fs/9p/vfs_inode_dotl.c | 22 +++++++++++----------- include/net/9p/client.h | 12 ++++++------ init/Kconfig | 4 ---- net/9p/client.c | 28 ++++++++++++++++------------ 8 files changed, 78 insertions(+), 57 deletions(-)
fs/9p/fid.c +9 -8
@@ -74,19 +74,20 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)* */ -static struct p9_fid *v9fs_fid_find (struct dentry *dentry,u32 uid,int any) +static struct p9_fid *v9fs_fid_find (struct dentry *dentry,kuid_t uid,int any) {struct v9fs_dentry *dent;struct p9_fid *fid, *ret;p9_debug (P9_DEBUG_VFS ," dentry: %s (%p) uid %d any %d\n" , - dentry->d_name.name, dentry, uid, any); + dentry->d_name.name, dentry,from_kuid (&init_user_ns, uid), + any); dent = (struct v9fs_dentry *) dentry->d_fsdata; ret =NULL ;if (dent) {spin_lock (&dent->lock);list_for_each_entry (fid, &dent->fidlist, dlist) { -if (any || fid->uid == uid) { +if (any ||uid_eq (fid->uid, uid)) { ret = fid;break ; }
@@ -126,7 +127,7 @@ err_out: }static struct p9_fid *v9fs_fid_lookup_with_uid (struct dentry *dentry, -uid_t uid,int any) +kuid_t uid,int any) {struct dentry *ds;char **wnames, *uname;
@@ -233,7 +234,7 @@ err_out:struct p9_fid *v9fs_fid_lookup (struct dentry *dentry) { -uid_t uid; +kuid_t uid;int any, access;struct v9fs_session_info *v9ses;
@@ -253,7 +254,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)break ;default : - uid = ~0 ; + uid =INVALID_UID ; any =0 ;break ; }
@@ -272,7 +273,7 @@ struct p9_fid *v9fs_fid_clone(struct dentry *dentry)return ret; } -static struct p9_fid *v9fs_fid_clone_with_uid (struct dentry *dentry,uid_t uid) +static struct p9_fid *v9fs_fid_clone_with_uid (struct dentry *dentry,kuid_t uid) {struct p9_fid *fid, *ret;
@@ -289,7 +290,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)int err;struct p9_fid *fid; - fid =v9fs_fid_clone_with_uid (dentry,0 ); + fid =v9fs_fid_clone_with_uid (dentry,GLOBAL_ROOT_UID );if (IS_ERR (fid)) goto error_out;/*
fs/9p/v9fs.c +27 -7
@@ -161,7 +161,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) ret = r;continue ; } - v9ses->dfltuid = option; + v9ses->dfltuid =make_kuid (&init_user_ns, option); +if (!uid_valid (v9ses->dfltuid)) { +p9_debug (P9_DEBUG_ERROR , +"uid field, but not a uid?\n" ); + ret = -EINVAL ; +continue ; + }break ;case Opt_dfltgid: r =match_int (&args[0 ], &option);
@@ -171,7 +177,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) ret = r;continue ; } - v9ses->dfltgid = option; + v9ses->dfltgid =make_kgid (&init_user_ns, option); +if (!gid_valid (v9ses->dfltgid)) { +p9_debug (P9_DEBUG_ERROR , +"gid field, but not a gid?\n" ); + ret = -EINVAL ; +continue ; + }break ;case Opt_afid: r =match_int (&args[0 ], &option);
@@ -248,8 +260,9 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)else if (strcmp (s,"client" ) ==0 ) { v9ses->flags |=V9FS_ACCESS_CLIENT ; }else { +uid_t uid; v9ses->flags |=V9FS_ACCESS_SINGLE ; - v9ses->uid =simple_strtoul (s, &e,10 ); + uid =simple_strtoul (s, &e,10 );if (*e !='\0' ) { ret = -EINVAL ; pr_info("Unknown access argument %s\n",
@@ -257,6 +270,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)kfree (s); goto free_and_return; } + v9ses->uid =make_kuid (&init_user_ns, uid); +if (!uid_valid (v9ses->uid)) { + ret = -EINVAL ; +pr_info ("Uknown uid %s\n" , s); +kfree (s); + goto free_and_return; + } }kfree (s);
@@ -319,7 +339,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,list_add (&v9ses->slist, &v9fs_sessionlist);spin_unlock (&v9fs_sessionlist_lock); - v9ses->uid = ~0 ; + v9ses->uid =INVALID_UID ; v9ses->dfltuid =V9FS_DEFUID ; v9ses->dfltgid =V9FS_DEFGID ;
@@ -364,7 +384,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->flags &= ~V9FS_ACCESS_MASK ; v9ses->flags |=V9FS_ACCESS_ANY ; - v9ses->uid = ~0 ; + v9ses->uid =INVALID_UID ; }if (!v9fs_proto_dotl (v9ses) || !((v9ses->flags &V9FS_ACCESS_MASK ) ==V9FS_ACCESS_CLIENT )) {
@@ -375,7 +395,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->flags &= ~V9FS_ACL_MASK ; } - fid =p9_client_attach (v9ses->clnt,NULL , v9ses->uname, ~0 , + fid =p9_client_attach (v9ses->clnt,NULL , v9ses->uname,INVALID_UID , v9ses->aname);if (IS_ERR (fid)) { retval =PTR_ERR (fid);
@@ -387,7 +407,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,if ((v9ses->flags &V9FS_ACCESS_MASK ) ==V9FS_ACCESS_SINGLE ) fid->uid = v9ses->uid;else - fid->uid = ~0 ; + fid->uid =INVALID_UID ;#ifdef CONFIG_9P_FSCACHE /* register the session for caching */
fs/9p/v9fs.h +5 -5
@@ -109,9 +109,9 @@ struct v9fs_session_info {char *uname;/* user name to mount as */ char *aname;/* name of remote hierarchy being mounted */ unsigned int maxdata;/* max data for client interface */ -unsigned int dfltuid;/* default uid/muid for legacy support */ -unsigned int dfltgid;/* default gid for legacy support */ -u32 uid;/* if ACCESS_SINGLE, the uid that has access */ +kuid_t dfltuid;/* default uid/muid for legacy support */ +kgid_t dfltgid;/* default gid for legacy support */ +kuid_t uid;/* if ACCESS_SINGLE, the uid that has access */ struct p9_client *clnt;/* 9p client */ struct list_head slist;/* list of sessions registered with v9fs */ struct backing_dev_info bdi;
@@ -165,8 +165,8 @@ extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,#define V9FS_PORT 564#define V9FS_DEFUSER "nobody"#define V9FS_DEFANAME "" -#define V9FS_DEFUID (-2) -#define V9FS_DEFGID (-2) +#define V9FS_DEFUID KUIDT_INIT(-2) +#define V9FS_DEFGID KGIDT_INIT(-2)static inline struct v9fs_session_info *v9fs_inode2v9ses (struct inode *inode) {
fs/9p/vfs_inode.c +4 -4
@@ -1137,10 +1137,10 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)if (v9fs_proto_dotu (v9ses)) {if (iattr->ia_valid &ATTR_UID ) - wstat.n_uid = iattr->ia_uid; + wstat.n_uid =from_kuid (&init_user_ns, iattr->ia_uid);if (iattr->ia_valid &ATTR_GID ) - wstat.n_gid = iattr->ia_gid; + wstat.n_gid =from_kgid (&init_user_ns, iattr->ia_gid); }/* Write all dirty data */
@@ -1191,8 +1191,8 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, inode->i_gid = v9ses->dfltgid;if (v9fs_proto_dotu (v9ses)) { - inode->i_uid = stat->n_uid; - inode->i_gid = stat->n_gid; +i_uid_write (inode, stat->n_uid); +i_gid_write (inode, stat->n_gid); }if ((S_ISREG (inode->i_mode)) || (S_ISDIR (inode->i_mode))) {if (v9fs_proto_dotu (v9ses) && (stat->extension[0 ] !='\0' )) {
fs/9p/vfs_inode_dotl.c +11 -11
@@ -57,7 +57,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,* group of the new file system object. */ -static gid_t v9fs_get_fsgid_for_create (struct inode *dir_inode) +static kgid_t v9fs_get_fsgid_for_create (struct inode *dir_inode) {BUG_ON (dir_inode ==NULL );
@@ -246,7 +246,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, int *opened) {int err =0 ; -gid_t gid; +kgid_t gid;umode_t mode;char *name =NULL ;struct p9_qid qid;
@@ -391,7 +391,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,int err;struct v9fs_session_info *v9ses;struct p9_fid *fid =NULL , *dfid =NULL ; -gid_t gid; +kgid_t gid;char *name;umode_t mode;struct inode *inode;
@@ -576,8 +576,8 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) p9attr.valid =v9fs_mapped_iattr_valid (iattr->ia_valid); p9attr.mode = iattr->ia_mode; - p9attr.uid = iattr->ia_uid; - p9attr.gid = iattr->ia_gid; + p9attr.uid =from_kuid (&init_user_ns, iattr->ia_uid); + p9attr.gid =from_kgid (&init_user_ns, iattr->ia_gid); p9attr.size = iattr->ia_size; p9attr.atime_sec = iattr->ia_atime.tv_sec; p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
@@ -635,8 +635,8 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) inode->i_mtime.tv_nsec = stat->st_mtime_nsec; inode->i_ctime.tv_sec = stat->st_ctime_sec; inode->i_ctime.tv_nsec = stat->st_ctime_nsec; - inode->i_uid = stat->st_uid; - inode->i_gid = stat->st_gid; +i_uid_write (inode, stat->st_uid); +i_gid_write (inode, stat->st_gid);set_nlink (inode, stat->st_nlink); mode = stat->st_mode &S_IALLUGO ;
@@ -659,9 +659,9 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) inode->i_ctime.tv_nsec = stat->st_ctime_nsec; }if (stat->st_result_mask &P9_STATS_UID ) - inode->i_uid = stat->st_uid; +i_uid_write (inode, stat->st_uid);if (stat->st_result_mask &P9_STATS_GID ) - inode->i_gid = stat->st_gid; +i_gid_write (inode, stat->st_gid);if (stat->st_result_mask &P9_STATS_NLINK )set_nlink (inode, stat->st_nlink);if (stat->st_result_mask &P9_STATS_MODE ) {
@@ -692,7 +692,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, const char *symname) {int err; -gid_t gid; +kgid_t gid;char *name;struct p9_qid qid;struct inode *inode;
@@ -832,7 +832,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, dev_t rdev) {int err; -gid_t gid; +kgid_t gid;char *name;umode_t mode;struct v9fs_session_info *v9ses;
include/net/9p/client.h +6 -6
@@ -187,7 +187,7 @@ struct p9_fid {int mode;struct p9_qid qid;u32 iounit; -uid_t uid; +kuid_t uid;void *rdir;
@@ -220,17 +220,17 @@ void p9_client_destroy(struct p9_client *clnt);void p9_client_disconnect (struct p9_client *clnt);void p9_client_begin_disconnect (struct p9_client *clnt);struct p9_fid *p9_client_attach (struct p9_client *clnt,struct p9_fid *afid, -char *uname,u32 n_uname,char *aname); +char *uname,kuid_t n_uname,char *aname);struct p9_fid *p9_client_walk (struct p9_fid *oldfid,uint16_t nwname,char **wnames,int clone);int p9_client_open (struct p9_fid *fid,int mode);int p9_client_fcreate (struct p9_fid *fid,char *name,u32 perm,int mode,char *extension);int p9_client_link (struct p9_fid *fid,struct p9_fid *oldfid,char *newname); -int p9_client_symlink (struct p9_fid *fid,char *name,char *symname,gid_t gid, +int p9_client_symlink (struct p9_fid *fid,char *name,char *symname,kgid_t gid,struct p9_qid *qid);int p9_client_create_dotl (struct p9_fid *ofid,char *name,u32 flags,u32 mode, -gid_t gid,struct p9_qid *qid); +kgid_t gid,struct p9_qid *qid);int p9_client_clunk (struct p9_fid *fid);int p9_client_fsync (struct p9_fid *fid,int datasync);int p9_client_remove (struct p9_fid *fid);
@@ -250,9 +250,9 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, u64 request_mask);int p9_client_mknod_dotl (struct p9_fid *oldfid,char *name,int mode, -dev_t rdev,gid_t gid,struct p9_qid *); +dev_t rdev,kgid_t gid,struct p9_qid *);int p9_client_mkdir_dotl (struct p9_fid *fid,char *name,int mode, -gid_t gid,struct p9_qid *); +kgid_t gid,struct p9_qid *);int p9_client_lock_dotl (struct p9_fid *fid,struct p9_flock *flock,u8 *status);int p9_client_getlock_dotl (struct p9_fid *fid,struct p9_getlock *fl);struct p9_req_t *p9_tag_lookup (struct p9_client *,u16 );
init/Kconfig +0 -4
@@ -998,11 +998,7 @@ config UIDGID_CONVERTED bool default y - # Networking - depends on NET_9P = n - # Filesystems - depends on 9P_FS = n depends on AFS_FS = n depends on CEPH_FS = n depends on CIFS = n
net/9p/client.c +16 -12
@@ -1100,7 +1100,7 @@ void p9_client_begin_disconnect(struct p9_client *clnt)EXPORT_SYMBOL (p9_client_begin_disconnect);struct p9_fid *p9_client_attach (struct p9_client *clnt,struct p9_fid *afid, -char *uname,u32 n_uname,char *aname) +char *uname,kuid_t n_uname,char *aname) {int err =0 ;struct p9_req_t *req;
@@ -1118,7 +1118,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, } req =p9_client_rpc (clnt,P9_TATTACH ,"ddss?d" , fid->fid, - afid ? afid->fid :P9_NOFID , uname, aname, n_uname); + afid ? afid->fid :P9_NOFID , uname, aname, +from_kuid (&init_user_ns, n_uname));if (IS_ERR (req)) { err =PTR_ERR (req); goto error;
@@ -1270,7 +1271,7 @@ error:EXPORT_SYMBOL (p9_client_open);int p9_client_create_dotl (struct p9_fid *ofid,char *name,u32 flags,u32 mode, -gid_t gid,struct p9_qid *qid) +kgid_t gid,struct p9_qid *qid) {int err =0 ;struct p9_client *clnt;
@@ -1279,14 +1280,16 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,p9_debug (P9_DEBUG_9P ,">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n" , - ofid->fid, name, flags, mode, gid); + ofid->fid, name, flags, mode, +from_kgid (&init_user_ns, gid)); clnt = ofid->clnt;if (ofid->mode !=-1 )return -EINVAL ; req =p9_client_rpc (clnt,P9_TLCREATE ,"dsddd" , ofid->fid, name, flags, - mode, gid); + mode, +from_kgid (&init_user_ns, gid));if (IS_ERR (req)) { err =PTR_ERR (req); goto error;
@@ -1358,7 +1361,7 @@ error: }EXPORT_SYMBOL (p9_client_fcreate); -int p9_client_symlink (struct p9_fid *dfid,char *name,char *symtgt,gid_t gid, +int p9_client_symlink (struct p9_fid *dfid,char *name,char *symtgt,kgid_t gid,struct p9_qid *qid) {int err =0 ;
@@ -1370,7 +1373,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid, clnt = dfid->clnt; req =p9_client_rpc (clnt,P9_TSYMLINK ,"dssd" , dfid->fid, name, symtgt, - gid); +from_kgid (&init_user_ns, gid));if (IS_ERR (req)) { err =PTR_ERR (req); goto error;
@@ -2106,7 +2109,7 @@ error:EXPORT_SYMBOL (p9_client_readdir);int p9_client_mknod_dotl (struct p9_fid *fid,char *name,int mode, -dev_t rdev,gid_t gid,struct p9_qid *qid) +dev_t rdev,kgid_t gid,struct p9_qid *qid) {int err;struct p9_client *clnt;
@@ -2117,7 +2120,8 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,p9_debug (P9_DEBUG_9P ,">>> TMKNOD fid %d name %s mode %d major %d " "minor %d\n" , fid->fid, name, mode,MAJOR (rdev),MINOR (rdev)); req =p9_client_rpc (clnt,P9_TMKNOD ,"dsdddd" , fid->fid, name, mode, -MAJOR (rdev),MINOR (rdev), gid); +MAJOR (rdev),MINOR (rdev), +from_kgid (&init_user_ns, gid));if (IS_ERR (req))return PTR_ERR (req);
@@ -2137,7 +2141,7 @@ error:EXPORT_SYMBOL (p9_client_mknod_dotl);int p9_client_mkdir_dotl (struct p9_fid *fid,char *name,int mode, -gid_t gid,struct p9_qid *qid) +kgid_t gid,struct p9_qid *qid) {int err;struct p9_client *clnt;
@@ -2146,9 +2150,9 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, err =0 ; clnt = fid->clnt;p9_debug (P9_DEBUG_9P ,">>> TMKDIR fid %d name %s mode %d gid %d\n" , - fid->fid, name, mode, gid); + fid->fid, name, mode,from_kgid (&init_user_ns, gid)); req =p9_client_rpc (clnt,P9_TMKDIR ,"dsdd" , fid->fid, name, mode, - gid); +from_kgid (&init_user_ns, gid));if (IS_ERR (req))return PTR_ERR (req);
Signature · 1 line
1.7.5.4
RFC PATCH 2/12 userns: Convert afs to use kuid/kgid where appropriate
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/afs/afs.h | 4 ++-- fs/afs/fsclient.c | 14 ++++++++++---- fs/afs/inode.c | 6 +++--- init/Kconfig | 1 - 4 files changed, 15 insertions(+), 10 deletions(-)
fs/afs/afs.h +2 -2
@@ -119,8 +119,8 @@ struct afs_file_status {u64 size;/* file size */ afs_dataversion_t data_version;/* current data version */ u32 author;/* author ID */ -u32 owner;/* owner ID */ -u32 group;/* group ID */ +kuid_t owner;/* owner ID */ +kgid_t group;/* group ID */ afs_access_t caller_access;/* access rights for authenticated caller */ afs_access_t anon_access;/* access rights for unauthenticated caller */ umode_t mode;/* UNIX mode */
fs/afs/fsclient.c +10 -4
@@ -42,6 +42,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,umode_t mode;u64 data_version, size;u32 changed =0 ;/* becomes non-zero if ctime-type changes seen */ +u32 owner; +u32 group;#define EXTRACT (DST ) \ do { \
@@ -56,7 +58,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, size =ntohl (*bp++); data_version =ntohl (*bp++);EXTRACT (status->author); -EXTRACT (status->owner); + owner =from_kuid (&init_user_ns, status->owner); +EXTRACT (owner); + status->owner =make_kuid (&init_user_ns, owner);EXTRACT (status->caller_access);/* call ticket dependent */ EXTRACT (status->anon_access);EXTRACT (status->mode);
@@ -65,7 +69,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, bp++;/* seg size */ status->mtime_client =ntohl (*bp++); status->mtime_server =ntohl (*bp++); -EXTRACT (status->group); + group =from_kgid (&init_user_ns, status->group); +EXTRACT (group); + status->group =make_kgid (&init_user_ns, group); bp++;/* sync counter */ data_version |= (u64 )ntohl (*bp++) <<32 ;EXTRACT (status->lock_count);
@@ -181,12 +187,12 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)if (attr->ia_valid &ATTR_UID ) { mask |=AFS_SET_OWNER ; - owner = attr->ia_uid; + owner =from_kuid (&init_user_ns, attr->ia_uid); }if (attr->ia_valid &ATTR_GID ) { mask |=AFS_SET_GROUP ; - group = attr->ia_gid; + group =from_kgid (&init_user_ns, attr->ia_gid); }if (attr->ia_valid &ATTR_MODE ) {
fs/afs/inode.c +3 -3
@@ -69,7 +69,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)set_nlink (inode, vnode->status.nlink); inode->i_uid = vnode->status.owner; - inode->i_gid =0 ; + inode->i_gid =GLOBAL_ROOT_GID ; inode->i_size = vnode->status.size; inode->i_ctime.tv_sec = vnode->status.mtime_server; inode->i_ctime.tv_nsec =0 ;
@@ -175,8 +175,8 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, inode->i_mode =S_IFDIR |S_IRUGO |S_IXUGO ; inode->i_op = &afs_autocell_inode_operations;set_nlink (inode,2 ); - inode->i_uid =0 ; - inode->i_gid =0 ; + inode->i_uid =GLOBAL_ROOT_UID ; + inode->i_gid =GLOBAL_ROOT_GID ; inode->i_ctime.tv_sec =get_seconds (); inode->i_ctime.tv_nsec =0 ; inode->i_atime = inode->i_mtime = inode->i_ctime;
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on AFS_FS = n depends on CEPH_FS = n depends on CIFS = n depends on CODA_FS = n
Signature · 1 line
1.7.5.4
RFC PATCH 3/12 userns: Convert ceph to use kuid/kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ceph/caps.c | 16 ++++++++-------- fs/ceph/inode.c | 18 +++++++++--------- fs/ceph/mds_client.c | 4 ++-- fs/ceph/super.h | 4 ++-- init/Kconfig | 1 - 5 files changed, 21 insertions(+), 22 deletions(-)
fs/ceph/caps.c +8 -8
@@ -928,7 +928,7 @@ static int send_cap_msg(struct ceph_mds_session *session, u64 size, u64 max_size, struct timespec *mtime, struct timespec *atime, u64 time_warp_seq, - uid_t uid, gid_t gid, umode_t mode, + kuid_t uid, kgid_t gid, umode_t mode, u64 xattr_version, struct ceph_buffer *xattrs_buf, u64 follows)
@@ -972,8 +972,8 @@ static int send_cap_msg(struct ceph_mds_session *session,ceph_encode_timespec (&fc->atime, atime); fc->time_warp_seq =cpu_to_le32 (time_warp_seq); - fc->uid =cpu_to_le32 (uid); - fc->gid =cpu_to_le32 (gid); + fc->uid =cpu_to_le32 (from_kuid (&init_user_ns, uid)); + fc->gid =cpu_to_le32 (from_kgid (&init_user_ns, gid)); fc->mode =cpu_to_le32 (mode); fc->xattr_version =cpu_to_le64 (xattr_version);
@@ -1079,8 +1079,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,struct timespec mtime, atime;int wake =0 ;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_mds_session *session;u64 xattr_version =0 ;struct ceph_buffer *xattr_blob =NULL ;
@@ -2353,10 +2353,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (grant->mode); - inode->i_uid =le32_to_cpu (grant->uid); - inode->i_gid =le32_to_cpu (grant->gid); +i_uid_write (inode,le32_to_cpu (grant->uid)); +i_gid_write (inode,le32_to_cpu (grant->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )
fs/ceph/inode.c +9 -9
@@ -612,10 +612,10 @@ static int fill_inode(struct inode *inode,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (info->mode); - inode->i_uid =le32_to_cpu (info->uid); - inode->i_gid =le32_to_cpu (info->gid); +i_uid_write (inode,le32_to_cpu (info->uid)); +i_gid_write (inode,le32_to_cpu (info->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )
@@ -1562,26 +1562,26 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)if (ia_valid &ATTR_UID ) {dout ("setattr %p uid %d -> %d\n" , inode, - inode->i_uid, attr->ia_uid); +i_uid_read (inode),from_kuid (&init_user_ns, attr->ia_uid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_uid = attr->ia_uid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_uid != inode->i_uid) { - req->r_args.setattr.uid =cpu_to_le32 (attr->ia_uid); + !uid_eq (attr->ia_uid, inode->i_uid)) { + req->r_args.setattr.uid =cpu_to_le32 (from_kuid (&init_user_ns, attr->ia_uid)); mask |=CEPH_SETATTR_UID ; release |=CEPH_CAP_AUTH_SHARED ; } }if (ia_valid &ATTR_GID ) {dout ("setattr %p gid %d -> %d\n" , inode, - inode->i_gid, attr->ia_gid); +i_gid_read (inode),from_kgid (&init_user_ns, attr->ia_gid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_gid = attr->ia_gid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_gid != inode->i_gid) { - req->r_args.setattr.gid =cpu_to_le32 (attr->ia_gid); + !gid_eq (attr->ia_gid, inode->i_gid)) { + req->r_args.setattr.gid =cpu_to_le32 (from_kgid (&init_user_ns, attr->ia_gid)); mask |=CEPH_SETATTR_GID ; release |=CEPH_CAP_AUTH_SHARED ; }
fs/ceph/mds_client.c +2 -2
@@ -578,8 +578,8 @@ static void __register_request(struct ceph_mds_client *mdsc,ceph_mdsc_get_request (req);__insert_request (mdsc, req); - req->r_uid =current_fsuid (); - req->r_gid =current_fsgid (); + req->r_uid =from_kuid (&init_user_ns,current_fsuid ()); + req->r_gid =from_kgid (&init_user_ns,current_fsgid ());if (dir) {struct ceph_inode_info *ci =ceph_inode (dir);
fs/ceph/super.h +2 -2
@@ -138,8 +138,8 @@ struct ceph_cap_snap {struct ceph_snap_context *context;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_buffer *xattr_blob;u64 xattr_version;
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CEPH_FS = n depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n
Signature · 1 line
1.7.5.4
Re: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate
Quoted 5 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
Cc Sage Weil <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Eric W. Biederman <[email protected]>
Do you want me to take this via the ceph tree?
sage
Quoted 154 lines
--- fs/ceph/caps.c | 16 ++++++++-------- fs/ceph/inode.c | 18 +++++++++--------- fs/ceph/mds_client.c | 4 ++-- fs/ceph/super.h | 4 ++-- init/Kconfig | 1 - 5 files changed, 21 insertions(+), 22 deletions(-)fs/ceph/caps.c +8
-8@@ -928,7 +928,7 @@ static int send_cap_msg(struct ceph_mds_session *session, u64 size, u64 max_size, struct timespec *mtime, struct timespec *atime, u64 time_warp_seq, - uid_t uid, gid_t gid, umode_t mode, + kuid_t uid, kgid_t gid, umode_t mode, u64 xattr_version, struct ceph_buffer *xattrs_buf, u64 follows)@@ -972,8 +972,8 @@ static int send_cap_msg(struct ceph_mds_session *session,ceph_encode_timespec (&fc->atime, atime); fc->time_warp_seq =cpu_to_le32 (time_warp_seq); - fc->uid =cpu_to_le32 (uid); - fc->gid =cpu_to_le32 (gid); + fc->uid =cpu_to_le32 (from_kuid (&init_user_ns, uid)); + fc->gid =cpu_to_le32 (from_kgid (&init_user_ns, gid)); fc->mode =cpu_to_le32 (mode); fc->xattr_version =cpu_to_le64 (xattr_version);@@ -1079,8 +1079,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,struct timespec mtime, atime;int wake =0 ;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_mds_session *session;u64 xattr_version =0 ;struct ceph_buffer *xattr_blob =NULL ;@@ -2353,10 +2353,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (grant->mode); - inode->i_uid =le32_to_cpu (grant->uid); - inode->i_gid =le32_to_cpu (grant->gid); +i_uid_write (inode,le32_to_cpu (grant->uid)); +i_gid_write (inode,le32_to_cpu (grant->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )fs/ceph/inode.c +9
-9@@ -612,10 +612,10 @@ static int fill_inode(struct inode *inode,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (info->mode); - inode->i_uid =le32_to_cpu (info->uid); - inode->i_gid =le32_to_cpu (info->gid); +i_uid_write (inode,le32_to_cpu (info->uid)); +i_gid_write (inode,le32_to_cpu (info->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )@@ -1562,26 +1562,26 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)if (ia_valid &ATTR_UID ) {dout ("setattr %p uid %d -> %d\n" , inode, - inode->i_uid, attr->ia_uid); +i_uid_read (inode),from_kuid (&init_user_ns, attr->ia_uid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_uid = attr->ia_uid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_uid != inode->i_uid) { - req->r_args.setattr.uid =cpu_to_le32 (attr->ia_uid); + !uid_eq (attr->ia_uid, inode->i_uid)) { + req->r_args.setattr.uid =cpu_to_le32 (from_kuid (&init_user_ns, attr->ia_uid)); mask |=CEPH_SETATTR_UID ; release |=CEPH_CAP_AUTH_SHARED ; } }if (ia_valid &ATTR_GID ) {dout ("setattr %p gid %d -> %d\n" , inode, - inode->i_gid, attr->ia_gid); +i_gid_read (inode),from_kgid (&init_user_ns, attr->ia_gid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_gid = attr->ia_gid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_gid != inode->i_gid) { - req->r_args.setattr.gid =cpu_to_le32 (attr->ia_gid); + !gid_eq (attr->ia_gid, inode->i_gid)) { + req->r_args.setattr.gid =cpu_to_le32 (from_kgid (&init_user_ns, attr->ia_gid)); mask |=CEPH_SETATTR_GID ; release |=CEPH_CAP_AUTH_SHARED ; }fs/ceph/mds_client.c +2
-2@@ -578,8 +578,8 @@ static void __register_request(struct ceph_mds_client *mdsc,ceph_mdsc_get_request (req);__insert_request (mdsc, req); - req->r_uid =current_fsuid (); - req->r_gid =current_fsgid (); + req->r_uid =from_kuid (&init_user_ns,current_fsuid ()); + req->r_gid =from_kgid (&init_user_ns,current_fsgid ());if (dir) {struct ceph_inode_info *ci =ceph_inode (dir);fs/ceph/super.h +2
-2@@ -138,8 +138,8 @@ struct ceph_cap_snap {struct ceph_snap_context *context;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_buffer *xattr_blob;u64 xattr_version;init/Kconfig +0
-1@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CEPH_FS = n depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = nSignature · 1 line
1.7.5.4
Re: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate
Quoted 10 lines · Sage Weil
Quoted 5 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Sage Weil <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Sage Weil <[email protected]>Do you want me to take this via the ceph tree?
If you have reviewed the changes, understand them and don't have problems with them, having the changes go through your tree would be great.
Eric
A message that is not in the archive (sent off-list or not yet received): 1353415420-5457-3-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Sage Weil
Acked-byRe: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate
Quoted 5 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Sage Weil <[email protected]>Acked-by Serge Hallyn <[email protected]>
Do you want me to take this via the ceph tree?
sage
Quoted 154 lines
--- fs/ceph/caps.c | 16 ++++++++-------- fs/ceph/inode.c | 18 +++++++++--------- fs/ceph/mds_client.c | 4 ++-- fs/ceph/super.h | 4 ++-- init/Kconfig | 1 - 5 files changed, 21 insertions(+), 22 deletions(-)fs/ceph/caps.c +8
-8@@ -928,7 +928,7 @@ static int send_cap_msg(struct ceph_mds_session *session, u64 size, u64 max_size, struct timespec *mtime, struct timespec *atime, u64 time_warp_seq, - uid_t uid, gid_t gid, umode_t mode, + kuid_t uid, kgid_t gid, umode_t mode, u64 xattr_version, struct ceph_buffer *xattrs_buf, u64 follows)@@ -972,8 +972,8 @@ static int send_cap_msg(struct ceph_mds_session *session,ceph_encode_timespec (&fc->atime, atime); fc->time_warp_seq =cpu_to_le32 (time_warp_seq); - fc->uid =cpu_to_le32 (uid); - fc->gid =cpu_to_le32 (gid); + fc->uid =cpu_to_le32 (from_kuid (&init_user_ns, uid)); + fc->gid =cpu_to_le32 (from_kgid (&init_user_ns, gid)); fc->mode =cpu_to_le32 (mode); fc->xattr_version =cpu_to_le64 (xattr_version);@@ -1079,8 +1079,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,struct timespec mtime, atime;int wake =0 ;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_mds_session *session;u64 xattr_version =0 ;struct ceph_buffer *xattr_blob =NULL ;@@ -2353,10 +2353,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (grant->mode); - inode->i_uid =le32_to_cpu (grant->uid); - inode->i_gid =le32_to_cpu (grant->gid); +i_uid_write (inode,le32_to_cpu (grant->uid)); +i_gid_write (inode,le32_to_cpu (grant->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )fs/ceph/inode.c +9
-9@@ -612,10 +612,10 @@ static int fill_inode(struct inode *inode,if ((issued &CEPH_CAP_AUTH_EXCL ) ==0 ) { inode->i_mode =le32_to_cpu (info->mode); - inode->i_uid =le32_to_cpu (info->uid); - inode->i_gid =le32_to_cpu (info->gid); +i_uid_write (inode,le32_to_cpu (info->uid)); +i_gid_write (inode,le32_to_cpu (info->gid));dout ("%p mode 0%o uid.gid %d.%d\n" , inode, inode->i_mode, - inode->i_uid, inode->i_gid); +i_uid_read (inode),i_gid_read (inode)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )@@ -1562,26 +1562,26 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)if (ia_valid &ATTR_UID ) {dout ("setattr %p uid %d -> %d\n" , inode, - inode->i_uid, attr->ia_uid); +i_uid_read (inode),from_kuid (&init_user_ns, attr->ia_uid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_uid = attr->ia_uid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_uid != inode->i_uid) { - req->r_args.setattr.uid =cpu_to_le32 (attr->ia_uid); + !uid_eq (attr->ia_uid, inode->i_uid)) { + req->r_args.setattr.uid =cpu_to_le32 (from_kuid (&init_user_ns, attr->ia_uid)); mask |=CEPH_SETATTR_UID ; release |=CEPH_CAP_AUTH_SHARED ; } }if (ia_valid &ATTR_GID ) {dout ("setattr %p gid %d -> %d\n" , inode, - inode->i_gid, attr->ia_gid); +i_gid_read (inode),from_kgid (&init_user_ns, attr->ia_gid));if (issued &CEPH_CAP_AUTH_EXCL ) { inode->i_gid = attr->ia_gid; dirtied |=CEPH_CAP_AUTH_EXCL ; }else if ((issued &CEPH_CAP_AUTH_SHARED ) ==0 || - attr->ia_gid != inode->i_gid) { - req->r_args.setattr.gid =cpu_to_le32 (attr->ia_gid); + !gid_eq (attr->ia_gid, inode->i_gid)) { + req->r_args.setattr.gid =cpu_to_le32 (from_kgid (&init_user_ns, attr->ia_gid)); mask |=CEPH_SETATTR_GID ; release |=CEPH_CAP_AUTH_SHARED ; }fs/ceph/mds_client.c +2
-2@@ -578,8 +578,8 @@ static void __register_request(struct ceph_mds_client *mdsc,ceph_mdsc_get_request (req);__insert_request (mdsc, req); - req->r_uid =current_fsuid (); - req->r_gid =current_fsgid (); + req->r_uid =from_kuid (&init_user_ns,current_fsuid ()); + req->r_gid =from_kgid (&init_user_ns,current_fsgid ());if (dir) {struct ceph_inode_info *ci =ceph_inode (dir);fs/ceph/super.h +2
-2@@ -138,8 +138,8 @@ struct ceph_cap_snap {struct ceph_snap_context *context;umode_t mode; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct ceph_buffer *xattr_blob;u64 xattr_version;init/Kconfig +0
-1@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CEPH_FS = n depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = nSignature · 1 line
1.7.5.4
RFC PATCH 4/12 userns: Convert cifs to use kuid/kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/cifs/cifs_fs_sb.h | 8 ++-- fs/cifs/cifs_spnego.c | 4 +- fs/cifs/cifsacl.c | 115 ++++++++++++++++++++++++++++++++++++------------ fs/cifs/cifsacl.h | 16 ++++++- fs/cifs/cifsfs.c | 12 +++-- fs/cifs/cifsglob.h | 22 +++++----- fs/cifs/cifspdu.h | 2 + fs/cifs/cifsproto.h | 9 ++-- fs/cifs/cifssmb.c | 11 ++++- fs/cifs/connect.c | 58 +++++++++++++++++++------ fs/cifs/dir.c | 18 ++++---- fs/cifs/file.c | 8 ++-- fs/cifs/inode.c | 28 ++++++------ fs/cifs/misc.c | 2 +- init/Kconfig | 1 - 15 files changed, 213 insertions(+), 101 deletions(-)
fs/cifs/cifs_fs_sb.h +4 -4
@@ -55,10 +55,10 @@ struct cifs_sb_info {unsigned int wsize;unsigned long actimeo;/* attribute cache timeout (jiffies) */ atomic_t active; -uid_t mnt_uid; -gid_t mnt_gid; -uid_t mnt_backupuid; -gid_t mnt_backupgid; +kuid_t mnt_uid; +kgid_t mnt_gid; +kuid_t mnt_backupuid; +kgid_t mnt_backupgid;umode_t mnt_file_mode;umode_t mnt_dir_mode;unsigned int mnt_cifs_flags;
fs/cifs/cifs_spnego.c +2 -2
@@ -149,10 +149,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) goto out; dp = description +strlen (description); -sprintf (dp,";uid=0x%x" , sesInfo->linux_uid); +sprintf (dp,";uid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->linux_uid)); dp = description +strlen (description); -sprintf (dp,";creduid=0x%x" , sesInfo->cred_uid); +sprintf (dp,";creduid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->cred_uid));if (sesInfo->user_name) { dp = description +strlen (description);
fs/cifs/cifsacl.c +86 -29
255 lines not on this page · raw message
fs/cifs/cifsacl.h +13 -3
@@ -39,8 +39,10 @@#define ACCESS_ALLOWED 0#define ACCESS_DENIED 1 -#define SIDOWNER 1 -#define SIDGROUP 2 +enum sidtype { +SIDOWNER =1 , +SIDGROUP =2 , +};#define SIDLEN 150/* S- 1 revision- 6 authorities- max 5 sub authorities */ #define SID_ID_MAPPED 0
@@ -83,9 +85,17 @@ struct cifs_wksid {char sidname[SIDNAMELENGTH ]; } __attribute__((packed)); +struct cifs_id { +enum sidtype type; +union { +kuid_t uid; +kgid_t gid; + }; +}; +struct cifs_sid_id {unsigned int refcount;/* increment with spinlock, decrement without */ -unsigned long id; +struct cifs_id id;unsigned long time;unsigned long state;char *sidstr;
fs/cifs/cifsfs.c +8 -4
@@ -377,13 +377,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root) (int)(srcaddr->sa_family)); } -seq_printf (s,",uid=%u" , cifs_sb->mnt_uid); +seq_printf (s,",uid=%u" ,from_kuid_munged (&init_user_ns, cifs_sb->mnt_uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID )seq_printf (s,",forceuid" );else seq_printf (s,",noforceuid" ); -seq_printf (s,",gid=%u" , cifs_sb->mnt_gid); +seq_printf (s,",gid=%u" ,from_kgid_munged (&init_user_ns, cifs_sb->mnt_gid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID )seq_printf (s,",forcegid" );else
@@ -438,9 +438,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_NO_PERM )seq_printf (s,",noperm" );if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) -seq_printf (s,",backupuid=%u" , cifs_sb->mnt_backupuid); +seq_printf (s,",backupuid=%u" , +from_kuid_munged (&init_user_ns, + cifs_sb->mnt_backupuid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) -seq_printf (s,",backupgid=%u" , cifs_sb->mnt_backupgid); +seq_printf (s,",backupgid=%u" , +from_kgid_munged (&init_user_ns, + cifs_sb->mnt_backupgid));seq_printf (s,",rsize=%u" , cifs_sb->rsize);seq_printf (s,",wsize=%u" , cifs_sb->wsize);
fs/cifs/cifsglob.h +11 -11
@@ -400,11 +400,11 @@ struct smb_vol {char *iocharset;/* local code page for mapping to and from Unicode */ char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL ];/* clnt nb name */ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL ];/* srvr nb name */ -uid_t cred_uid; -uid_t linux_uid; -gid_t linux_gid; -uid_t backupuid; -gid_t backupgid; +kuid_t cred_uid; +kuid_t linux_uid; +kgid_t linux_gid; +kuid_t backupuid; +kgid_t backupgid;umode_t file_mode;umode_t dir_mode;unsigned secFlg;
@@ -703,8 +703,8 @@ struct cifs_ses {char *serverNOS;/* name of network operating system of server */ char *serverDomain;/* security realm of server */ __u64 Suid;/* remote smb uid */ -uid_t linux_uid;/* overriding owner of files on the mount */ -uid_t cred_uid;/* owner of credentials */ +kuid_t linux_uid;/* overriding owner of files on the mount */ +kuid_t cred_uid;/* owner of credentials */ unsigned int capabilities;char serverName[SERVER_NAME_LEN_WITH_NULL *2 ];/* BB make bigger for TCP names - will ipv6 and sctp addresses fit? */
@@ -838,7 +838,7 @@ struct cifs_tcon {*/ struct tcon_link {struct rb_node tl_rbnode; -uid_t tl_uid; +kuid_t tl_uid;unsigned long tl_flags;#define TCON_LINK_MASTER 0#define TCON_LINK_PENDING 1
@@ -931,7 +931,7 @@ struct cifsFileInfo {struct list_head tlist;/* pointer to next fid owned by tcon */ struct list_head flist;/* next fid (file instance) for this inode */ struct cifs_fid_locks *llist;/* brlocks held by this fid */ -unsigned int uid;/* allows finding which FileInfo structure */ +kuid_t uid;/* allows finding which FileInfo structure */ __u32 pid;/* process id who opened file */ struct cifs_fid fid;/* file id from remote */ /* BB add lock scope info here if needed */ ;
@@ -1259,8 +1259,8 @@ struct cifs_fattr {u64 cf_eof;u64 cf_bytes;u64 cf_createtime; -uid_t cf_uid; -gid_t cf_gid; +kuid_t cf_uid; +kgid_t cf_gid;umode_t cf_mode;dev_t cf_rdev;unsigned int cf_nlink;
fs/cifs/cifspdu.h +2 -0
@@ -278,6 +278,8 @@#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL#define NO_CHANGE_32 0xFFFFFFFFUL +#define NO_CHANGE_UID INVALID_UID +#define NO_CHANGE_GID INVALID_GID/* IPC$ in ASCII */ #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
fs/cifs/cifsproto.h +5 -4
@@ -46,7 +46,8 @@ extern void _free_xid(unsigned int); ({ \unsigned int __xid =_get_xid (); \cFYI (1 ,"CIFS VFS: in %s as Xid: %u with uid: %d" , \ - __func__, __xid,current_fsuid ()); \ + __func__, __xid, \ +from_kuid (&init_user_ns,current_fsuid ())); \ __xid; \ })
@@ -161,7 +162,7 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid);extern int id_mode_to_cifs_acl (struct inode *inode,const char *path,__u64 , -uid_t ,gid_t ); +kuid_t ,kgid_t );extern struct cifs_ntsd *get_cifs_acl (struct cifs_sb_info *,struct inode *,const char *,u32 *); extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
@@ -304,8 +305,8 @@ struct cifs_unix_set_info_args {__u64 atime;__u64 mtime;__u64 mode; -__u64 uid; -__u64 gid; +kuid_t uid; +kgid_t gid;dev_t device; };
fs/cifs/cifssmb.c +9 -2
@@ -5820,6 +5820,13 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, const struct cifs_unix_set_info_args *args) {u64 mode = args->mode; +__u64 uid; +__u64 gid; + + uid =uid_eq (args->uid,NO_CHANGE_UID ) ?NO_CHANGE_64 : + (__u64 )from_kuid (&init_user_ns, args->uid); + gid =gid_eq (args->gid,NO_CHANGE_GID ) ?NO_CHANGE_64 : + (__u64 )from_kgid (&init_user_ns, args->gid);/* * Samba server ignores set of file size to zero due to bugs in some
@@ -5833,8 +5840,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, data_offset->LastStatusChange =cpu_to_le64 (args->ctime); data_offset->LastAccessTime =cpu_to_le64 (args->atime); data_offset->LastModificationTime =cpu_to_le64 (args->mtime); - data_offset->Uid =cpu_to_le64 (args->uid); - data_offset->Gid =cpu_to_le64 (args->gid); + data_offset->Uid =cpu_to_le64 (uid); + data_offset->Gid =cpu_to_le64 (gid);/* better to leave device as zero when it is */ data_offset->DevMajor =cpu_to_le64 (MAJOR (args->device)); data_offset->DevMinor =cpu_to_le64 (MINOR (args->device));
fs/cifs/connect.c +45 -13
137 lines not on this page · raw message
fs/cifs/dir.c +9 -9
@@ -310,14 +310,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, *created |=FILE_CREATED ;if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); + args.uid =current_fsuid ();if (inode->i_mode &S_ISGID ) - args.gid = (__u64 ) inode->i_gid; + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; }CIFSSMBUnixSetFileInfo (xid, tcon, &args, fid->netfid, current->tgid);
@@ -547,11 +547,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, .device = device_number, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); - args.gid = (__u64 )current_fsgid (); + args.uid =current_fsuid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; } rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, cifs_sb->local_nls,
fs/cifs/file.c +4 -4
@@ -487,8 +487,8 @@ int cifs_open(struct inode *inode, struct file *file)*/ struct cifs_unix_set_info_args args = { .mode = inode->i_mode, - .uid =NO_CHANGE_64 , - .gid =NO_CHANGE_64 , + .uid =NO_CHANGE_UID , + .gid =NO_CHANGE_GID , .ctime =NO_CHANGE_64 , .atime =NO_CHANGE_64 , .mtime =NO_CHANGE_64 ,
@@ -1631,7 +1631,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,are always at the end of the list but since the first entry might have a close pending, we go through the whole list */ list_for_each_entry (open_file, &cifs_inode->openFileList, flist) { -if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_READ ) {if (!open_file->invalidHandle) {
@@ -1684,7 +1684,7 @@ refind_writable:list_for_each_entry (open_file, &cifs_inode->openFileList, flist) {if (!any_available && open_file->pid != current->tgid)continue ; -if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_WRITE ) {if (!open_file->invalidHandle) {
fs/cifs/inode.c +14 -14
@@ -247,12 +247,12 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID ) fattr->cf_uid = cifs_sb->mnt_uid;else - fattr->cf_uid =le64_to_cpu (info->Uid); + fattr->cf_uid =make_kuid (&init_user_ns,le64_to_cpu (info->Uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID ) fattr->cf_gid = cifs_sb->mnt_gid;else - fattr->cf_gid =le64_to_cpu (info->Gid); + fattr->cf_gid =make_kgid (&init_user_ns,le64_to_cpu (info->Gid)); fattr->cf_nlink =le64_to_cpu (info->Nlinks); }
@@ -1245,14 +1245,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, .device = 0, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); -if (parent->i_mode &S_ISGID ) - args.gid = (__u64 )parent->i_gid; + args.uid =current_fsuid (); +if (inode->i_mode &S_ISGID ) + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =INVALID_UID ; + args.gid =INVALID_GID ; } CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, cifs_sb->local_nls,
@@ -2012,12 +2012,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)if (attrs->ia_valid &ATTR_UID ) args->uid = attrs->ia_uid;else - args->uid =NO_CHANGE_64 ; + args->uid =NO_CHANGE_UID ;if (attrs->ia_valid &ATTR_GID ) args->gid = attrs->ia_gid;else - args->gid =NO_CHANGE_64 ; + args->gid =NO_CHANGE_GID ;if (attrs->ia_valid &ATTR_ATIME ) args->atime =cifs_UnixTimeToNT (attrs->ia_atime);
@@ -2085,8 +2085,8 @@ static int cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) { unsigned int xid; -uid_t uid =NO_CHANGE_32 ; -gid_t gid =NO_CHANGE_32 ; +kuid_t uid =NO_CHANGE_UID ; +kgid_t gid =NO_CHANGE_GID ;struct inode *inode = direntry->d_inode;struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode);
@@ -2145,7 +2145,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { -if (uid !=NO_CHANGE_32 || gid !=NO_CHANGE_32 ) { +if (!uid_eq (uid,NO_CHANGE_UID ) || !gid_eq (gid,NO_CHANGE_GID )) { rc =id_mode_to_cifs_acl (inode, full_path,NO_CHANGE_64 , uid, gid);if (rc) {
@@ -2169,7 +2169,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { rc =id_mode_to_cifs_acl (inode, full_path, mode, -NO_CHANGE_32 ,NO_CHANGE_32 ); +NO_CHANGE_UID ,NO_CHANGE_GID );if (rc) {cFYI (1 ,"%s: Setting ACL failed with error: %d" , __func__, rc);
fs/cifs/misc.c +1 -1
@@ -569,7 +569,7 @@ bool backup_cred(struct cifs_sb_info *cifs_sb) {if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) { -if (cifs_sb->mnt_backupuid ==current_fsuid ()) +if (uid_eq (cifs_sb->mnt_backupuid,current_fsuid ()))return true; }if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) {
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n depends on NCP_FS = n
Signature · 1 line
1.7.5.4
A message that is not in the archive (sent off-list or not yet received): 1353415420-5457-4-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate
Do you have a pointer to the background on kuid/kgid
Quoted 973 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Steve French <[email protected]>Acked-by Serge Hallyn <[email protected]>--- fs/cifs/cifs_fs_sb.h | 8 ++-- fs/cifs/cifs_spnego.c | 4 +- fs/cifs/cifsacl.c | 115 ++++++++++++++++++++++++++++++++++++------------ fs/cifs/cifsacl.h | 16 ++++++- fs/cifs/cifsfs.c | 12 +++-- fs/cifs/cifsglob.h | 22 +++++----- fs/cifs/cifspdu.h | 2 + fs/cifs/cifsproto.h | 9 ++-- fs/cifs/cifssmb.c | 11 ++++- fs/cifs/connect.c | 58 +++++++++++++++++++------ fs/cifs/dir.c | 18 ++++---- fs/cifs/file.c | 8 ++-- fs/cifs/inode.c | 28 ++++++------ fs/cifs/misc.c | 2 +- init/Kconfig | 1 - 15 files changed, 213 insertions(+), 101 deletions(-)fs/cifs/cifs_fs_sb.h +4
-4@@ -55,10 +55,10 @@ struct cifs_sb_info {unsigned int wsize;unsigned long actimeo;/* attribute cache timeout (jiffies) */ atomic_t active; -uid_t mnt_uid; -gid_t mnt_gid; -uid_t mnt_backupuid; -gid_t mnt_backupgid; +kuid_t mnt_uid; +kgid_t mnt_gid; +kuid_t mnt_backupuid; +kgid_t mnt_backupgid;umode_t mnt_file_mode;umode_t mnt_dir_mode;unsigned int mnt_cifs_flags;fs/cifs/cifs_spnego.c +2
-2@@ -149,10 +149,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) goto out; dp = description +strlen (description); -sprintf (dp,";uid=0x%x" , sesInfo->linux_uid); +sprintf (dp,";uid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->linux_uid)); dp = description +strlen (description); -sprintf (dp,";creduid=0x%x" , sesInfo->cred_uid); +sprintf (dp,";creduid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->cred_uid));if (sesInfo->user_name) { dp = description + strlen(description);fs/cifs/cifsacl.c +49
-0@@ -44,6 +44,55 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };const struct cred *root_cred; +static inline struct cifs_id kuid_to_cid (kuid_t uid) +{ +struct cifs_id cid; + cid.type =SIDOWNER ; + cid.uid = uid; +return cid; +} + +static inline struct cifs_id kgid_to_cid (kgid_t gid) +{ +struct cifs_id cid; + cid.type =SIDGROUP ; + cid.gid = gid; +return cid; +} + +static unsigned long from_cid (struct user_namespace *user_ns,struct cifs_id cid) +{ +switch (cid.type) { +case SIDOWNER : +return from_kuid (user_ns, cid.uid); +case SIDGROUP : +return from_kgid (user_ns, cid.gid); +default : +BUG (); + } +} + +static bool cid_lt (struct cifs_id left,struct cifs_id right) +{ +if (left.type < right.type) +return true; +if (left.type > right.type) +return false; +switch (left.type) { +case SIDOWNER : +return uid_lt (left.uid, right.uid); +case SIDGROUP : +return gid_lt (left.gid, right.gid); +default : +BUG (); + } +} + +static inline bool cid_gt (struct cifs_id left,struct cifs_id right) +{ +return cid_lt (right, left); +} + static voidshrink_idmap_tree(struct
rb_root*root, intnr_to_scan, int*nr_rem,
int*nr_del)fs/cifs/cifsacl.c +1
-1@@ -105,7 +154,7 @@ cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc) }static void -sid_rb_insert (struct rb_root *root,unsigned long cid, +sid_rb_insert (struct rb_root *root,struct cifs_id cid,struct cifs_sid_id **psidid,char *typestr) {char *strptr;fs/cifs/cifsacl.c +2
-2@@ -117,11 +166,11 @@ sid_rb_insert(struct rb_root *root, unsigned long cid, while (node) { lsidid = rb_entry(node, struct cifs_sid_id, rbnode); parent = node; -if (cid > lsidid->id) { +if (cid_gt (cid, lsidid->id)) { linkto = &(node->rb_left); node = node->rb_left; } -if (cid < lsidid->id) { +if (cid_lt (cid, lsidid->id)) { linkto = &(node->rb_right); node = node->rb_right;}fs/cifs/cifsacl.c +4
-4@@ -133,7 +182,7 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,sprintf ((*psidid)->sidstr,"%s" , typestr); strptr = (*psidid)->sidstr +strlen ((*psidid)->sidstr); -sprintf (strptr,"%ld" , cid); +sprintf (strptr,"%ld" ,from_cid (&init_user_ns, cid));clear_bit (SID_ID_PENDING , &(*psidid)->state);clear_bit (SID_ID_MAPPED , &(*psidid)->state);@@ -143,16 +192,16 @@ sid_rb_insert(struct rb_root *root, unsigned long cid, }static struct cifs_sid_id * -sid_rb_search (struct rb_root *root,unsigned long cid) +sid_rb_search (struct rb_root *root,struct cifs_id cid) {struct rb_node *node = root->rb_node;struct cifs_sid_id *lsidid;while (node) { lsidid = rb_entry(node, struct cifs_sid_id, rbnode); -if (cid > lsidid->id) +if (cid_gt (cid, lsidid->id)) node = node->rb_left; -else if (cid < lsidid->id) +else if (cid_lt (cid, lsidid->id)) node = node->rb_right;else /* node found */ return lsidid;fs/cifs/cifsacl.c +3
-3@@ -292,7 +341,7 @@ sidid_pending_wait(void *unused) }static int -id_to_sid (unsigned long cid,uint sidtype,struct cifs_sid *ssid) +id_to_sid (struct cifs_id cid,struct cifs_sid *ssid) {int rc =0 ;struct key *sidkey;@@ -302,10 +351,10 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)struct rb_root *cidtree;spinlock_t *cidlock; -if (sidtype ==SIDOWNER ) { +if (cid.type ==SIDOWNER ) { cidlock = &siduidlock; cidtree = &uidtree; - }else if (sidtype ==SIDGROUP ) { + }else if (cid.type ==SIDGROUP ) { cidlock = &sidgidlock; cidtree = &gidtree;} elsefs/cifs/cifsacl.c +1
-1@@ -336,7 +385,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) }else { psidid = npsidid;sid_rb_insert (cidtree, cid, &psidid, - sidtype ==SIDOWNER ?"oi:" :"gi:" ); + cid.type ==SIDOWNER ?"oi:" : "gi:");++psidid->refcount; spin_unlock(cidlock); }fs/cifs/cifsacl.c +1
-1@@ -410,7 +459,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, structcifs_sid *psid, struct cifs_fattr *fattr, uint sidtype) { int rc; -unsigned long cid; +struct cifs_id cid;struct key *idkey;const struct cred *saved_cred;struct cifs_sid_id *psidid, *npsidid;fs/cifs/cifsacl.c +0
-1@@ -418,11 +467,11 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, spinlock_t *cidlock;if (sidtype ==SIDOWNER ) { - cid = cifs_sb->mnt_uid;/* default uid, in case upcall fails */
+ cid =kuid_to_cid(cifs_sb->mnt_uid); /* default uid, in
case upcall fails */cidlock = &siduidlock; cidtree = &uidtree; } else if (sidtype == SIDGROUP) {- cid =
cifs_sb->mnt_gid; /* default gid, in case upcall
fails */
+ cid =kgid_to_cid(cifs_sb->mnt_gid); /* default gid, in
case upcall fails */cidlock = &sidgidlock; cidtree = &gidtree; } elsefs/cifs/cifsacl.c +1
-1@@ -471,7 +520,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, structcifs_sid *psid, * any fields of the node after a reference is put . */ if (test_bit (SID_ID_MAPPED , &psidid->state)) { - cid = psidid->id; +//cid = psidid->id; psidid->time = jiffies;/* update ts for accessing */ goto sid_to_id_out;}fs/cifs/cifsacl.c +7
-2@@ -485,8 +534,13 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, if (IS_ERR(idkey)) cFYI(1, "%s: Can't map SID to an id", __func__); else { - cid = *(unsigned long *)idkey->payload.value; - psidid->id = cid; + u32 id; + id = *(u32 *)idkey->payload.value; + psidid->id.type = sidtype; + if (sidtype == SIDOWNER) + psidid->id.uid = make_kuid(&init_user_ns, id); + else + psidid->id.gid = make_kgid(&init_user_ns, id);set_bit(SID_ID_MAPPED, &psidid->state); key_put(idkey); kfree(psidid->sidstr);fs/cifs/cifsacl.c +3
-3@@ -510,10 +564,10 @@ sid_to_id(struct cifs_sb_info *cifs_sb, structcifs_sid *psid, sid_to_id_out: --psidid->refcount; /* decremented without spinlock */ -if (sidtype ==SIDOWNER ) - fattr->cf_uid = cid; +if (cid.type ==SIDOWNER ) + fattr->cf_uid = cid.uid;else - fattr->cf_gid = cid; + fattr->cf_gid = cid.gid;return 0 ;}
fs/cifs/cifsacl.c +3
-2@@ -537,7 +591,8 @@ init_cifs_idmap(void)if (!cred)return -ENOMEM ; - keyring =key_alloc (&key_type_keyring,".cifs_idmap" ,0 ,0 , cred, + keyring =key_alloc (&key_type_keyring,".cifs_idmap" , +GLOBAL_ROOT_UID ,GLOBAL_ROOT_GID , cred, (KEY_POS_ALL & ~KEY_POS_SETATTR ) |KEY_USR_VIEW |KEY_USR_READ ,KEY_ALLOC_NOT_IN_QUOTA );@@ -1074,7 +1129,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,/* Convert permission bits from mode to equivalent CIFS ACL */ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, - __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag) +__u32 secdesclen,__u64 nmode,kuid_t uid,kgid_t gid,int *aclflag){ int rc = 0; __u32 dacloffset;fs/cifs/cifsacl.c +5
-3@@ -1106,17 +1161,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd,struct cifs_ntsd *pnntsd, *aclflag =CIFS_ACL_DACL ; }else {memcpy (pnntsd, pntsd, secdesclen); -if (uid !=NO_CHANGE_32 ) {/* chown */ +if (!uid_eq (uid,NO_CHANGE_UID )) {/* chown */ owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +le32_to_cpu (pnntsd->osidoffset)); nowner_sid_ptr =kmalloc (sizeof (struct cifs_sid ),GFP_KERNEL );if (!nowner_sid_ptr)return -ENOMEM ; - rc =id_to_sid (uid,SIDOWNER , nowner_sid_ptr); + rc =id_to_sid (kuid_to_cid (uid), nowner_sid_ptr);if (rc) { cFYI(1, "%s: Mapping error %d for owner id %d", - __func__, rc, uid); + __func__, rc, + from_kuid(&init_user_ns,uid)); kfree(nowner_sid_ptr); return rc; }fs/cifs/cifsacl.c +5
-3@@ -1125,17 +1181,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd,struct cifs_ntsd *pnntsd,kfree (nowner_sid_ptr ); *aclflag =CIFS_ACL_OWNER ; } -if (gid !=NO_CHANGE_32 ) {/* chgrp */ +if (!gid_eq (gid,NO_CHANGE_GID )) {/* chgrp */ group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +le32_to_cpu (pnntsd->gsidoffset)); ngroup_sid_ptr =kmalloc (sizeof (struct cifs_sid ),GFP_KERNEL );if (!ngroup_sid_ptr)return -ENOMEM ; - rc =id_to_sid (gid,SIDGROUP , ngroup_sid_ptr); + rc =id_to_sid (kgid_to_cid (gid), ngroup_sid_ptr);if (rc) { cFYI(1, "%s: Mapping error %d for group id %d", - __func__, rc, gid); + __func__, rc, + from_kgid(&init_user_ns,gid)); kfree(ngroup_sid_ptr); return rc; }fs/cifs/cifsacl.c +1
-1@@ -1304,7 +1361,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,struct cifs_fattr *fattr,/* Convert mode bits to an ACL so we can update the ACL on the server */ int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, - uid_t uid, gid_t gid) + kuid_t uid, kgid_t gid) { int rc = 0;int aclflag =
CIFS_ACL_DACL; /* default flag to set */fs/cifs/cifsacl.h +4
-2@@ -39,8 +39,10 @@#define ACCESS_ALLOWED 0#define ACCESS_DENIED 1 -#define SIDOWNER 1 -#define SIDGROUP 2 +enum sidtype { +SIDOWNER =1 , +SIDGROUP =2 , +};#define SIDLEN 150/* S- 1 revision- 6 authorities- max 5 sub authorities */ #define
SID_ID_MAPPED0fs/cifs/cifsacl.h +8
-0@@ -83,9 +85,17 @@ struct cifs_wksid {char sidname[SIDNAMELENGTH ]; } __attribute__((packed)); +struct cifs_id { +enum sidtype type; +union { +kuid_t uid; +kgid_t gid; + }; +}; +struct cifs_sid_id {unsigned int refcount;/* increment with spinlock, decrement without */
fs/cifs/cifsacl.h +1
-1-unsigned long id; +struct cifs_id id;unsigned long time;unsigned long state;char *sidstr;fs/cifs/cifsfs.c +2
-2@@ -377,13 +377,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root) (int)(srcaddr->sa_family)); } -seq_printf (s,",uid=%u" , cifs_sb->mnt_uid); +seq_printf (s,",uid=%u" ,from_kuid_munged (&init_user_ns, cifs_sb->mnt_uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID )seq_printf (s,",forceuid" );else seq_printf (s,",noforceuid" ); -seq_printf (s,",gid=%u" , cifs_sb->mnt_gid); +seq_printf (s,",gid=%u" ,from_kgid_munged (&init_user_ns, cifs_sb->mnt_gid));if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) seq_printf(s, ",forcegid"); elsefs/cifs/cifsfs.c +6
-2@@ -438,9 +438,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_NO_PERM )seq_printf (s,",noperm" );if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) -seq_printf (s,",backupuid=%u" , cifs_sb->mnt_backupuid); +seq_printf (s,",backupuid=%u" , +from_kuid_munged (&init_user_ns, + cifs_sb->mnt_backupuid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) -seq_printf (s,",backupgid=%u" , cifs_sb->mnt_backupgid); +seq_printf (s,",backupgid=%u" , +from_kgid_munged (&init_user_ns, + cifs_sb->mnt_backupgid));seq_printf (s,",rsize=%u" , cifs_sb->rsize);seq_printf(s, ",wsize=%u", cifs_sb->wsize);fs/cifs/cifsglob.h +0
-0@@ -400,11 +400,11 @@ struct smb_vol {char *iocharset;/* local code page for mapping to and from Unicode */
char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nbname */
fs/cifs/cifsglob.h +5
-5-uid_t cred_uid; -uid_t linux_uid; -gid_t linux_gid; -uid_t backupuid; -gid_t backupgid; +kuid_t cred_uid; +kuid_t linux_uid; +kgid_t linux_gid; +kuid_t backupuid; +kgid_t backupgid;umode_t file_mode;umode_t dir_mode;unsigned secFlg;@@ -703,8 +703,8 @@ struct cifs_ses {char *serverNOS;/* name of network operating system of server */
char *serverDomain; /* security realm of server */ __u64 Suid; /* remote smb uid */ - uid_t linux_uid; /* overriding owner of files on the mount*/
fs/cifs/cifsglob.h +1
-1-uid_t cred_uid;/* owner of credentials */ +kuid_t linux_uid;/* overriding owner of files on the mount */
+kuid_tcred_uid; /* owner of credentials */
unsigned int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger
for
TCP names - will ipv6 and sctp addresses
fit? */fs/cifs/cifsglob.h +2
-2@@ -838,7 +838,7 @@ struct cifs_tcon {*/ struct tcon_link {struct rb_node tl_rbnode; -uid_t tl_uid; +kuid_t tl_uid;unsigned long tl_flags;#define TCON_LINK_MASTER 0#define TCON_LINK_PENDING 1@@ -931,7 +931,7 @@ struct cifsFileInfo {struct list_head tlist; /* pointer to next fid owned by tcon */ struct list_head flist;/* next fid (file instance) for this inode */ struct cifs_fid_locks *llist;/* brlocks held by this fid */ -unsigned int uid;/* allows finding which FileInfo structure */ + kuid_t uid; /* allows finding which FileInfo structure*/
__u32pid; /* process id who opened file */
structcifs_fidfid; /* file id from remote */
/* BB add lock scope info here if needed */ ;fs/cifs/cifsglob.h +2
-2@@ -1259,8 +1259,8 @@ struct cifs_fattr {u64 cf_eof;u64 cf_bytes;u64 cf_createtime; -uid_t cf_uid; -gid_t cf_gid; +kuid_t cf_uid; +kgid_t cf_gid;umode_t cf_mode;dev_t cf_rdev;unsigned int cf_nlink;fs/cifs/cifspdu.h +2
-0@@ -278,6 +278,8 @@#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL#define NO_CHANGE_32 0xFFFFFFFFUL +#define NO_CHANGE_UID INVALID_UID +#define NO_CHANGE_GID INVALID_GID/* IPC$ in ASCII */ #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"fs/cifs/cifsproto.h +3
-2@@ -46,7 +46,8 @@ extern void _free_xid(unsigned int); ({ \unsigned int __xid =_get_xid (); \cFYI (1 ,"CIFS VFS: in %s as Xid: %u with uid: %d" , \ - __func__, __xid,current_fsuid ()); \ + __func__, __xid, \ +from_kuid (&init_user_ns,current_fsuid ())); \ __xid; \ })@@ -161,7 +162,7 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid);extern int id_mode_to_cifs_acl (struct inode *inode,const char *path,__u64 , -uid_t ,gid_t ); +kuid_t ,kgid_t );extern struct
cifs_ntsd*get_cifs_acl(structcifs_sb_info*, struct inode
*,const char *, u32 *);extern int set_cifs_acl(struct
cifs_ntsd*,__u32, struct inode *,fs/cifs/cifsproto.h +2
-2@@ -304,8 +305,8 @@ struct cifs_unix_set_info_args {__u64 atime;__u64 mtime;__u64 mode; -__u64 uid; -__u64 gid; +kuid_t uid; +kgid_t gid;dev_t device; };fs/cifs/cifssmb.c +7
-0@@ -5820,6 +5820,13 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, const struct cifs_unix_set_info_args *args) {u64 mode = args->mode; +__u64 uid; +__u64 gid; + + uid =uid_eq (args->uid,NO_CHANGE_UID ) ?NO_CHANGE_64 : + (__u64 )from_kuid (&init_user_ns, args->uid); + gid =gid_eq (args->gid,NO_CHANGE_GID ) ?NO_CHANGE_64 : + (__u64 )from_kgid (&init_user_ns, args->gid);/* * Samba server ignores set of file size to zero due to bugs in
somefs/cifs/cifssmb.c +2
-2@@ -5833,8 +5840,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, data_offset->LastStatusChange =cpu_to_le64 (args->ctime); data_offset->LastAccessTime =cpu_to_le64 (args->atime); data_offset->LastModificationTime =cpu_to_le64 (args->mtime); - data_offset->Uid =cpu_to_le64 (args->uid); - data_offset->Gid =cpu_to_le64 (args->gid); + data_offset->Uid =cpu_to_le64 (uid); + data_offset->Gid =cpu_to_le64 (gid);/* better to leave device as zero when it is */ data_offset->DevMajor =cpu_to_le64 (MAJOR (args->device));data_offset->DevMinor = cpu_to_le64(MINOR(args->device));fs/cifs/connect.c +2
-0@@ -1108,6 +1108,8 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, char *string = NULL;char *tmp_end, *value;char delim; +kuid_t uid; +kgid_t gid; separator[0 ] =',' ;separator[1] = 0;fs/cifs/connect.c +7
-1@@ -1361,7 +1363,13 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, __func__); goto cifs_parse_mount_err; } - vol->backupuid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid backupuid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->backupuid = uid; vol->backupuid_specified = true;break ;case
Opt_backupgid:fs/cifs/connect.c +7
-1@@ -1370,7 +1378,13 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, __func__); goto cifs_parse_mount_err; } - vol->backupgid = option; + gid =make_kgid (current_user_ns (), option); +if (!gid_valid (gid)) { +cERROR (1 ,"%s: Invalid backupgid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->backupgid = gid; vol->backupgid_specified = true;break ;case
Opt_uid:fs/cifs/connect.c +7
-1@@ -1379,7 +1393,13 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, __func__); goto cifs_parse_mount_err; } - vol->linux_uid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid uid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->linux_uid = uid; uid_specified = true;break ;case
Opt_cruid:fs/cifs/connect.c +7
-1@@ -1388,7 +1408,13 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, __func__); goto cifs_parse_mount_err; } - vol->cred_uid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid cruid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->cred_uid = uid;break ;case Opt_gid:if (get_option_ul(args, &option)) {fs/cifs/connect.c +7
-1@@ -1396,7 +1422,13 @@ cifs_parse_mount_options(const char *mountdata,const char *devname, __func__); goto cifs_parse_mount_err; } - vol->linux_gid = option; + gid =make_kgid (current_user_ns (), option); +if (!gid_valid (gid)) { +cERROR (1 ,"%s: Invalid gid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->linux_gid = gid; gid_specified = true;break ;case
Opt_file_mode:fs/cifs/connect.c +1
-1@@ -2203,7 +2235,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) {switch (ses->server->secType) {case Kerberos: -if (vol->cred_uid != ses->cred_uid) +if (!uid_eq (vol->cred_uid, ses->cred_uid))return 0 ;break ;default:
fs/cifs/connect.c +1
-1@@ -2692,7 +2724,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)if (new->rsize && new->rsize < old->rsize)return 0 ; -if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) +if (!uid_eq (old->mnt_uid, new->mnt_uid) || !gid_eq (old->mnt_gid, new->mnt_gid))return 0 ;if (old->mnt_file_mode != new->mnt_file_mode ||fs/cifs/connect.c +1
-1@@ -3910,7 +3942,7 @@ cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) }static struct cifs_tcon * -cifs_construct_tcon (struct cifs_sb_info *cifs_sb,uid_t fsuid) +cifs_construct_tcon (struct cifs_sb_info *cifs_sb,kuid_t fsuid) {int rc;struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);fs/cifs/connect.c +4
-4@@ -3980,7 +4012,7 @@ cifs_sb_tcon_pending_wait(void *unused)/* find and return a tlink with given uid */ static struct tcon_link * -tlink_rb_search (struct rb_root *root,uid_t uid) +tlink_rb_search (struct rb_root *root,kuid_t uid) {struct rb_node *node = root->rb_node;struct tcon_link *tlink;@@ -3988,9 +4020,9 @@ tlink_rb_search(struct rb_root *root, uid_t uid)while (node) { tlink = rb_entry(node, struct tcon_link, tl_rbnode); -if (tlink->tl_uid > uid) +if (uid_gt (tlink->tl_uid, uid)) node = node->rb_left; -else if (tlink->tl_uid < uid) +else if (uid_lt (tlink->tl_uid, uid)) node = node->rb_right;else return tlink;@@ -4009,7 +4041,7 @@ tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink) tlink = rb_entry(*new, struct tcon_link, tl_rbnode); parent = *new; -if (tlink->tl_uid > new_tlink->tl_uid) +if (uid_gt (tlink->tl_uid, new_tlink->tl_uid)) new = &((*new)->rb_left);else new = &((*new)->rb_right);fs/cifs/connect.c +1
-1@@ -4039,7 +4071,7 @@ struct tcon_link * cifs_sb_tlink(struct cifs_sb_info *cifs_sb) {int ret; -uid_t fsuid =current_fsuid (); +kuid_t fsuid =current_fsuid ();struct tcon_link *tlink, *newtlink;if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_MULTIUSER ))fs/cifs/dir.c +5
-5@@ -310,14 +310,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, *created |=FILE_CREATED ;if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); + args.uid =current_fsuid ();if (inode->i_mode &S_ISGID ) - args.gid = (__u64 ) inode->i_gid; + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; } CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,current->tgid);fs/cifs/dir.c +4
-4@@ -547,11 +547,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, .device = device_number, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); - args.gid = (__u64 )current_fsgid (); + args.uid =current_fsuid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; } rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,cifs_sb->local_nls,fs/cifs/file.c +2
-2@@ -487,8 +487,8 @@ int cifs_open(struct inode *inode, struct file *file)*/ struct cifs_unix_set_info_args args = { .mode = inode->i_mode, - .uid =NO_CHANGE_64 , - .gid =NO_CHANGE_64 , + .uid =NO_CHANGE_UID , + .gid =NO_CHANGE_GID , .ctime =NO_CHANGE_64 , .atime =NO_CHANGE_64 , .mtime =NO_CHANGE_64 ,@@ -1631,7 +1631,7 @@ struct cifsFileInfo *find_readable_file(structcifsInodeInfo *cifs_inode, are always at the end of the list but since the first entrymight
have a close pending, we go through the whole list */
list_for_each_entry(open_file, &cifs_inode->openFileList, flist){fs/cifs/file.c +2
-2-if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_READ ) {if (!open_file->invalidHandle) {@@ -1684,7 +1684,7 @@ refind_writable:list_for_each_entry (open_file, &cifs_inode->openFileList, flist) {if (!any_available && open_file->pid != current->tgid)continue ; -if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_WRITE ) {if (!open_file->invalidHandle) {fs/cifs/inode.c +2
-2@@ -247,12 +247,12 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,FILE_UNIX_BASIC_INFO *info, if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) fattr->cf_uid = cifs_sb->mnt_uid; else - fattr->cf_uid = le64_to_cpu(info->Uid); + fattr->cf_uid = make_kuid(&init_user_ns,le64_to_cpu (info->Uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID ) fattr->cf_gid = cifs_sb->mnt_gid;else - fattr->cf_gid =le64_to_cpu (info->Gid); + fattr->cf_gid =make_kgid (&init_user_ns,le64_to_cpu (info->Gid));fattr->cf_nlink = le64_to_cpu(info->Nlinks);}
fs/cifs/inode.c +6
-6@@ -1245,14 +1245,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, .device = 0, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); -if (parent->i_mode &S_ISGID ) - args.gid = (__u64 )parent->i_gid; + args.uid =current_fsuid (); +if (inode->i_mode &S_ISGID ) + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =INVALID_UID ; + args.gid =INVALID_GID ; } CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,cifs_sb->local_nls,fs/cifs/inode.c +2
-2@@ -2012,12 +2012,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)if (attrs->ia_valid &ATTR_UID ) args->uid = attrs->ia_uid;else - args->uid =NO_CHANGE_64 ; + args->uid =NO_CHANGE_UID ;if (attrs->ia_valid &ATTR_GID ) args->gid = attrs->ia_gid;else - args->gid =NO_CHANGE_64 ; + args->gid =NO_CHANGE_GID ;if (attrs->ia_valid &ATTR_ATIME )args->atime = cifs_UnixTimeToNT(attrs->ia_atime);fs/cifs/inode.c +3
-3@@ -2085,8 +2085,8 @@ static int cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) { unsigned int xid; -uid_t uid =NO_CHANGE_32 ; -gid_t gid =NO_CHANGE_32 ; +kuid_t uid =NO_CHANGE_UID ; +kgid_t gid =NO_CHANGE_GID ;struct inode *inode = direntry->d_inode;struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode);@@ -2145,7 +2145,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { - if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) { +if (!uid_eq (uid,NO_CHANGE_UID ) || !gid_eq (gid,NO_CHANGE_GID )) { rc = id_mode_to_cifs_acl(inode, full_path,
NO_CHANGE_64,uid, gid); if (rc) {fs/cifs/inode.c +1
-1@@ -2169,7 +2169,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { rc =id_mode_to_cifs_acl (inode, full_path, mode, -NO_CHANGE_32 ,NO_CHANGE_32 ); +NO_CHANGE_UID , NO_CHANGE_GID);if (rc) {
cFYI(1, "%s: Setting ACL failed with
error: %d",__func__, rc);fs/cifs/misc.c +1
-1@@ -569,7 +569,7 @@ bool backup_cred(struct cifs_sb_info *cifs_sb) {if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) { -if (cifs_sb->mnt_backupuid ==current_fsuid ()) +if (uid_eq (cifs_sb->mnt_backupuid,current_fsuid ()))return true; }if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) {init/Kconfig +0
-2@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n depends on NCP_FS = n --1.7.5.4
Signature · 3 lines
Thanks, Steve
A message that is not in the archive (sent off-list or not yet received): CAH2r5mt91Av7w6GQUPNu2A9EGRNbPGGAhMO=EobOMi5Cn8gh5g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate
Quoted 1 line · Steve French
Do you have a pointer to the background on kuid/kgid
You might try this lwn article
https://lwn.net/Articles/491310/
In a nutshell each user namespace has it's own view of uid_t and gid_t values. Those values are mapped into kernel internal kuid_t and kgid_t values. Then user space interfaces convert from kuid_t and kgid_t when read from userspace.
The initial user namespace as a 1-1 identity mapping between kuid_t and uid_t values.
kuid_t and kgid_t are not assignment compatible with uid_t and gid_t so that if the conversions are left out a compile error results.
My strategy is to push kuid_t and kgid_t values as deeply into the kernel data structures as possible so that there is a high propbability that when we get it wrong a compile error will happen.
Eric
Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate
In reply to Steve FrenchQuoted 1 line · Steve French
Do you have a pointer to the background on kuid/kgid
You might try this lwn article
https://lwn.net/Articles/491310/
In a nutshell each user namespace has it's own view of uid_t and gid_t values. Those values are mapped into kernel internal kuid_t and kgid_t values. Then user space interfaces convert from kuid_t and kgid_t when read from userspace.
The initial user namespace as a 1-1 identity mapping between kuid_t and uid_t values.
kuid_t and kgid_t are not assignment compatible with uid_t and gid_t so that if the conversions are left out a compile error results.
My strategy is to push kuid_t and kgid_t values as deeply into the kernel data structures as possible so that there is a high propbability that when we get it wrong a compile error will happen.
Eric
Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate
In reply to Eric W. BiedermanQuoted 874 lines · On Tue, 20 Nov 2012 04:43:32 -0800 "Eric W. Biederman"…
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Steve French <[email protected]>Acked-by Serge Hallyn <[email protected]>--- fs/cifs/cifs_fs_sb.h | 8 ++-- fs/cifs/cifs_spnego.c | 4 +- fs/cifs/cifsacl.c | 115 ++++++++++++++++++++++++++++++++++++------------ fs/cifs/cifsacl.h | 16 ++++++- fs/cifs/cifsfs.c | 12 +++-- fs/cifs/cifsglob.h | 22 +++++----- fs/cifs/cifspdu.h | 2 + fs/cifs/cifsproto.h | 9 ++-- fs/cifs/cifssmb.c | 11 ++++- fs/cifs/connect.c | 58 +++++++++++++++++++------ fs/cifs/dir.c | 18 ++++---- fs/cifs/file.c | 8 ++-- fs/cifs/inode.c | 28 ++++++------ fs/cifs/misc.c | 2 +- init/Kconfig | 1 - 15 files changed, 213 insertions(+), 101 deletions(-)fs/cifs/cifs_fs_sb.h +4
-4@@ -55,10 +55,10 @@ struct cifs_sb_info {unsigned int wsize;unsigned long actimeo;/* attribute cache timeout (jiffies) */ atomic_t active; -uid_t mnt_uid; -gid_t mnt_gid; -uid_t mnt_backupuid; -gid_t mnt_backupgid; +kuid_t mnt_uid; +kgid_t mnt_gid; +kuid_t mnt_backupuid; +kgid_t mnt_backupgid;umode_t mnt_file_mode;umode_t mnt_dir_mode;unsigned int mnt_cifs_flags;fs/cifs/cifs_spnego.c +2
-2@@ -149,10 +149,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) goto out; dp = description +strlen (description); -sprintf (dp,";uid=0x%x" , sesInfo->linux_uid); +sprintf (dp,";uid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->linux_uid)); dp = description +strlen (description); -sprintf (dp,";creduid=0x%x" , sesInfo->cred_uid); +sprintf (dp,";creduid=0x%x" ,from_kuid_munged (&init_user_ns, sesInfo->cred_uid));if (sesInfo->user_name) { dp = description +strlen (description);fs/cifs/cifsacl.c +86
-29@@ -44,6 +44,55 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };const struct cred *root_cred; +static inline struct cifs_id kuid_to_cid (kuid_t uid) +{ +struct cifs_id cid; + cid.type =SIDOWNER ; + cid.uid = uid; +return cid; +} + +static inline struct cifs_id kgid_to_cid (kgid_t gid) +{ +struct cifs_id cid; + cid.type =SIDGROUP ; + cid.gid = gid; +return cid; +} + +static unsigned long from_cid (struct user_namespace *user_ns,struct cifs_id cid) +{ +switch (cid.type) { +case SIDOWNER : +return from_kuid (user_ns, cid.uid); +case SIDGROUP : +return from_kgid (user_ns, cid.gid); +default : +BUG (); + } +} + +static bool cid_lt (struct cifs_id left,struct cifs_id right) +{ +if (left.type < right.type) +return true; +if (left.type > right.type) +return false; +switch (left.type) { +case SIDOWNER : +return uid_lt (left.uid, right.uid); +case SIDGROUP : +return gid_lt (left.gid, right.gid); +default : +BUG (); + } +} + +static inline bool cid_gt (struct cifs_id left,struct cifs_id right) +{ +return cid_lt (right, left); +} +static void shrink_idmap_tree (struct rb_root *root,int nr_to_scan,int *nr_rem,int *nr_del)@@ -105,7 +154,7 @@ cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc) }static void -sid_rb_insert (struct rb_root *root,unsigned long cid, +sid_rb_insert (struct rb_root *root,struct cifs_id cid,struct cifs_sid_id **psidid,char *typestr) {char *strptr;@@ -117,11 +166,11 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,while (node) { lsidid = rb_entry(node, struct cifs_sid_id, rbnode); parent = node; -if (cid > lsidid->id) { +if (cid_gt (cid, lsidid->id)) { linkto = &(node->rb_left); node = node->rb_left; } -if (cid < lsidid->id) { +if (cid_lt (cid, lsidid->id)) { linkto = &(node->rb_right); node = node->rb_right; }@@ -133,7 +182,7 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,sprintf ((*psidid)->sidstr,"%s" , typestr); strptr = (*psidid)->sidstr +strlen ((*psidid)->sidstr); -sprintf (strptr,"%ld" , cid); +sprintf (strptr,"%ld" ,from_cid (&init_user_ns, cid));clear_bit (SID_ID_PENDING , &(*psidid)->state);clear_bit (SID_ID_MAPPED , &(*psidid)->state);@@ -143,16 +192,16 @@ sid_rb_insert(struct rb_root *root, unsigned long cid, }static struct cifs_sid_id * -sid_rb_search (struct rb_root *root,unsigned long cid) +sid_rb_search (struct rb_root *root,struct cifs_id cid) {struct rb_node *node = root->rb_node;struct cifs_sid_id *lsidid;while (node) { lsidid = rb_entry(node, struct cifs_sid_id, rbnode); -if (cid > lsidid->id) +if (cid_gt (cid, lsidid->id)) node = node->rb_left; -else if (cid < lsidid->id) +else if (cid_lt (cid, lsidid->id)) node = node->rb_right;else /* node found */ return lsidid;@@ -292,7 +341,7 @@ sidid_pending_wait(void *unused) }static int -id_to_sid (unsigned long cid,uint sidtype,struct cifs_sid *ssid) +id_to_sid (struct cifs_id cid,struct cifs_sid *ssid) {int rc =0 ;struct key *sidkey;@@ -302,10 +351,10 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)struct rb_root *cidtree;spinlock_t *cidlock; -if (sidtype ==SIDOWNER ) { +if (cid.type ==SIDOWNER ) { cidlock = &siduidlock; cidtree = &uidtree; - }else if (sidtype ==SIDGROUP ) { + }else if (cid.type ==SIDGROUP ) { cidlock = &sidgidlock; cidtree = &gidtree; }else @@ -336,7 +385,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) }else { psidid = npsidid;sid_rb_insert (cidtree, cid, &psidid, - sidtype ==SIDOWNER ?"oi:" :"gi:" ); + cid.type ==SIDOWNER ?"oi:" :"gi:" ); ++psidid->refcount;spin_unlock (cidlock); }@@ -410,7 +459,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, struct cifs_fattr *fattr, uint sidtype) { int rc; -unsigned long cid; +struct cifs_id cid;struct key *idkey;const struct cred *saved_cred;struct cifs_sid_id *psidid, *npsidid;@@ -418,11 +467,11 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,spinlock_t *cidlock;if (sidtype ==SIDOWNER ) { - cid = cifs_sb->mnt_uid;/* default uid, in case upcall fails */ + cid =kuid_to_cid (cifs_sb->mnt_uid);/* default uid, in case upcall fails */ cidlock = &siduidlock; cidtree = &uidtree; }else if (sidtype ==SIDGROUP ) { - cid = cifs_sb->mnt_gid;/* default gid, in case upcall fails */ + cid =kgid_to_cid (cifs_sb->mnt_gid);/* default gid, in case upcall fails */ cidlock = &sidgidlock; cidtree = &gidtree; }else @@ -471,7 +520,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,* any fields of the node after a reference is put . */ if (test_bit (SID_ID_MAPPED , &psidid->state)) { - cid = psidid->id; +//cid = psidid->id; psidid->time = jiffies;/* update ts for accessing */ goto sid_to_id_out; }@@ -485,8 +534,13 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,if (IS_ERR (idkey))cFYI (1 ,"%s: Can't map SID to an id" , __func__);else { - cid = *(unsigned long *)idkey->payload.value; - psidid->id = cid; +u32 id; + id = *(u32 *)idkey->payload.value; + psidid->id.type = sidtype; +if (sidtype ==SIDOWNER ) + psidid->id.uid =make_kuid (&init_user_ns, id); +else + psidid->id.gid =make_kgid (&init_user_ns, id);set_bit (SID_ID_MAPPED , &psidid->state);key_put (idkey);kfree (psidid->sidstr);@@ -510,10 +564,10 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, sid_to_id_out: --psidid->refcount;/* decremented without spinlock */ -if (sidtype ==SIDOWNER ) - fattr->cf_uid = cid; +if (cid.type ==SIDOWNER ) + fattr->cf_uid = cid.uid;else - fattr->cf_gid = cid; + fattr->cf_gid = cid.gid;return 0 ; }@@ -537,7 +591,8 @@ init_cifs_idmap(void)if (!cred)return -ENOMEM ; - keyring =key_alloc (&key_type_keyring,".cifs_idmap" ,0 ,0 , cred, + keyring =key_alloc (&key_type_keyring,".cifs_idmap" , +GLOBAL_ROOT_UID ,GLOBAL_ROOT_GID , cred, (KEY_POS_ALL & ~KEY_POS_SETATTR ) |KEY_USR_VIEW |KEY_USR_READ ,KEY_ALLOC_NOT_IN_QUOTA );@@ -1074,7 +1129,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,/* Convert permission bits from mode to equivalent CIFS ACL */ static int build_sec_desc (struct cifs_ntsd *pntsd,struct cifs_ntsd *pnntsd, -__u32 secdesclen,__u64 nmode,uid_t uid,gid_t gid,int *aclflag) +__u32 secdesclen,__u64 nmode,kuid_t uid,kgid_t gid,int *aclflag) {int rc =0 ;__u32 dacloffset;@@ -1106,17 +1161,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, *aclflag =CIFS_ACL_DACL ; }else {memcpy (pnntsd, pntsd, secdesclen); -if (uid !=NO_CHANGE_32 ) {/* chown */ +if (!uid_eq (uid,NO_CHANGE_UID )) {/* chown */ owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +le32_to_cpu (pnntsd->osidoffset)); nowner_sid_ptr =kmalloc (sizeof (struct cifs_sid ),GFP_KERNEL );if (!nowner_sid_ptr)return -ENOMEM ; - rc =id_to_sid (uid,SIDOWNER , nowner_sid_ptr); + rc =id_to_sid (kuid_to_cid (uid), nowner_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for owner id %d" , - __func__, rc, uid); + __func__, rc, +from_kuid (&init_user_ns, uid));kfree (nowner_sid_ptr);return rc; }@@ -1125,17 +1181,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,kfree (nowner_sid_ptr); *aclflag =CIFS_ACL_OWNER ; } -if (gid !=NO_CHANGE_32 ) {/* chgrp */ +if (!gid_eq (gid,NO_CHANGE_GID )) {/* chgrp */ group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +le32_to_cpu (pnntsd->gsidoffset)); ngroup_sid_ptr =kmalloc (sizeof (struct cifs_sid ),GFP_KERNEL );if (!ngroup_sid_ptr)return -ENOMEM ; - rc =id_to_sid (gid,SIDGROUP , ngroup_sid_ptr); + rc =id_to_sid (kgid_to_cid (gid), ngroup_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for group id %d" , - __func__, rc, gid); + __func__, rc, +from_kgid (&init_user_ns, gid));kfree (ngroup_sid_ptr);return rc; }@@ -1304,7 +1361,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,/* Convert mode bits to an ACL so we can update the ACL on the server */ int id_mode_to_cifs_acl (struct inode *inode,const char *path,__u64 nmode, -uid_t uid,gid_t gid) +kuid_t uid,kgid_t gid) {int rc =0 ;int aclflag =CIFS_ACL_DACL ;/* default flag to set */ fs/cifs/cifsacl.h +13
-3@@ -39,8 +39,10 @@#define ACCESS_ALLOWED 0#define ACCESS_DENIED 1 -#define SIDOWNER 1 -#define SIDGROUP 2 +enum sidtype { +SIDOWNER =1 , +SIDGROUP =2 , +};#define SIDLEN 150/* S- 1 revision- 6 authorities- max 5 sub authorities */ #define SID_ID_MAPPED 0@@ -83,9 +85,17 @@ struct cifs_wksid {char sidname[SIDNAMELENGTH ]; } __attribute__((packed)); +struct cifs_id { +enum sidtype type; +union { +kuid_t uid; +kgid_t gid; + }; +}; +struct cifs_sid_id {unsigned int refcount;/* increment with spinlock, decrement without */ -unsigned long id; +struct cifs_id id;unsigned long time;unsigned long state;char *sidstr;fs/cifs/cifsfs.c +8
-4@@ -377,13 +377,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root) (int)(srcaddr->sa_family)); } -seq_printf (s,",uid=%u" , cifs_sb->mnt_uid); +seq_printf (s,",uid=%u" ,from_kuid_munged (&init_user_ns, cifs_sb->mnt_uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID )seq_printf (s,",forceuid" );else seq_printf (s,",noforceuid" ); -seq_printf (s,",gid=%u" , cifs_sb->mnt_gid); +seq_printf (s,",gid=%u" ,from_kgid_munged (&init_user_ns, cifs_sb->mnt_gid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID )seq_printf (s,",forcegid" );else @@ -438,9 +438,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_NO_PERM )seq_printf (s,",noperm" );if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) -seq_printf (s,",backupuid=%u" , cifs_sb->mnt_backupuid); +seq_printf (s,",backupuid=%u" , +from_kuid_munged (&init_user_ns, + cifs_sb->mnt_backupuid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) -seq_printf (s,",backupgid=%u" , cifs_sb->mnt_backupgid); +seq_printf (s,",backupgid=%u" , +from_kgid_munged (&init_user_ns, + cifs_sb->mnt_backupgid));seq_printf (s,",rsize=%u" , cifs_sb->rsize);seq_printf (s,",wsize=%u" , cifs_sb->wsize);fs/cifs/cifsglob.h +11
-11@@ -400,11 +400,11 @@ struct smb_vol {char *iocharset;/* local code page for mapping to and from Unicode */ char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL ];/* clnt nb name */ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL ];/* srvr nb name */ -uid_t cred_uid; -uid_t linux_uid; -gid_t linux_gid; -uid_t backupuid; -gid_t backupgid; +kuid_t cred_uid; +kuid_t linux_uid; +kgid_t linux_gid; +kuid_t backupuid; +kgid_t backupgid;umode_t file_mode;umode_t dir_mode;unsigned secFlg;@@ -703,8 +703,8 @@ struct cifs_ses {char *serverNOS;/* name of network operating system of server */ char *serverDomain;/* security realm of server */ __u64 Suid;/* remote smb uid */ -uid_t linux_uid;/* overriding owner of files on the mount */ -uid_t cred_uid;/* owner of credentials */ +kuid_t linux_uid;/* overriding owner of files on the mount */ +kuid_t cred_uid;/* owner of credentials */ unsigned int capabilities;char serverName[SERVER_NAME_LEN_WITH_NULL *2 ];/* BB make bigger for TCP names - will ipv6 and sctp addresses fit? */ @@ -838,7 +838,7 @@ struct cifs_tcon {*/ struct tcon_link {struct rb_node tl_rbnode; -uid_t tl_uid; +kuid_t tl_uid;unsigned long tl_flags;#define TCON_LINK_MASTER 0#define TCON_LINK_PENDING 1@@ -931,7 +931,7 @@ struct cifsFileInfo {struct list_head tlist;/* pointer to next fid owned by tcon */ struct list_head flist;/* next fid (file instance) for this inode */ struct cifs_fid_locks *llist;/* brlocks held by this fid */ -unsigned int uid;/* allows finding which FileInfo structure */ +kuid_t uid;/* allows finding which FileInfo structure */ __u32 pid;/* process id who opened file */ struct cifs_fid fid;/* file id from remote */ /* BB add lock scope info here if needed */ ;@@ -1259,8 +1259,8 @@ struct cifs_fattr {u64 cf_eof;u64 cf_bytes;u64 cf_createtime; -uid_t cf_uid; -gid_t cf_gid; +kuid_t cf_uid; +kgid_t cf_gid;umode_t cf_mode;dev_t cf_rdev;unsigned int cf_nlink;fs/cifs/cifspdu.h +2
-0@@ -278,6 +278,8 @@#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL#define NO_CHANGE_32 0xFFFFFFFFUL +#define NO_CHANGE_UID INVALID_UID +#define NO_CHANGE_GID INVALID_GID/* IPC$ in ASCII */ #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"fs/cifs/cifsproto.h +5
-4@@ -46,7 +46,8 @@ extern void _free_xid(unsigned int); ({ \unsigned int __xid =_get_xid (); \cFYI (1 ,"CIFS VFS: in %s as Xid: %u with uid: %d" , \ - __func__, __xid,current_fsuid ()); \ + __func__, __xid, \ +from_kuid (&init_user_ns,current_fsuid ())); \ __xid; \ })@@ -161,7 +162,7 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid);extern int id_mode_to_cifs_acl (struct inode *inode,const char *path,__u64 , -uid_t ,gid_t ); +kuid_t ,kgid_t );extern struct cifs_ntsd *get_cifs_acl (struct cifs_sb_info *,struct inode *,const char *,u32 *); extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,@@ -304,8 +305,8 @@ struct cifs_unix_set_info_args {__u64 atime;__u64 mtime;__u64 mode; -__u64 uid; -__u64 gid; +kuid_t uid; +kgid_t gid;dev_t device; };fs/cifs/cifssmb.c +9
-2@@ -5820,6 +5820,13 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, const struct cifs_unix_set_info_args *args) {u64 mode = args->mode; +__u64 uid; +__u64 gid; + + uid =uid_eq (args->uid,NO_CHANGE_UID ) ?NO_CHANGE_64 : + (__u64 )from_kuid (&init_user_ns, args->uid); + gid =gid_eq (args->gid,NO_CHANGE_GID ) ?NO_CHANGE_64 : + (__u64 )from_kgid (&init_user_ns, args->gid);/* * Samba server ignores set of file size to zero due to bugs in some @@ -5833,8 +5840,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, data_offset->LastStatusChange =cpu_to_le64 (args->ctime); data_offset->LastAccessTime =cpu_to_le64 (args->atime); data_offset->LastModificationTime =cpu_to_le64 (args->mtime); - data_offset->Uid =cpu_to_le64 (args->uid); - data_offset->Gid =cpu_to_le64 (args->gid); + data_offset->Uid =cpu_to_le64 (uid); + data_offset->Gid =cpu_to_le64 (gid);/* better to leave device as zero when it is */ data_offset->DevMajor =cpu_to_le64 (MAJOR (args->device)); data_offset->DevMinor =cpu_to_le64 (MINOR (args->device));fs/cifs/connect.c +45
-13@@ -1108,6 +1108,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,char *string =NULL ;char *tmp_end, *value;char delim; +kuid_t uid; +kgid_t gid; separator[0 ] =',' ; separator[1 ] =0 ;@@ -1361,7 +1363,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, __func__); goto cifs_parse_mount_err; } - vol->backupuid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid backupuid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->backupuid = uid; vol->backupuid_specified = true;break ;case Opt_backupgid:@@ -1370,7 +1378,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, __func__); goto cifs_parse_mount_err; } - vol->backupgid = option; + gid =make_kgid (current_user_ns (), option); +if (!gid_valid (gid)) { +cERROR (1 ,"%s: Invalid backupgid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->backupgid = gid; vol->backupgid_specified = true;break ;case Opt_uid:@@ -1379,7 +1393,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, __func__); goto cifs_parse_mount_err; } - vol->linux_uid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid uid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->linux_uid = uid; uid_specified = true;break ;case Opt_cruid:@@ -1388,7 +1408,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, __func__); goto cifs_parse_mount_err; } - vol->cred_uid = option; + uid =make_kuid (current_user_ns (), option); +if (!uid_valid (uid)) { +cERROR (1 ,"%s: Invalid cruid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->cred_uid = uid;break ;case Opt_gid:if (get_option_ul (args, &option)) {@@ -1396,7 +1422,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, __func__); goto cifs_parse_mount_err; } - vol->linux_gid = option; + gid =make_kgid (current_user_ns (), option); +if (!gid_valid (gid)) { +cERROR (1 ,"%s: Invalid gid value" , + __func__); + goto cifs_parse_mount_err; + } + vol->linux_gid = gid; gid_specified = true;break ;case Opt_file_mode:@@ -2203,7 +2235,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) {switch (ses->server->secType) {case Kerberos: -if (vol->cred_uid != ses->cred_uid) +if (!uid_eq (vol->cred_uid, ses->cred_uid))return 0 ;break ;default :@@ -2692,7 +2724,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)if (new->rsize && new->rsize < old->rsize)return 0 ; -if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) +if (!uid_eq (old->mnt_uid, new->mnt_uid) || !gid_eq (old->mnt_gid, new->mnt_gid))return 0 ; if (old->mnt_file_mode != new->mnt_file_mode ||@@ -3910,7 +3942,7 @@ cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) }static struct cifs_tcon * -cifs_construct_tcon (struct cifs_sb_info *cifs_sb,uid_t fsuid) +cifs_construct_tcon (struct cifs_sb_info *cifs_sb,kuid_t fsuid) {int rc;struct cifs_tcon *master_tcon =cifs_sb_master_tcon (cifs_sb);@@ -3980,7 +4012,7 @@ cifs_sb_tcon_pending_wait(void *unused)/* find and return a tlink with given uid */ static struct tcon_link * -tlink_rb_search (struct rb_root *root,uid_t uid) +tlink_rb_search (struct rb_root *root,kuid_t uid) {struct rb_node *node = root->rb_node;struct tcon_link *tlink;@@ -3988,9 +4020,9 @@ tlink_rb_search(struct rb_root *root, uid_t uid)while (node) { tlink = rb_entry(node, struct tcon_link, tl_rbnode); -if (tlink->tl_uid > uid) +if (uid_gt (tlink->tl_uid, uid)) node = node->rb_left; -else if (tlink->tl_uid < uid) +else if (uid_lt (tlink->tl_uid, uid)) node = node->rb_right;else return tlink;@@ -4009,7 +4041,7 @@ tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink) tlink = rb_entry(*new, struct tcon_link, tl_rbnode); parent = *new; -if (tlink->tl_uid > new_tlink->tl_uid) +if (uid_gt (tlink->tl_uid, new_tlink->tl_uid)) new = &((*new)->rb_left);else new = &((*new)->rb_right);@@ -4039,7 +4071,7 @@ struct tcon_link * cifs_sb_tlink(struct cifs_sb_info *cifs_sb) {int ret; -uid_t fsuid =current_fsuid (); +kuid_t fsuid =current_fsuid ();struct tcon_link *tlink, *newtlink;if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_MULTIUSER ))fs/cifs/dir.c +9
-9@@ -310,14 +310,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, *created |=FILE_CREATED ;if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); + args.uid =current_fsuid ();if (inode->i_mode &S_ISGID ) - args.gid = (__u64 ) inode->i_gid; + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; }CIFSSMBUnixSetFileInfo (xid, tcon, &args, fid->netfid, current->tgid);@@ -547,11 +547,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, .device = device_number, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); - args.gid = (__u64 )current_fsgid (); + args.uid =current_fsuid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =NO_CHANGE_UID ; + args.gid =NO_CHANGE_GID ; } rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, cifs_sb->local_nls,fs/cifs/file.c +4
-4@@ -487,8 +487,8 @@ int cifs_open(struct inode *inode, struct file *file)*/ struct cifs_unix_set_info_args args = { .mode = inode->i_mode, - .uid =NO_CHANGE_64 , - .gid =NO_CHANGE_64 , + .uid =NO_CHANGE_UID , + .gid =NO_CHANGE_GID , .ctime =NO_CHANGE_64 , .atime =NO_CHANGE_64 , .mtime =NO_CHANGE_64 ,@@ -1631,7 +1631,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,are always at the end of the list but since the first entry might have a close pending, we go through the whole list */ list_for_each_entry (open_file, &cifs_inode->openFileList, flist) { -if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_READ ) {if (!open_file->invalidHandle) {@@ -1684,7 +1684,7 @@ refind_writable:list_for_each_entry (open_file, &cifs_inode->openFileList, flist) {if (!any_available && open_file->pid != current->tgid)continue ; -if (fsuid_only && open_file->uid !=current_fsuid ()) +if (fsuid_only && !uid_eq (open_file->uid,current_fsuid ()))continue ;if (OPEN_FMODE (open_file->f_flags) &FMODE_WRITE ) {if (!open_file->invalidHandle) {fs/cifs/inode.c +14
-14@@ -247,12 +247,12 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID ) fattr->cf_uid = cifs_sb->mnt_uid;else - fattr->cf_uid =le64_to_cpu (info->Uid); + fattr->cf_uid =make_kuid (&init_user_ns,le64_to_cpu (info->Uid));if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID ) fattr->cf_gid = cifs_sb->mnt_gid;else - fattr->cf_gid =le64_to_cpu (info->Gid); + fattr->cf_gid =make_kgid (&init_user_ns,le64_to_cpu (info->Gid)); fattr->cf_nlink =le64_to_cpu (info->Nlinks); }@@ -1245,14 +1245,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, .device = 0, };if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { - args.uid = (__u64 )current_fsuid (); -if (parent->i_mode &S_ISGID ) - args.gid = (__u64 )parent->i_gid; + args.uid =current_fsuid (); +if (inode->i_mode &S_ISGID ) + args.gid = inode->i_gid;else - args.gid = (__u64 )current_fsgid (); + args.gid =current_fsgid (); }else { - args.uid =NO_CHANGE_64 ; - args.gid =NO_CHANGE_64 ; + args.uid =INVALID_UID ; + args.gid =INVALID_GID ; } CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, cifs_sb->local_nls,@@ -2012,12 +2012,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)if (attrs->ia_valid &ATTR_UID ) args->uid = attrs->ia_uid;else - args->uid =NO_CHANGE_64 ; + args->uid =NO_CHANGE_UID ;if (attrs->ia_valid &ATTR_GID ) args->gid = attrs->ia_gid;else - args->gid =NO_CHANGE_64 ; + args->gid =NO_CHANGE_GID ;if (attrs->ia_valid &ATTR_ATIME ) args->atime =cifs_UnixTimeToNT (attrs->ia_atime);@@ -2085,8 +2085,8 @@ static int cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) { unsigned int xid; -uid_t uid =NO_CHANGE_32 ; -gid_t gid =NO_CHANGE_32 ; +kuid_t uid =NO_CHANGE_UID ; +kgid_t gid =NO_CHANGE_GID ;struct inode *inode = direntry->d_inode;struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode);@@ -2145,7 +2145,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { -if (uid !=NO_CHANGE_32 || gid !=NO_CHANGE_32 ) { +if (!uid_eq (uid,NO_CHANGE_UID ) || !gid_eq (gid,NO_CHANGE_GID )) { rc =id_mode_to_cifs_acl (inode, full_path,NO_CHANGE_64 , uid, gid);if (rc) {@@ -2169,7 +2169,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)#ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) { rc =id_mode_to_cifs_acl (inode, full_path, mode, -NO_CHANGE_32 ,NO_CHANGE_32 ); +NO_CHANGE_UID ,NO_CHANGE_GID );if (rc) {cFYI (1 ,"%s: Setting ACL failed with error: %d" , __func__, rc);fs/cifs/misc.c +1
-1@@ -569,7 +569,7 @@ bool backup_cred(struct cifs_sb_info *cifs_sb) {if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPUID ) { -if (cifs_sb->mnt_backupuid ==current_fsuid ()) +if (uid_eq (cifs_sb->mnt_backupuid,current_fsuid ()))return true; }if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_BACKUPGID ) {init/Kconfig +0
-0
init/Kconfig config UIDGID_CONVERTED · line 1004
Quoted 7 lines
init/Kconfig +0
-1@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n depends on NCP_FS = n
Looks fairly reasonable to me. Note that I have a patchset queued up for 3.8 that rips all of the rbtree stuff out of cifsacl.c. This patch will need to be rebased on top of that, but that should mostly consist of dropping hunks that are no longer needed.
Signature · 1 line
Jeff Layton <[email protected]>
RFC PATCH 5/12 userns: Convert coda's to use kuid/kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/coda/cache.c | 4 ++-- fs/coda/coda_fs_i.h | 2 +- fs/coda/coda_linux.c | 8 ++++---- fs/coda/inode.c | 2 +- fs/coda/upcall.c | 6 +++--- include/linux/coda_psdev.h | 2 +- init/Kconfig | 1 - 7 files changed, 12 insertions(+), 13 deletions(-)
fs/coda/cache.c +2 -2
@@ -33,7 +33,7 @@ void coda_cache_enter(struct inode *inode, int mask)spin_lock (&cii->c_lock); cii->c_cached_epoch =atomic_read (&permission_epoch); -if (cii->c_uid !=current_fsuid ()) { +if (!uid_eq (cii->c_uid,current_fsuid ())) { cii->c_uid =current_fsuid (); cii->c_cached_perm = mask; }else
@@ -65,7 +65,7 @@ int coda_cache_check(struct inode *inode, int mask)spin_lock (&cii->c_lock); hit = (mask & cii->c_cached_perm) == mask && - cii->c_uid ==current_fsuid () && +uid_eq (cii->c_uid,current_fsuid ()) && cii->c_cached_epoch ==atomic_read (&permission_epoch);spin_unlock (&cii->c_lock);
fs/coda/coda_fs_i.h +1 -1
@@ -25,7 +25,7 @@ struct coda_inode_info {u_short c_flags;/* flags (see below) */ unsigned int c_mapcount;/* nr of times this inode is mapped */ unsigned int c_cached_epoch;/* epoch for cached permissions */ -vuid_t c_uid;/* fsuid for cached permissions */ +kuid_t c_uid;/* fsuid for cached permissions */ unsigned int c_cached_perm;/* cached access permissions */ spinlock_t c_lock;struct inode vfs_inode;
fs/coda/coda_linux.c +4 -4
@@ -100,9 +100,9 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)if (attr->va_mode != (u_short) -1 ) inode->i_mode = attr->va_mode | inode_type;if (attr->va_uid !=-1 ) - inode->i_uid = (uid_t ) attr->va_uid; +i_uid_write (inode, (uid_t ) attr->va_uid);if (attr->va_gid !=-1 ) - inode->i_gid = (gid_t ) attr->va_gid; +i_gid_write (inode, (gid_t ) attr->va_gid);if (attr->va_nlink !=-1 )set_nlink (inode, attr->va_nlink);if (attr->va_size !=-1 )
@@ -171,10 +171,10 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr) vattr->va_mode = iattr->ia_mode; }if ( valid &ATTR_UID ) { - vattr->va_uid = (vuid_t ) iattr->ia_uid; + vattr->va_uid = (vuid_t )from_kuid (&init_user_ns, iattr->ia_uid); }if ( valid &ATTR_GID ) { - vattr->va_gid = (vgid_t ) iattr->ia_gid; + vattr->va_gid = (vgid_t )from_kgid (&init_user_ns, iattr->ia_gid); }if ( valid &ATTR_SIZE ) { vattr->va_size = iattr->ia_size;
fs/coda/inode.c +1 -1
@@ -48,7 +48,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)return NULL ;memset (&ei->c_fid,0 ,sizeof (struct CodaFid )); ei->c_flags =0 ; - ei->c_uid =0 ; + ei->c_uid =GLOBAL_ROOT_UID ; ei->c_cached_perm =0 ;spin_lock_init (&ei->c_lock);return &ei->vfs_inode;
fs/coda/upcall.c +3 -3
@@ -52,7 +52,7 @@ static void *alloc_upcall(int opcode, int size) inp->ih.opcode = opcode; inp->ih.pid = current->pid; inp->ih.pgid =task_pgrp_nr (current); - inp->ih.uid =current_fsuid (); + inp->ih.uid =from_kuid (&init_user_ns,current_fsuid ());return (void *)inp; }
@@ -157,7 +157,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid, }int venus_close (struct super_block *sb,struct CodaFid *fid,int flags, -vuid_t uid) +kuid_t uid) {union inputArgs *inp;union outputArgs *outp;
@@ -166,7 +166,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, insize =SIZE (release);UPARG (CODA_CLOSE ); - inp->ih.uid = uid; + inp->ih.uid =from_kuid (&init_user_ns, uid); inp->coda_close.VFid = *fid; inp->coda_close.flags = flags;
include/linux/coda_psdev.h +1 -1
@@ -34,7 +34,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid, const char *name, int length, int *type, struct CodaFid *resfid);int venus_close (struct super_block *sb,struct CodaFid *fid,int flags, -vuid_t uid); +kuid_t uid);int venus_open (struct super_block *sb,struct CodaFid *fid,int flags,struct file **f); int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CODA_FS = n depends on GFS2_FS = n depends on NCP_FS = n depends on NFSD = n
Signature · 1 line
1.7.5.4
RFC PATCH 6/12 userns: Convert gfs2 to use kuid/kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use struct kqid to hold the identifier of in core quota objects
- Use qid.type uniformly for all in core quota type computation.
- kill QDF_USER
- kill QUOTA_USER and QUOTA_GROUP
--- fs/gfs2/acl.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/glops.c | 4 +- fs/gfs2/incore.h | 3 +- fs/gfs2/inode.c | 36 ++++++++------- fs/gfs2/quota.c | 128 +++++++++++++++++++++++------------------------------ fs/gfs2/quota.h | 15 +++--- fs/gfs2/super.c | 6 +- fs/gfs2/sys.c | 14 +++++- fs/gfs2/xattr.c | 4 +- init/Kconfig | 1 - 12 files changed, 106 insertions(+), 111 deletions(-)
fs/gfs2/acl.c +1 -1
@@ -237,7 +237,7 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,return -EINVAL ;if (type ==ACL_TYPE_DEFAULT && !S_ISDIR (inode->i_mode))return value ? -EACCES :0 ; -if ((current_fsuid () != inode->i_uid) && !capable (CAP_FOWNER )) +if (!uid_eq (current_fsuid (), inode->i_uid) && !capable (CAP_FOWNER ))return -EPERM ;if (S_ISLNK (inode->i_mode))return -EOPNOTSUPP ;
fs/gfs2/bmap.c +1 -1
@@ -1052,7 +1052,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;
fs/gfs2/dir.c +1 -1
@@ -1854,7 +1854,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,if (!ht)return -ENOMEM ; - error =gfs2_quota_hold (dip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (dip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto out;
fs/gfs2/glops.c +2 -2
@@ -322,8 +322,8 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)break ; }; - ip->i_inode.i_uid =be32_to_cpu (str->di_uid); - ip->i_inode.i_gid =be32_to_cpu (str->di_gid); +i_uid_write (&ip->i_inode,be32_to_cpu (str->di_uid)); +i_gid_write (&ip->i_inode,be32_to_cpu (str->di_gid));gfs2_set_nlink (&ip->i_inode,be32_to_cpu (str->di_nlink));i_size_write (&ip->i_inode,be64_to_cpu (str->di_size));gfs2_set_inode_blocks (&ip->i_inode,be64_to_cpu (str->di_blocks));
fs/gfs2/incore.h +1 -2
@@ -391,7 +391,6 @@ struct gfs2_revoke_replay { };enum { -QDF_USER =0 ,QDF_CHANGE =1 ,QDF_LOCKED =2 ,QDF_REFRESH =3 ,
@@ -403,7 +402,7 @@ struct gfs2_quota_data {atomic_t qd_count; -u32 qd_id; +struct kqid qd_id;unsigned long qd_flags;/* QDF_... */ s64 qd_change;
fs/gfs2/inode.c +19 -17
@@ -365,13 +365,13 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, }static void munge_mode_uid_gid (struct gfs2_inode *dip,umode_t *mode, -unsigned int *uid,unsigned int *gid) +kuid_t *uid,kgid_t *gid) {if (GFS2_SB (&dip->i_inode)->sd_args.ar_suiddir && - (dip->i_inode.i_mode &S_ISUID ) && dip->i_inode.i_uid) { + (dip->i_inode.i_mode &S_ISUID ) &&i_uid_read (&dip->i_inode)) {if (S_ISDIR (*mode)) *mode |=S_ISUID ; -else if (dip->i_inode.i_uid !=current_fsuid ()) +else if (!uid_eq (dip->i_inode.i_uid,current_fsuid ())) *mode &= ~07111 ; *uid = dip->i_inode.i_uid; }else
@@ -444,7 +444,7 @@ static void gfs2_init_dir(struct buffer_head *dibh,static void init_dinode (struct gfs2_inode *dip,struct gfs2_glock *gl,const struct gfs2_inum_host *inum,umode_t mode, -unsigned int uid,unsigned int gid, +kuid_t uid,kgid_t gid,const u64 *generation,dev_t dev,const char *symname,unsigned size,struct buffer_head **bhp) {
@@ -462,8 +462,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, di->di_num.no_formal_ino =cpu_to_be64 (inum->no_formal_ino); di->di_num.no_addr =cpu_to_be64 (inum->no_addr); di->di_mode =cpu_to_be32 (mode); - di->di_uid =cpu_to_be32 (uid); - di->di_gid =cpu_to_be32 (gid); + di->di_uid =cpu_to_be32 (from_kuid (&init_user_ns, uid)); + di->di_gid =cpu_to_be32 (from_kgid (&init_user_ns, gid)); di->di_nlink =0 ; di->di_size =cpu_to_be64 (size); di->di_blocks =cpu_to_be64 (1 );
@@ -517,7 +517,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, unsigned int size, struct buffer_head **bhp) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); -unsigned int uid, gid; +kuid_t uid; +kgid_t gid;int error;munge_mode_uid_gid (dip, &mode, &uid, &gid);
@@ -558,7 +559,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,if (error)return error; - error =gfs2_quota_lock (dip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_lock (dip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto fail;
@@ -955,8 +956,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,return -EPERM ;if ((dip->i_inode.i_mode &S_ISVTX ) && - dip->i_inode.i_uid !=current_fsuid () && - ip->i_inode.i_uid !=current_fsuid () && !capable (CAP_FOWNER )) + !uid_eq (dip->i_inode.i_uid,current_fsuid ()) && + !uid_eq (ip->i_inode.i_uid,current_fsuid ()) && !capable (CAP_FOWNER ))return -EPERM ;if (IS_APPEND (&dip->i_inode))
@@ -1571,7 +1572,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) {struct gfs2_inode *ip =GFS2_I (inode);struct gfs2_sbd *sdp =GFS2_SB (inode); -u32 ouid, ogid, nuid, ngid; +kuid_t ouid, nuid; +kgid_t ogid, ngid;int error; ouid = inode->i_uid;
@@ -1579,16 +1581,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) nuid = attr->ia_uid; ngid = attr->ia_gid; -if (!(attr->ia_valid &ATTR_UID ) || ouid == nuid) - ouid = nuid =NO_QUOTA_CHANGE ; -if (!(attr->ia_valid &ATTR_GID ) || ogid == ngid) - ogid = ngid =NO_QUOTA_CHANGE ; +if (!(attr->ia_valid &ATTR_UID ) ||uid_eq (ouid, nuid)) + ouid = nuid =NO_UID_QUOTA_CHANGE ; +if (!(attr->ia_valid &ATTR_GID ) ||gid_eq (ogid, ngid)) + ogid = ngid =NO_GID_QUOTA_CHANGE ; error =gfs2_quota_lock (ip, nuid, ngid);if (error)return error; -if (ouid !=NO_QUOTA_CHANGE || ogid !=NO_QUOTA_CHANGE ) { +if (uid_valid (ouid) ||gid_valid (ogid)) { error =gfs2_quota_check (ip, nuid, ngid);if (error) goto out_gunlock_q;
@@ -1602,7 +1604,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)if (error) goto out_end_trans; -if (ouid !=NO_QUOTA_CHANGE || ogid !=NO_QUOTA_CHANGE ) { +if (uid_valid (ouid) ||gid_valid (ogid)) {u64 blocks =gfs2_get_inode_blocks (&ip->i_inode);gfs2_quota_change (ip, -blocks, ouid, ogid);gfs2_quota_change (ip, blocks, nuid, ngid);
fs/gfs2/quota.c +56 -72
356 lines not on this page · raw message
fs/gfs2/quota.h +8 -7
@@ -14,20 +14,21 @@ struct gfs2_inode;struct gfs2_sbd ;struct shrink_control ; -#define NO_QUOTA_CHANGE ((u32)-1) +#define NO_UID_QUOTA_CHANGE INVALID_UID +#define NO_GID_QUOTA_CHANGE INVALID_GID -extern int gfs2_quota_hold (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_hold (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_unhold (struct gfs2_inode *ip); -extern int gfs2_quota_lock (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_lock (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_unlock (struct gfs2_inode *ip); -extern int gfs2_quota_check (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_check (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_change (struct gfs2_inode *ip,s64 change, -u32 uid,u32 gid); +kuid_t uid,kgid_t gid);extern int gfs2_quota_sync (struct super_block *sb,int type); -extern int gfs2_quota_refresh (struct gfs2_sbd *sdp,int user,u32 id); +extern int gfs2_quota_refresh (struct gfs2_sbd *sdp,struct kqid qid);extern int gfs2_quota_init (struct gfs2_sbd *sdp);extern void gfs2_quota_cleanup (struct gfs2_sbd *sdp);
@@ -41,7 +42,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)int ret;if (sdp->sd_args.ar_quota ==GFS2_QUOTA_OFF )return 0 ; - ret =gfs2_quota_lock (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + ret =gfs2_quota_lock (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (ret)return ret;if (sdp->sd_args.ar_quota !=GFS2_QUOTA_ON )
fs/gfs2/super.c +3 -3
@@ -721,8 +721,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_num.no_addr =cpu_to_be64 (ip->i_no_addr); str->di_num.no_formal_ino =cpu_to_be64 (ip->i_no_formal_ino); str->di_mode =cpu_to_be32 (ip->i_inode.i_mode); - str->di_uid =cpu_to_be32 (ip->i_inode.i_uid); - str->di_gid =cpu_to_be32 (ip->i_inode.i_gid); + str->di_uid =cpu_to_be32 (i_uid_read (&ip->i_inode)); + str->di_gid =cpu_to_be32 (i_gid_read (&ip->i_inode)); str->di_nlink =cpu_to_be32 (ip->i_inode.i_nlink); str->di_size =cpu_to_be64 (i_size_read (&ip->i_inode)); str->di_blocks =cpu_to_be64 (gfs2_get_inode_blocks (&ip->i_inode));
@@ -1428,7 +1428,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;
fs/gfs2/sys.c +12 -2
@@ -176,6 +176,7 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, size_t len) {int error; +struct kqid qid;u32 id;if (!capable (CAP_SYS_ADMIN ))
@@ -183,7 +184,11 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, id =simple_strtoul (buf,NULL ,0 ); - error =gfs2_quota_refresh (sdp,1 , id); + qid =make_kqid (&init_user_ns,USRQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }
@@ -191,6 +196,7 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, size_t len) {int error; +struct kqid qid;u32 id;if (!capable (CAP_SYS_ADMIN ))
@@ -198,7 +204,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, id =simple_strtoul (buf,NULL ,0 ); - error =gfs2_quota_refresh (sdp,0 , id); + qid =make_kqid (&init_user_ns,GRPQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }
fs/gfs2/xattr.c +2 -2
@@ -331,7 +331,7 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto out_alloc;
@@ -1461,7 +1461,7 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on GFS2_FS = n depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n
Signature · 1 line
1.7.5.4
Re: [PATCH RFC 06/12] userns: Convert gfs2 to use kuid/kgid where appropriate
Hi,
Quoted 7 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
- Use struct kqid to hold the identifier of in core quota objects
- Use qid.type uniformly for all in core quota type computation.
- killQDF_USER
- killQUOTA_USERandQUOTA_GROUP
There are some GFS2 changes in linux-next for merging shortly which are likely to conflict with your changes in inode.c, but otherwise this looks ok to me. I don't think that it will be very tricky to fix up the conflicts.
I've not actually tested this, but it looks ok having read through it. I'm also copying in Abhi since he looks after quotas in GFS2,
Steve.
Quoted 734 lines
Cc Steven Whitehouse <[email protected]>Signed-off-by Eric W. Biederman <[email protected]>--- fs/gfs2/acl.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/glops.c | 4 +- fs/gfs2/incore.h | 3 +- fs/gfs2/inode.c | 36 ++++++++------- fs/gfs2/quota.c | 128 +++++++++++++++++++++++------------------------------ fs/gfs2/quota.h | 15 +++--- fs/gfs2/super.c | 6 +- fs/gfs2/sys.c | 14 +++++- fs/gfs2/xattr.c | 4 +- init/Kconfig | 1 - 12 files changed, 106 insertions(+), 111 deletions(-)fs/gfs2/acl.c +1
-1@@ -237,7 +237,7 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,return -EINVAL ;if (type ==ACL_TYPE_DEFAULT && !S_ISDIR (inode->i_mode))return value ? -EACCES :0 ; -if ((current_fsuid () != inode->i_uid) && !capable (CAP_FOWNER )) +if (!uid_eq (current_fsuid (), inode->i_uid) && !capable (CAP_FOWNER ))return -EPERM ;if (S_ISLNK (inode->i_mode))return -EOPNOTSUPP ;fs/gfs2/bmap.c +1
-1@@ -1052,7 +1052,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;fs/gfs2/dir.c +1
-1@@ -1854,7 +1854,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,if (!ht)return -ENOMEM ; - error =gfs2_quota_hold (dip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (dip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto out;fs/gfs2/glops.c +2
-2@@ -322,8 +322,8 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)break ; }; - ip->i_inode.i_uid =be32_to_cpu (str->di_uid); - ip->i_inode.i_gid =be32_to_cpu (str->di_gid); +i_uid_write (&ip->i_inode,be32_to_cpu (str->di_uid)); +i_gid_write (&ip->i_inode,be32_to_cpu (str->di_gid));gfs2_set_nlink (&ip->i_inode,be32_to_cpu (str->di_nlink));i_size_write (&ip->i_inode,be64_to_cpu (str->di_size));gfs2_set_inode_blocks (&ip->i_inode,be64_to_cpu (str->di_blocks));fs/gfs2/incore.h +1
-2@@ -391,7 +391,6 @@ struct gfs2_revoke_replay { };enum { -QDF_USER =0 ,QDF_CHANGE =1 ,QDF_LOCKED =2 ,QDF_REFRESH =3 ,@@ -403,7 +402,7 @@ struct gfs2_quota_data {atomic_t qd_count; -u32 qd_id; +struct kqid qd_id;unsigned long qd_flags;/* QDF_... */ s64 qd_change;fs/gfs2/inode.c +19
-17@@ -365,13 +365,13 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, }static void munge_mode_uid_gid (struct gfs2_inode *dip,umode_t *mode, -unsigned int *uid,unsigned int *gid) +kuid_t *uid,kgid_t *gid) {if (GFS2_SB (&dip->i_inode)->sd_args.ar_suiddir && - (dip->i_inode.i_mode &S_ISUID ) && dip->i_inode.i_uid) { + (dip->i_inode.i_mode &S_ISUID ) &&i_uid_read (&dip->i_inode)) {if (S_ISDIR (*mode)) *mode |=S_ISUID ; -else if (dip->i_inode.i_uid !=current_fsuid ()) +else if (!uid_eq (dip->i_inode.i_uid,current_fsuid ())) *mode &= ~07111 ; *uid = dip->i_inode.i_uid; }else @@ -444,7 +444,7 @@ static void gfs2_init_dir(struct buffer_head *dibh,static void init_dinode (struct gfs2_inode *dip,struct gfs2_glock *gl,const struct gfs2_inum_host *inum,umode_t mode, -unsigned int uid,unsigned int gid, +kuid_t uid,kgid_t gid,const u64 *generation,dev_t dev,const char *symname,unsigned size,struct buffer_head **bhp) {@@ -462,8 +462,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, di->di_num.no_formal_ino =cpu_to_be64 (inum->no_formal_ino); di->di_num.no_addr =cpu_to_be64 (inum->no_addr); di->di_mode =cpu_to_be32 (mode); - di->di_uid =cpu_to_be32 (uid); - di->di_gid =cpu_to_be32 (gid); + di->di_uid =cpu_to_be32 (from_kuid (&init_user_ns, uid)); + di->di_gid =cpu_to_be32 (from_kgid (&init_user_ns, gid)); di->di_nlink =0 ; di->di_size =cpu_to_be64 (size); di->di_blocks =cpu_to_be64 (1 );@@ -517,7 +517,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, unsigned int size, struct buffer_head **bhp) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); -unsigned int uid, gid; +kuid_t uid; +kgid_t gid;int error;munge_mode_uid_gid (dip, &mode, &uid, &gid);@@ -558,7 +559,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,if (error)return error; - error =gfs2_quota_lock (dip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_lock (dip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto fail;@@ -955,8 +956,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,return -EPERM ;if ((dip->i_inode.i_mode &S_ISVTX ) && - dip->i_inode.i_uid !=current_fsuid () && - ip->i_inode.i_uid !=current_fsuid () && !capable (CAP_FOWNER )) + !uid_eq (dip->i_inode.i_uid,current_fsuid ()) && + !uid_eq (ip->i_inode.i_uid,current_fsuid ()) && !capable (CAP_FOWNER ))return -EPERM ;if (IS_APPEND (&dip->i_inode))@@ -1571,7 +1572,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) {struct gfs2_inode *ip =GFS2_I (inode);struct gfs2_sbd *sdp =GFS2_SB (inode); -u32 ouid, ogid, nuid, ngid; +kuid_t ouid, nuid; +kgid_t ogid, ngid;int error; ouid = inode->i_uid;@@ -1579,16 +1581,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) nuid = attr->ia_uid; ngid = attr->ia_gid; -if (!(attr->ia_valid &ATTR_UID ) || ouid == nuid) - ouid = nuid =NO_QUOTA_CHANGE ; -if (!(attr->ia_valid &ATTR_GID ) || ogid == ngid) - ogid = ngid =NO_QUOTA_CHANGE ; +if (!(attr->ia_valid &ATTR_UID ) ||uid_eq (ouid, nuid)) + ouid = nuid =NO_UID_QUOTA_CHANGE ; +if (!(attr->ia_valid &ATTR_GID ) ||gid_eq (ogid, ngid)) + ogid = ngid =NO_GID_QUOTA_CHANGE ; error =gfs2_quota_lock (ip, nuid, ngid);if (error)return error; -if (ouid !=NO_QUOTA_CHANGE || ogid !=NO_QUOTA_CHANGE ) { +if (uid_valid (ouid) ||gid_valid (ogid)) { error =gfs2_quota_check (ip, nuid, ngid);if (error) goto out_gunlock_q;@@ -1602,7 +1604,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)if (error) goto out_end_trans; -if (ouid !=NO_QUOTA_CHANGE || ogid !=NO_QUOTA_CHANGE ) { +if (uid_valid (ouid) ||gid_valid (ogid)) {u64 blocks =gfs2_get_inode_blocks (&ip->i_inode);gfs2_quota_change (ip, -blocks, ouid, ogid);gfs2_quota_change (ip, blocks, nuid, ngid);fs/gfs2/quota.c +56
-72@@ -65,19 +65,22 @@#include "inode.h" #include "util.h" -#define QUOTA_USER 1 -#define QUOTA_GROUP 0 -struct gfs2_quota_change_host {u64 qc_change;u32 qc_flags;/* GFS2_QCF_... */ -u32 qc_id; +struct kqid qc_id; };static LIST_HEAD (qd_lru_list);static atomic_t qd_lru_count =ATOMIC_INIT (0 );static DEFINE_SPINLOCK (qd_lru_lock); +static u64 gfs2_qid_number (struct kqid qid) +{ +return (2 * (u64 )from_kqid (&init_user_ns, qid)) + + (qid.type ==USRQUOTA ) ?0 :1 ; +} +int gfs2_shrink_qd_memory (struct shrinker *shrink,struct shrink_control *sc) {struct gfs2_quota_data *qd;@@ -124,13 +127,13 @@ static u64 qd2offset(struct gfs2_quota_data *qd) {u64 offset; - offset =2 * (u64 )qd->qd_id + !test_bit (QDF_USER , &qd->qd_flags); + offset =gfs2_qid_number (qd->qd_id); offset *=sizeof (struct gfs2_quota );return offset; } -static int qd_alloc (struct gfs2_sbd *sdp,int user,u32 id, +static int qd_alloc (struct gfs2_sbd *sdp,struct kqid qid,struct gfs2_quota_data **qdp) {struct gfs2_quota_data *qd;@@ -141,13 +144,11 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,return -ENOMEM ;atomic_set (&qd->qd_count,1 ); - qd->qd_id = id; -if (user) -set_bit (QDF_USER , &qd->qd_flags); + qd->qd_id = qid; qd->qd_slot =-1 ;INIT_LIST_HEAD (&qd->qd_reclaim); - error =gfs2_glock_get (sdp,2 * (u64 )id + !user, + error =gfs2_glock_get (sdp,gfs2_qid_number (qid), &gfs2_quota_glops,CREATE , &qd->qd_gl);if (error) goto fail;@@ -161,8 +162,8 @@ fail:return error; } -static int qd_get (struct gfs2_sbd *sdp,int user,u32 id, -struct gfs2_quota_data **qdp) +static int qd_get (struct gfs2_sbd *sdp, +struct kqid qid,struct gfs2_quota_data **qdp) {struct gfs2_quota_data *qd =NULL , *new_qd =NULL ;int error, found;@@ -173,8 +174,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, found =0 ;spin_lock (&qd_lru_lock);list_for_each_entry (qd, &sdp->sd_quota_list, qd_list) { -if (qd->qd_id == id && - !test_bit (QDF_USER , &qd->qd_flags) == !user) { +if (qid_eq (qd->qd_id, qid)) {if (!atomic_read (&qd->qd_count) && !list_empty (&qd->qd_reclaim)) {/* Remove it from reclaim list */ @@ -208,7 +208,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,return 0 ; } - error =qd_alloc (sdp, user, id, &new_qd); + error =qd_alloc (sdp, qid, &new_qd);if (error)return error; }@@ -458,12 +458,12 @@ static void qd_unlock(struct gfs2_quota_data *qd)qd_put (qd); } -static int qdsb_get (struct gfs2_sbd *sdp,int user,u32 id, +static int qdsb_get (struct gfs2_sbd *sdp,struct kqid qid,struct gfs2_quota_data **qdp) {int error; - error =qd_get (sdp, user, id, qdp); + error =qd_get (sdp, qid, qdp);if (error)return error;@@ -491,7 +491,7 @@ static void qdsb_put(struct gfs2_quota_data *qd)qd_put (qd); } -int gfs2_quota_hold (struct gfs2_inode *ip,u32 uid,u32 gid) +int gfs2_quota_hold (struct gfs2_inode *ip,kuid_t uid,kgid_t gid) {struct gfs2_sbd *sdp =GFS2_SB (&ip->i_inode);struct gfs2_quota_data **qd;@@ -509,28 +509,28 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)if (sdp->sd_args.ar_quota ==GFS2_QUOTA_OFF )return 0 ; - error =qdsb_get (sdp,QUOTA_USER , ip->i_inode.i_uid, qd); + error =qdsb_get (sdp,make_kqid_uid (ip->i_inode.i_uid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++; qd++; - error =qdsb_get (sdp,QUOTA_GROUP , ip->i_inode.i_gid, qd); + error =qdsb_get (sdp,make_kqid_gid (ip->i_inode.i_gid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++; qd++; -if (uid !=NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { - error =qdsb_get (sdp,QUOTA_USER , uid, qd); +if (uid_valid (uid) && !uid_eq (uid, ip->i_inode.i_uid)) { + error =qdsb_get (sdp,make_kqid_uid (uid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++; qd++; } -if (gid !=NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { - error =qdsb_get (sdp,QUOTA_GROUP , gid, qd); +if (gid_valid (gid) && !gid_eq (gid, ip->i_inode.i_gid)) { + error =qdsb_get (sdp,make_kqid_gid (gid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++;@@ -564,18 +564,10 @@ static int sort_qd(const void *a, const void *b)const struct gfs2_quota_data *qd_a = *(const struct gfs2_quota_data **)a;const struct gfs2_quota_data *qd_b = *(const struct gfs2_quota_data **)b; -if (!test_bit (QDF_USER , &qd_a->qd_flags) != - !test_bit (QDF_USER , &qd_b->qd_flags)) { -if (test_bit (QDF_USER , &qd_a->qd_flags)) -return -1 ; -else -return 1 ; - } -if (qd_a->qd_id < qd_b->qd_id) +if (qid_lt (qd_a->qd_id, qd_b->qd_id))return -1 ; -if (qd_a->qd_id > qd_b->qd_id) +if (qid_lt (qd_b->qd_id, qd_a->qd_id))return 1 ; -return 0 ; }@@ -592,9 +584,9 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)if (!test_bit (QDF_CHANGE , &qd->qd_flags)) { qc->qc_change =0 ; qc->qc_flags =0 ; -if (test_bit (QDF_USER , &qd->qd_flags)) +if (qd->qd_id.type ==USRQUOTA ) qc->qc_flags =cpu_to_be32 (GFS2_QCF_USER ); - qc->qc_id =cpu_to_be32 (qd->qd_id); + qc->qc_id =cpu_to_be32 (from_kqid (&init_user_ns, qd->qd_id)); } x =be64_to_cpu (qc->qc_change) + change;@@ -922,7 +914,7 @@ fail:return error; } -int gfs2_quota_lock (struct gfs2_inode *ip,u32 uid,u32 gid) +int gfs2_quota_lock (struct gfs2_inode *ip,kuid_t uid,kgid_t gid) {struct gfs2_sbd *sdp =GFS2_SB (&ip->i_inode);struct gfs2_quota_data *qd;@@ -1037,19 +1029,20 @@ static int print_message(struct gfs2_quota_data *qd, char *type)printk (KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n" , sdp->sd_fsname, type, - (test_bit (QDF_USER , &qd->qd_flags)) ?"user" :"group" , - qd->qd_id); + (qd->qd_id.type ==USRQUOTA ) ?"user" :"group" , +from_kqid (&init_user_ns, qd->qd_id));return 0 ; } -int gfs2_quota_check (struct gfs2_inode *ip,u32 uid,u32 gid) +int gfs2_quota_check (struct gfs2_inode *ip,kuid_t uid,kgid_t gid) {struct gfs2_sbd *sdp =GFS2_SB (&ip->i_inode);struct gfs2_quota_data *qd;s64 value;unsigned int x;int error =0 ; +int user;if (!test_bit (GIF_QD_LOCKED , &ip->i_flags))return 0 ;@@ -1060,8 +1053,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)for (x =0 ; x < ip->i_res->rs_qa_qd_num; x++) { qd = ip->i_res->rs_qa_qd[x]; -if (!((qd->qd_id == uid &&test_bit (QDF_USER , &qd->qd_flags)) || - (qd->qd_id == gid && !test_bit (QDF_USER , &qd->qd_flags)))) + user = (qd->qd_id.type ==USRQUOTA ); +if (!((user &&uid_eq (qd->qd_id.uid, uid)) || + (!user &&gid_eq (qd->qd_id.gid, gid))))continue ; value = (s64 )be64_to_cpu (qd->qd_qb.qb_value);@@ -1071,10 +1065,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)if (be64_to_cpu (qd->qd_qb.qb_limit) && (s64 )be64_to_cpu (qd->qd_qb.qb_limit) < value) {print_message (qd,"exceeded" ); -quota_send_warning (make_kqid (&init_user_ns, -test_bit (QDF_USER , &qd->qd_flags) ? -USRQUOTA :GRPQUOTA , - qd->qd_id), +quota_send_warning (qd->qd_id, sdp->sd_vfs->s_dev,QUOTA_NL_BHARDWARN ); error = -EDQUOT ;@@ -1084,10 +1075,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) time_after_eq(jiffies, qd->qd_last_warn + gfs2_tune_get(sdp, gt_quota_warn_period) * HZ)) { -quota_send_warning (make_kqid (&init_user_ns, -test_bit (QDF_USER , &qd->qd_flags) ? -USRQUOTA :GRPQUOTA , - qd->qd_id), +quota_send_warning (qd->qd_id, sdp->sd_vfs->s_dev,QUOTA_NL_BSOFTWARN ); error =print_message (qd,"warning" ); qd->qd_last_warn = jiffies;@@ -1098,10 +1086,11 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) }void gfs2_quota_change (struct gfs2_inode *ip,s64 change, -u32 uid,u32 gid) +kuid_t uid,kgid_t gid) {struct gfs2_quota_data *qd;unsigned int x; +int user;if (gfs2_assert_warn (GFS2_SB (&ip->i_inode), change))return ;@@ -1111,8 +1100,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,for (x =0 ; x < ip->i_res->rs_qa_qd_num; x++) { qd = ip->i_res->rs_qa_qd[x]; -if ((qd->qd_id == uid &&test_bit (QDF_USER , &qd->qd_flags)) || - (qd->qd_id == gid && !test_bit (QDF_USER , &qd->qd_flags))) { + user = (qd->qd_id.type ==USRQUOTA ); +if ((user &&uid_eq (qd->qd_id.uid, uid)) || + (!user &&gid_eq (qd->qd_id.gid, gid))) {do_qc (qd, change); } }@@ -1167,13 +1157,13 @@ static int gfs2_quota_sync_timeo(struct super_block *sb, int type)return gfs2_quota_sync (sb, type); } -int gfs2_quota_refresh (struct gfs2_sbd *sdp,int user,u32 id) +int gfs2_quota_refresh (struct gfs2_sbd *sdp,struct kqid qid) {struct gfs2_quota_data *qd;struct gfs2_holder q_gh;int error; - error =qd_get (sdp, user, id, &qd); + error =qd_get (sdp, qid, &qd);if (error)return error;@@ -1191,7 +1181,9 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void * qc->qc_change =be64_to_cpu (str->qc_change); qc->qc_flags =be32_to_cpu (str->qc_flags); - qc->qc_id =be32_to_cpu (str->qc_id); + qc->qc_id =make_kqid (&init_user_ns, + (qc->qc_flags &GFS2_QCF_USER )?USRQUOTA :GRPQUOTA , +be32_to_cpu (str->qc_id)); }int gfs2_quota_init (struct gfs2_sbd *sdp)@@ -1254,8 +1246,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)if (!qc.qc_change)continue ; - error =qd_alloc (sdp, (qc.qc_flags &GFS2_QCF_USER ), - qc.qc_id, &qd); + error =qd_alloc (sdp, qc.qc_id, &qd);if (error) {brelse (bh); goto fail;@@ -1482,21 +1473,17 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,struct gfs2_quota_data *qd;struct gfs2_holder q_gh;int error; -int type;memset (fdq,0 ,sizeof (struct fs_disk_quota ));if (sdp->sd_args.ar_quota ==GFS2_QUOTA_OFF )return -ESRCH ;/* Crazy XFS error code */ -if (qid.type ==USRQUOTA ) - type =QUOTA_USER ; -else if (qid.type ==GRPQUOTA ) - type =QUOTA_GROUP ; -else +if ((qid.type !=USRQUOTA ) && + (qid.type !=GRPQUOTA ))return -EINVAL ; - error =qd_get (sdp, type,from_kqid (&init_user_ns, qid), &qd); + error =qd_get (sdp, qid, &qd);if (error)return error; error =do_glock (qd,FORCE , &q_gh);@@ -1505,8 +1492,8 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; fdq->d_version =FS_DQUOT_VERSION ; - fdq->d_flags = (type ==QUOTA_USER ) ?FS_USER_QUOTA :FS_GROUP_QUOTA ; - fdq->d_id =from_kqid (&init_user_ns, qid); + fdq->d_flags = (qid.type ==USRQUOTA ) ?FS_USER_QUOTA :FS_GROUP_QUOTA ; + fdq->d_id =from_kqid_munged (current_user_ns (), qid); fdq->d_blk_hardlimit =be64_to_cpu (qlvb->qb_limit) << sdp->sd_fsb2bb_shift; fdq->d_blk_softlimit =be64_to_cpu (qlvb->qb_warn) << sdp->sd_fsb2bb_shift; fdq->d_bcount =be64_to_cpu (qlvb->qb_value) << sdp->sd_fsb2bb_shift;@@ -1532,19 +1519,16 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,int alloc_required;loff_t offset;int error; -int type;if (sdp->sd_args.ar_quota ==GFS2_QUOTA_OFF )return -ESRCH ;/* Crazy XFS error code */ switch (qid.type) {case USRQUOTA : - type =QUOTA_USER ;if (fdq->d_flags !=FS_USER_QUOTA )return -EINVAL ;break ;case GRPQUOTA : - type =QUOTA_GROUP ;if (fdq->d_flags !=FS_GROUP_QUOTA )return -EINVAL ;break ;@@ -1554,10 +1538,10 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,if (fdq->d_fieldmask & ~GFS2_FIELDMASK )return -EINVAL ; -if (fdq->d_id !=from_kqid (&init_user_ns, qid)) +if (!qid_eq (make_kqid (current_user_ns (), qid.type, fdq->d_id), qid))return -EINVAL ; - error =qd_get (sdp, type,from_kqid (&init_user_ns, qid), &qd); + error =qd_get (sdp, qid, &qd);if (error)return error;fs/gfs2/quota.h +8
-7@@ -14,20 +14,21 @@ struct gfs2_inode;struct gfs2_sbd ;struct shrink_control ; -#define NO_QUOTA_CHANGE ((u32)-1) +#define NO_UID_QUOTA_CHANGE INVALID_UID +#define NO_GID_QUOTA_CHANGE INVALID_GID -extern int gfs2_quota_hold (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_hold (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_unhold (struct gfs2_inode *ip); -extern int gfs2_quota_lock (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_lock (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_unlock (struct gfs2_inode *ip); -extern int gfs2_quota_check (struct gfs2_inode *ip,u32 uid,u32 gid); +extern int gfs2_quota_check (struct gfs2_inode *ip,kuid_t uid,kgid_t gid);extern void gfs2_quota_change (struct gfs2_inode *ip,s64 change, -u32 uid,u32 gid); +kuid_t uid,kgid_t gid);extern int gfs2_quota_sync (struct super_block *sb,int type); -extern int gfs2_quota_refresh (struct gfs2_sbd *sdp,int user,u32 id); +extern int gfs2_quota_refresh (struct gfs2_sbd *sdp,struct kqid qid);extern int gfs2_quota_init (struct gfs2_sbd *sdp);extern void gfs2_quota_cleanup (struct gfs2_sbd *sdp);@@ -41,7 +42,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)int ret;if (sdp->sd_args.ar_quota ==GFS2_QUOTA_OFF )return 0 ; - ret =gfs2_quota_lock (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + ret =gfs2_quota_lock (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (ret)return ret;if (sdp->sd_args.ar_quota !=GFS2_QUOTA_ON )fs/gfs2/super.c +3
-3@@ -721,8 +721,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_num.no_addr =cpu_to_be64 (ip->i_no_addr); str->di_num.no_formal_ino =cpu_to_be64 (ip->i_no_formal_ino); str->di_mode =cpu_to_be32 (ip->i_inode.i_mode); - str->di_uid =cpu_to_be32 (ip->i_inode.i_uid); - str->di_gid =cpu_to_be32 (ip->i_inode.i_gid); + str->di_uid =cpu_to_be32 (i_uid_read (&ip->i_inode)); + str->di_gid =cpu_to_be32 (i_gid_read (&ip->i_inode)); str->di_nlink =cpu_to_be32 (ip->i_inode.i_nlink); str->di_size =cpu_to_be64 (i_size_read (&ip->i_inode)); str->di_blocks =cpu_to_be64 (gfs2_get_inode_blocks (&ip->i_inode));@@ -1428,7 +1428,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;fs/gfs2/sys.c +12
-2@@ -176,6 +176,7 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, size_t len) {int error; +struct kqid qid;u32 id;if (!capable (CAP_SYS_ADMIN ))@@ -183,7 +184,11 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, id =simple_strtoul (buf,NULL ,0 ); - error =gfs2_quota_refresh (sdp,1 , id); + qid =make_kqid (&init_user_ns,USRQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }@@ -191,6 +196,7 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, size_t len) {int error; +struct kqid qid;u32 id;if (!capable (CAP_SYS_ADMIN ))@@ -198,7 +204,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, id =simple_strtoul (buf,NULL ,0 ); - error =gfs2_quota_refresh (sdp,0 , id); + qid =make_kqid (&init_user_ns,GRPQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }fs/gfs2/xattr.c +2
-2@@ -331,7 +331,7 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error) goto out_alloc;@@ -1461,7 +1461,7 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)if (error)return error; - error =gfs2_quota_hold (ip,NO_QUOTA_CHANGE ,NO_QUOTA_CHANGE ); + error =gfs2_quota_hold (ip,NO_UID_QUOTA_CHANGE ,NO_GID_QUOTA_CHANGE );if (error)return error;init/Kconfig +0
-1@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on GFS2_FS = n depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n
RFC PATCH 7/12 userns: Convert ncpfs to use kuid and kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ncpfs/inode.c | 55 ++++++++++++++++++++++++++++++-------------------- fs/ncpfs/ioctl.c | 25 ++++++++++++---------- fs/ncpfs/ncp_fs_sb.h | 6 ++-- init/Kconfig | 1 - 4 files changed, 50 insertions(+), 37 deletions(-)
fs/ncpfs/inode.c +33 -22
@@ -331,12 +331,15 @@ static int ncp_show_options(struct seq_file *seq, struct dentry *root)struct ncp_server *server =NCP_SBP (root->d_sb);unsigned int tmp; -if (server->m.uid !=0 ) -seq_printf (seq,",uid=%u" , server->m.uid); -if (server->m.gid !=0 ) -seq_printf (seq,",gid=%u" , server->m.gid); -if (server->m.mounted_uid !=0 ) -seq_printf (seq,",owner=%u" , server->m.mounted_uid); +if (!uid_eq (server->m.uid,GLOBAL_ROOT_UID )) +seq_printf (seq,",uid=%u" , +from_kuid_munged (&init_user_ns, server->m.uid)); +if (!gid_eq (server->m.gid,GLOBAL_ROOT_GID )) +seq_printf (seq,",gid=%u" , +from_kgid_munged (&init_user_ns, server->m.gid)); +if (!uid_eq (server->m.mounted_uid,GLOBAL_ROOT_UID )) +seq_printf (seq,",owner=%u" , +from_kuid_munged (&init_user_ns, server->m.mounted_uid)); tmp = server->m.file_mode &S_IALLUGO ;if (tmp !=NCP_DEFAULT_FILE_MODE )seq_printf (seq,",mode=0%o" , tmp);
@@ -381,13 +384,13 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) data->flags =0 ; data->int_flags =0 ; - data->mounted_uid =0 ; + data->mounted_uid =GLOBAL_ROOT_UID ; data->wdog_pid =NULL ; data->ncp_fd = ~0 ; data->time_out =NCP_DEFAULT_TIME_OUT ; data->retry_count =NCP_DEFAULT_RETRY_COUNT ; - data->uid =0 ; - data->gid =0 ; + data->uid =GLOBAL_ROOT_UID ; + data->gid =GLOBAL_ROOT_GID ; data->file_mode =NCP_DEFAULT_FILE_MODE ; data->dir_mode =NCP_DEFAULT_DIR_MODE ; data->info_fd =-1 ;
@@ -399,13 +402,19 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) goto err;switch (optval) {case 'u' : - data->uid = optint; + data->uid =make_kuid (current_user_ns (), optint); +if (!uid_valid (data->uid)) + goto err;break ;case 'g' : - data->gid = optint; + data->gid =make_kgid (current_user_ns (), optint); +if (!gid_valid (data->gid)) + goto err;break ;case 'o' : - data->mounted_uid = optint; + data->mounted_uid =make_kuid (current_user_ns (), optint); +if (!uid_valid (data->mounted_uid)) + goto err;break ;case 'm' : data->file_mode = optint;
@@ -480,13 +489,13 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) data.flags = md->flags; data.int_flags =NCP_IMOUNT_LOGGEDIN_POSSIBLE ; - data.mounted_uid = md->mounted_uid; + data.mounted_uid =make_kuid (current_user_ns (), md->mounted_uid); data.wdog_pid =find_get_pid (md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; - data.uid = md->uid; - data.gid = md->gid; + data.uid =make_kuid (current_user_ns (), md->uid); + data.gid =make_kgid (current_user_ns (), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd =-1 ;
@@ -499,13 +508,13 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)struct ncp_mount_data_v4 * md = (struct ncp_mount_data_v4 *)raw_data; data.flags = md->flags; - data.mounted_uid = md->mounted_uid; + data.mounted_uid =make_kuid (current_user_ns (), md->mounted_uid); data.wdog_pid =find_get_pid (md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; - data.uid = md->uid; - data.gid = md->gid; + data.uid =make_kuid (current_user_ns (), md->uid); + data.gid =make_kgid (current_user_ns (), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd =-1 ;
@@ -520,6 +529,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) goto out;break ; } + error = -EINVAL ; +if (!uid_valid (data.mounted_uid) || !uid_valid (data.uid) || + !gid_valid (data.gid)) + goto out; error = -EBADF ; ncp_filp =fget (data.ncp_fd);if (!ncp_filp)
@@ -886,12 +899,10 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) goto out; result = -EPERM ; -if (((attr->ia_valid &ATTR_UID ) && - (attr->ia_uid != server->m.uid))) +if ((attr->ia_valid &ATTR_UID ) && !uid_eq (attr->ia_uid, server->m.uid)) goto out; -if (((attr->ia_valid &ATTR_GID ) && - (attr->ia_gid != server->m.gid))) +if ((attr->ia_valid &ATTR_GID ) && !gid_eq (attr->ia_gid, server->m.gid)) goto out; if (((attr->ia_valid & ATTR_MODE) &&
fs/ncpfs/ioctl.c +14 -11
@@ -45,7 +45,7 @@ ncp_get_fs_info(struct ncp_server * server, struct inode *inode,return -EINVAL ; }/* TODO: info.addr = server->m.serv_addr; */ -SET_UID (info.mounted_uid, server->m.mounted_uid); +SET_UID (info.mounted_uid,from_kuid_munged (current_user_ns (), server->m.mounted_uid)); info.connection = server->connection; info.buffer_size = server->buffer_size; info.volume_number =NCP_FINFO (inode)->volNumber;
@@ -69,7 +69,7 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,DPRINTK ("info.version invalid: %d\n" , info2.version);return -EINVAL ; } - info2.mounted_uid = server->m.mounted_uid; + info2.mounted_uid =from_kuid_munged (current_user_ns (), server->m.mounted_uid); info2.connection = server->connection; info2.buffer_size = server->buffer_size; info2.volume_number =NCP_FINFO (inode)->volNumber;
@@ -135,7 +135,7 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,DPRINTK ("info.version invalid: %d\n" , info2.version);return -EINVAL ; } - info2.mounted_uid = server->m.mounted_uid; + info2.mounted_uid =from_kuid_munged (current_user_ns (), server->m.mounted_uid); info2.connection = server->connection; info2.buffer_size = server->buffer_size; info2.volume_number =NCP_FINFO (inode)->volNumber;
@@ -348,22 +348,25 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg {u16 uid; -SET_UID (uid, server->m.mounted_uid); +SET_UID (uid,from_kuid_munged (current_user_ns (), server->m.mounted_uid));if (put_user (uid, (u16 __user *)argp))return -EFAULT ;return 0 ; }case NCP_IOC_GETMOUNTUID32 : -if (put_user (server->m.mounted_uid, - (u32 __user *)argp)) + { +uid_t uid =from_kuid_munged (current_user_ns (), server->m.mounted_uid); +if (put_user (uid, (u32 __user *)argp))return -EFAULT ;return 0 ; + }case NCP_IOC_GETMOUNTUID64 : -if (put_user (server->m.mounted_uid, - (u64 __user *)argp)) + { +uid_t uid =from_kuid_munged (current_user_ns (), server->m.mounted_uid); +if (put_user (uid, (u64 __user *)argp))return -EFAULT ;return 0 ; - + }case NCP_IOC_GETROOT : {struct ncp_setroot_ioctl sr;
@@ -810,7 +813,7 @@ long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {struct inode *inode = filp->f_dentry->d_inode;struct ncp_server *server =NCP_SERVER (inode); -uid_t uid =current_uid (); +kuid_t uid =current_uid ();int need_drop_write =0 ;long ret;
@@ -824,7 +827,7 @@ long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) }break ; } -if (server->m.mounted_uid != uid) { +if (!uid_eq (server->m.mounted_uid, uid)) {switch (cmd) {/* * Only mount owner can issue these ioctls. Information
fs/ncpfs/ncp_fs_sb.h +3 -3
@@ -23,15 +23,15 @@ struct ncp_mount_data_kernel {unsigned long flags;/* NCP_MOUNT_* flags */ unsigned int int_flags;/* internal flags */ #define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 -uid_t mounted_uid;/* Who may umount() this filesystem? */ +kuid_t mounted_uid;/* Who may umount() this filesystem? */ struct pid *wdog_pid;/* Who cares for our watchdog packets? */ unsigned int ncp_fd;/* The socket to the ncp port */ unsigned int time_out;/* How long should I wait after sending a NCP request? */ unsigned int retry_count;/* And how often should I retry? */ unsigned char mounted_vol[NCP_VOLNAME_LEN +1 ]; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;umode_t file_mode;umode_t dir_mode;int info_fd;
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n depends on OCFS2_FS = n
Signature · 1 line
1.7.5.4
RFC PATCH 8/12 userns: Convert nfs and nfsd to use kuid/kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Changed as many fields as practical to be kuid_t and kgid_t. With the result that we create kuids and kgids in the network decodes and we change out of kuids and kgids in the network encoders.
The one slight exception to this is the name to id mapping where we use a plane unsigned integer as the key, instead of a kuid_t or a kgid_t. Using a plain integer is necessary to prevent duplication of all of the mapping state.
This one was a little tricky as nfs has some special cases where INVALID_UID aka -1 is used to indicate that the uid does not have a mapping and where 2^16 -2 is used to talk about nobody or the overflowuid, and similary for gids.
I believe I have converted everything correctly, but if I have not in the worst case there will be a place or two where a uid_valid or a gid_valid check will need to be removed.
--- fs/nfs/idmap.c | 45 ++++++++++++++++---------- fs/nfs/inode.c | 12 +++--- fs/nfs/nfs2xdr.c | 8 ++-- fs/nfs/nfs3xdr.c | 8 ++-- fs/nfs/nfs4xdr.c | 16 +++++----- fs/nfs_common/nfsacl.c | 37 +++++++++++++--------- fs/nfsd/acl.h | 2 - fs/nfsd/auth.c | 12 +++--- fs/nfsd/export.c | 22 ++++++++----- fs/nfsd/idmap.h | 8 ++-- fs/nfsd/nfs3xdr.c | 9 +++-- fs/nfsd/nfs4acl.c | 63 +++++++++++++++++++++++++++---------- fs/nfsd/nfs4idmap.c | 34 +++++++++++++------- fs/nfsd/nfs4recover.c | 4 +- fs/nfsd/nfs4state.c | 6 ++-- fs/nfsd/nfs4xdr.c | 42 +++++++++++++++--------- fs/nfsd/nfsxdr.c | 9 +++-- fs/nfsd/vfs.c | 8 ++-- include/linux/nfs4.h | 6 +++- include/linux/nfs_idmap.h | 10 +++--- include/linux/nfs_xdr.h | 4 +- include/linux/nfsd/export.h | 4 +- include/linux/sunrpc/auth.h | 7 ++-- include/linux/sunrpc/svcauth.h | 4 +- init/Kconfig | 2 - net/sunrpc/auth.c | 6 ++-- net/sunrpc/auth_generic.c | 16 +++++---- net/sunrpc/auth_gss/auth_gss.c | 33 ++++++++++++------- net/sunrpc/auth_gss/svcauth_gss.c | 14 +++++++- net/sunrpc/auth_unix.c | 36 +++++++++------------ net/sunrpc/svcauth_unix.c | 40 ++++++++++++++--------- 31 files changed, 312 insertions(+), 215 deletions(-)
fs/nfs/idmap.c +28 -17
@@ -97,7 +97,7 @@ static void nfs_fattr_free_group_name(struct nfs_fattr *fattr)static bool nfs_fattr_map_owner_name (struct nfs_server *server,struct nfs_fattr *fattr) {struct nfs4_string *owner = fattr->owner_name; -__u32 uid; +kuid_t uid;if (!(fattr->valid &NFS_ATTR_FATTR_OWNER_NAME ))return false;
@@ -111,7 +111,7 @@ static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattrstatic bool nfs_fattr_map_group_name (struct nfs_server *server,struct nfs_fattr *fattr) {struct nfs4_string *group = fattr->group_name; -__u32 gid; +kgid_t gid;if (!(fattr->valid &NFS_ATTR_FATTR_GROUP_NAME ))return false;
@@ -193,7 +193,8 @@ static int nfs_idmap_init_keyring(void)if (!cred)return -ENOMEM ; - keyring =key_alloc (&key_type_keyring,".id_resolver" ,0 ,0 , cred, + keyring =key_alloc (&key_type_keyring,".id_resolver" , +GLOBAL_ROOT_UID ,GLOBAL_ROOT_GID , cred, (KEY_POS_ALL & ~KEY_POS_SETATTR ) |KEY_USR_VIEW |KEY_USR_READ ,KEY_ALLOC_NOT_IN_QUOTA );
@@ -840,43 +841,53 @@ idmap_release_pipe(struct inode *inode)nfs_idmap_abort_pipe_upcall (idmap, -EPIPE ); } -int nfs_map_name_to_uid (const struct nfs_server *server,const char *name,size_t namelen,__u32 *uid) +int nfs_map_name_to_uid (const struct nfs_server *server,const char *name,size_t namelen,kuid_t *uid) {struct idmap *idmap = server->nfs_client->cl_idmap; +__u32 id =-1 ; +int ret =0 ; -if (nfs_map_string_to_numeric (name, namelen, uid)) -return 0 ; -return nfs_idmap_lookup_id (name, namelen,"uid" , uid, idmap); +if (!nfs_map_string_to_numeric (name, namelen, &id)) + ret =nfs_idmap_lookup_id (name, namelen,"uid" , &id, idmap); + *uid =make_kuid (&init_user_ns, id); +return ret; } -int nfs_map_group_to_gid (const struct nfs_server *server,const char *name,size_t namelen,__u32 *gid) +int nfs_map_group_to_gid (const struct nfs_server *server,const char *name,size_t namelen,kgid_t *gid) {struct idmap *idmap = server->nfs_client->cl_idmap; +__u32 id =-1 ; +int ret =0 ; -if (nfs_map_string_to_numeric (name, namelen, gid)) -return 0 ; -return nfs_idmap_lookup_id (name, namelen,"gid" , gid, idmap); +if (!nfs_map_string_to_numeric (name, namelen, &id)) +nfs_idmap_lookup_id (name, namelen,"gid" , &id, idmap); + *gid =make_kgid (&init_user_ns, id); +return ret; } -int nfs_map_uid_to_name (const struct nfs_server *server,__u32 uid,char *buf,size_t buflen) +int nfs_map_uid_to_name (const struct nfs_server *server,kuid_t uid,char *buf,size_t buflen) {struct idmap *idmap = server->nfs_client->cl_idmap;int ret = -EINVAL ; +unsigned int id; + id =from_kuid (&init_user_ns, uid);if (!(server->caps &NFS_CAP_UIDGID_NOMAP )) - ret =nfs_idmap_lookup_name (uid,"user" , buf, buflen, idmap); + ret =nfs_idmap_lookup_name (id,"user" , buf, buflen, idmap);if (ret <0 ) - ret =nfs_map_numeric_to_string (uid, buf, buflen); + ret =nfs_map_numeric_to_string (id, buf, buflen);return ret; } -int nfs_map_gid_to_group (const struct nfs_server *server,__u32 gid,char *buf,size_t buflen) +int nfs_map_gid_to_group (const struct nfs_server *server,kgid_t gid,char *buf,size_t buflen) {struct idmap *idmap = server->nfs_client->cl_idmap;int ret = -EINVAL ; +unsigned int id; + id =from_kgid (&init_user_ns, gid);if (!(server->caps &NFS_CAP_UIDGID_NOMAP )) - ret =nfs_idmap_lookup_name (gid,"group" , buf, buflen, idmap); + ret =nfs_idmap_lookup_name (id,"group" , buf, buflen, idmap);if (ret <0 ) - ret =nfs_map_numeric_to_string (gid, buf, buflen); + ret =nfs_map_numeric_to_string (id, buf, buflen);return ret; }
fs/nfs/inode.c +6 -6
@@ -323,8 +323,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) inode->i_version =0 ; inode->i_size =0 ;clear_nlink (inode); - inode->i_uid =-2 ; - inode->i_gid =-2 ; +i_uid_write (inode,-2 ); +i_gid_write (inode,-2 ); inode->i_blocks =0 ;memset (nfsi->cookieverf,0 ,sizeof (nfsi->cookieverf)); nfsi->write_io =0 ;
@@ -993,9 +993,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat/* Have any file permissions changed? */ if ((fattr->valid &NFS_ATTR_FATTR_MODE ) && (inode->i_mode &S_IALLUGO ) != (fattr->mode &S_IALLUGO )) invalid |=NFS_INO_INVALID_ATTR |NFS_INO_INVALID_ACCESS |NFS_INO_INVALID_ACL ; -if ((fattr->valid &NFS_ATTR_FATTR_OWNER ) && inode->i_uid != fattr->uid) +if ((fattr->valid &NFS_ATTR_FATTR_OWNER ) && !uid_eq (inode->i_uid, fattr->uid)) invalid |=NFS_INO_INVALID_ATTR |NFS_INO_INVALID_ACCESS |NFS_INO_INVALID_ACL ; -if ((fattr->valid &NFS_ATTR_FATTR_GROUP ) && inode->i_gid != fattr->gid) +if ((fattr->valid &NFS_ATTR_FATTR_GROUP ) && !gid_eq (inode->i_gid, fattr->gid)) invalid |=NFS_INO_INVALID_ATTR |NFS_INO_INVALID_ACCESS |NFS_INO_INVALID_ACL ;/* Has the link count changed? */
@@ -1422,7 +1422,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | NFS_INO_REVAL_FORCED);if (fattr->valid &NFS_ATTR_FATTR_OWNER ) { -if (inode->i_uid != fattr->uid) { +if (!uid_eq (inode->i_uid, fattr->uid)) { invalid |=NFS_INO_INVALID_ATTR |NFS_INO_INVALID_ACCESS |NFS_INO_INVALID_ACL ; inode->i_uid = fattr->uid; }
@@ -1433,7 +1433,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | NFS_INO_REVAL_FORCED);if (fattr->valid &NFS_ATTR_FATTR_GROUP ) { -if (inode->i_gid != fattr->gid) { +if (!gid_eq (inode->i_gid, fattr->gid)) { invalid |=NFS_INO_INVALID_ATTR |NFS_INO_INVALID_ACCESS |NFS_INO_INVALID_ACL ; inode->i_gid = fattr->gid; }
fs/nfs/nfs2xdr.c +4 -4
@@ -291,8 +291,8 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) fattr->mode =be32_to_cpup (p++); fattr->nlink =be32_to_cpup (p++); - fattr->uid =be32_to_cpup (p++); - fattr->gid =be32_to_cpup (p++); + fattr->uid =make_kuid (&init_user_ns,be32_to_cpup (p++)); + fattr->gid =make_kgid (&init_user_ns,be32_to_cpup (p++)); fattr->size =be32_to_cpup (p++); fattr->du.nfs2.blocksize =be32_to_cpup (p++);
@@ -352,11 +352,11 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)else *p++ =cpu_to_be32 (NFS2_SATTR_NOT_SET );if (attr->ia_valid &ATTR_UID ) - *p++ =cpu_to_be32 (attr->ia_uid); + *p++ =cpu_to_be32 (from_kuid (&init_user_ns, attr->ia_uid));else *p++ =cpu_to_be32 (NFS2_SATTR_NOT_SET );if (attr->ia_valid &ATTR_GID ) - *p++ =cpu_to_be32 (attr->ia_gid); + *p++ =cpu_to_be32 (from_kgid (&init_user_ns, attr->ia_gid));else *p++ =cpu_to_be32 (NFS2_SATTR_NOT_SET );if (attr->ia_valid &ATTR_SIZE )
fs/nfs/nfs3xdr.c +4 -4
@@ -594,13 +594,13 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)if (attr->ia_valid &ATTR_UID ) { *p++ = xdr_one; - *p++ =cpu_to_be32 (attr->ia_uid); + *p++ =cpu_to_be32 (from_kuid (&init_user_ns, attr->ia_uid)); }else *p++ = xdr_zero;if (attr->ia_valid &ATTR_GID ) { *p++ = xdr_one; - *p++ =cpu_to_be32 (attr->ia_gid); + *p++ =cpu_to_be32 (from_kgid (&init_user_ns, attr->ia_gid)); }else *p++ = xdr_zero;
@@ -659,8 +659,8 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) fattr->mode = (be32_to_cpup (p++) & ~S_IFMT ) | fmode; fattr->nlink =be32_to_cpup (p++); - fattr->uid =be32_to_cpup (p++); - fattr->gid =be32_to_cpup (p++); + fattr->uid =make_kuid (&init_user_ns,be32_to_cpup (p++)); + fattr->gid =make_kgid (&init_user_ns,be32_to_cpup (p++)); p =xdr_decode_size3 (p, &fattr->size); p =xdr_decode_size3 (p, &fattr->du.nfs3.used);
fs/nfs/nfs4xdr.c +8 -8
@@ -999,7 +999,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const owner_namelen =nfs_map_uid_to_name (server, iap->ia_uid, owner_name,IDMAP_NAMESZ );if (owner_namelen <0 ) {dprintk ("nfs: couldn't resolve uid %d to string\n" , - iap->ia_uid); +from_kuid (&init_user_ns, iap->ia_uid));/* XXX */ strcpy (owner_name,"nobody" ); owner_namelen =sizeof ("nobody" ) -1 ;
@@ -1011,7 +1011,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const owner_grouplen =nfs_map_gid_to_group (server, iap->ia_gid, owner_group,IDMAP_NAMESZ );if (owner_grouplen <0 ) {dprintk ("nfs: couldn't resolve gid %d to string\n" , - iap->ia_gid); +from_kgid (&init_user_ns, iap->ia_gid));strcpy (owner_group,"nobody" ); owner_grouplen =sizeof ("nobody" ) -1 ;/* goto out; */
@@ -3778,14 +3778,14 @@ out_overflow: }static int decode_attr_owner (struct xdr_stream *xdr,uint32_t *bitmap, -const struct nfs_server *server,uint32_t *uid, +const struct nfs_server *server,kuid_t *uid,struct nfs4_string *owner_name) {uint32_t len;__be32 *p;int ret =0 ; - *uid =-2 ; + *uid =make_kuid (&init_user_ns,-2 );if (unlikely (bitmap[1 ] & (FATTR4_WORD1_OWNER -1U )))return -EIO ;if (likely (bitmap[1 ] &FATTR4_WORD1_OWNER )) {
@@ -3813,7 +3813,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, __func__, len); bitmap[1 ] &= ~FATTR4_WORD1_OWNER ; } -dprintk ("%s: uid=%d\n" , __func__, (int )*uid); +dprintk ("%s: uid=%d\n" , __func__, (int )from_kuid (&init_user_ns, *uid));return ret; out_overflow:print_overflow_msg (__func__, xdr);
@@ -3821,14 +3821,14 @@ out_overflow: }static int decode_attr_group (struct xdr_stream *xdr,uint32_t *bitmap, -const struct nfs_server *server,uint32_t *gid, +const struct nfs_server *server,kgid_t *gid,struct nfs4_string *group_name) {uint32_t len;__be32 *p;int ret =0 ; - *gid =-2 ; + *gid =make_kgid (&init_user_ns,-2 );if (unlikely (bitmap[1 ] & (FATTR4_WORD1_OWNER_GROUP -1U )))return -EIO ;if (likely (bitmap[1 ] &FATTR4_WORD1_OWNER_GROUP )) {
@@ -3856,7 +3856,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, __func__, len); bitmap[1 ] &= ~FATTR4_WORD1_OWNER_GROUP ; } -dprintk ("%s: gid=%d\n" , __func__, (int )*gid); +dprintk ("%s: gid=%d\n" , __func__, (int )from_kgid (&init_user_ns, *gid));return ret; out_overflow:print_overflow_msg (__func__, xdr);
fs/nfs_common/nfsacl.c +22 -15
@@ -38,8 +38,8 @@ struct nfsacl_encode_desc {unsigned int count;struct posix_acl *acl;int typeflag; -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid; };struct nfsacl_simple_acl {
@@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) *p++ =htonl (entry->e_tag | nfsacl_desc->typeflag);switch (entry->e_tag) {case ACL_USER_OBJ : - *p++ =htonl (nfsacl_desc->uid); + *p++ =htonl (from_kuid (&init_user_ns, nfsacl_desc->uid));break ;case ACL_GROUP_OBJ : - *p++ =htonl (nfsacl_desc->gid); + *p++ =htonl (from_kgid (&init_user_ns, nfsacl_desc->gid));break ;case ACL_USER : + *p++ =htonl (from_kuid (&init_user_ns, entry->e_uid)); +break ;case ACL_GROUP : - *p++ =htonl (entry->e_id); + *p++ =htonl (from_kgid (&init_user_ns, entry->e_gid));break ;default :/* Solaris depends on that! */ *p++ =0 ;
@@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) (struct nfsacl_decode_desc *) desc;__be32 *p = elem;struct posix_acl_entry *entry; +unsigned int id;if (!nfsacl_desc->acl) {if (desc->array_len >NFS_ACL_MAX_ENTRIES )
@@ -160,14 +163,18 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; entry->e_tag =ntohl (*p++) & ~NFS_ACL_DEFAULT ; - entry->e_id =ntohl (*p++); + id =ntohl (*p++); entry->e_perm =ntohl (*p++);switch (entry->e_tag) { -case ACL_USER_OBJ :case ACL_USER : -case ACL_GROUP_OBJ : + entry->e_uid =make_kuid (&init_user_ns, id); +break ;case ACL_GROUP : + entry->e_gid =make_kgid (&init_user_ns, id); +break ; +case ACL_USER_OBJ : +case ACL_GROUP_OBJ :case ACL_OTHER :if (entry->e_perm & ~S_IRWXO )return -EINVAL ;
@@ -190,9 +197,13 @@ cmp_acl_entry(const void *x, const void *y)if (a->e_tag != b->e_tag)return a->e_tag - b->e_tag; -else if (a->e_id > b->e_id) +else if ((a->e_tag ==ACL_USER ) &&uid_gt (a->e_uid, b->e_uid)) +return 1 ; +else if ((a->e_tag ==ACL_USER ) &&uid_lt (a->e_uid, b->e_uid)) +return -1 ; +else if ((a->e_tag ==ACL_GROUP ) &&gid_gt (a->e_gid, b->e_gid))return 1 ; -else if (a->e_id < b->e_id) +else if ((a->e_tag ==ACL_GROUP ) &&gid_lt (a->e_gid, b->e_gid))return -1 ;else return 0 ;
@@ -213,22 +224,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl)sort (acl->a_entries, acl->a_count,sizeof (struct posix_acl_entry ), cmp_acl_entry,NULL ); -/* Clear undefined identifier fields and find the ACL_GROUP_OBJ -and ACL_MASK entries. */ +/* Find the ACL_GROUP_OBJ and ACL_MASK entries. */ FOREACH_ACL_ENTRY(pa, acl, pe) {switch (pa->e_tag) {case ACL_USER_OBJ : - pa->e_id =ACL_UNDEFINED_ID ;break ;case ACL_GROUP_OBJ : - pa->e_id =ACL_UNDEFINED_ID ; group_obj = pa;break ;case ACL_MASK : mask = pa;/* fall through */ case ACL_OTHER : - pa->e_id =ACL_UNDEFINED_ID ;break ; } }
fs/nfsd/acl.h +0 -2
@@ -44,8 +44,6 @@struct nfs4_acl *nfs4_acl_new (int );int nfs4_acl_get_whotype (char *,u32 );int nfs4_acl_write_who (int who,char *p); -int nfs4_acl_permission (struct nfs4_acl *acl,uid_t owner,gid_t group, -uid_t who,u32 mask);#define NFS4_ACL_TYPE_DEFAULT 0x01#define NFS4_ACL_DIR 0x02
fs/nfsd/auth.c +6 -6
@@ -47,9 +47,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)if (!gi) goto oom; }else if (flags &NFSEXP_ROOTSQUASH ) { -if (!new->fsuid) +if (uid_eq (new->fsuid,GLOBAL_ROOT_UID )) new->fsuid = exp->ex_anon_uid; -if (!new->fsgid) +if (gid_eq (new->fsgid,GLOBAL_ROOT_GID )) new->fsgid = exp->ex_anon_gid; gi =groups_alloc (rqgi->ngroups);
@@ -58,7 +58,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)for (i =0 ; i < rqgi->ngroups; i++) {if (gid_eq (GLOBAL_ROOT_GID ,GROUP_AT (rqgi, i))) -GROUP_AT (gi, i) =make_kgid (&init_user_ns, exp->ex_anon_gid); +GROUP_AT (gi, i) = exp->ex_anon_gid;else GROUP_AT (gi, i) =GROUP_AT (rqgi, i); }
@@ -66,9 +66,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) gi =get_group_info (rqgi); } -if (new->fsuid == (uid_t) -1 ) +if (uid_eq (new->fsuid,INVALID_UID )) new->fsuid = exp->ex_anon_uid; -if (new->fsgid == (gid_t) -1 ) +if (gid_eq (new->fsgid,INVALID_GID )) new->fsgid = exp->ex_anon_gid; ret =set_groups (new, gi);
@@ -76,7 +76,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)if (ret <0 ) goto error; -if (new->fsuid) +if (!uid_eq (new->fsuid,GLOBAL_ROOT_UID )) new->cap_effective =cap_drop_nfsd_set (new->cap_effective);else new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
fs/nfsd/export.c +14 -8
@@ -544,13 +544,17 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) err =get_int (&mesg, &an_int);if (err) goto out3; - exp.ex_anon_uid= an_int; + exp.ex_anon_uid =make_kuid (&init_user_ns, an_int); +if (!uid_valid (exp.ex_anon_uid)) + goto out3;/* anon gid */ err =get_int (&mesg, &an_int);if (err) goto out3; - exp.ex_anon_gid= an_int; + exp.ex_anon_gid =make_kgid (&init_user_ns, an_int); +if (!gid_valid (exp.ex_anon_gid)) + goto out3;/* fsid */ err =get_int (&mesg, &an_int);
@@ -613,7 +617,7 @@ out: }static void exp_flags (struct seq_file *m,int flag,int fsid, -uid_t anonu,uid_t anong,struct nfsd4_fs_locations *fslocs); +kuid_t anonu,kgid_t anong,struct nfsd4_fs_locations *fslocs);static void show_secinfo (struct seq_file *m,struct svc_export *exp); static int svc_export_show(struct seq_file *m,
@@ -1179,15 +1183,17 @@ static void show_secinfo(struct seq_file *m, struct svc_export *exp) }static void exp_flags (struct seq_file *m,int flag,int fsid, -uid_t anonu,uid_t anong,struct nfsd4_fs_locations *fsloc) +kuid_t anonu,kgid_t anong,struct nfsd4_fs_locations *fsloc) {show_expflags (m, flag,NFSEXP_ALLFLAGS );if (flag &NFSEXP_FSID )seq_printf (m,",fsid=%d" , fsid); -if (anonu != (uid_t)-2 && anonu != (0x10000 -2 )) -seq_printf (m,",anonuid=%u" , anonu); -if (anong != (gid_t)-2 && anong != (0x10000 -2 )) -seq_printf (m,",anongid=%u" , anong); +if (!uid_eq (anonu,make_kuid (&init_user_ns, (uid_t)-2 )) && + !uid_eq (anonu,make_kuid (&init_user_ns,0x10000 -2 ))) +seq_printf (m,",anonuid=%u" ,from_kuid (&init_user_ns, anonu)); +if (!gid_eq (anong,make_kgid (&init_user_ns, (gid_t)-2 )) && + !gid_eq (anong,make_kgid (&init_user_ns,0x10000 -2 ))) +seq_printf (m,",anongid=%u" ,from_kgid (&init_user_ns, anong));if (fsloc && fsloc->locations_count >0 ) {char *loctype = (fsloc->migrated) ?"refer" :"replicas" ;int i;
fs/nfsd/idmap.h +4 -4
@@ -54,9 +54,9 @@ static inline void nfsd_idmap_shutdown(struct net *net) }#endif -__be32 nfsd_map_name_to_uid (struct svc_rqst *,const char *,size_t ,__u32 *); -__be32 nfsd_map_name_to_gid (struct svc_rqst *,const char *,size_t ,__u32 *); -int nfsd_map_uid_to_name (struct svc_rqst *,__u32 ,char *); -int nfsd_map_gid_to_name (struct svc_rqst *,__u32 ,char *); +__be32 nfsd_map_name_to_uid (struct svc_rqst *,const char *,size_t ,kuid_t *); +__be32 nfsd_map_name_to_gid (struct svc_rqst *,const char *,size_t ,kgid_t *); +int nfsd_map_uid_to_name (struct svc_rqst *,kuid_t ,char *); +int nfsd_map_gid_to_name (struct svc_rqst *,kgid_t ,char *);#endif /* LINUX_NFSD_IDMAP_H */
fs/nfsd/nfs3xdr.c +5 -4
@@ -7,6 +7,7 @@*/ #include <linux/namei.h> +#include <linux/user_namespace.h> #include "xdr3.h" #include "auth.h"
@@ -104,11 +105,11 @@ decode_sattr3(__be32 *p, struct iattr *iap) }if (*p++) { iap->ia_valid |=ATTR_UID ; - iap->ia_uid =ntohl (*p++); + iap->ia_uid =make_kuid (&init_user_ns,ntohl (*p++)); }if (*p++) { iap->ia_valid |=ATTR_GID ; - iap->ia_gid =ntohl (*p++); + iap->ia_gid =make_kgid (&init_user_ns,ntohl (*p++)); }if (*p++) {u64 newsize;
@@ -165,8 +166,8 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, *p++ =htonl (nfs3_ftypes[(stat->mode &S_IFMT ) >>12 ]); *p++ =htonl ((u32 ) stat->mode); *p++ =htonl ((u32 ) stat->nlink); - *p++ =htonl ((u32 )nfsd_ruid (rqstp, stat->uid)); - *p++ =htonl ((u32 )nfsd_rgid (rqstp, stat->gid)); + *p++ =htonl ((u32 )nfsd_ruid (rqstp,from_kuid (&init_user_ns, stat->uid))); + *p++ =htonl ((u32 )nfsd_rgid (rqstp,from_kgid (&init_user_ns, stat->gid)));if (S_ISLNK (stat->mode) && stat->size >NFS3_MAXPATHLEN ) { p =xdr_encode_hyper (p, (u64 )NFS3_MAXPATHLEN ); }else {
fs/nfsd/nfs4acl.c +46 -17
169 lines not on this page · raw message
fs/nfsd/nfs4idmap.c +22 -12
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(nfs4_disable_idmapping,struct ent {struct cache_head h;int type;/* User / Group */ -uid_t id; +u32 id;char name[IDMAP_NAMESZ ];char authname[IDMAP_NAMESZ ]; };
@@ -540,7 +540,7 @@ rqst_authname(struct svc_rqst *rqstp)static __be32 idmap_name_to_id (struct svc_rqst *rqstp,int type,const char *name,u32 namelen, -uid_t *id) +u32 *id) {struct ent *item, key = { .type = type,
@@ -564,7 +564,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen }static int -idmap_id_to_name (struct svc_rqst *rqstp,int type,uid_t id,char *name) +idmap_id_to_name (struct svc_rqst *rqstp,int type,u32 id,char *name) {struct ent *item, key = { .id = id,
@@ -587,7 +587,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) }static bool -numeric_name_to_id (struct svc_rqst *rqstp,int type,const char *name,u32 namelen,uid_t *id) +numeric_name_to_id (struct svc_rqst *rqstp,int type,const char *name,u32 namelen,u32 *id) {int ret;char buf[11 ];
@@ -603,7 +603,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel }static __be32 -do_name_to_id (struct svc_rqst *rqstp,int type,const char *name,u32 namelen,uid_t *id) +do_name_to_id (struct svc_rqst *rqstp,int type,const char *name,u32 namelen,u32 *id) {if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor <RPC_AUTH_GSS )if (numeric_name_to_id (rqstp, type, name, namelen, id))
@@ -616,7 +616,7 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u }static int -do_id_to_name (struct svc_rqst *rqstp,int type,uid_t id,char *name) +do_id_to_name (struct svc_rqst *rqstp,int type,u32 id,char *name) {if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor <RPC_AUTH_GSS )return sprintf (name,"%u" , id);
@@ -625,26 +625,36 @@ do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)__be32 nfsd_map_name_to_uid (struct svc_rqst *rqstp,const char *name,size_t namelen, -__u32 *id) +kuid_t *uid) { -return do_name_to_id (rqstp,IDMAP_TYPE_USER , name, namelen, id); +__be32 status; +__u32 id =-1 ; + status =do_name_to_id (rqstp,IDMAP_TYPE_USER , name, namelen, &id); + *uid =make_kuid (&init_user_ns, id); +return status; }__be32 nfsd_map_name_to_gid (struct svc_rqst *rqstp,const char *name,size_t namelen, -__u32 *id) +kgid_t *gid) { -return do_name_to_id (rqstp,IDMAP_TYPE_GROUP , name, namelen, id); +__be32 status; +__u32 id =-1 ; + status =do_name_to_id (rqstp,IDMAP_TYPE_GROUP , name, namelen, &id); + *gid =make_kgid (&init_user_ns, id); +return status; }int -nfsd_map_uid_to_name (struct svc_rqst *rqstp,__u32 id,char *name) +nfsd_map_uid_to_name (struct svc_rqst *rqstp,kuid_t uid,char *name) { +__u32 id =from_kuid (&init_user_ns, uid);return do_id_to_name (rqstp,IDMAP_TYPE_USER , id, name); }int -nfsd_map_gid_to_name (struct svc_rqst *rqstp,__u32 id,char *name) +nfsd_map_gid_to_name (struct svc_rqst *rqstp,kgid_t gid,char *name) { +__u32 id =from_kgid (&init_user_ns, gid);return do_id_to_name (rqstp,IDMAP_TYPE_GROUP , id, name); }
fs/nfsd/nfs4recover.c +2 -2
@@ -75,8 +75,8 @@ nfs4_save_creds(const struct cred **original_creds)if (!new)return -ENOMEM ; - new->fsuid =0 ; - new->fsgid =0 ; + new->fsuid =GLOBAL_ROOT_UID ; + new->fsgid =GLOBAL_ROOT_GID ; *original_creds =override_creds (new);put_cred (new);return 0 ;
fs/nfsd/nfs4state.c +3 -3
@@ -1211,7 +1211,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)if (g1->ngroups != g2->ngroups)return false;for (i=0 ; i<g1->ngroups; i++) -if (GROUP_AT (g1, i) !=GROUP_AT (g2, i)) +if (!gid_eq (GROUP_AT (g1, i),GROUP_AT (g2, i)))return false;return true; }
@@ -1236,8 +1236,8 @@ static bool same_creds(struct svc_cred *cr1, struct svc_cred *cr2) {if ((is_gss_cred (cr1) !=is_gss_cred (cr2)) - || (cr1->cr_uid != cr2->cr_uid) - || (cr1->cr_gid != cr2->cr_gid) + || (!uid_eq (cr1->cr_uid, cr2->cr_uid)) + || (!gid_eq (cr1->cr_gid, cr2->cr_gid)) || !groups_equal (cr1->cr_group_info, cr2->cr_group_info))return false;if (cr1->cr_principal == cr2->cr_principal)
fs/nfsd/nfs4xdr.c +26 -16
87 lines not on this page · raw message
fs/nfsd/nfsxdr.c +5 -4
@@ -4,6 +4,7 @@* Copyright (C) 1995, 1996 Olaf Kirch <[email protected]> */ +#include <linux/user_namespace.h> #include "xdr.h" #include "auth.h"
@@ -101,11 +102,11 @@ decode_sattr(__be32 *p, struct iattr *iap) }if ((tmp =ntohl (*p++)) != (u32)-1 ) { iap->ia_valid |=ATTR_UID ; - iap->ia_uid = tmp; + iap->ia_uid =make_kuid (&init_user_ns, tmp); }if ((tmp =ntohl (*p++)) != (u32)-1 ) { iap->ia_valid |=ATTR_GID ; - iap->ia_gid = tmp; + iap->ia_gid =make_kgid (&init_user_ns, tmp); }if ((tmp =ntohl (*p++)) != (u32)-1 ) { iap->ia_valid |=ATTR_SIZE ;
@@ -151,8 +152,8 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, *p++ =htonl (nfs_ftypes[type >>12 ]); *p++ =htonl ((u32 ) stat->mode); *p++ =htonl ((u32 ) stat->nlink); - *p++ =htonl ((u32 )nfsd_ruid (rqstp, stat->uid)); - *p++ =htonl ((u32 )nfsd_rgid (rqstp, stat->gid)); + *p++ =htonl ((u32 )nfsd_ruid (rqstp,from_kuid (&init_user_ns, stat->uid))); + *p++ =htonl ((u32 )nfsd_rgid (rqstp,from_kgid (&init_user_ns, stat->gid)));if (S_ISLNK (type) && stat->size >NFS_MAXPATHLEN ) { *p++ =htonl (NFS_MAXPATHLEN );
fs/nfsd/vfs.c +4 -4
@@ -401,8 +401,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,/* Revoke setuid/setgid on chown */ if (!S_ISDIR (inode->i_mode) && - (((iap->ia_valid &ATTR_UID ) && iap->ia_uid != inode->i_uid) || - ((iap->ia_valid &ATTR_GID ) && iap->ia_gid != inode->i_gid))) { + (((iap->ia_valid &ATTR_UID ) && !uid_eq (iap->ia_uid, inode->i_uid)) || + ((iap->ia_valid &ATTR_GID ) && !gid_eq (iap->ia_gid, inode->i_gid)))) { iap->ia_valid |=ATTR_KILL_PRIV ;if (iap->ia_valid &ATTR_MODE ) {/* we're setting mode too, just clear the s*id bits */
@@ -1221,7 +1221,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,* send along the gid on create when it tries to implement * setgid directories via NFS: */ -if (current_fsuid () !=0 ) +if (!uid_eq (current_fsuid (),GLOBAL_ROOT_UID )) iap->ia_valid &= ~(ATTR_UID |ATTR_GID );if (iap->ia_valid)return nfsd_setattr (rqstp, resfhp, iap,0 , (time_t )0 );
@@ -2160,7 +2160,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,* with NFSv3. */ if ((acc &NFSD_MAY_OWNER_OVERRIDE ) && - inode->i_uid ==current_fsuid ()) +uid_eq (inode->i_uid,current_fsuid ()))return 0 ;/* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
include/linux/nfs4.h +5 -1
@@ -13,6 +13,7 @@#define _LINUX_NFS4_H#include <linux/list.h> +#include <linux/uidgid.h> #include <uapi/linux/nfs4.h> struct nfs4_ace {
@@ -20,7 +21,10 @@ struct nfs4_ace {uint32_t flag;uint32_t access_mask;int whotype; -uid_t who; +union { +kuid_t who_uid; +kgid_t who_gid; + }; };struct nfs4_acl {
include/linux/nfs_idmap.h +5 -5
@@ -36,9 +36,9 @@#ifndef NFS_IDMAP_H #define NFS_IDMAP_H +#include <linux/uidgid.h> #include <uapi/linux/nfs_idmap.h> -/* Forward declaration to make this header independent of others */ struct nfs_client ;struct nfs_server ;
@@ -67,10 +67,10 @@ void nfs_fattr_init_names(struct nfs_fattr *fattr,void nfs_fattr_free_names (struct nfs_fattr *);void nfs_fattr_map_and_free_names (struct nfs_server *,struct nfs_fattr *); -int nfs_map_name_to_uid (const struct nfs_server *,const char *,size_t ,__u32 *); -int nfs_map_group_to_gid (const struct nfs_server *,const char *,size_t ,__u32 *); -int nfs_map_uid_to_name (const struct nfs_server *,__u32 ,char *,size_t ); -int nfs_map_gid_to_group (const struct nfs_server *,__u32 ,char *,size_t ); +int nfs_map_name_to_uid (const struct nfs_server *,const char *,size_t ,kuid_t *); +int nfs_map_group_to_gid (const struct nfs_server *,const char *,size_t ,kgid_t *); +int nfs_map_uid_to_name (const struct nfs_server *,kuid_t ,char *,size_t ); +int nfs_map_gid_to_group (const struct nfs_server *,kgid_t ,char *,size_t );extern unsigned int nfs_idmap_cache_timeout;#endif /* NFS_IDMAP_H */
include/linux/nfs_xdr.h +2 -2
@@ -48,8 +48,8 @@ struct nfs_fattr {unsigned int valid;/* which fields are valid */ umode_t mode;__u32 nlink; -__u32 uid; -__u32 gid; +kuid_t uid; +kgid_t gid;dev_t rdev;__u64 size;union {
include/linux/nfsd/export.h +2 -2
@@ -49,8 +49,8 @@ struct svc_export {struct auth_domain * ex_client;int ex_flags;struct path ex_path; -uid_t ex_anon_uid; -gid_t ex_anon_gid; +kuid_t ex_anon_uid; +kgid_t ex_anon_gid;int ex_fsid;unsigned char * ex_uuid;/* 16 byte fsid */ struct nfsd4_fs_locations ex_fslocs;
include/linux/sunrpc/auth.h +4 -3
@@ -17,14 +17,15 @@#include <linux/atomic.h> #include <linux/rcupdate.h> +#include <linux/uidgid.h> /* size of the nodename buffer */ #define UNX_MAXNODENAME 32/* Work around the lack of a VFS credential */ struct auth_cred { -uid_t uid; -gid_t gid; +kuid_t uid; +kgid_t gid;struct group_info *group_info;const char *principal;unsigned char machine_cred :1 ;
@@ -48,7 +49,7 @@ struct rpc_cred {unsigned long cr_flags;/* various flags */ atomic_t cr_count;/* ref count */ -uid_t cr_uid; +kuid_t cr_uid;/* per-flavor data */ };
include/linux/sunrpc/svcauth.h +2 -2
@@ -18,8 +18,8 @@#include <linux/cred.h> struct svc_cred { -uid_t cr_uid; -gid_t cr_gid; +kuid_t cr_uid; +kgid_t cr_gid;struct group_info *cr_group_info;u32 cr_flavor;/* pseudoflavor */ char *cr_principal;/* for gss */
init/Kconfig +0 -2
@@ -999,8 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on NFSD = n - depends on NFS_FS = n depends on OCFS2_FS = n depends on XFS_FS = n
net/sunrpc/auth.c +3 -3
@@ -412,7 +412,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, *entry, *new;unsigned int nr; - nr =hash_long (acred->uid, cache->hashbits); + nr =hash_long (from_kuid (&init_user_ns, acred->uid), cache->hashbits);rcu_read_lock ();hlist_for_each_entry_rcu (entry, pos, &cache->hashtable[nr], cr_hash) {
@@ -519,8 +519,8 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) {struct rpc_auth *auth = task->tk_client->cl_auth;struct auth_cred acred = { - .uid =0 , - .gid =0 , + .uid =GLOBAL_ROOT_UID , + .gid =GLOBAL_ROOT_GID , }; dprintk("RPC: %5u looking up %s cred\n",
net/sunrpc/auth_generic.c +9 -7
@@ -18,8 +18,8 @@# define RPCDBG_FACILITY RPCDBG_AUTH#endif -#define RPC_MACHINE_CRED_USERID ((uid_t)0) -#define RPC_MACHINE_CRED_GROUPID ((gid_t)0) +#define RPC_MACHINE_CRED_USERID GLOBAL_ROOT_UID +#define RPC_MACHINE_CRED_GROUPID GLOBAL_ROOT_GIDstruct generic_cred {struct rpc_cred gc_base;
@@ -96,7 +96,9 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)dprintk ("RPC: allocated %s cred %p for uid %d gid %d\n" , gcred->acred.machine_cred ?"machine" :"generic" , - gcred, acred->uid, acred->gid); + gcred, +from_kuid (&init_user_ns, acred->uid), +from_kgid (&init_user_ns, acred->gid));return &gcred->gc_base; }
@@ -129,8 +131,8 @@ machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flag {if (!gcred->acred.machine_cred || gcred->acred.principal != acred->principal || - gcred->acred.uid != acred->uid || - gcred->acred.gid != acred->gid) + !uid_eq (gcred->acred.uid, acred->uid) || + !gid_eq (gcred->acred.gid, acred->gid))return 0 ;return 1 ; }
@@ -147,8 +149,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)if (acred->machine_cred)return machine_cred_match (acred, gcred, flags); -if (gcred->acred.uid != acred->uid || - gcred->acred.gid != acred->gid || +if (!uid_eq (gcred->acred.uid, acred->uid) || + !gid_eq (gcred->acred.gid, acred->gid) || gcred->acred.machine_cred !=0 ) goto out_nomatch;
net/sunrpc/auth_gss/auth_gss.c +20 -13
@@ -247,7 +247,7 @@ err:struct gss_upcall_msg {atomic_t count; -uid_t uid; +kuid_t uid;struct rpc_pipe_msg msg;struct list_head list;struct gss_auth *auth;
@@ -294,11 +294,11 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) }static struct gss_upcall_msg * -__gss_find_upcall (struct rpc_pipe *pipe,uid_t uid) +__gss_find_upcall (struct rpc_pipe *pipe,kuid_t uid) {struct gss_upcall_msg *pos;list_for_each_entry (pos, &pipe->in_downcall, list) { -if (pos->uid != uid) +if (!uid_eq (pos->uid, uid))continue ;atomic_inc (&pos->count);dprintk ("RPC: %s found msg %p\n" , __func__, pos);
@@ -400,7 +400,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, gss_msg->msg.len =sprintf (gss_msg->databuf,"mech=%s uid=%d " , mech->gm_name, - gss_msg->uid); +from_kuid (&init_user_ns, gss_msg->uid)); p += gss_msg->msg.len;if (clnt->cl_principal) { len =sprintf (p,"target=%s " , clnt->cl_principal);
@@ -436,7 +436,7 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,static struct gss_upcall_msg *gss_alloc_msg (struct gss_auth *gss_auth,struct rpc_clnt *clnt, -uid_t uid,const char *service_name) +kuid_t uid,const char *service_name) {struct gss_upcall_msg *gss_msg;int vers;
@@ -466,7 +466,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_crstruct gss_cred *gss_cred =container_of (cred, struct gss_cred, gc_base);struct gss_upcall_msg *gss_new, *gss_msg; -uid_t uid = cred->cr_uid; +kuid_t uid = cred->cr_uid; gss_new =gss_alloc_msg (gss_auth, clnt, uid, gss_cred->gc_principal);if (IS_ERR (gss_new))
@@ -508,7 +508,7 @@ gss_refresh_upcall(struct rpc_task *task)int err =0 ;dprintk ("RPC: %5u %s for uid %u\n" , - task->tk_pid, __func__, cred->cr_uid); + task->tk_pid, __func__,from_kuid (&init_user_ns, cred->cr_uid)); gss_msg =gss_setup_upcall (task->tk_client, gss_auth, cred);if (PTR_ERR (gss_msg) == -EAGAIN ) {/* XXX: warning on the first, under the assumption we
@@ -540,7 +540,7 @@ gss_refresh_upcall(struct rpc_task *task)gss_release_msg (gss_msg); out:dprintk ("RPC: %5u %s for uid %u result %d\n" , - task->tk_pid, __func__, cred->cr_uid, err); + task->tk_pid, __func__,from_kuid (&init_user_ns, cred->cr_uid), err);return err; }
@@ -553,7 +553,8 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)DEFINE_WAIT (wait);int err =0 ; -dprintk ("RPC: %s for uid %u\n" , __func__, cred->cr_uid); +dprintk ("RPC: %s for uid %u\n" , + __func__,from_kuid (&init_user_ns, cred->cr_uid)); retry: gss_msg =gss_setup_upcall (gss_auth->client, gss_auth, cred);if (PTR_ERR (gss_msg) == -EAGAIN ) {
@@ -595,7 +596,7 @@ out_intr:gss_release_msg (gss_msg); out:dprintk ("RPC: %s for uid %u result %d\n" , - __func__, cred->cr_uid, err); + __func__,from_kuid (&init_user_ns, cred->cr_uid), err);return err; }
@@ -610,6 +611,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)struct rpc_pipe *pipe =RPC_I (filp->f_dentry->d_inode)->pipe;struct gss_cl_ctx *ctx;uid_t uid; +kuid_t kuid;ssize_t err = -EFBIG ;if (mlen >MSG_BUF_MAXSIZE )
@@ -629,6 +631,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) err =PTR_ERR (p); goto err; } + kuid =make_kuid (&init_user_ns, uid); +if (!uid_valid (kuid)) { + err = -EINVAL ; + goto err; + } err = -ENOMEM ; ctx =gss_alloc_context ();
@@ -638,7 +645,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) err = -ENOENT ;/* Find a matching upcall */ spin_lock (&pipe->lock); - gss_msg =__gss_find_upcall (pipe, uid); + gss_msg =__gss_find_upcall (pipe, kuid);if (gss_msg ==NULL ) {spin_unlock (&pipe->lock); goto err_put_ctx;
@@ -1050,7 +1057,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)int err = -ENOMEM ;dprintk ("RPC: %s for uid %d, flavor %d\n" , - __func__, acred->uid, auth->au_flavor); + __func__,from_kuid (&init_user_ns, acred->uid), auth->au_flavor);if (!(cred =kzalloc (sizeof (*cred),GFP_NOFS ))) goto out_err;
@@ -1106,7 +1113,7 @@ out: }if (gss_cred->gc_principal !=NULL )return 0 ; -return rc->cr_uid == acred->uid; +return uid_eq (rc->cr_uid, acred->uid); }/*
net/sunrpc/auth_gss/svcauth_gss.c +12 -2
@@ -418,6 +418,7 @@ static int rsc_parse(struct cache_detail *cd, {/* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */ char *buf = mesg; +int id;int len, rv;struct rsc rsci, *rscp =NULL ;time_t expiry;
@@ -444,7 +445,12 @@ static int rsc_parse(struct cache_detail *cd, goto out;/* uid, or NEGATIVE */ - rv =get_int (&mesg, &rsci.cred.cr_uid); + rv =get_int (&mesg, &id); +if (rv ==0 ) { + rsci.cred.cr_uid =make_kuid (&init_user_ns, id); +if (!uid_valid (rsci.cred.cr_uid)) + goto out; + }if (rv == -EINVAL ) goto out;if (rv == -ENOENT )
@@ -453,7 +459,11 @@ static int rsc_parse(struct cache_detail *cd,int N , i;/* gid */ -if (get_int (&mesg, &rsci.cred.cr_gid)) +if (get_int (&mesg, &id)) + goto out; + + rsci.cred.cr_gid =make_kgid (&init_user_ns, id); +if (!gid_valid (rsci.cred.cr_gid)) goto out;/* number of additional gid's */
net/sunrpc/auth_unix.c +15 -21
@@ -18,8 +18,8 @@struct unx_cred {struct rpc_cred uc_base; -gid_t uc_gid; -gid_t uc_gids[NFS_NGROUPS ]; +kgid_t uc_gid; +kgid_t uc_gids[NFS_NGROUPS ]; };#define uc_uid uc_base.cr_uid
@@ -65,7 +65,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)unsigned int i;dprintk ("RPC: allocating UNIX cred for uid %d gid %d\n" , - acred->uid, acred->gid); +from_kuid (&init_user_ns, acred->uid), +from_kgid (&init_user_ns, acred->gid));if (!(cred =kmalloc (sizeof (*cred),GFP_NOFS )))return ERR_PTR (-ENOMEM );
@@ -79,13 +80,10 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) groups =NFS_NGROUPS ; cred->uc_gid = acred->gid; -for (i =0 ; i < groups; i++) { -gid_t gid; - gid =from_kgid (&init_user_ns,GROUP_AT (acred->group_info, i)); - cred->uc_gids[i] = gid; - } +for (i =0 ; i < groups; i++) + cred->uc_gids[i] =GROUP_AT (acred->group_info, i);if (i <NFS_NGROUPS ) - cred->uc_gids[i] =NOGROUP ; + cred->uc_gids[i] =INVALID_GID ;return &cred->uc_base; }
@@ -123,21 +121,17 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)unsigned int i; -if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid) +if (!uid_eq (cred->uc_uid, acred->uid) || !gid_eq (cred->uc_gid, acred->gid))return 0 ;if (acred->group_info !=NULL ) groups = acred->group_info->ngroups;if (groups >NFS_NGROUPS ) groups =NFS_NGROUPS ; -for (i =0 ; i < groups ; i++) { -gid_t gid; - gid =from_kgid (&init_user_ns,GROUP_AT (acred->group_info, i)); -if (cred->uc_gids[i] != gid) +for (i =0 ; i < groups ; i++) +if (!gid_eq (cred->uc_gids[i],GROUP_AT (acred->group_info, i)))return 0 ; - } -if (groups <NFS_NGROUPS && - cred->uc_gids[groups] !=NOGROUP ) +if (groups <NFS_NGROUPS &&gid_valid (cred->uc_gids[groups]))return 0 ;return 1 ; }
@@ -163,11 +157,11 @@ unx_marshal(struct rpc_task *task, __be32 *p)*/ p =xdr_encode_array (p, clnt->cl_nodename, clnt->cl_nodelen); - *p++ =htonl ((u32 ) cred->uc_uid); - *p++ =htonl ((u32 ) cred->uc_gid); + *p++ =htonl ((u32 )from_kuid (&init_user_ns, cred->uc_uid)); + *p++ =htonl ((u32 )from_kgid (&init_user_ns, cred->uc_gid)); hold = p++; -for (i =0 ; i <16 && cred->uc_gids[i] != (gid_t )NOGROUP ; i++) - *p++ =htonl ((u32 ) cred->uc_gids[i]); +for (i =0 ; i <16 &&gid_valid (cred->uc_gids[i]); i++) + *p++ =htonl ((u32 )from_kgid (&init_user_ns, cred->uc_gids[i])); *hold =htonl (p - hold -1 );/* gid array length */ *base =htonl ((p - base -1 ) <<2 );/* cred length */
net/sunrpc/svcauth_unix.c +24 -16
@@ -415,7 +415,7 @@ svcauth_unix_info_release(struct svc_xprt *xpt)struct unix_gid {struct cache_head h; -uid_t uid; +kuid_t uid;struct group_info *gi; };
@@ -433,7 +433,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) { struct unix_gid *orig = container_of(corig, struct unix_gid, h); struct unix_gid *new = container_of(cnew, struct unix_gid, h); -return orig->uid == new->uid; +return uid_eq (orig->uid, new->uid); }static void unix_gid_init (struct cache_head *cnew,struct cache_head *citem) {
@@ -465,7 +465,7 @@ static void unix_gid_request(struct cache_detail *cd,char tuid[20 ]; struct unix_gid *ug = container_of(h, struct unix_gid, h); -snprintf (tuid,20 ,"%u" , ug->uid); +snprintf (tuid,20 ,"%u" ,from_kuid (&init_user_ns, ug->uid));qword_add (bpp, blen, tuid); (*bpp)[-1 ] ='\n' ; }
@@ -475,13 +475,14 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)return sunrpc_cache_pipe_upcall (cd, h, unix_gid_request); } -static struct unix_gid *unix_gid_lookup (struct cache_detail *cd,uid_t uid); +static struct unix_gid *unix_gid_lookup (struct cache_detail *cd,kuid_t uid);static int unix_gid_parse (struct cache_detail *cd,char *mesg,int mlen) {/* uid expiry Ngid gid0 gid1 ... gidN-1 */ -int uid; +int id; +kuid_t uid;int gids;int rv;int i;
@@ -493,9 +494,14 @@ static int unix_gid_parse(struct cache_detail *cd,return -EINVAL ; mesg[mlen-1 ] =0 ; - rv =get_int (&mesg, &uid); + rv =get_int (&mesg, &id);if (rv)return -EINVAL ; + + uid =make_kuid (&init_user_ns, id); +if (!uid_valid (uid)) +return -EINVAL ; + ug.uid = uid; expiry =get_expiry (&mesg);
@@ -530,7 +536,7 @@ static int unix_gid_parse(struct cache_detail *cd, ug.h.expiry_time = expiry; ch =sunrpc_cache_update (cd, &ug.h, &ugp->h, -hash_long (uid,GID_HASHBITS )); +hash_long (from_kuid (&init_user_ns, uid),GID_HASHBITS ));if (!ch) err = -ENOMEM ;else {
@@ -549,7 +555,7 @@ static int unix_gid_show(struct seq_file *m,struct cache_detail *cd, struct cache_head *h) { - struct user_namespace *user_ns = current_user_ns(); + struct user_namespace *user_ns = seq_user_ns(m);struct unix_gid *ug;int i;int glen;
@@ -565,7 +571,7 @@ static int unix_gid_show(struct seq_file *m,else glen =0 ; -seq_printf (m,"%u %d:" , ug->uid, glen); +seq_printf (m,"%u %d:" ,from_kuid_munged (user_ns, ug->uid), glen);for (i =0 ; i < glen; i++)seq_printf (m," %d" ,from_kgid_munged (user_ns,GROUP_AT (ug->gi, i)));seq_printf (m,"\n" );
@@ -615,20 +621,20 @@ void unix_gid_cache_destroy(struct net *net)cache_destroy_net (cd, net); } -static struct unix_gid *unix_gid_lookup (struct cache_detail *cd,uid_t uid) +static struct unix_gid *unix_gid_lookup (struct cache_detail *cd,kuid_t uid) {struct unix_gid ug;struct cache_head *ch; ug.uid = uid; - ch =sunrpc_cache_lookup (cd, &ug.h,hash_long (uid,GID_HASHBITS )); + ch =sunrpc_cache_lookup (cd, &ug.h,hash_long (from_kuid (&init_user_ns, uid),GID_HASHBITS ));if (ch) return container_of(ch, struct unix_gid, h);else return NULL ; } -static struct group_info *unix_gid_find (uid_t uid,struct svc_rqst *rqstp) +static struct group_info *unix_gid_find (kuid_t uid,struct svc_rqst *rqstp) {struct unix_gid *ug;struct group_info *gi;
@@ -750,8 +756,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) }/* Signal that mapping to nobody uid/gid is required */ - cred->cr_uid = (uid_t) -1 ; - cred->cr_gid = (gid_t) -1 ; + cred->cr_uid =INVALID_UID ; + cred->cr_gid =INVALID_GID ; cred->cr_group_info =groups_alloc (0 );if (cred->cr_group_info ==NULL )return SVC_CLOSE ;/* kmalloc failure - client must retry */
@@ -812,8 +818,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) argv->iov_base = (void *)((__be32 *)argv->iov_base + slen);/* skip machname */ argv->iov_len -= slen*4 ; - cred->cr_uid =svc_getnl (argv);/* uid */ - cred->cr_gid =svc_getnl (argv);/* gid */ + cred->cr_uid =make_kuid (&init_user_ns,svc_getnl (argv));/* uid */ + cred->cr_gid =make_kgid (&init_user_ns,svc_getnl (argv));/* gid */ +if (!uid_valid (cred->cr_uid) || !gid_valid (cred->cr_gid)) + goto badcred; slen =svc_getnl (argv);/* gids length */ if (slen >16 || (len -= (slen +2 )*4 ) <0 ) goto badcred;
Signature · 1 line
1.7.5.4
RFC PATCH 9/12 userns: Convert ocfs2 to use kuid and kgid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ocfs2/acl.c | 31 +++++++++++++++++++++++++++++-- fs/ocfs2/dlmglue.c | 8 ++++---- fs/ocfs2/file.c | 11 ++++++----- fs/ocfs2/inode.c | 12 ++++++------ fs/ocfs2/namei.c | 4 ++-- fs/ocfs2/refcounttree.c | 2 +- init/Kconfig | 1 - 7 files changed, 48 insertions(+), 21 deletions(-)
fs/ocfs2/acl.c +29 -2
@@ -65,7 +65,20 @@ static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) acl->a_entries[n].e_tag =le16_to_cpu (entry->e_tag); acl->a_entries[n].e_perm =le16_to_cpu (entry->e_perm); - acl->a_entries[n].e_id =le32_to_cpu (entry->e_id); +switch (acl->a_entries[n].e_tag) { +case ACL_USER : + acl->a_entries[n].e_uid = +make_kuid (&init_user_ns, +le32_to_cpu (entry->e_id)); +break ; +case ACL_GROUP : + acl->a_entries[n].e_gid = +make_kgid (&init_user_ns, +le32_to_cpu (entry->e_id)); +break ; +default : +break ; + } value +=sizeof (struct posix_acl_entry ); }
@@ -91,7 +104,21 @@ static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size)for (n =0 ; n < acl->a_count; n++, entry++) { entry->e_tag =cpu_to_le16 (acl->a_entries[n].e_tag); entry->e_perm =cpu_to_le16 (acl->a_entries[n].e_perm); - entry->e_id =cpu_to_le32 (acl->a_entries[n].e_id); +switch (acl->a_entries[n].e_tag) { +case ACL_USER : + entry->e_id =cpu_to_le32 ( +from_kuid (&init_user_ns, + acl->a_entries[n].e_uid)); +break ; +case ACL_GROUP : + entry->e_id =cpu_to_le32 ( +from_kgid (&init_user_ns, + acl->a_entries[n].e_gid)); +break ; +default : + entry->e_id =cpu_to_le32 (ACL_UNDEFINED_ID ); +break ; + } }return ocfs2_acl; }
fs/ocfs2/dlmglue.c +4 -4
@@ -2045,8 +2045,8 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb->lvb_version =OCFS2_LVB_VERSION ; lvb->lvb_isize =cpu_to_be64 (i_size_read (inode)); lvb->lvb_iclusters =cpu_to_be32 (oi->ip_clusters); - lvb->lvb_iuid =cpu_to_be32 (inode->i_uid); - lvb->lvb_igid =cpu_to_be32 (inode->i_gid); + lvb->lvb_iuid =cpu_to_be32 (i_uid_read (inode)); + lvb->lvb_igid =cpu_to_be32 (i_gid_read (inode)); lvb->lvb_imode =cpu_to_be16 (inode->i_mode); lvb->lvb_inlink =cpu_to_be16 (inode->i_nlink); lvb->lvb_iatime_packed =
@@ -2095,8 +2095,8 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)else inode->i_blocks =ocfs2_inode_sector_count (inode); - inode->i_uid =be32_to_cpu (lvb->lvb_iuid); - inode->i_gid =be32_to_cpu (lvb->lvb_igid); +i_uid_write (inode,be32_to_cpu (lvb->lvb_iuid)); +i_gid_write (inode,be32_to_cpu (lvb->lvb_igid)); inode->i_mode =be16_to_cpu (lvb->lvb_imode);set_nlink (inode,be16_to_cpu (lvb->lvb_inlink)); ocfs2_unpack_timespec(&inode->i_atime,
fs/ocfs2/file.c +6 -5
@@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) (unsigned long long )OCFS2_I (inode)->ip_blkno, dentry->d_name.len, dentry->d_name.name, attr->ia_valid, attr->ia_mode, - attr->ia_uid, attr->ia_gid); +from_kuid (&init_user_ns, attr->ia_uid), + from_kgid(&init_user_ns, attr->ia_gid));/* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK (inode->i_mode))
@@ -1174,14 +1175,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) } } -if ((attr->ia_valid &ATTR_UID && attr->ia_uid != inode->i_uid) || - (attr->ia_valid &ATTR_GID && attr->ia_gid != inode->i_gid)) { +if ((attr->ia_valid &ATTR_UID && !uid_eq (attr->ia_uid, inode->i_uid)) || + (attr->ia_valid &ATTR_GID && !gid_eq (attr->ia_gid, inode->i_gid))) {/* * Gather pointers to quota structures so that allocation / * freeing of quota structures happens here and not inside * dquot_transfer() where we have problems with lock ordering */ -if (attr->ia_valid &ATTR_UID && attr->ia_uid != inode->i_uid +if (attr->ia_valid &ATTR_UID && !uid_eq (attr->ia_uid, inode->i_uid) &&OCFS2_HAS_RO_COMPAT_FEATURE (sb,OCFS2_FEATURE_RO_COMPAT_USRQUOTA )) { transfer_to[USRQUOTA ] =dqget (sb,make_kqid_uid (attr->ia_uid));
@@ -1190,7 +1191,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) goto bail_unlock; } } -if (attr->ia_valid &ATTR_GID && attr->ia_gid != inode->i_gid +if (attr->ia_valid &ATTR_GID && !gid_eq (attr->ia_gid, inode->i_gid) &&OCFS2_HAS_RO_COMPAT_FEATURE (sb,OCFS2_FEATURE_RO_COMPAT_GRPQUOTA )) { transfer_to[GRPQUOTA ] =dqget (sb,make_kqid_gid (attr->ia_gid));
fs/ocfs2/inode.c +6 -6
@@ -269,8 +269,8 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, inode->i_generation =le32_to_cpu (fe->i_generation); inode->i_rdev =huge_decode_dev (le64_to_cpu (fe->id1.dev1.i_rdev)); inode->i_mode =le16_to_cpu (fe->i_mode); - inode->i_uid =le32_to_cpu (fe->i_uid); - inode->i_gid =le32_to_cpu (fe->i_gid); +i_uid_write (inode,le32_to_cpu (fe->i_uid)); +i_gid_write (inode,le32_to_cpu (fe->i_gid));/* Fast symlinks will have i_size but no allocated clusters. */ if (S_ISLNK (inode->i_mode) && !fe->i_clusters) {
@@ -1259,8 +1259,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle, fe->i_size =cpu_to_le64 (i_size_read (inode));ocfs2_set_links_count (fe, inode->i_nlink); - fe->i_uid =cpu_to_le32 (inode->i_uid); - fe->i_gid =cpu_to_le32 (inode->i_gid); + fe->i_uid =cpu_to_le32 (i_uid_read (inode)); + fe->i_gid =cpu_to_le32 (i_gid_read (inode)); fe->i_mode =cpu_to_le16 (inode->i_mode); fe->i_atime =cpu_to_le64 (inode->i_atime.tv_sec); fe->i_atime_nsec =cpu_to_le32 (inode->i_atime.tv_nsec);
@@ -1290,8 +1290,8 @@ void ocfs2_refresh_inode(struct inode *inode,ocfs2_set_inode_flags (inode);i_size_write (inode,le64_to_cpu (fe->i_size));set_nlink (inode,ocfs2_read_links_count (fe)); - inode->i_uid =le32_to_cpu (fe->i_uid); - inode->i_gid =le32_to_cpu (fe->i_gid); +i_uid_write (inode,le32_to_cpu (fe->i_uid)); +i_gid_write (inode,le32_to_cpu (fe->i_gid)); inode->i_mode =le16_to_cpu (fe->i_mode);if (S_ISLNK (inode->i_mode) &&le32_to_cpu (fe->i_clusters) ==0 ) inode->i_blocks =0 ;
fs/ocfs2/namei.c +2 -2
@@ -512,8 +512,8 @@ static int __ocfs2_mknod_locked(struct inode *dir, fe->i_suballoc_loc =cpu_to_le64 (suballoc_loc); fe->i_suballoc_bit =cpu_to_le16 (suballoc_bit); fe->i_suballoc_slot =cpu_to_le16 (inode_ac->ac_alloc_slot); - fe->i_uid =cpu_to_le32 (inode->i_uid); - fe->i_gid =cpu_to_le32 (inode->i_gid); + fe->i_uid =cpu_to_le32 (i_uid_read (inode)); + fe->i_gid =cpu_to_le32 (i_gid_read (inode)); fe->i_mode =cpu_to_le16 (inode->i_mode);if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode)) fe->id1.dev1.i_rdev =cpu_to_le64 (huge_encode_dev (dev));
fs/ocfs2/refcounttree.c +1 -1
@@ -4407,7 +4407,7 @@ static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,* rights to do so. */ if (preserve) { -if ((current_fsuid () != inode->i_uid) && !capable (CAP_CHOWN )) +if (!uid_eq (current_fsuid (), inode->i_uid) && !capable (CAP_CHOWN ))return -EPERM ;if (!in_group_p (inode->i_gid) && !capable (CAP_CHOWN ))return -EPERM ;
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on OCFS2_FS = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
Joel Becker
maintainerRe: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate
fs/ocfs2/file.c int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) · line 1120
Quoted 9 lines · Eric W. Biederman
fs/ocfs2/file.c +2
-1@@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) (unsigned long long )OCFS2_I (inode)->ip_blkno, dentry->d_name.len, dentry->d_name.name, attr->ia_valid, attr->ia_mode, - attr->ia_uid, attr->ia_gid); +from_kuid (&init_user_ns, attr->ia_uid), + from_kgid(&init_user_ns, attr->ia_gid));
Dear Eric,
I have a similar question about init_user_ns to Dave. As far as
I can tell, using init_user_ns here means we'll never get translations based on the current process namespace. It just so happens that include/linux/user_namespace.h doesn't allow new namespaces yet, but I can't see why we would propagate that knowledge elsewhere.
Is there some magic about when init_user_ns should be used
regardless?
Joel
Signature · 8 lines
Brain: I shall pollute the water supply with this DNAdefibuliser,
turning everyone into mindless slaves.
Pinky: What about the people who drink bottled water?
Brain: Pinky, people who pay 5 dollars for a bottle of water are
already mindless slaves.
http://www.jlbec.org/
[email protected]Re: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate
Quoted 18 lines · Joel Becker
fs/ocfs2/file.c int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) · line 1120
Quoted 9 lines · Eric W. Biederman
fs/ocfs2/file.c +2
-1@@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) (unsigned long long )OCFS2_I (inode)->ip_blkno, dentry->d_name.len, dentry->d_name.name, attr->ia_valid, attr->ia_mode, - attr->ia_uid, attr->ia_gid); +from_kuid (&init_user_ns, attr->ia_uid), + from_kgid(&init_user_ns, attr->ia_gid));Dear Eric,
I have a similar question aboutinit_user_nsto Dave. As far as
I can tell, usinginit_user_nshere means we'll never get translations based on the current process namespace. It just so happens thatinclude/linux/user_namespace.hdoesn't allow new namespaces yet, but I can't see why we would propagate that knowledge elsewhere.
Quoted 2 lines
Is there some magic about when
init_user_nsshould be used
regardless?
Trace statements are fancy print statements, and the tracing infrastructure is not setup to deal with anyone other than the one-true-root using it. Trace is like printk in that way.
So for print statements I always convert the value into the initial user namespace which every value can be converted to without loss, and is the same value that we have always been printing.
If at some point the tracing people figure out how deal with multiple user namespaces it won't be hard to pass the kuids and kgids into the trace funtions and have the readers of the data perform the conversions.
Eric
A message that is not in the archive (sent off-list or not yet received): 1353415420-5457-9-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate
fs/ocfs2/file.c int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) · line 1120
Quoted 9 lines · Eric W. Biederman
fs/ocfs2/file.c +2
-1@@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) (unsigned long long )OCFS2_I (inode)->ip_blkno, dentry->d_name.len, dentry->d_name.name, attr->ia_valid, attr->ia_mode, - attr->ia_uid, attr->ia_gid); +from_kuid (&init_user_ns, attr->ia_uid), + from_kgid(&init_user_ns, attr->ia_gid));
Dear Eric,
I have a similar question about init_user_ns to Dave. As far as
I can tell, using init_user_ns here means we'll never get translations based on the current process namespace. It just so happens that include/linux/user_namespace.h doesn't allow new namespaces yet, but I can't see why we would propagate that knowledge elsewhere.
Is there some magic about when init_user_ns should be used
regardless?
Joel
Signature · 8 lines
Brain: I shall pollute the water supply with this DNAdefibuliser,
turning everyone into mindless slaves.
Pinky: What about the people who drink bottled water?
Brain: Pinky, people who pay 5 dollars for a bottle of water are
already mindless slaves.
http://www.jlbec.org/
[email protected]Joel Becker
maintainerRe: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate
In reply to Eric W. BiedermanQuoted 5 lines · Eric W. Biederman
fs/ocfs2/acl.c +0
-0
fs/ocfs2/acl.c static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) · line 73
Quoted 10 lines
fs/ocfs2/acl.c +6
-1@@ -65,7 +65,20 @@ static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) acl->a_entries[n].e_tag =le16_to_cpu (entry->e_tag); acl->a_entries[n].e_perm =le16_to_cpu (entry->e_perm); - acl->a_entries[n].e_id =le32_to_cpu (entry->e_id); +switch (acl->a_entries[n].e_tag) { +case ACL_USER : + acl->a_entries[n].e_uid = +make_kuid (&init_user_ns, +le32_to_cpu (entry->e_id)); +break ;
Stupid question: do you consider disjoint namespaces on multiple machines to be a problem? Remember that ocfs2 is a cluster filesystem. If I have uid 100 on machine A in the default namespace, and then I mount the filesystem on machine B with uid 100 in a different namespace, what happens? I presume that both can access as the same nominal uid, and configuring this correctly is left as an exercise to the namespace administrator?
fs/ocfs2/dlmglue.c static void __ocfs2_stuff_meta_lvb(struct inode *inode) · line 2049
Quoted 12 lines
fs/ocfs2/dlmglue.c +2
-2@@ -2045,8 +2045,8 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb->lvb_version =OCFS2_LVB_VERSION ; lvb->lvb_isize =cpu_to_be64 (i_size_read (inode)); lvb->lvb_iclusters =cpu_to_be32 (oi->ip_clusters); - lvb->lvb_iuid =cpu_to_be32 (inode->i_uid); - lvb->lvb_igid =cpu_to_be32 (inode->i_gid); + lvb->lvb_iuid =cpu_to_be32 (i_uid_read (inode)); + lvb->lvb_igid =cpu_to_be32 (i_gid_read (inode));
I have the reverse question here. Are we guaranteed that the
on-disk uid/gid will not change regardless of the namespace? That is, if I create a file on machine A in init_user_ns as uid 100, then access it over on machine B in some other namespace with a user-visible uid of 100, will the wire be passing 100 in both directions? This absolutely must be true for the cluster communication to work.
Joel
Signature · 6 lines
Life's Little Instruction Book #80 "Slow dance" http://www.jlbec.org/ [email protected]
Re: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate
Quoted 17 lines · Joel Becker
Quoted 5 lines · Eric W. Biederman
fs/ocfs2/acl.c +0
-0fs/ocfs2/acl.c static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) · line 73
Quoted 10 lines
fs/ocfs2/acl.c +6
-1@@ -65,7 +65,20 @@ static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) acl->a_entries[n].e_tag =le16_to_cpu (entry->e_tag); acl->a_entries[n].e_perm =le16_to_cpu (entry->e_perm); - acl->a_entries[n].e_id =le32_to_cpu (entry->e_id); +switch (acl->a_entries[n].e_tag) { +case ACL_USER : + acl->a_entries[n].e_uid = +make_kuid (&init_user_ns, +le32_to_cpu (entry->e_id)); +break ;
Quoted 7 lines
Stupid question: do you consider disjoint namespaces on multiple machines to be a problem? Remember that ocfs2 is a cluster filesystem. If I have uid 100 on machine A in the default namespace, and then I mount the filesystem on machine B with uid 100 in a different namespace, what happens? I presume that both can access as the same nominal uid, and configuring this correctly is left as an exercise to the namespace administrator?
Yep. That is the way it has been since nfs first gave us that challenge. Sane user administrators of shared filesystems use the same uids for the same functions accross all machines that use that filesystem.
That said it possible (but not implemented in these patches) to have a notion of a filesystem that lives in another user namespace than the
initial user namespace. Essentially by capturing the usernamespace
at mount time and storing it on the super block. For the generic case that requires a little bit of infrastructure work for quotas.
At this point my goal is to get all of the conversions into all of the right places and then for the people who care do the work to allow mounting their filesystem in another user namespace.
It is a very practical problem that user namespace support can not be enabled when filesystems that have not had kuid/kgid support pushed down into them are enabled in the kernel. So I am working hard to push down kuids and kgids and find all of the places that need conversions, so enabling user namespaces will not cause incorrect kernel behavior because the wrong types were used somewhere.
Quoted 11 lines
Quoted 11 lines
fs/ocfs2/dlmglue.c +1
-2@@ -2045,8 +2045,8 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb->lvb_version =OCFS2_LVB_VERSION ; lvb->lvb_isize =cpu_to_be64 (i_size_read (inode)); lvb->lvb_iclusters =cpu_to_be32 (oi->ip_clusters); - lvb->lvb_iuid =cpu_to_be32 (inode->i_uid); - lvb->lvb_igid =cpu_to_be32 (inode->i_gid); + lvb->lvb_iuid =cpu_to_be32 (i_uid_read (inode));
Quoted 8 lines
fs/ocfs2/dlmglue.c static void __ocfs2_stuff_meta_lvb(struct inode *inode) · line 2049
Quoted 1 line
fs/ocfs2/dlmglue.c +1
-0+ lvb->lvb_igid =cpu_to_be32 (i_gid_read (inode));I have the reverse question here. Are we guaranteed that the
on-disk uid/gid will not change regardless of the namespace? That is, if I create a file on machine A ininit_user_nsas uid 100, then access it over on machine B in some other namespace with a user-visible uid of 100, will the wire be passing 100 in both directions? This absolutely must be true for the cluster communication to work.
The model I am working with is that for every filesystem there is
exactly one user namespace it stores the uids and gids in. That user
namespace does not have to be the initial user namespace but there there is one user namespace.
A user running in a user namespace different from the user namespace of the filesystem will first have their uids and gids mapped to kuids and kgids and then those kuids and kgids will be mapped to the on disk representation.
Except for the odd ioctl or quota callback the vfs handles all of the translation of uids and gids from user space to kuids and kgids. Which means the filesystems don't need to deal with what users are thinking, and I don't need to teach filesystems to store an extended attribute with user namespace information.
Which simplifies the problem for filesystems of dealing with kuid and kgids coming from the vfs and translating those into the numbers you want to store on disk. Currently all filesystems are stored on disk in the initial user namespace of the kernel. So all of the conversions into on disk structures are to the initial user namespace.
For network protocols there is the added challenge that you want to make as certain as you can all of the parties are talking about uids and gids in the same user namespace. In general I make the assumption that the filesystem's uid and gids are stored in the user namespace of the process that mounts the filesystem, and those user space processes take care of connecting you to other folks speaking of uids and gids in the same user namespace.
In a few of my patches I have places where I can prevent and so I check that the userspace process is in the initial user namespace and fail otherwise.
Until someone does the work to deal with something other than the initial user namespace in a filesystem and set the FS_USERNS_MOUNT flag .fs_flags in struct filesystem a filesystem is guaranteed to always be mounted in the initial user namespace. So while there may be users in other user namespaces the filesystem can just worring about getting kuids and kgids and storing and communicating uids and gids in the initial user namespace with the same logic it has always done.
Which is all a long way of saying if a user in another user namespace with uid 100 which maps to uid 100100 in the initial user namespace. Filesystems are expeted to treat that as a write from uid 100100 and if that isn't what the user who set up the other user namespace wants to see in the on disk structures they should have used a differenet mapping when setting up the user namespace.
And of course every uid maps in any user namespace has a lossless mapping to and from the inital user namespace.
Hopefully that hopes to clear some confusion if there the intervening time hadn't cleared that up.
Eric
RFC PATCH 10/12 userns: Convert xfs to use kuid/kgid/kprojid where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Modify the incore inode to use kuid_t, kgid_t and kprojid_t.
- Remove xfs_get_projid and xfs_set_projid with projid being stored in a single field they are unnecessary.
- Add dq_id (a struct kqid) to struct xfs_dquot to retain the incore version of the quota identifiers.
- Pass struct kquid all of the way into xfs_qm_dqgetn and xfs_qm_dqread, and move xfs_quota_type into xfs_dquot.c from xfs_quotaops.c to support this change.
--- fs/xfs/xfs_acl.c | 23 ++++++++++-- fs/xfs/xfs_dquot.c | 36 +++++++++++++------ fs/xfs/xfs_dquot.h | 5 ++- fs/xfs/xfs_inode.c | 33 ++++++++++------- fs/xfs/xfs_inode.h | 32 +++-------------- fs/xfs/xfs_ioctl.c | 23 +++++++++--- fs/xfs/xfs_iops.c | 18 +++++----- fs/xfs/xfs_itable.c | 8 ++-- fs/xfs/xfs_qm.c | 87 ++++++++++++++++++++++++--------------------- fs/xfs/xfs_qm.h | 4 +- fs/xfs/xfs_qm_bhv.c | 3 +- fs/xfs/xfs_qm_syscalls.c | 24 +++++++------ fs/xfs/xfs_quota.h | 4 +- fs/xfs/xfs_quotaops.c | 20 +--------- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_trans_dquot.c | 6 +--- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- fs/xfs/xfs_vnodeops.c | 14 ++++---- init/Kconfig | 1 - 20 files changed, 179 insertions(+), 168 deletions(-)
fs/xfs/xfs_acl.c +19 -4
@@ -64,14 +64,17 @@ xfs_acl_from_disk(struct xfs_acl *aclp)switch (acl_e->e_tag) {case ACL_USER : + acl_e->e_uid =make_kuid (&init_user_ns, +be32_to_cpu (ace->ae_id)); +break ;case ACL_GROUP : - acl_e->e_id =be32_to_cpu (ace->ae_id); + acl_e->e_gid =make_kgid (&init_user_ns, +be32_to_cpu (ace->ae_id));break ;case ACL_USER_OBJ :case ACL_GROUP_OBJ :case ACL_MASK :case ACL_OTHER : - acl_e->e_id =ACL_UNDEFINED_ID ;break ;default : goto fail;
@@ -97,8 +100,20 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) acl_e = &acl->a_entries[i]; ace->ae_tag =cpu_to_be32 (acl_e->e_tag); - ace->ae_id =cpu_to_be32 (acl_e->e_id); ace->ae_perm =cpu_to_be16 (acl_e->e_perm); +switch (acl_e->e_tag) { +case ACL_USER : + ace->ae_id =cpu_to_be32 ( +from_kuid (&init_user_ns, acl_e->e_uid)); +break ; +case ACL_GROUP : + ace->ae_id =cpu_to_be32 ( +from_kgid (&init_user_ns, acl_e->e_gid)); +break ; +default : + ace->ae_id =cpu_to_be32 (ACL_UNDEFINED_ID ); +break ; + } } }
@@ -355,7 +370,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,return -EINVAL ;if (type ==ACL_TYPE_DEFAULT && !S_ISDIR (inode->i_mode))return value ? -EACCES :0 ; -if ((current_fsuid () != inode->i_uid) && !capable (CAP_FOWNER )) +if ((!uid_eq (current_fsuid (), inode->i_uid)) && !capable (CAP_FOWNER ))return -EPERM ;if (!value)
fs/xfs/xfs_dquot.c +24 -12
@@ -63,6 +63,19 @@ static struct kmem_zone *xfs_qm_dqzone;static struct lock_class_key xfs_dquot_other_class; +STATIC int +xfs_quota_type (int type) +{ +switch (type) { +case USRQUOTA : +return XFS_DQ_USER ; +case GRPQUOTA : +return XFS_DQ_GROUP ; +default : +return XFS_DQ_PROJ ; + } +} +/* * This is called to free all the memory associated with a dquot */
@@ -480,8 +493,7 @@ xfs_qm_dqtobp(int xfs_qm_dqread (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,uint flags,struct xfs_dquot **O_dqpp) {
@@ -495,8 +507,9 @@ xfs_qm_dqread( dqp =kmem_zone_zalloc (xfs_qm_dqzone,KM_SLEEP ); - dqp->dq_flags = type; - dqp->q_core.d_id =cpu_to_be32 (id); + dqp->dq_id = id; + dqp->dq_flags =xfs_quota_type (id.type); + dqp->q_core.d_id =cpu_to_be32 (from_kqid (&init_user_ns, id)); dqp->q_mount = mp;INIT_LIST_HEAD (&dqp->q_lru);mutex_init (&dqp->q_qlock);
@@ -514,7 +527,7 @@ xfs_qm_dqread(* Make sure group quotas have a different lock class than user * quotas. */ -if (!(type &XFS_DQ_USER )) +if (id.type !=USRQUOTA )lockdep_set_class (&dqp->q_qlock, &xfs_dquot_other_class);XFS_STATS_INC (xs_qm_dquot);
@@ -614,12 +627,12 @@ intxfs_qm_dqget ( xfs_mount_t *mp, xfs_inode_t *ip,/* locked inode (optional) */ - xfs_dqid_t id, /* uid/projid/gid depending on type */ - uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */ + struct kqid id, /* uid/projid/gid depending on type */ uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ {struct xfs_quotainfo *qi = mp->m_quotainfo; +uint type =xfs_quota_type (id.type);struct radix_tree_root *tree =XFS_DQUOT_TREE (qi, type);struct xfs_dquot *dqp;int error;
@@ -651,7 +664,7 @@ xfs_qm_dqget( restart:mutex_lock (&qi->qi_tree_lock); - dqp =radix_tree_lookup (tree, id); + dqp =radix_tree_lookup (tree,from_kqid (&init_user_ns, id));if (dqp) {xfs_dqlock (dqp);if (dqp->dq_flags &XFS_DQ_FREEING ) {
@@ -683,7 +696,7 @@ restart:if (ip)xfs_iunlock (ip,XFS_ILOCK_EXCL ); - error =xfs_qm_dqread (mp, id, type, flags, &dqp); + error =xfs_qm_dqread (mp, id, flags, &dqp);if (ip)xfs_ilock (ip,XFS_ILOCK_EXCL );
@@ -714,7 +727,7 @@ restart: }mutex_lock (&qi->qi_tree_lock); - error = -radix_tree_insert (tree, id, dqp); + error = -radix_tree_insert (tree,from_kqid (&init_user_ns, id), dqp);if (unlikely (error)) {WARN_ON (error !=EEXIST );
@@ -990,8 +1003,7 @@ xfs_dqlock2( {if (d1 && d2) {ASSERT (d1 != d2); -if (be32_to_cpu (d1->q_core.d_id) > -be32_to_cpu (d2->q_core.d_id)) { +if (qid_lt (d2->dq_id, d1->dq_id)) {mutex_lock (&d2->q_qlock);mutex_lock_nested (&d1->q_qlock,XFS_QLOCK_NESTED ); }else {
fs/xfs/xfs_dquot.h +3 -2
@@ -36,6 +36,7 @@ struct xfs_trans;* The incore dquot structure */ typedef struct xfs_dquot { + struct kqid dq_id; /* Quota identifier */ uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */
@@ -138,7 +139,7 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type) XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ XFS_DQ_TO_QINF(dqp)->qi_gquotaip) -extern int xfs_qm_dqread (struct xfs_mount *,xfs_dqid_t ,uint , +extern int xfs_qm_dqread (struct xfs_mount *,struct kqid ,uint ,struct xfs_dquot **);extern void xfs_qm_dqdestroy (xfs_dquot_t *);extern int xfs_qm_dqflush (struct xfs_dquot *,struct xfs_buf **);
@@ -148,7 +149,7 @@ extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,extern void xfs_qm_adjust_dqlimits (xfs_mount_t *,xfs_disk_dquot_t *);extern int xfs_qm_dqget (xfs_mount_t *,xfs_inode_t *, -xfs_dqid_t ,uint ,uint ,xfs_dquot_t **); +struct kqid ,uint ,xfs_dquot_t **);extern void xfs_qm_dqput (xfs_dquot_t *);extern void xfs_dqlock2 (struct xfs_dquot *,struct xfs_dquot *);
fs/xfs/xfs_inode.c +19 -14
@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid)); to->di_nlink =be32_to_cpu (from->di_nlink); - to->di_projid_lo =be16_to_cpu (from->di_projid_lo); - to->di_projid_hi =be16_to_cpu (from->di_projid_hi); + to->di_projid =make_kprojid (&init_user_ns, +be16_to_cpu (from->di_projid_lo) | + (be16_to_cpu (from->di_projid_hi) <<16 ));memcpy (to->di_pad, from->di_pad,sizeof (to->di_pad)); to->di_flushiter =be16_to_cpu (from->di_flushiter); to->di_atime.t_sec =be32_to_cpu (from->di_atime.t_sec);
@@ -601,16 +602,18 @@ xfs_dinode_to_disk( xfs_dinode_t *to, xfs_icdinode_t *from) { +projid_t projid =from_kprojid (&init_user_ns, from->di_projid); + to->di_magic =cpu_to_be16 (from->di_magic); to->di_mode =cpu_to_be16 (from->di_mode); to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink =cpu_to_be16 (from->di_onlink); - to->di_uid =cpu_to_be32 (from->di_uid); - to->di_gid =cpu_to_be32 (from->di_gid); + to->di_uid =cpu_to_be32 (from_kuid (&init_user_ns, from->di_uid)); + to->di_gid =cpu_to_be32 (from_kgid (&init_user_ns, from->di_gid)); to->di_nlink =cpu_to_be32 (from->di_nlink); - to->di_projid_lo =cpu_to_be16 (from->di_projid_lo); - to->di_projid_hi =cpu_to_be16 (from->di_projid_hi); + to->di_projid_lo =cpu_to_be16 (projid &0xffff ); + to->di_projid_hi =cpu_to_be16 (projid >>16 );memcpy (to->di_pad, from->di_pad,sizeof (to->di_pad)); to->di_flushiter =cpu_to_be16 (from->di_flushiter); to->di_atime.t_sec =cpu_to_be32 (from->di_atime.t_sec);
@@ -778,7 +781,7 @@ xfs_iread(if (ip->i_d.di_version ==1 ) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink =0 ; -xfs_set_projid (ip,0 ); + ip->i_d.di_projid =make_kprojid (&init_user_ns,0 ); } ip->i_delayed_blks =0 ;
@@ -884,7 +887,7 @@ xfs_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, + kprojid_t prid, int okalloc, xfs_buf_t **ialloc_context, xfs_inode_t **ipp)
@@ -927,7 +930,7 @@ xfs_ialloc(ASSERT (ip->i_d.di_nlink == nlink); ip->i_d.di_uid =current_fsuid (); ip->i_d.di_gid =current_fsgid (); -xfs_set_projid (ip, prid); + ip->i_d.di_projid = prid;memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));/*
@@ -948,7 +951,8 @@ xfs_ialloc(/* * Project ids won't be stored on disk if we are using a version 1 inode. */ -if ((prid !=0 ) && (ip->i_d.di_version ==1 )) +if (!projid_eq (prid,make_kprojid (&init_user_ns,0 )) && + (ip->i_d.di_version ==1 ))xfs_bump_ino_vers2 (tp, ip);if (pip &&XFS_INHERIT_GID (pip)) {
@@ -965,7 +969,7 @@ xfs_ialloc(*/ if ((irix_sgid_inherit) && (ip->i_d.di_mode &S_ISGID ) && - (!in_group_p ((gid_t )ip->i_d.di_gid))) { + (!in_group_p (ip->i_d.di_gid))) { ip->i_d.di_mode &= ~S_ISGID ; }
@@ -2554,7 +2558,8 @@ xfs_iflush_int(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));memset (&(dip->di_pad[0 ]),0 ,sizeof (dip->di_pad)); -ASSERT (xfs_get_projid (ip) ==0 ); +ASSERT (projid_eq (ip->i_d.di_projid, +make_kprojid (&init_user_ns,0 ))); } }
fs/xfs/xfs_inode.h +6 -26
@@ -120,8 +120,8 @@ typedef struct xfs_ictimestamp { } xfs_ictimestamp_t;/* -* NOTE: This structure must be kept identical to struct xfs_dinode -* in xfs_dinode.h except for the endianness annotations. +* NOTE: This structure must contain all of the same informationas struct xfs_dinode +* in xfs_dinode.h except in core format. */ typedef struct xfs_icdinode { __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
@@ -129,11 +129,10 @@ typedef struct xfs_icdinode {__int8_t di_version;/* inode version */ __int8_t di_format;/* format of di_c data */ __uint16_t di_onlink;/* old number of links to file */ -__uint32_t di_uid;/* owner's user id */ -__uint32_t di_gid;/* owner's group id */ +kuid_t di_uid;/* owner's user id */ +kgid_t di_gid;/* owner's group id */ __uint32_t di_nlink;/* number of links to file */ -__uint16_t di_projid_lo;/* lower part of owner's project id */ -__uint16_t di_projid_hi;/* higher part of owner's project id */ +kprojid_t di_projid;/* project id */ __uint8_t di_pad[6 ];/* unused, zeroed space */ __uint16_t di_flushiter;/* incremented on flush */ xfs_ictimestamp_t di_atime;/* time last accessed */
@@ -355,25 +354,6 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags) }/* -* Project quota id helpers (previously projid was 16bit only -* and using two 16bit values to hold new 32bit projid was chosen -* to retain compatibility with "old" filesystems). -*/ -static inline prid_t -xfs_get_projid (struct xfs_inode *ip) -{ -return (prid_t )ip->i_d.di_projid_hi <<16 | ip->i_d.di_projid_lo; -} - -static inline void -xfs_set_projid (struct xfs_inode *ip, -prid_t projid) -{ - ip->i_d.di_projid_hi = (__uint16_t) (projid >>16 ); - ip->i_d.di_projid_lo = (__uint16_t) (projid &0xffff ); -} - -/* * In-core inode flags. */ #define XFS_IRECLAIM (1 << 0)/* started reclaiming this inode */
@@ -514,7 +494,7 @@ void xfs_inode_free(struct xfs_inode *ip);* xfs_inode.c prototypes. */ int xfs_ialloc (struct xfs_trans *,xfs_inode_t *,umode_t , -xfs_nlink_t ,xfs_dev_t ,prid_t ,int , +xfs_nlink_t ,xfs_dev_t ,kprojid_t ,int ,struct xfs_buf **,xfs_inode_t **);uint xfs_ip2xflags (struct xfs_inode *);
fs/xfs/xfs_ioctl.c +17 -6
@@ -814,7 +814,7 @@ xfs_ioc_fsgetxattr(xfs_ilock (ip,XFS_ILOCK_SHARED ); fa.fsx_xflags =xfs_ip2xflags (ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; - fa.fsx_projid =xfs_get_projid (ip); + fa.fsx_projid =from_kprojid_munged (current_user_ns (), ip->i_d.di_projid);if (attr) {if (ip->i_afp) {
@@ -924,6 +924,7 @@ xfs_ioctl_setattr(struct xfs_dquot *gdqp =NULL ;struct xfs_dquot *olddquot =NULL ;int code; +kprojid_t projid =INVALID_PROJID ;trace_xfs_ioctl_setattr (ip);
@@ -940,6 +941,15 @@ xfs_ioctl_setattr(return XFS_ERROR (EINVAL );/* +* Verify the specifid project id is valid. +*/ +if (mask &FSX_PROJID ) { + projid =make_kprojid (current_user_ns (), fa->fsx_projid); +if (!projid_valid (projid)) +return XFS_ERROR (EINVAL ); + } + +/* * If disk quotas is on, we make sure that the dquots do exist on disk, * before we start any other transactions. Trying to do this later * is messy. We don't care to take a readlock to look at the ids
@@ -949,7 +959,7 @@ xfs_ioctl_setattr(*/ if (XFS_IS_QUOTA_ON (mp) && (mask &FSX_PROJID )) { code =xfs_qm_vop_dqalloc (ip, ip->i_d.di_uid, - ip->i_d.di_gid, fa->fsx_projid, + ip->i_d.di_gid, projid,XFS_QMOPT_PQUOTA , &udqp, &gdqp);if (code)return code;
@@ -974,7 +984,8 @@ xfs_ioctl_setattr(* to the file owner ID, except in cases where the * CAP_FSETID capability is applicable. */ -if (current_fsuid () != ip->i_d.di_uid && !capable (CAP_FOWNER )) { +if (!uid_eq (current_fsuid (), ip->i_d.di_uid) && + !capable (CAP_FOWNER )) { code =XFS_ERROR (EPERM ); goto error_return; }
@@ -985,7 +996,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && -xfs_get_projid (ip) != fa->fsx_projid) { + !projid_eq (ip->i_d.di_projid, projid)) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1103,12 +1114,12 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (xfs_get_projid (ip) != fa->fsx_projid) { +if (!projid_eq (ip->i_d.di_projid, projid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp); } -xfs_set_projid (ip, fa->fsx_projid); + ip->i_d.di_projid = projid;/* * We may have to rev the inode as well as
fs/xfs/xfs_iops.c +9 -9
@@ -465,8 +465,8 @@ xfs_setattr_nonsize(int mask = iattr->ia_valid;xfs_trans_t *tp;int error; -uid_t uid =0 , iuid =0 ; -gid_t gid =0 , igid =0 ; +kuid_t uid =GLOBAL_ROOT_UID , iuid =GLOBAL_ROOT_UID ; +kgid_t gid =GLOBAL_ROOT_GID , igid =GLOBAL_ROOT_GID ;struct xfs_dquot *udqp =NULL , *gdqp =NULL ;struct xfs_dquot *olddquot1 =NULL , *olddquot2 =NULL ;
@@ -515,7 +515,7 @@ xfs_setattr_nonsize(*/ ASSERT (udqp ==NULL );ASSERT (gdqp ==NULL ); - error =xfs_qm_vop_dqalloc (ip, uid, gid,xfs_get_projid (ip), + error =xfs_qm_vop_dqalloc (ip, uid, gid, ip->i_d.di_projid, qflags, &udqp, &gdqp);if (error)return error;
@@ -548,8 +548,8 @@ xfs_setattr_nonsize(* going to change. */ if (XFS_IS_QUOTA_RUNNING (mp) && - ((XFS_IS_UQUOTA_ON (mp) && iuid != uid) || - (XFS_IS_GQUOTA_ON (mp) && igid != gid))) { + ((XFS_IS_UQUOTA_ON (mp) && !uid_eq (iuid, uid)) || + (XFS_IS_GQUOTA_ON (mp) && !gid_eq (igid, gid)))) {ASSERT (tp); error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -579,7 +579,7 @@ xfs_setattr_nonsize(* Change the ownerships and register quota modifications * in the transaction. */ -if (iuid != uid) { +if (!uid_eq (iuid, uid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_UQUOTA_ON (mp)) {ASSERT (mask &ATTR_UID );ASSERT (udqp);
@@ -589,7 +589,7 @@ xfs_setattr_nonsize( ip->i_d.di_uid = uid; inode->i_uid = uid; } -if (igid != gid) { +if (!gid_eq (igid, gid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_GQUOTA_ON (mp)) {ASSERT (!XFS_IS_PQUOTA_ON (mp));ASSERT (mask &ATTR_GID );
@@ -1151,8 +1151,8 @@ xfs_setup_inode( inode->i_mode = ip->i_d.di_mode;set_nlink (inode, ip->i_d.di_nlink); - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; + inode->i_uid = ip->i_d.di_uid; + inode->i_gid = ip->i_d.di_gid;switch (inode->i_mode &S_IFMT ) {case S_IFBLK :
fs/xfs/xfs_itable.c +4 -4
@@ -90,12 +90,12 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = dic->di_nlink; - buf->bs_projid_lo = dic->di_projid_lo; - buf->bs_projid_hi = dic->di_projid_hi; + buf->bs_projid_lo =from_kprojid (current_user_ns (), dic->di_projid) &0xffff ; + buf->bs_projid_hi =from_kprojid (current_user_ns (), dic->di_projid) >>16 ; buf->bs_ino = ino; buf->bs_mode = dic->di_mode; - buf->bs_uid = dic->di_uid; - buf->bs_gid = dic->di_gid; + buf->bs_uid =from_kuid (&init_user_ns, dic->di_uid); + buf->bs_gid =from_kgid (&init_user_ns, dic->di_gid); buf->bs_size = dic->di_size; buf->bs_atime.tv_sec = dic->di_atime.t_sec; buf->bs_atime.tv_nsec = dic->di_atime.t_nsec;
fs/xfs/xfs_qm.c +46 -41
231 lines not on this page · raw message
fs/xfs/xfs_qm.h +2 -2
@@ -114,9 +114,9 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);/* quota ops */ extern int xfs_qm_scall_trunc_qfiles (xfs_mount_t *,uint ); -extern int xfs_qm_scall_getquota (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_getquota (xfs_mount_t *,struct kqid ,fs_disk_quota_t *); -extern int xfs_qm_scall_setqlim (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_setqlim (xfs_mount_t *,struct kqid ,fs_disk_quota_t *);extern int xfs_qm_scall_getqstat (xfs_mount_t *,fs_quota_stat_t *);extern int xfs_qm_scall_quotaon (xfs_mount_t *,uint );
fs/xfs/xfs_qm_bhv.c +2 -1
@@ -79,7 +79,8 @@ xfs_qm_statvfs(xfs_mount_t *mp = ip->i_mount;xfs_dquot_t *dqp; -if (!xfs_qm_dqget (mp,NULL ,xfs_get_projid (ip),XFS_DQ_PROJ ,0 , &dqp)) { +if (!xfs_qm_dqget (mp,NULL ,make_kqid_projid (ip->i_d.di_projid), +0 , &dqp)) {xfs_fill_statvfs_from_dquot (statp, dqp);xfs_qm_dqput (dqp); }
fs/xfs/xfs_qm_syscalls.c +13 -11
@@ -472,8 +472,7 @@ xfs_qm_scall_getqstat(int xfs_qm_scall_setqlim (xfs_mount_t *mp, -xfs_dqid_t id, -uint type, +struct kqid id,fs_disk_quota_t *newlim) {struct xfs_quotainfo *q = mp->m_quotainfo;
@@ -482,6 +481,7 @@ xfs_qm_scall_setqlim(xfs_trans_t *tp;int error;xfs_qcnt_t hard, soft; +bool root_qid;if (newlim->d_fieldmask & ~XFS_DQ_MASK )return EINVAL ;
@@ -495,6 +495,9 @@ xfs_qm_scall_setqlim(return (error); } +/* Are we setting the root users quota? */ + root_qid =qid_eq (id,make_kqid (&init_user_ns, id.type,0 )); +/* * We don't want to race with a quotaoff so take the quotaoff lock. * (We don't hold an inode lock, so there's nothing else to stop
@@ -507,7 +510,7 @@ xfs_qm_scall_setqlim(* Get the dquot (locked), and join it to the transaction. * Allocate the dquot if this doesn't exist. */ -if ((error =xfs_qm_dqget (mp,NULL , id, type,XFS_QMOPT_DQALLOC , &dqp))) { +if ((error =xfs_qm_dqget (mp,NULL , id,XFS_QMOPT_DQALLOC , &dqp))) {xfs_trans_cancel (tp,XFS_TRANS_ABORT );ASSERT (error !=ENOENT ); goto out_unlock;
@@ -527,7 +530,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_blk_hardlimit =cpu_to_be64 (hard); ddq->d_blk_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (root_qid) { q->qi_bhardlimit = hard; q->qi_bsoftlimit = soft; }
@@ -543,7 +546,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_rtb_hardlimit =cpu_to_be64 (hard); ddq->d_rtb_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (root_qid) { q->qi_rtbhardlimit = hard; q->qi_rtbsoftlimit = soft; }
@@ -560,7 +563,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_ino_hardlimit =cpu_to_be64 (hard); ddq->d_ino_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (root_qid) { q->qi_ihardlimit = hard; q->qi_isoftlimit = soft; }
@@ -578,7 +581,7 @@ xfs_qm_scall_setqlim(if (newlim->d_fieldmask &FS_DQ_RTBWARNS ) ddq->d_rtbwarns =cpu_to_be16 (newlim->d_rtbwarns); -if (id ==0 ) { +if (root_qid) {/* * Timelimits for the super user set the relative time * the other users can be over quota for this file system.
@@ -716,8 +719,7 @@ error0:int xfs_qm_scall_getquota (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,struct fs_disk_quota *dst) {struct xfs_dquot *dqp;
@@ -728,7 +730,7 @@ xfs_qm_scall_getquota(* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't * exist, we'll get ENOENT back. */ - error =xfs_qm_dqget (mp,NULL , id, type,0 , &dqp); + error =xfs_qm_dqget (mp,NULL , id,0 , &dqp);if (error)return error;
@@ -744,7 +746,7 @@ xfs_qm_scall_getquota(memset (dst,0 ,sizeof (*dst)); dst->d_version =FS_DQUOT_VERSION ; dst->d_flags =xfs_qm_export_qtype_flags (dqp->q_core.d_flags); - dst->d_id =be32_to_cpu (dqp->q_core.d_id); + dst->d_id =from_kqid_munged (current_user_ns (), dqp->dq_id); dst->d_blk_hardlimit =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_blk_hardlimit)); dst->d_blk_softlimit =
fs/xfs/xfs_quota.h +2 -2
@@ -311,7 +311,7 @@ extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, struct xfs_dquot *, long, long, uint); -extern int xfs_qm_vop_dqalloc (struct xfs_inode *,uid_t ,gid_t ,prid_t ,uint , +extern int xfs_qm_vop_dqalloc (struct xfs_inode *,kuid_t ,kgid_t ,kprojid_t ,uint ,struct xfs_dquot **,struct xfs_dquot **);extern void xfs_qm_vop_create_dqattach (struct xfs_trans *,struct xfs_inode *,struct xfs_dquot *,struct xfs_dquot *);
@@ -332,7 +332,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);#else static inline int -xfs_qm_vop_dqalloc (struct xfs_inode *ip,uid_t uid,gid_t gid,prid_t prid, +xfs_qm_vop_dqalloc (struct xfs_inode *ip,kuid_t uid,kgid_t gid,kprojid_t prid,uint flags,struct xfs_dquot **udqp,struct xfs_dquot **gdqp) { *udqp =NULL ;
fs/xfs/xfs_quotaops.c +2 -18
@@ -27,20 +27,6 @@#include "xfs_qm.h" #include <linux/quota.h> - -STATIC int -xfs_quota_type (int type) -{ -switch (type) { -case USRQUOTA : -return XFS_DQ_USER ; -case GRPQUOTA : -return XFS_DQ_GROUP ; -default : -return XFS_DQ_PROJ ; - } -} - STATIC int xfs_fs_get_xstate( struct super_block *sb,
@@ -107,8 +93,7 @@ xfs_fs_get_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_getquota (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_getquota (mp, qid, fdq); }STATIC int
@@ -126,8 +111,7 @@ xfs_fs_set_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_setqlim (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_setqlim (mp, qid, fdq); }const struct quotactl_ops xfs_quotactl_operations = {
fs/xfs/xfs_rename.c +1 -1
@@ -171,7 +171,7 @@ xfs_rename(* tree quota mechanism would be circumvented. */ if (unlikely ((target_dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (target_dp) !=xfs_get_projid (src_ip)))) { + !projid_eq (target_dp->i_d.di_projid, src_ip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
fs/xfs/xfs_trans_dquot.c +1 -5
@@ -578,11 +578,7 @@ xfs_quota_warn(/* no warnings for project quotas - we just return ENOSPC later */ if (dqp->dq_flags &XFS_DQ_PROJ )return ; -quota_send_warning (make_kqid (&init_user_ns, - (dqp->dq_flags &XFS_DQ_USER ) ? -USRQUOTA :GRPQUOTA , -be32_to_cpu (dqp->q_core.d_id)), - mp->m_super->s_dev, type); +quota_send_warning (dqp->dq_id, mp->m_super->s_dev, type); }/*
fs/xfs/xfs_utils.c +1 -1
@@ -54,7 +54,7 @@ xfs_dir_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, /* project id */ + kprojid_t prid, /* project id */ int okalloc, /* ok to allocate new space */ xfs_inode_t **ipp, /* pointer to inode; it will be locked. */
fs/xfs/xfs_utils.h +1 -1
@@ -19,7 +19,7 @@#define __XFS_UTILS_H__extern int xfs_dir_ialloc (xfs_trans_t **,xfs_inode_t *,umode_t ,xfs_nlink_t , -xfs_dev_t ,prid_t ,int ,xfs_inode_t **,int *); +xfs_dev_t ,kprojid_t ,int ,xfs_inode_t **,int *);extern int xfs_droplink (xfs_trans_t *,xfs_inode_t *);extern int xfs_bumplink (xfs_trans_t *,xfs_inode_t *);extern void xfs_bump_ino_vers2 (xfs_trans_t *,xfs_inode_t *);
fs/xfs/xfs_vnodeops.c +7 -7
@@ -727,7 +727,7 @@ xfs_create(boolean_t unlock_dp_on_error =B_FALSE ;uint cancel_flags;int committed; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp =NULL ;struct xfs_dquot *gdqp =NULL ;uint resblks;
@@ -740,9 +740,9 @@ xfs_create(return XFS_ERROR (EIO );if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
@@ -1304,7 +1304,7 @@ xfs_link(* the tree quota mechanism could be circumvented. */ if (unlikely ((tdp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (tdp) !=xfs_get_projid (sip)))) { + !projid_eq (tdp->i_d.di_projid, sip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
@@ -1378,7 +1378,7 @@ xfs_symlink(int byte_cnt;int n;xfs_buf_t *bp; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp, *gdqp;uint resblks;
@@ -1401,9 +1401,9 @@ xfs_symlink( udqp = gdqp =NULL ;if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
init/Kconfig +0 -1
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS bool "Require conversions between uid/gids and their internal representation"
Signature · 1 line
1.7.5.4
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 16 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
- Modify the incore inode to use
kuid_t,kgid_tandkprojid_t.
- Removexfs_get_projidandxfs_set_projidwith projid being stored in a single field they are unnecessary.
- Adddq_id(a struct kqid) to structxfs_dquotto retain the incore version of the quota identifiers.
- Pass struct kquid all of the way intoxfs_qm_dqgetnandxfs_qm_dqread, and movexfs_quota_typeintoxfs_dquot.cfromxfs_quotaops.cto support this change.Cc Ben Myers <[email protected]>Cc Alex Elder <[email protected]>Cc Dave Chinner <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>---
.....
fs/xfs/xfs_dquot.c int · line 635
Quoted 12 lines
fs/xfs/xfs_dquot.c +2
-2@@ -614,12 +627,12 @@ intxfs_qm_dqget ( xfs_mount_t *mp, xfs_inode_t *ip,/* locked inode (optional) */ - xfs_dqid_t id, /* uid/projid/gid depending on type */ - uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */ + struct kqid id, /* uid/projid/gid depending on type */ uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ {struct xfs_quotainfo *qi = mp->m_quotainfo; +uint type =xfs_quota_type (id.type);
uint type = xfs_quota_type(id.type);
....
fs/xfs/xfs_dquot.h struct xfs_trans; · line 42
Quoted 12 lines
fs/xfs/xfs_dquot.h +1
-0@@ -36,6 +36,7 @@ struct xfs_trans;* The incore dquot structure */ typedef struct xfs_dquot { + struct kqid dq_id; /* Quota identifier */ uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */
Can you place new entries at the end of the structure, please?
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 12 lines
fs/xfs/xfs_inode.c +2
-2@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));
You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 578
Quoted 6 lines
fs/xfs/xfs_inode.c +3
-2to->di_nlink =be32_to_cpu (from->di_nlink); - to->di_projid_lo =be16_to_cpu (from->di_projid_lo); - to->di_projid_hi =be16_to_cpu (from->di_projid_hi); + to->di_projid =make_kprojid (&init_user_ns, +be16_to_cpu (from->di_projid_lo) | + (be16_to_cpu (from->di_projid_hi) <<16 ));
As is this. I won't comment on all the other problems that stem from changing this structure, apart from....
fs/xfs/xfs_inode.h typedef struct xfs_ictimestamp { · line 124
Quoted 12 lines
fs/xfs/xfs_inode.h +2
-2@@ -120,8 +120,8 @@ typedef struct xfs_ictimestamp { } xfs_ictimestamp_t;/* -* NOTE: This structure must be kept identical to struct xfs_dinode -* in xfs_dinode.h except for the endianness annotations. +* NOTE: This structure must contain all of the same informationas struct xfs_dinode +* in xfs_dinode.h except in core format.
.... noting that you even read the comment that says the incore inode must remain identical to struct xfs_dinode. Changing the comment doesn't make the change correct. :/
Quoted 5 lines
fs/xfs/xfs_inode.h +0
-0*/ typedef struct xfs_icdinode { __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */@@ -129,11 +129,10 @@ typedef struct xfs_icdinode {__int8_t di_version;/* inode version */
fs/xfs/xfs_inode.h typedef struct xfs_icdinode { · line 135
Quoted 10 lines
fs/xfs/xfs_inode.h +3
-4__int8_t di_format;/* format of di_c data */ __uint16_t di_onlink;/* old number of links to file */ -__uint32_t di_uid;/* owner's user id */ -__uint32_t di_gid;/* owner's group id */ +kuid_t di_uid;/* owner's user id */ +kgid_t di_gid;/* owner's group id */ __uint32_t di_nlink;/* number of links to file */ -__uint16_t di_projid_lo;/* lower part of owner's project id */ -__uint16_t di_projid_hi;/* higher part of owner's project id */ +kprojid_t di_projid;/* project id */
Basically, you cannot replace these with your new structure because it changes the layout of the structure, and because it is written directly into the journal it is an on-disk format change. We might be able to work around that, but there's a high bar that needs to be passed before this sort of change canbe made.
The question I have is why do you need to make changes this deeply to the filesystem? We already pass the {type, id} tuple throughout the code, and it really only needs to be translated from the special {kuid_t/kguid_t/kprojid_t, namespace} notation once at entry to the filesystem.
You are not changing anything on disk or how {type, id} is being interpreted by the filesystem, so do you really need to propagate the namespace changes this far down to the low-level filesystem uid/gid/prid management code? I do not see why it is necessary, especially as doing so opens several large, smelly cans of worms that are going to require significant verification effort.
fs/xfs/xfs_inode.h xfs_setup_inode( · line 1155
Quoted 8 lines
fs/xfs/xfs_inode.h +2
-2@@ -1151,8 +1151,8 @@ xfs_setup_inode( inode->i_mode = ip->i_d.di_mode;set_nlink (inode, ip->i_d.di_nlink); - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; + inode->i_uid = ip->i_d.di_uid; + inode->i_gid = ip->i_d.di_gid;
You've already added the special structures to the struct inode, so perhaps that's where the XFS uid/gid on-disk values need to be translated.
Quoted 8 lines
fs/xfs/xfs_inode.h +0
-0switch (inode->i_mode &S_IFMT ) {case S_IFBLK :fs/xfs/xfs_itable.c +0
-0
fs/xfs/xfs_itable.c xfs_bulkstat_one_int( · line 94
Quoted 7 lines
fs/xfs/xfs_itable.c +2
-2@@ -90,12 +90,12 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = dic->di_nlink; - buf->bs_projid_lo = dic->di_projid_lo; - buf->bs_projid_hi = dic->di_projid_hi; + buf->bs_projid_lo =from_kprojid (current_user_ns (), dic->di_projid) &0xffff ; + buf->bs_projid_hi =from_kprojid (current_user_ns (), dic->di_projid) >>16 ;
Another question: why are you using current_user_ns() for project IDs, but:
fs/xfs/xfs_itable.c xfs_bulkstat_one_int( · line 98
Quoted 6 lines
fs/xfs/xfs_itable.c +2
-2buf->bs_ino = ino; buf->bs_mode = dic->di_mode; - buf->bs_uid = dic->di_uid; - buf->bs_gid = dic->di_gid; + buf->bs_uid =from_kuid (&init_user_ns, dic->di_uid); + buf->bs_gid =from_kgid (&init_user_ns, dic->di_gid);
init_user_ns for uid/gid?
As it is, I think that even just using namespaces here is wrong - bulkstat is for filesystem utilities to get the information that is on disk as efficiently as possible. e.g. xfsdump wants the exact information in the inode on disk for backup purposes, not what some random namespace thinks is valid. i.e. if there's projid set on the inode, it must be reported *unchanged* to xfsdump so that when it is restored it has the same value on disk.
Hmmm, that also means that using current_user_ns() for setting the project id is also problematic, because that's what xfs_restore uses and it has to be written unmolested to the inode.
IOWs, this set of changes is not something that can be done with a simple search-and-replace, and certainly not a change that can be asserted to be "obviously correct". That means you're going to need to write new xfstests for xfsdump/restore to validate that they correctly backup and restore filesystems in the presence of multiple namespaces.
fs/xfs/xfs_itable.c xfs_qm_qino_alloc( · line 782
Quoted 8 lines
fs/xfs/xfs_itable.c +3
-1@@ -776,7 +777,9 @@ xfs_qm_qino_alloc(return error; } - error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 ,0 ,1 , ip, &committed); + error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 , +make_kprojid (&init_user_ns,0 ), +1 , ip, &committed);
This sort of thing just makes me cringe. This is all internal project ID management that has nothing to do with namespaces. It's for project ID's that are inherited from the parent inode, and as such we do not care one bit what the namespace is. Internal passing of project IDs like this this should not be converted at all as it has nothing at all to do with the namespaces.
Overall, I think this patch needs to be broken up into several steps. The first is to propagate the new structures into the VFS entry points of the filesystem, one to convert the quota entry points, another to convert the generic ACL code, another to convert the ioctl entry points. At that point, XFS supports namespaces fully, and it should be possible to review and test the changes sanely.
Quoted 1 line
From there, targetted patches can drive the kernel structures inward
from the entry points where it makes sense to do so (e.g. common places that the quota entry points call that take a type/id pair). The last thing that should happen is internal structures be converted from type/id pairs to the kernel types if it makes sense to do so and it makes the code simpler and easier to read....
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Joel Becker
maintainerRe: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 7 lines · Dave Chinner
Quoted 7 lines
fs/xfs/xfs_inode.c +0
-0@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format;
Quoted 8 lines
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 5 lines
fs/xfs/xfs_inode.c +2
-2to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
Yeah, I don't get this either. Over in ocfs2, you do the
correct thing, translating at the boundary from ocfs2_dinode to struct inode.
Joel
Signature · 6 lines
"I always thought the hardest questions were those I could not answer. Now I know they are the ones I can never ask." - Charlie Watkins http://www.jlbec.org/ [email protected]
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 17 lines · Joel Becker
Quoted 7 lines · Dave Chinner
Quoted 7 lines
fs/xfs/xfs_inode.c +0
-0@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format;Quoted 8 lines
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 5 lines
fs/xfs/xfs_inode.c +2
-2to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
Quoted 3 lines
Yeah, I don't get this either. Over in ocfs2, you do the
correct thing, translating at the boundary fromocfs2_dinodeto struct inode.
This is the boundary. The crazy thing is that is that xfs appears to directly write their incore inode structure into their journal. I had missed the journal reference the first time through and simply assumed since this is where the disk inode to the incore inode coversion happened that the weird scary comment in the xfs header file was wrong.
I would have no problems with not converting those uids and gids except they are used directly in comparisons against current_fsuid so it really isn't ok to not convert those values.
I wish that incore structure was managed more like the lvb in ocfs2. Even though it is cached in core it is first converted into a specific byte order and then shoved into a character array. Keeping anyone from getting any funny ideas about using those values directly.
I have sent my xfs changes back to the drawing board and am concentrating on getting my conversions for the rest of the filesystems merged. When I get the time I will come back to xfs. xfs is a very peculiar filesystem.
Eric
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 19 lines · Eric W. Biederman
Quoted 17 lines · Joel Becker
Quoted 15 lines · Dave Chinner
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 12 lines
fs/xfs/xfs_inode.c +2
-2@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
Quoted 5 lines
Quoted 3 lines
Yeah, I don't get this either. Over in ocfs2, you do the
correct thing, translating at the boundary fromocfs2_dinodeto struct inode.This is the boundary.
It is *a* boundary. It is the in-core disk inode to on disk inode boundary (i.e. struct xfs_icdinode to struct xfs_dinode). Namespaces don't belong at this boundary - this is internal XFS stuff that nothing from the VFS should be interacting with. The structure of XFS is roughly:
userspace --------- VFS --------- VFS/XFS <<<<<< here is where you need to modify interface --------- core XFS --------- XFS/disk <<<<<< here is where you actually modified interface --------- storage
IOWs, the boundary you are looking for is the VFS/XFS boundary (i.e. struct inode to struct xfs_icdinode). i.e. namespace aware uid/gid is in the struct inode, flattened 32 bit values are in the struct xfs_icdinode. The struct inode and the struct xfs_icdinode are both embedded in the struct xfs_inode, so we just have to translate between the two internal structures are the right point in time.
Hence for namespaces to work correctly, anything that is currently using current_fs*id() for uid/gid comparison needs to be converted to use the VFS inode values (i.e. VFS_I(ip)->i_*id). For values written to the xfs inode, the VFS uid/gid needs to be flattened to a 32bit value.
These flattened values are needed during inode allocation (for initial on-disk values) and creating dquots associated with the new inodes. You should be able to derive them from current_fs*id(), right? Then when changing uid/gid via .setattr, we can flatten the namespace aware VFS uid/gid and into the XFS incore idinode (i.e. ip->i_d.di_*id) via the same method. Conversion from XFS on-disk to namespace aware VFS uid/gid then occurs when when initialising the VFS inode from the XFS inode (i.e. in xfs_setup_inode() like I previously suggested).
This keeps namespace aware uid/gid up at the VFS layer and conversion at the VFS/XFS boundaries in the XFS code, and everything should work fine.
Quoted 2 lines
The crazy thing is that is that xfs appears to directly write their incore inode structure into their journal.
Off topic, but it's actually a very sane thing to do. It's called logical object logging, as opposed to physical logging like ext3/4 and ocfs2 use. XFS uses a combination of logical logging (superblock, dquots, inodes) and physical logging (via buffers).
Logical logging decouples in-memory object modification from buffer IO and ensures the buffer is not a single point of serialisation when multiple objects share a single buffer. Hence we can read/write an inode buffer and concurrent modify inodes in memory from that buffer at the same time. i.e. we only need buffers for IO, not for ongoing modifications.
This decoupling allows XFS to use large buffers for inodes and so minimise IO for reading and/or writing inodes. Further, we can also easily serialise logged, in-memory modifications for all objects in a single backing buffer with only minor interruption to ongoing modifications. It also allows us to use simple fire-and-forget writeback semantics for metadata.
IOWs, the use of logical logging techniques vastly improves concurrency and scalability over the physical logging methods other filesystems use. Call it crazy if you want, but I find general most people say this simply because they don't understand why XFS does what it does....
Quoted 4 lines
I had
missed the journal reference the first time through and simply assumed since this is where the disk inode to the incore inode coversion happened that the weird scary comment in the xfs header file was wrong.
Comments in XFS, especially weird scary ones, are rarely wrong. Some of them might have been there for close on 20 years, but they are our documentation for all the weird, scary stuff that XFS does. I rely on them being correct, so it's something I always pay attention to during code review. IOWs, When we add, modify or remove something weird and scary, the comments are updated appropriately so we'll know why the code is doing something weird and scary in another 20 years time. ;)
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 9 lines · Dave Chinner
Quoted 2 lines · Eric W. Biederman
The crazy thing is that is that xfs appears to directly write their incore inode structure into their journal.
Off topic, but it's actually a very sane thing to do. It's called logical object logging, as opposed to physical logging like ext3/4 and ocfs2 use. XFS uses a combination of logical logging (superblock, dquots, inodes) and physical logging (via buffers).
Not putting your structures in disk-endian before putting them on-disk seems silly. As far as I can tell if you switch endianness of the machine accessing your xfs filesystem and have to do a log recover it won't work because a lot of the log entries will appear corrupted.
It also seems silly to require your in-memory structure to be binary compatibile with your log when you immediately copy that structure to another buffer when it comes time to queue a version of it to put into the log.
The fact that you sometimes need to allocate memory and make a copy so you can stuff your data into the logvec whose only purpose is to then copy the data a second time seems silly and wasteful.
Logical logging itself seems reasonable. I just find the implementation in xfs odd.
It looks like with a few little changes xfs could retain backwards compatibility with today, remove extra memory copies, and completely decouple the format of the in-core structures with the format of the on-disk structures. Allowing scary comments to be removed.
Eric
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 26 lines · Eric W. Biederman
Quoted 9 lines · Dave Chinner
Quoted 2 lines · Eric W. Biederman
The crazy thing is that is that xfs appears to directly write their incore inode structure into their journal.
Off topic, but it's actually a very sane thing to do. It's called logical object logging, as opposed to physical logging like ext3/4 and ocfs2 use. XFS uses a combination of logical logging (superblock, dquots, inodes) and physical logging (via buffers).
Not putting your structures in disk-endian before putting them on-disk seems silly. As far as I can tell if you switch endianness of the machine accessing your xfs filesystem and have to do a log recover it won't work because a lot of the log entries will appear corrupted.
It also seems silly to require your in-memory structure to be binary compatibile with your log when you immediately copy that structure to another buffer when it comes time to queue a version of it to put into the log.
The fact that you sometimes need to allocate memory and make a copy so you can stuff your data into the logvec whose only purpose is to then copy the data a second time seems silly and wasteful.
Quoted 7 lines
Logical logging itself seems reasonable. I just find the implementation in xfs odd.
It looks like with a few little changes xfs could retain backwards compatibility with today, remove extra memory copies, and completely decouple the format of the in-core structures with the format of the on-disk structures. Allowing scary comments to be removed.
If you think removing the copies is that easy, go right ahead - I'd love to see patches that checkpoint changes directly from the in-memory objects to the log without deadlocking....
Decoupling the in-memory structure from the log format could be done at any time. But it's just not something that is needed, and for the rare cases where it is needed it's better to put the format detection and conversion code into log recovery. i.e. take the conversion penalty once when needed on the slow path rather than on every operation through the fast path....
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
In reply to Dave ChinnerQuoted 7 lines · Dave Chinner
Quoted 7 lines
fs/xfs/xfs_inode.c +0
-0@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format;
Quoted 8 lines
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 5 lines
fs/xfs/xfs_inode.c +2
-2to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
Yeah, I don't get this either. Over in ocfs2, you do the
correct thing, translating at the boundary from ocfs2_dinode to struct inode.
Joel
Signature · 6 lines
"I always thought the hardest questions were those I could not answer. Now I know they are the ones I can never ask." - Charlie Watkins http://www.jlbec.org/ [email protected]
A message that is not in the archive (sent off-list or not yet received): 1353415420-5457-10-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate
Quoted 16 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Modify the incore inode to use
kuid_t,kgid_tandkprojid_t.
- Removexfs_get_projidandxfs_set_projidwith projid being stored in a single field they are unnecessary.
- Adddq_id(a struct kqid) to structxfs_dquotto retain the incore version of the quota identifiers.
- Pass struct kquid all of the way intoxfs_qm_dqgetnandxfs_qm_dqread, and movexfs_quota_typeintoxfs_dquot.cfromxfs_quotaops.cto support this change.Cc Ben Myers <bpm-sJ/[email protected]>Cc Alex Elder <[email protected]>Cc Dave Chinner <[email protected]>---
.....
fs/xfs/xfs_dquot.c int · line 635
Quoted 12 lines
fs/xfs/xfs_dquot.c +2
-2@@ -614,12 +627,12 @@ intxfs_qm_dqget ( xfs_mount_t *mp, xfs_inode_t *ip,/* locked inode (optional) */ - xfs_dqid_t id, /* uid/projid/gid depending on type */ - uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */ + struct kqid id, /* uid/projid/gid depending on type */ uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ {struct xfs_quotainfo *qi = mp->m_quotainfo; +uint type =xfs_quota_type (id.type);
uint type = xfs_quota_type(id.type);
....
fs/xfs/xfs_dquot.h struct xfs_trans; · line 42
Quoted 12 lines
fs/xfs/xfs_dquot.h +1
-0@@ -36,6 +36,7 @@ struct xfs_trans;* The incore dquot structure */ typedef struct xfs_dquot { + struct kqid dq_id; /* Quota identifier */ uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */
Can you place new entries at the end of the structure, please?
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 574
Quoted 12 lines
fs/xfs/xfs_inode.c +2
-2@@ -570,11 +570,12 @@ xfs_dinode_from_disk( to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink =be16_to_cpu (from->di_onlink); - to->di_uid =be32_to_cpu (from->di_uid); - to->di_gid =be32_to_cpu (from->di_gid); + to->di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid));
You can't do this, because the incore inode structure is written directly to the log. This is effectively an on-disk format change.
fs/xfs/xfs_inode.c xfs_dinode_from_disk( · line 578
Quoted 6 lines
fs/xfs/xfs_inode.c +3
-2to->di_nlink =be32_to_cpu (from->di_nlink); - to->di_projid_lo =be16_to_cpu (from->di_projid_lo); - to->di_projid_hi =be16_to_cpu (from->di_projid_hi); + to->di_projid =make_kprojid (&init_user_ns, +be16_to_cpu (from->di_projid_lo) | + (be16_to_cpu (from->di_projid_hi) <<16 ));
As is this. I won't comment on all the other problems that stem from changing this structure, apart from....
fs/xfs/xfs_inode.h typedef struct xfs_ictimestamp { · line 124
Quoted 12 lines
fs/xfs/xfs_inode.h +2
-2@@ -120,8 +120,8 @@ typedef struct xfs_ictimestamp { } xfs_ictimestamp_t;/* -* NOTE: This structure must be kept identical to struct xfs_dinode -* in xfs_dinode.h except for the endianness annotations. +* NOTE: This structure must contain all of the same informationas struct xfs_dinode +* in xfs_dinode.h except in core format.
.... noting that you even read the comment that says the incore inode must remain identical to struct xfs_dinode. Changing the comment doesn't make the change correct. :/
Quoted 5 lines
fs/xfs/xfs_inode.h +0
-0*/ typedef struct xfs_icdinode { __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */@@ -129,11 +129,10 @@ typedef struct xfs_icdinode {__int8_t di_version;/* inode version */
fs/xfs/xfs_inode.h typedef struct xfs_icdinode { · line 135
Quoted 10 lines
fs/xfs/xfs_inode.h +3
-4__int8_t di_format;/* format of di_c data */ __uint16_t di_onlink;/* old number of links to file */ -__uint32_t di_uid;/* owner's user id */ -__uint32_t di_gid;/* owner's group id */ +kuid_t di_uid;/* owner's user id */ +kgid_t di_gid;/* owner's group id */ __uint32_t di_nlink;/* number of links to file */ -__uint16_t di_projid_lo;/* lower part of owner's project id */ -__uint16_t di_projid_hi;/* higher part of owner's project id */ +kprojid_t di_projid;/* project id */
Basically, you cannot replace these with your new structure because it changes the layout of the structure, and because it is written directly into the journal it is an on-disk format change. We might be able to work around that, but there's a high bar that needs to be passed before this sort of change canbe made.
The question I have is why do you need to make changes this deeply to the filesystem? We already pass the {type, id} tuple throughout the code, and it really only needs to be translated from the special {kuid_t/kguid_t/kprojid_t, namespace} notation once at entry to the filesystem.
You are not changing anything on disk or how {type, id} is being interpreted by the filesystem, so do you really need to propagate the namespace changes this far down to the low-level filesystem uid/gid/prid management code? I do not see why it is necessary, especially as doing so opens several large, smelly cans of worms that are going to require significant verification effort.
fs/xfs/xfs_inode.h xfs_setup_inode( · line 1155
Quoted 8 lines
fs/xfs/xfs_inode.h +2
-2@@ -1151,8 +1151,8 @@ xfs_setup_inode( inode->i_mode = ip->i_d.di_mode;set_nlink (inode, ip->i_d.di_nlink); - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; + inode->i_uid = ip->i_d.di_uid; + inode->i_gid = ip->i_d.di_gid;
You've already added the special structures to the struct inode, so perhaps that's where the XFS uid/gid on-disk values need to be translated.
Quoted 8 lines
fs/xfs/xfs_inode.h +0
-0switch (inode->i_mode &S_IFMT ) {case S_IFBLK :fs/xfs/xfs_itable.c +0
-0
fs/xfs/xfs_itable.c xfs_bulkstat_one_int( · line 94
Quoted 7 lines
fs/xfs/xfs_itable.c +2
-2@@ -90,12 +90,12 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = dic->di_nlink; - buf->bs_projid_lo = dic->di_projid_lo; - buf->bs_projid_hi = dic->di_projid_hi; + buf->bs_projid_lo =from_kprojid (current_user_ns (), dic->di_projid) &0xffff ; + buf->bs_projid_hi =from_kprojid (current_user_ns (), dic->di_projid) >>16 ;
Another question: why are you using current_user_ns() for project IDs, but:
fs/xfs/xfs_itable.c xfs_bulkstat_one_int( · line 98
Quoted 6 lines
fs/xfs/xfs_itable.c +2
-2buf->bs_ino = ino; buf->bs_mode = dic->di_mode; - buf->bs_uid = dic->di_uid; - buf->bs_gid = dic->di_gid; + buf->bs_uid =from_kuid (&init_user_ns, dic->di_uid); + buf->bs_gid =from_kgid (&init_user_ns, dic->di_gid);
init_user_ns for uid/gid?
As it is, I think that even just using namespaces here is wrong - bulkstat is for filesystem utilities to get the information that is on disk as efficiently as possible. e.g. xfsdump wants the exact information in the inode on disk for backup purposes, not what some random namespace thinks is valid. i.e. if there's projid set on the inode, it must be reported *unchanged* to xfsdump so that when it is restored it has the same value on disk.
Hmmm, that also means that using current_user_ns() for setting the project id is also problematic, because that's what xfs_restore uses and it has to be written unmolested to the inode.
IOWs, this set of changes is not something that can be done with a simple search-and-replace, and certainly not a change that can be asserted to be "obviously correct". That means you're going to need to write new xfstests for xfsdump/restore to validate that they correctly backup and restore filesystems in the presence of multiple namespaces.
fs/xfs/xfs_itable.c xfs_qm_qino_alloc( · line 782
Quoted 8 lines
fs/xfs/xfs_itable.c +3
-1@@ -776,7 +777,9 @@ xfs_qm_qino_alloc(return error; } - error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 ,0 ,1 , ip, &committed); + error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 , +make_kprojid (&init_user_ns,0 ), +1 , ip, &committed);
This sort of thing just makes me cringe. This is all internal project ID management that has nothing to do with namespaces. It's for project ID's that are inherited from the parent inode, and as such we do not care one bit what the namespace is. Internal passing of project IDs like this this should not be converted at all as it has nothing at all to do with the namespaces.
Overall, I think this patch needs to be broken up into several steps. The first is to propagate the new structures into the VFS entry points of the filesystem, one to convert the quota entry points, another to convert the generic ACL code, another to convert the ioctl entry points. At that point, XFS supports namespaces fully, and it should be possible to review and test the changes sanely.
From there, targetted patches can drive the kernel structures inward from the entry points where it makes sense to do so (e.g. common places that the quota entry points call that take a type/id pair). The last thing that should happen is internal structures be converted from type/id pairs to the kernel types if it makes sense to do so and it makes the code simpler and easier to read....
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
RFC PATCH 11/12 userns: Now that everything has been converted remove the unnecessary infrastructure
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In particular kill UIDGID_CONVERTED and UIDGID_STRICT_TYPE_CHECKS and have the code treat them as always true.
--- include/linux/posix_acl.h | 3 --- include/linux/projid.h | 15 --------------- include/linux/uidgid.h | 22 ---------------------- init/Kconfig | 23 ----------------------- 4 files changed, 0 insertions(+), 63 deletions(-)
include/linux/posix_acl.h +0 -3
@@ -39,9 +39,6 @@ struct posix_acl_entry {union {kuid_t e_uid;kgid_t e_gid; -#ifndef CONFIG_UIDGID_STRICT_TYPE_CHECKS -unsigned int e_id; -#endif }; };
include/linux/projid.h +0 -15
@@ -18,8 +18,6 @@ extern struct user_namespace init_user_ns;typedef __kernel_uid32_t projid_t ; -#ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS -typedef struct {projid_t val; }kprojid_t ;
@@ -31,19 +29,6 @@ static inline projid_t __kprojid_val(kprojid_t projid)#define KPROJIDT_INIT (value) (kprojid_t){ value } -#else - -typedef projid_t kprojid_t ; - -static inline projid_t __kprojid_val (kprojid_t projid) -{ -return projid; -} - -#define KPROJIDT_INIT (value) ((kprojid_t) value ) - -#endif -#define INVALID_PROJID KPROJIDT_INIT(-1)#define OVERFLOW_PROJID 65534
include/linux/uidgid.h +0 -22
@@ -17,8 +17,6 @@struct user_namespace ;extern struct user_namespace init_user_ns; -#ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS -typedef struct {uid_t val; }kuid_t ;
@@ -41,26 +39,6 @@ static inline gid_t __kgid_val(kgid_t gid)return gid.val; } -#else - -typedef uid_t kuid_t ; -typedef gid_t kgid_t ; - -static inline uid_t __kuid_val (kuid_t uid) -{ -return uid; -} - -static inline gid_t __kgid_val (kgid_t gid) -{ -return gid; -} - -#define KUIDT_INIT (value) ((kuid_t) value ) -#define KGIDT_INIT (value) ((kgid_t) value ) - -#endif -#define GLOBAL_ROOT_UID KUIDT_INIT(0)#define GLOBAL_ROOT_GID KGIDT_INIT(0)
init/Kconfig +0 -23
@@ -963,9 +963,6 @@ config IPC_NS config USER_NS bool "User namespace (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on UIDGID_CONVERTED - select UIDGID_STRICT_TYPE_CHECKS - default n help This allows containers, i.e. vservers, to use user namespaces
@@ -990,26 +987,6 @@ config NET_NS endif # NAMESPACES -config UIDGID_CONVERTED - # True if all of the selected software conmponents are known - # to have uid_t and gid_t converted to kuid_t and kgid_t - # where appropriate and are otherwise safe to use with - # the user namespace. - bool - default y - - # Filesystems - -config UIDGID_STRICT_TYPE_CHECKS - bool "Require conversions between uid/gids and their internal representation" - depends on UIDGID_CONVERTED - default n - help - While the nececessary conversions are being added to all subsystems this option allows - the code to continue to build for unconverted subsystems. - - Say Y here if you want the strict type checking enabled - config SCHED_AUTOGROUP bool "Automatic process group scheduling" select EVENTFD
Signature · 1 line
1.7.5.4
RFC PATCH 12/12 userns: Remove the EXPERMINTAL kconfig tag
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
While there is more work to be done in the form of allowing more to happen when you have root inside of a user namespace there is nothing experimental about them.
--- init/Kconfig | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
init/Kconfig +1 -2
@@ -961,8 +961,7 @@ config IPC_NS different IPC objects in different namespaces. config USER_NS - bool "User namespace (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "User namespace" default n help This allows containers, i.e. vservers, to use user namespaces
Signature · 1 line
1.7.5.4
Quoted 11 lines · Eric W. Biederman
This patchset contain the basic user namespace changes for filesystems that have needed nontrivial work. Along with the 2 patches that depend on these changes.
I belive these patches to be correct for allowing the remaining filesystems to work in the presence of user namespaces. At the same time I would like to give all of these much deeper scrutiny, just because there is so much going on. Unfortunately these patches individually are not obviously correct.
Quoted 4 lines
Since I won't have much time until after Thanksgiving and because the merge window is looming I figure I will put these changes out there and let people see I am looking at these changes, and see if anyone happens to spot anything.
The XFS stuff is non-trivial, causes on-disk format changes and likely breaks xfsdump/xfsrestore, so the XFS patch is a no-go until that is sorted out.
Given the short time until the merge window and that the XFS patch needs to be significantly revised, it's already too late for the XFS changes to be considered for the 3.8 merge window. Hence I'd suggest that you are going to be targeting 3.9 for the XFS changes.
Quoted 3 lines
If I can figure out how to responsibly get these changes into linux-next I want to get these changes into linux-next so that user namespace bugs show up in allyesconfig builds.
The XFS changes definitely need to be staged through the XFS tree given the complexity of the changes, the amount of validation that is required. Also, it is likely that there are significant conflicts against changes already staged for 3.8, so getting it upstream through the XFS tree is the only option that I'd consider acceptible...
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]