userns changes for 9p, afs, ceph, cifs, coda, gfs2, ncpfs, nfs, nfsd, and ocfs2
Subsystems (11)
cover userns changes for 9p, afs, ceph, cifs, coda, gfs2, ncpfs, nfs, nfsd, and ocfs2
This is my set of userns changes for 9p, afs, ceph, cifs, coda, gfs2, ncpfs, nfs, nfsd, and ocfs2. Except for afs and ncpfs the changes for these filesystems were to large to make a single readable patch per filesystem. So I have broken the patches down into what should be small logical changes to make it easier to see what changes I have made.
Mostly the changes are simple case of pushing kuid_t and kgid_t down as far as they will go in the filesystems. There are a couple of places where I had to engage in a small bit of code development, and there are a couple of trivial cleanup patches, cleaning up areas before I made my kuid and kgid changes.
I have performed a test merge of these changes against linux-next and there were no conflicts. So unless there are strong opinions to the contrary I plan to push these changes through my userns tree for 3.9.
I have done my best to ensure the following patches introduce no bugs or regressions but I am human so I might have messed up. If you spot any problems please let me know.
fs/9p/fid.c | 17 +++-- fs/9p/v9fs.c | 34 +++++++-- fs/9p/v9fs.h | 10 ++-- fs/9p/vfs_inode.c | 6 +- fs/9p/vfs_inode_dotl.c | 10 ++-- fs/afs/afs.h | 11 +--- fs/afs/fsclient.c | 14 +++- fs/afs/inode.c | 6 +- fs/afs/super.c | 6 ++ fs/ceph/caps.c | 17 +++-- fs/ceph/inode.c | 23 ++++--- fs/ceph/mds_client.c | 4 +- fs/ceph/mds_client.h | 4 +- fs/ceph/super.h | 4 +- fs/cifs/cifs_fs_sb.h | 8 +- fs/cifs/cifs_spnego.c | 6 +- fs/cifs/cifsacl.c | 47 +++++++++---- fs/cifs/cifsfs.c | 14 +++- fs/cifs/cifsglob.h | 22 +++--- fs/cifs/cifspdu.h | 1 - fs/cifs/cifsproto.h | 9 ++- fs/cifs/cifssmb.c | 10 ++- fs/cifs/connect.c | 66 +++++++++++++----- fs/cifs/dir.c | 18 +++--- fs/cifs/file.c | 8 +- fs/cifs/inode.c | 50 ++++++++----- 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 | 6 ++- fs/coda/psdev.c | 7 ++ fs/coda/upcall.c | 10 ++-- 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 | 32 +++++---- fs/gfs2/quota.c | 138 +++++++++++++++---------------------- 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 | 53 ++++++++++----- fs/nfs/inode.c | 12 ++-- fs/nfs/nfs2xdr.c | 19 ++++- fs/nfs/nfs3xdr.c | 18 ++++- fs/nfs/nfs4xdr.c | 16 ++-- fs/nfs_common/nfsacl.c | 41 +++++++---- fs/nfsd/acl.h | 2 - fs/nfsd/auth.c | 12 ++-- fs/nfsd/auth.h | 6 -- fs/nfsd/export.c | 22 ++++-- fs/nfsd/idmap.h | 8 +- fs/nfsd/nfs3xdr.c | 14 ++-- fs/nfsd/nfs4acl.c | 63 ++++++++++++----- fs/nfsd/nfs4idmap.c | 38 +++++++--- fs/nfsd/nfs4recover.c | 4 +- fs/nfsd/nfs4state.c | 6 +- fs/nfsd/nfs4xdr.c | 54 +++++++++----- fs/nfsd/nfsxdr.c | 14 ++-- fs/nfsd/state.h | 4 +- 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 +- include/linux/coda_psdev.h | 2 +- include/linux/nfs4.h | 6 ++- include/linux/nfs_idmap.h | 9 ++- include/linux/nfs_xdr.h | 4 +- include/linux/nfsd/export.h | 4 +- include/linux/sunrpc/auth.h | 7 +- include/linux/sunrpc/svcauth.h | 4 +- include/net/9p/9p.h | 14 ++-- include/net/9p/client.h | 12 ++-- init/Kconfig | 13 ---- net/9p/client.c | 43 +++++++----- net/9p/protocol.c | 49 ++++++++++++-- net/ceph/ceph_common.c | 5 ++ net/sunrpc/auth.c | 6 +- net/sunrpc/auth_generic.c | 16 +++-- net/sunrpc/auth_gss/auth_gss.c | 45 ++++++++---- net/sunrpc/auth_gss/svcauth_gss.c | 18 ++++-- net/sunrpc/auth_unix.c | 36 ++++------ net/sunrpc/svcauth_unix.c | 43 +++++++---- 92 files changed, 958 insertions(+), 632 deletions(-)
Eric W. Biederman (85):
ceph: Only allow mounts in the initial network namespace
ceph: Translate between uid and gids in cap messages and kuids and kgids
ceph: Translate inode uid and gid attributes to/from kuids and kgids.
ceph: Convert struct ceph_mds_request to use kuid_t and kgid_t
ceph: Convert kuids and kgids before printing them.
ceph: Enable building when user namespaces are enabled.
9p: Add 'u' and 'g' format specifies for kuids and kgids
9p: Transmit kuid and kgid values
9p: Modify the stat structures to use kuid_t and kgid_t
9p: Modify struct 9p_fid to use a kuid_t not a uid_t
9p: Modify struct v9fs_session_info to use a kuids and kgids
9p: Modify v9fs_get_fsgid_for_create to return a kgid
9p: Allow building 9p with user namespaces enabled.
afs: Remove unused structure afs_store_status
afs: Only allow mounting afs in the intial network namespace
afs: Support interacting with multiple user namespaces
coda: Restrict coda messages to the initial pid namespace
coda: Restrict coda messages to the initial user namespace
coda: Cache permisions in struct coda_inode_info in a kuid_t.
coda: Allow coda to be built when user namespace support is enabled
ocfs2: Handle kuids and kgids in acl/xattr conversions.
ocfs2: convert between kuids and kgids and DLM locks
ocfs2: Convert uid and gids between in core and on disk inodes
ocfs2: For tracing report the uid and gid values in the initial user namespace
ocfs2: Compare kuids and kgids using uid_eq and gid_eq
ocfs2: Enable building with user namespaces enabled
gfs2: Remove improper checks in gfs2_set_dqblk.
gfs2: Split NO_QUOTA_CHANGE inot NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE
gfs2: Report quotas in the caller's user namespace.
gfs2: Introduce qd2index
gfs2: Modify struct gfs2_quota_change_host to use struct kqid
gfs2: Modify qdsb_get to take a struct kqid
gfs2: Convert gfs2_quota_refresh to take a kqid
gfs2: Store qd_id in struct gfs2_quota_data as a struct kqid
gfs2: Remove the QUOTA_USER and QUOTA_GROUP defines
gfs2: Use kuid_t and kgid_t types where appropriate.
gfs2: Use uid_eq and gid_eq where appropriate
gfs2: Convert uids and gids between dinodes and vfs inodes.
gfs2: Enable building with user namespaces enabled
ncpfs: Support interacting with multiple user namespaces
nfs_common: Update the translation between nfsv3 acls linux posix acls
sunrpc: Use userns friendly constants.
sunrpc: Use kuid_t and kgid_t where appropriate
sunrpc: Use uid_eq and gid_eq where appropriate
sunrpc: Simplify auth_unix now that everything is a kgid_t
sunrpc: Convert kuids and kgids to uids and gids for printing
sunrpc: Use gid_valid to test for gid != INVALID_GID
sunrpc: Update gss uid to security context mapping.
sunrpc: Update svcgss xdr handle to rpsec_contect cache
sunrpc: Hash uids by first computing their value in the initial userns
sunrpc: Properly encode kuids and kgids in RPC_AUTH_UNIX credentials
sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
sunrpc: Properly decode kuids and kgids in RPC_AUTH_UNIX credentials
nfs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring alloc
nfs: Convert struct nfs_fattr to Use kuid_t and kgid_t
nfs: Convert idmap to use kuids and kgids
nfs: Convert nfs2xdr to use kuids and kgids
nfs: Convert nfs3xdr to use kuids and kgids
nfs: Convert nfs4xdr to use kuids and kgids
nfs: kuid and kgid conversions for nfs/inode.c
nfs: Enable building with user namespaces enabled.
nfsd: Remove declaration of nonexistent nfs4_acl_permisison
nfsd: idmap use u32 not uid_t as the intermediate type
nfsd: Convert idmap to use kuids and kgids
nfsd: Remove nfsd_luid, nfsd_lgid, nfsd_ruid and nfsd_rgid
nfsd: Convert nfs3xdr to use kuids and kgids
nfsd: Convert nfsxdr to use kuids and kgids
nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion
nfsd: Modify nfsd4_cb_sec to use kuids and kgids
nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids
nfsd: Properly compare and initialize kuids and kgids
nfsd: Enable building with user namespaces enabled.
cifs: Override unmappable incoming uids and gids
cifs: Use BUILD_BUG_ON to validate uids and gids are the same size
cifs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring_alloc
cifs: Use kuids and kgids SID to uid/gid mapping
cifs: Convert from a kuid before printing current_fsuid
cifs: Modify struct cifs_unix_set_info_args to hold a kuid_t and a kgid_t
cifs: Convert struct tcon_link to use a kuid.
cifs: Convert struct cifs_fattr to use kuid and kgids
cifs: Convert struct cifsFileInfo to use a kuid
cifs: Modify struct smb_vol to use kuids and kgids
cifs: Convert struct cifs_sb_info to use kuids and kgids
cifs: Convert struct cifs_ses to use a kuid_t and a kgid_t
cifs: Enable building with user namespaces enabled.
PATCH 1/85 ceph: Only allow mounts in the initial network namespace
From: "Eric W. Biederman" <[email protected]>
Today ceph opens tcp sockets from a delayed work callback. Delayed work happens from kernel threads which are always in the initial
network namespace. Therefore fail early if someone attempts
to mount a ceph filesystem from something other than the initial network namespace.
--- net/ceph/ceph_common.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
net/ceph/ceph_common.c +5 -0
@@ -15,6 +15,8 @@#include <linux/slab.h> #include <linux/statfs.h> #include <linux/string.h> +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include <linux/ceph/ceph_features.h>
@@ -292,6 +294,9 @@ ceph_parse_options(char *options, const char *dev_name,int err = -ENOMEM ;substring_t argstr[MAX_OPT_ARGS ]; +if (current->nsproxy->net_ns != &init_net) +return ERR_PTR (-EINVAL ); + opt =kzalloc (sizeof (*opt),GFP_KERNEL );if (!opt)return ERR_PTR (-ENOMEM );
Signature · 1 line
1.7.5.4
PATCH 2/85 ceph: Translate between uid and gids in cap messages and kuids and kgids
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Make the uid and gid arguments of send_cap_msg() used to compose ceph_mds_caps messages of type kuid_t and kgid_t.
- Pass inode->i_uid and inode->i_gid in __send_cap to send_cap_msg() through variables of type kuid_t and kgid_t.
- Modify struct ceph_cap_snap to store uids and gids in types kuid_t and kgid_t. This allows capturing inode->i_uid and inode->i_gid in ceph_queue_cap_snap() without loss and pssing them to __ceph_flush_snaps() where they are removed from struct ceph_cap_snap and passed to send_cap_msg().
- In handle_cap_grant translate uid and gids in the initial user namespace stored in struct ceph_mds_cap into kuids and kgids before setting inode->i_uid and inode->i_gid.
--- fs/ceph/caps.c | 14 +++++++------- fs/ceph/super.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-)
fs/ceph/caps.c +7 -7
@@ -930,7 +930,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)
@@ -974,8 +974,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);
@@ -1081,8 +1081,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 ;
@@ -2359,8 +2359,8 @@ 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); + inode->i_uid =make_kuid (&init_user_ns,le32_to_cpu (grant->uid)); + inode->i_gid =make_kgid (&init_user_ns,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); }
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;
Signature · 1 line
1.7.5.4
PATCH 3/85 ceph: Translate inode uid and gid attributes to/from kuids and kgids.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- In fill_inode() transate uids and gids in the initial user namespace into kuids and kgids stored in inode->i_uid and inode->i_gid.
- In ceph_setattr() if they have changed convert inode->i_uid and inode->i_gid into initial user namespace uids and gids for transmission.
--- fs/ceph/inode.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
fs/ceph/inode.c +8 -6
@@ -612,8 +612,8 @@ 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); + inode->i_uid =make_kuid (&init_user_ns,le32_to_cpu (info->uid)); + inode->i_gid =make_kgid (&init_user_ns,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); }
@@ -1570,8 +1570,9 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) 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 ; }
@@ -1583,8 +1584,9 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) 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 ; }
Signature · 1 line
1.7.5.4
PATCH 4/85 ceph: Convert struct ceph_mds_request to use kuid_t and kgid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Hold the uid and gid for a pending ceph mds request using the types kuid_t and kgid_t. When a request message is finally created convert the kuid_t and kgid_t values into uids and gids in the initial user namespace.
--- fs/ceph/mds_client.c | 4 ++-- fs/ceph/mds_client.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
fs/ceph/mds_client.c +2 -2
@@ -1658,8 +1658,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, head->mdsmap_epoch =cpu_to_le32 (mdsc->mdsmap->m_epoch); head->op =cpu_to_le32 (req->r_op); - head->caller_uid =cpu_to_le32 (req->r_uid); - head->caller_gid =cpu_to_le32 (req->r_gid); + head->caller_uid =cpu_to_le32 (from_kuid (&init_user_ns, req->r_uid)); + head->caller_gid =cpu_to_le32 (from_kgid (&init_user_ns, req->r_gid)); head->args = req->r_args;ceph_encode_filepath (&p, end, ino1, path1);
fs/ceph/mds_client.h +2 -2
@@ -184,8 +184,8 @@ struct ceph_mds_request {union ceph_mds_request_args r_args;int r_fmode;/* file mode, if expecting cap */ -uid_t r_uid; -gid_t r_gid; +kuid_t r_uid; +kgid_t r_gid;/* for choosing which mds to send this request to */ int r_direct_mode;
Signature · 1 line
1.7.5.4
PATCH 5/85 ceph: Convert kuids and kgids before printing them.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Before printing kuid and kgids values convert them into the initial user namespace.
--- fs/ceph/caps.c | 3 ++- fs/ceph/inode.c | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-)
fs/ceph/caps.c +2 -1
@@ -2362,7 +2362,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, inode->i_uid =make_kuid (&init_user_ns,le32_to_cpu (grant->uid)); inode->i_gid =make_kgid (&init_user_ns,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); +from_kuid (&init_user_ns, inode->i_uid), +from_kgid (&init_user_ns, inode->i_gid)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )
fs/ceph/inode.c +6 -3
@@ -615,7 +615,8 @@ static int fill_inode(struct inode *inode, inode->i_uid =make_kuid (&init_user_ns,le32_to_cpu (info->uid)); inode->i_gid =make_kgid (&init_user_ns,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); +from_kuid (&init_user_ns, inode->i_uid), +from_kgid (&init_user_ns, inode->i_gid)); }if ((issued &CEPH_CAP_LINK_EXCL ) ==0 )
@@ -1565,7 +1566,8 @@ 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); +from_kuid (&init_user_ns, inode->i_uid), +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 ;
@@ -1579,7 +1581,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) }if (ia_valid &ATTR_GID ) {dout ("setattr %p gid %d -> %d\n" , inode, - inode->i_gid, attr->ia_gid); +from_kgid (&init_user_ns, inode->i_gid), +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 ;
Signature · 1 line
1.7.5.4
PATCH 6/85 ceph: Enable building when user namespaces are enabled.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that conversions happen from kuids and kgids when generating ceph messages and conversion happen to kuids and kgids after receiving celph messages, and all intermediate data structures store uids and gids as type kuid_t and kgid_t it is safe to enable ceph with user namespace support enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1076,7 +1076,6 @@ config UIDGID_CONVERTED # Filesystems depends on 9P_FS = n depends on AFS_FS = n - 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
PATCH 7/85 9p: Add 'u' and 'g' format specifies for kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
This allows concentrating all of the conversion to and from kuids and kgids into the format needed by the 9p protocol into one location.
--- net/9p/protocol.c | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-)
net/9p/protocol.c +36 -0
@@ -85,6 +85,8 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) d - int32_t q - int64_t s - string + u - numeric uid + g - numeric gidS - stat Q - qid D - data blob (int32_t size followed by void *, results are not freed)
@@ -163,6 +165,26 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, (*sptr)[len] =0 ; }break ; +case 'u' : { + kuid_t *uid = va_arg(ap, kuid_t *); +__le32 le_val; +if (pdu_read (pdu, &le_val,sizeof (le_val))) { + errcode = -EFAULT ; +break ; + } + *uid =make_kuid (&init_user_ns, +le32_to_cpu (le_val)); + }break ; +case 'g' : { + kgid_t *gid = va_arg(ap, kgid_t *); +__le32 le_val; +if (pdu_read (pdu, &le_val,sizeof (le_val))) { + errcode = -EFAULT ; +break ; + } + *gid =make_kgid (&init_user_ns, +le32_to_cpu (le_val)); + }break ;case 'Q' :{struct p9_qid *qid = va_arg(ap, struct p9_qid *);
@@ -377,6 +399,20 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, errcode = -EFAULT ; }break ; +case 'u' : { +kuid_t uid =va_arg (ap, kuid_t); +__le32 val =cpu_to_le32 ( +from_kuid (&init_user_ns, uid)); +if (pdu_write (pdu, &val,sizeof (val))) + errcode = -EFAULT ; + }break ; +case 'g' : { +kgid_t gid =va_arg (ap, kgid_t); +__le32 val =cpu_to_le32 ( +from_kgid (&init_user_ns, gid)); +if (pdu_write (pdu, &val,sizeof (val))) + errcode = -EFAULT ; + }break ;case 'Q' :{const struct p9_qid *qid = va_arg(ap, const struct p9_qid *);
Signature · 1 line
1.7.5.4
PATCH 8/85 9p: Transmit kuid and kgid values
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Modify the p9_client_rpc format specifiers of every function that directly transmits a uid or a gid from 'd' to 'u' or 'g' as appropriate.
Modify those same functions to take kuid_t and kgid_t parameters instead of uid_t and gid_t parameters.
--- fs/9p/v9fs.c | 2 +- include/net/9p/client.h | 10 +++++----- net/9p/client.c | 25 +++++++++++++------------ 3 files changed, 19 insertions(+), 18 deletions(-)
fs/9p/v9fs.c +1 -1
@@ -375,7 +375,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);
include/net/9p/client.h +5 -5
@@ -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 );
net/9p/client.c +13 -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;
@@ -1117,7 +1117,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, goto error; } - req =p9_client_rpc (clnt,P9_TATTACH ,"ddss?d" , fid->fid, + req =p9_client_rpc (clnt,P9_TATTACH ,"ddss?u" , fid->fid, afid ? afid->fid :P9_NOFID , uname, aname, n_uname);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -1270,7 +1270,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,13 +1279,14 @@ 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, + req =p9_client_rpc (clnt,P9_TLCREATE ,"dsddg" , ofid->fid, name, flags, mode, gid);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -1358,7 +1359,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 ;
@@ -1369,7 +1370,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid, dfid->fid, name, symtgt); clnt = dfid->clnt; - req =p9_client_rpc (clnt,P9_TSYMLINK ,"dssd" , dfid->fid, name, symtgt, + req =p9_client_rpc (clnt,P9_TSYMLINK ,"dssg" , dfid->fid, name, symtgt, gid);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -2106,7 +2107,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;
@@ -2116,7 +2117,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode, clnt = fid->clnt;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, + req =p9_client_rpc (clnt,P9_TMKNOD ,"dsdddg" , fid->fid, name, mode,MAJOR (rdev),MINOR (rdev), gid);if (IS_ERR (req))return PTR_ERR (req);
@@ -2137,7 +2138,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,8 +2147,8 @@ 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); - req =p9_client_rpc (clnt,P9_TMKDIR ,"dsdd" , fid->fid, name, mode, + fid->fid, name, mode,from_kgid (&init_user_ns, gid)); + req =p9_client_rpc (clnt,P9_TMKDIR ,"dsdg" , fid->fid, name, mode, gid);if (IS_ERR (req))return PTR_ERR (req);
Signature · 1 line
1.7.5.4
A message that is not in the archive (sent off-list or not yet received): 1360777934-5663-1-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
PATCH 8/85 9p: Transmit kuid and kgid values
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Modify the p9_client_rpc format specifiers of every function that directly transmits a uid or a gid from 'd' to 'u' or 'g' as appropriate.
Modify those same functions to take kuid_t and kgid_t parameters instead of uid_t and gid_t parameters.
--- fs/9p/v9fs.c | 2 +- include/net/9p/client.h | 10 +++++----- net/9p/client.c | 25 +++++++++++++------------ 3 files changed, 19 insertions(+), 18 deletions(-)
fs/9p/v9fs.c +1 -1
@@ -375,7 +375,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);
include/net/9p/client.h +5 -5
@@ -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 );
net/9p/client.c +13 -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;
@@ -1117,7 +1117,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, goto error; } - req =p9_client_rpc (clnt,P9_TATTACH ,"ddss?d" , fid->fid, + req =p9_client_rpc (clnt,P9_TATTACH ,"ddss?u" , fid->fid, afid ? afid->fid :P9_NOFID , uname, aname, n_uname);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -1270,7 +1270,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,13 +1279,14 @@ 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, + req =p9_client_rpc (clnt,P9_TLCREATE ,"dsddg" , ofid->fid, name, flags, mode, gid);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -1358,7 +1359,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 ;
@@ -1369,7 +1370,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid, dfid->fid, name, symtgt); clnt = dfid->clnt; - req =p9_client_rpc (clnt,P9_TSYMLINK ,"dssd" , dfid->fid, name, symtgt, + req =p9_client_rpc (clnt,P9_TSYMLINK ,"dssg" , dfid->fid, name, symtgt, gid);if (IS_ERR (req)) { err =PTR_ERR (req);
@@ -2106,7 +2107,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;
@@ -2116,7 +2117,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode, clnt = fid->clnt;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, + req =p9_client_rpc (clnt,P9_TMKNOD ,"dsdddg" , fid->fid, name, mode,MAJOR (rdev),MINOR (rdev), gid);if (IS_ERR (req))return PTR_ERR (req);
@@ -2137,7 +2138,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,8 +2147,8 @@ 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); - req =p9_client_rpc (clnt,P9_TMKDIR ,"dsdd" , fid->fid, name, mode, + fid->fid, name, mode,from_kgid (&init_user_ns, gid)); + req =p9_client_rpc (clnt,P9_TMKDIR ,"dsdg" , fid->fid, name, mode, gid);if (IS_ERR (req))return PTR_ERR (req);
Signature · 1 line
1.7.5.4
PATCH 12/85 9p: Modify v9fs_get_fsgid_for_create to return a kgid
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Modify v9fs_get_fsgid_for_create to return a kgid and modify all of the variables that hold the result of v9fs_get_fsgid_for_create to be of type kgid_t.
--- fs/9p/vfs_inode_dotl.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
fs/9p/vfs_inode_dotl.c +5 -5
@@ -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;
@@ -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;
Signature · 1 line
1.7.5.4
PATCH 13/85 9p: Allow building 9p with user namespaces enabled.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that the uid_t -> kuid_t, gid_t -> kgid_t conversion has been completed in 9p allow 9p to be built when user namespaces are enabled.
--- init/Kconfig | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
init/Kconfig +0 -4
@@ -1070,11 +1070,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 CIFS = n depends on CODA_FS = n
Signature · 1 line
1.7.5.4
PATCH 16/85 afs: Support interacting with multiple user namespaces
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Modify struct afs_file_status to store owner as a kuid_t and group as a kgid_t.
In xdr_decode_AFSFetchStatus as owner is now a kuid_t and group is now a kgid_t don't use the EXTRACT macro. Instead perform the work of the extract macro explicitly. Read the value with ntohl and convert it to the appropriate type with make_kuid or make_kgid. Test if the value is different from what is stored in status and
update changed. Update the value in status.
In xdr_encode_AFS_StoreStatus call from_kuid or from_kgid as we are computing the on the wire encoding.
Initialize uids with GLOBAL_ROOT_UID instead of 0. Initialize gids with GLOBAL_ROOT_GID instead of 0.
--- 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 */ +kuid_t owner; +kgid_t 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 =make_kuid (&init_user_ns,ntohl (*bp++)); + changed |= !uid_eq (owner, status->owner); + status->owner = 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 =make_kgid (&init_user_ns,ntohl (*bp++)); + changed |= !gid_eq (group, status->group); + status->group = 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
@@ -1071,7 +1071,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on AFS_FS = n depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n
Signature · 1 line
1.7.5.4
PATCH 17/85 coda: Restrict coda messages to the initial pid namespace
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Remove the slight chance that pids in coda messages will be interpreted in the wrong pid namespace.
- Explicitly send all pids in coda messages in the initial pid namespace.
- Only allow mounts from processes in the initial pid namespace.
- Only allow processes in the initial pid namespace to open the coda character device to communicate with coda.
--- fs/coda/inode.c | 4 ++++ fs/coda/psdev.c | 4 ++++ fs/coda/upcall.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-)
fs/coda/inode.c +4 -0
@@ -20,6 +20,7 @@#include <linux/file.h> #include <linux/vfs.h> #include <linux/slab.h> +#include <linux/pid_namespace.h> #include <asm/uaccess.h>
@@ -157,6 +158,9 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)int error;int idx; +if (task_active_pid_ns (current) != &init_pid_ns) +return -EINVAL ; + idx =get_device_index ((struct coda_mount_data *) data);/* Ignore errors in data, for backward compatibility */
fs/coda/psdev.c +4 -0
@@ -37,6 +37,7 @@#include <linux/list.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/pid_namespace.h> #include <asm/io.h> #include <asm/poll.h> #include <asm/uaccess.h>
@@ -266,6 +267,9 @@ static int coda_psdev_open(struct inode * inode, struct file * file)struct venus_comm *vcp;int idx, err; +if (task_active_pid_ns (current) != &init_pid_ns) +return -EINVAL ; + idx =iminor (inode);if (idx <0 || idx >=MAX_CODADEVS )return -ENODEV ;
fs/coda/upcall.c +2 -2
@@ -50,8 +50,8 @@ static void *alloc_upcall(int opcode, int size)return ERR_PTR (-ENOMEM ); inp->ih.opcode = opcode; - inp->ih.pid = current->pid; - inp->ih.pgid =task_pgrp_nr (current); + inp->ih.pid =task_pid_nr_ns (current, &init_pid_ns); + inp->ih.pgid =task_pgrp_nr_ns (current, &init_pid_ns); inp->ih.uid =current_fsuid ();return (void *)inp;
Signature · 1 line
1.7.5.4
PATCH 22/85 ocfs2: convert between kuids and kgids and DLM locks
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Convert between uid and gids stored in the on the wire format of dlm locks aka struct ocfs2_meta_lvb and kuids and kgids stored in inode->i_uid and inode->i_gid.
--- fs/ocfs2/dlmglue.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
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,
Signature · 1 line
1.7.5.4
PATCH 23/85 ocfs2: Convert uid and gids between in core and on disk inodes
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ocfs2/inode.c | 12 ++++++------ fs/ocfs2/namei.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
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));
Signature · 1 line
1.7.5.4
PATCH 27/85 gfs2: Remove improper checks in gfs2_set_dqblk.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In set_dqblk it is an error to look at fdq->d_id or fdq->d_flags. Userspace quota applications do not set these fields when calling quotactl(Q_XSETQLIM,...), and the kernel does not set those fields when quota_setquota calls set_dqblk.
gfs2 never looks at fdq->d_id or fdq->d_flags after checking to see if they match the id and type supplied to set_dqblk.
No other linux filesystem in set_dqblk looks at either fdq->d_id or fdq->d_flags.
Therefore remove these bogus checks from gfs2 and allow normal quota setting applications to work.
--- fs/gfs2/quota.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
fs/gfs2/quota.c +0 -6
@@ -1543,13 +1543,9 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,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 ;default :return -EINVAL ;
@@ -1557,8 +1553,6 @@ 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)) -return -EINVAL ; error =qd_get (sdp, type,from_kqid (&init_user_ns, qid), &qd);if (error)
Signature · 1 line
1.7.5.4
PATCH 28/85 gfs2: Split NO_QUOTA_CHANGE inot NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Split NO_QUOTA_CHANGE into NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE so the constants may be well typed.
--- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/inode.c | 10 +++++----- fs/gfs2/quota.c | 4 ++-- fs/gfs2/quota.h | 5 +++-- fs/gfs2/super.c | 2 +- fs/gfs2/xattr.c | 4 ++-- 7 files changed, 15 insertions(+), 14 deletions(-)
fs/gfs2/bmap.c +1 -1
@@ -1098,7 +1098,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
@@ -1849,7 +1849,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/inode.c +5 -5
@@ -548,7 +548,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;
@@ -1589,15 +1589,15 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ngid = attr->ia_gid;if (!(attr->ia_valid &ATTR_UID ) || ouid == nuid) - ouid = nuid =NO_QUOTA_CHANGE ; + ouid = nuid =NO_UID_QUOTA_CHANGE ;if (!(attr->ia_valid &ATTR_GID ) || ogid == ngid) - ogid = ngid =NO_QUOTA_CHANGE ; + 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 (ouid !=NO_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) { error =gfs2_quota_check (ip, nuid, ngid);if (error) goto out_gunlock_q;
@@ -1611,7 +1611,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 (ouid !=NO_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) {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 +2 -2
@@ -524,7 +524,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) ip->i_res->rs_qa_qd_num++; qd++; -if (uid !=NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { +if (uid !=NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { error =qdsb_get (sdp,QUOTA_USER , uid, qd);if (error) goto out;
@@ -532,7 +532,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) qd++; } -if (gid !=NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { +if (gid !=NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { error =qdsb_get (sdp,QUOTA_GROUP , gid, qd);if (error) goto out;
fs/gfs2/quota.h +3 -2
@@ -14,7 +14,8 @@ 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_GIDextern int gfs2_quota_hold (struct gfs2_inode *ip,u32 uid,u32 gid);extern void gfs2_quota_unhold (struct gfs2_inode *ip);
@@ -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 +1 -1
@@ -1429,7 +1429,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/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;
Signature · 1 line
1.7.5.4
PATCH 29/85 gfs2: Report quotas in the caller's user namespace.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a quota is queried return the uid or the gid in the mapped into the caller's user namespace. In addition perform the munged version of the mapping so that instead of -1 a value that does not map is reported as the overflowuid or the overflowgid.
--- fs/gfs2/quota.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/gfs2/quota.c +1 -1
@@ -1509,7 +1509,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; 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_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;
Signature · 1 line
1.7.5.4
PATCH 30/85 gfs2: Introduce qd2index
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Both qd_alloc and qd2offset perform the exact same computation
to get an index from a gfs2_quota_data. Make life a little
simpler and factor out this index computation.
--- fs/gfs2/quota.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
fs/gfs2/quota.c +8 -2
@@ -120,11 +120,17 @@ out:return (atomic_read (&qd_lru_count) * sysctl_vfs_cache_pressure) /100 ; } +static u64 qd2index (struct gfs2_quota_data *qd) +{ +return (2 * (u64 )qd->qd_id) + +test_bit (QDF_USER , &qd->qd_flags) ?0 :1 ; +} +static u64 qd2offset (struct gfs2_quota_data *qd) {u64 offset; - offset =2 * (u64 )qd->qd_id + !test_bit (QDF_USER , &qd->qd_flags); + offset =qd2index (qd); offset *=sizeof (struct gfs2_quota );return offset;
@@ -147,7 +153,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, qd->qd_slot =-1 ;INIT_LIST_HEAD (&qd->qd_reclaim); - error =gfs2_glock_get (sdp,2 * (u64 )id + !user, + error =gfs2_glock_get (sdp,qd2index (qd), &gfs2_quota_glops,CREATE , &qd->qd_gl);if (error) goto fail;
Signature · 1 line
1.7.5.4
PATCH 31/85 gfs2: Modify struct gfs2_quota_change_host to use struct kqid
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/gfs2/quota.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)
fs/gfs2/quota.c +5 -3
@@ -71,7 +71,7 @@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);
@@ -1200,7 +1200,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)
@@ -1264,7 +1266,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)continue ; error =qd_alloc (sdp, (qc.qc_flags &GFS2_QCF_USER ), - qc.qc_id, &qd); +from_kqid (&init_user_ns, qc.qc_id), &qd);if (error) {brelse (bh); goto fail;
Signature · 1 line
1.7.5.4
PATCH 32/85 gfs2: Modify qdsb_get to take a struct kqid
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/gfs2/quota.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
fs/gfs2/quota.c +7 -6
@@ -464,12 +464,13 @@ 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.type ==USRQUOTA ?QUOTA_USER :QUOTA_GROUP , +from_kqid (&init_user_ns, qid), qdp);if (error)return error;
@@ -518,20 +519,20 @@ 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_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { - error =qdsb_get (sdp,QUOTA_USER , uid, qd); + error =qdsb_get (sdp,make_kqid_uid (uid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++;
@@ -539,7 +540,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) }if (gid !=NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { - error =qdsb_get (sdp,QUOTA_GROUP , gid, qd); + error =qdsb_get (sdp,make_kqid_gid (gid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++;
Signature · 1 line
1.7.5.4
PATCH 33/85 gfs2: Convert gfs2_quota_refresh to take a kqid
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- In quota_refresh_user_store convert the user supplied uid into a kqid and pass it to gfs2_quota_refresh.
- In quota_refresh_group_store convert the user supplied gid into a kqid and pass it to gfs2_quota_refresh.
--- fs/gfs2/quota.c | 5 +++-- fs/gfs2/quota.h | 2 +- fs/gfs2/sys.c | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-)
fs/gfs2/quota.c +3 -2
@@ -1177,13 +1177,14 @@ 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.type ==USRQUOTA ?QUOTA_USER :QUOTA_GROUP , +from_kqid (&init_user_ns, qid), &qd);if (error)return error;
fs/gfs2/quota.h +1 -1
@@ -28,7 +28,7 @@ extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, u32 uid, u32 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);
fs/gfs2/sys.c +12 -2
@@ -175,6 +175,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,static ssize_t quota_refresh_user_store (struct gfs2_sbd *sdp,const char *buf,size_t len) { +struct kqid qid;int error;u32 id;
@@ -183,13 +184,18 @@ 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 (current_user_ns (),USRQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }static ssize_t quota_refresh_group_store (struct gfs2_sbd *sdp,const char *buf,size_t len) { +struct kqid qid;int error;u32 id;
@@ -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 (current_user_ns (),GRPQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }
Signature · 1 line
1.7.5.4
PATCH 34/85 gfs2: Store qd_id in struct gfs2_quota_data as a struct kqid
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Change qd_id in struct gfs2_qutoa_data to struct kqid.
- Remove the now unnecessary QDF_USER bit field in qd_flags.
- Propopoage this change through the code generally making things simpler along the way.
--- fs/gfs2/incore.h | 3 +- fs/gfs2/quota.c | 69 +++++++++++++++++++---------------------------------- 2 files changed, 26 insertions(+), 46 deletions(-)
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/quota.c +25 -44
180 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH 40/85 ncpfs: Support interacting with multiple user namespaces
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
ncpfs does not natively support uids and gids so this conversion was simply a matter of updating the the type of the mounteduid, the uid and the gid on the superblock. Fixing the ioctls that read them, updating the mount option parser and the mount option printer.
--- 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
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n depends on XFS_FS = n
Signature · 1 line
1.7.5.4
PATCH 41/85 nfs_common: Update the translation between nfsv3 acls linux posix acls
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use kuid_t and kgit in struct nfsacl_encode_desc.
- Convert from kuids and kgids when generating on the wire values.
- Convert on the wire values to kuids and kgids when read.
- Modify cmp_acl_entry to be type safe comparison on posix acls. Only acls with type ACL_USER and ACL_GROUP can appear more than once and as such need to compare more than their tag.
- The e_id field is being removed from posix acls so don't initialize it.
--- fs/nfs_common/nfsacl.c | 41 ++++++++++++++++++++++++++--------------- 1 files changed, 26 insertions(+), 15 deletions(-)
fs/nfs_common/nfsacl.c +26 -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,22 @@ 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); +if (!uid_valid (entry->e_uid)) +return -EINVAL ; +break ;case ACL_GROUP : + entry->e_gid =make_kgid (&init_user_ns, id); +if (!gid_valid (entry->e_gid)) +return -EINVAL ; +break ; +case ACL_USER_OBJ : +case ACL_GROUP_OBJ :case ACL_OTHER :if (entry->e_perm & ~S_IRWXO )return -EINVAL ;
@@ -190,9 +201,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 +228,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 ; } }
Signature · 1 line
1.7.5.4
PATCH 45/85 sunrpc: Simplify auth_unix now that everything is a kgid_t
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In unx_create_cred directly assign gids from acred->group_info to cred->uc_gids.
In unx_match directly compare uc_gids with group_info.
Now that both group_info and unx_cred gids are stored as kgids this is valid and the extra layer of translation can be removed.
--- net/sunrpc/auth_unix.c | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-)
net/sunrpc/auth_unix.c +4 -10
@@ -79,11 +79,8 @@ 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] =INVALID_GID ;
@@ -130,12 +127,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) 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] !=INVALID_GID )return 0 ;
Signature · 1 line
1.7.5.4
PATCH 49/85 sunrpc: Update svcgss xdr handle to rpsec_contect cache
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
For each received uid call make_kuid and validate the result. For each received gid call make_kgid and validate the result.
--- net/sunrpc/auth_gss/svcauth_gss.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)
net/sunrpc/auth_gss/svcauth_gss.c +13 -5
@@ -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,7 @@ 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 == -EINVAL ) goto out;if (rv == -ENOENT )
@@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd,else {int N , i; +/* uid */ + rsci.cred.cr_uid =make_kuid (&init_user_ns, id); +if (!uid_valid (rsci.cred.cr_uid)) + goto out; +/* 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 */
@@ -467,11 +476,10 @@ static int rsc_parse(struct cache_detail *cd,/* gid's */ status = -EINVAL ;for (i=0 ; i<N ; i++) { -gid_t gid;kgid_t kgid; -if (get_int (&mesg, &gid)) +if (get_int (&mesg, &id)) goto out; - kgid =make_kgid (&init_user_ns, gid); + kgid =make_kgid (&init_user_ns, id);if (!gid_valid (kgid)) goto out;GROUP_AT (rsci.cred.cr_group_info, i) = kgid;
Signature · 1 line
1.7.5.4
PATCH 53/85 sunrpc: Properly decode kuids and kgids in RPC_AUTH_UNIX credentials
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading kuids from the wire map them into the initial user namespace, and validate the mapping succeded.
When reading kgids from the wire map them into the initial user namespace, and validate the mapping succeded.
--- net/sunrpc/svcauth_unix.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
net/sunrpc/svcauth_unix.c +4 -2
@@ -821,8 +821,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
PATCH 56/85 nfs: Convert idmap to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Convert nfs_map_name_to_uid to return a kuid_t value. Convert nfs_map_name_to_gid to return a kgid_t value. Convert nfs_map_uid_to_name to take a kuid_t paramater. Convert nfs_map_gid_to_name to take a kgid_t paramater.
Tweak nfs_fattr_map_owner_to_name to use a kuid_t intermediate value. Tweak nfs_fattr_map_group_to_name to use a kgid_t intermediate value.
Which makes these functions properly handle kuids and kgids, including erroring of the generated kuid or kgid is invalid.
--- fs/nfs/idmap.c | 50 ++++++++++++++++++++++++++++++-------------- include/linux/nfs_idmap.h | 9 ++++--- 2 files changed, 39 insertions(+), 20 deletions(-)
fs/nfs/idmap.c +34 -16
@@ -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;
@@ -837,43 +837,61 @@ 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); +if (ret ==0 ) { + *uid =make_kuid (&init_user_ns, id); +if (!uid_valid (*uid)) + ret = -ERANGE ; + } +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)) + ret =nfs_idmap_lookup_id (name, namelen,"gid" , &id, idmap); +if (ret ==0 ) { + *gid =make_kgid (&init_user_ns, id); +if (!gid_valid (*gid)) + ret = -ERANGE ; + } +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 ; +__u32 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 ; +__u32 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; }
include/linux/nfs_idmap.h +5 -4
@@ -36,6 +36,7 @@#ifndef NFS_IDMAP_H #define NFS_IDMAP_H +#include <linux/uidgid.h> #include <uapi/linux/nfs_idmap.h>
@@ -67,10 +68,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 */
Signature · 1 line
1.7.5.4
PATCH 58/85 nfs: Convert nfs3xdr to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
Add an additional failure mode incoming for uids or gids that are invalid.
--- fs/nfs/nfs3xdr.c | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-)
fs/nfs/nfs3xdr.c +14 -4
@@ -592,13 +592,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;
@@ -657,8 +657,12 @@ 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++)); +if (!uid_valid (fattr->uid)) + goto out_uid; + fattr->gid =make_kgid (&init_user_ns,be32_to_cpup (p++)); +if (!gid_valid (fattr->gid)) + goto out_gid; p =xdr_decode_size3 (p, &fattr->size); p =xdr_decode_size3 (p, &fattr->du.nfs3.used);
@@ -675,6 +679,12 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) fattr->valid |=NFS_ATTR_FATTR_V3 ;return 0 ; +out_uid: +dprintk ("NFS: returned invalid uid\n" ); +return -EINVAL ; +out_gid: +dprintk ("NFS: returned invalid gid\n" ); +return -EINVAL ; out_overflow:print_overflow_msg (__func__, xdr);return -EIO ;
Signature · 1 line
1.7.5.4
PATCH 61/85 nfs: Enable building with user namespaces enabled.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that the kuids and kgids conversion have propogated through net/sunrpc/ and the fs/nfs/ it is safe to enable building nfs when user namespaces are enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1073,7 +1073,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n depends on NFSD = n - depends on NFS_FS = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
PATCH 62/85 nfsd: Remove declaration of nonexistent nfs4_acl_permisison
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/nfsd/acl.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
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
Signature · 1 line
1.7.5.4
PATCH 64/85 nfsd: Convert idmap to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Convert nfsd_map_name_to_uid to return a kuid_t value. Convert nfsd_map_name_to_gid to return a kgid_t value. Convert nfsd_map_uid_to_name to take a kuid_t parameter. Convert nfsd_map_gid_to_name to take a kgid_t paramater.
--- fs/nfsd/idmap.h | 8 ++++---- fs/nfsd/nfs4idmap.c | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-)
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/nfs4idmap.c +20 -6
@@ -625,26 +625,40 @@ do_id_to_name(struct svc_rqst *rqstp, int type, u32 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); +if (!uid_valid (*uid)) + status = nfserr_badowner; +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); +if (!gid_valid (*gid)) + status = nfserr_badowner; +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); }
Signature · 1 line
1.7.5.4
PATCH 68/85 nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In struct nfs4_ace remove the member who and replace it with an anonymous union holding who_uid and who_gid. Allowing typesafe storage uids and gids.
Add a helper pace_gt for sorting posix_acl_entries.
In struct posix_user_ace_state to replace uid with a union of kuid_t uid and kgid_t gid.
Remove all initializations of the deprecated posic_acl_entry e_id field. Which is not present when user namespaces are enabled.
Split find_uid into two functions find_uid and find_gid that work in a typesafe manner.
In nfs4xdr update nfsd4_encode_fattr to deal with the changes in struct nfs4_ace.
Rewrite nfsd4_encode_name to take a kuid_t and a kgid_t instead of a generic id and flag if it is a group or a uid. Replace the group flag with a test for a valid gid.
Modify nfsd4_encode_user to take a kuid_t and call the modifed nfsd4_encode_name.
Modify nfsd4_encode_group to take a kgid_t and call the modified nfsd4_encode_name.
Modify nfsd4_encode_aclname to take an ace instead of taking the fields of an ace broken out. This allows it to detect if the ace is for a user or a group and to pass the appropriate value while still being typesafe.
--- fs/nfsd/nfs4acl.c | 63 ++++++++++++++++++++++++++++++++++++------------- fs/nfsd/nfs4xdr.c | 41 +++++++++++++++++++------------ include/linux/nfs4.h | 6 ++++- 3 files changed, 76 insertions(+), 34 deletions(-)
fs/nfsd/nfs4acl.c +46 -17
@@ -264,7 +264,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->flag = eflag; ace->access_mask =deny_mask_from_posix (deny, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_uid = pa->e_uid; ace++; acl->naces++; }
@@ -273,7 +273,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->access_mask =mask_from_posix (pa->e_perm & pas.mask, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_uid = pa->e_uid; ace++; acl->naces++; pa++;
@@ -300,7 +300,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->access_mask =mask_from_posix (pa->e_perm & pas.mask, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_gid = pa->e_gid; ace++; acl->naces++; pa++;
@@ -329,7 +329,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->flag = eflag |NFS4_ACE_IDENTIFIER_GROUP ; ace->access_mask =deny_mask_from_posix (deny, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_gid = pa->e_gid; ace++; acl->naces++; }
@@ -345,6 +345,18 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, acl->naces++; } +static bool +pace_gt (struct posix_acl_entry *pace1,struct posix_acl_entry *pace2) +{ +if (pace1->e_tag != pace2->e_tag) +return pace1->e_tag > pace2->e_tag; +if (pace1->e_tag ==ACL_USER ) +return uid_gt (pace1->e_uid, pace2->e_uid); +if (pace1->e_tag ==ACL_GROUP ) +return gid_gt (pace1->e_gid, pace2->e_gid); +return false; +} +static void sort_pacl_range (struct posix_acl *pacl,int start,int end) {int sorted =0 , i;
@@ -355,8 +367,8 @@ sort_pacl_range(struct posix_acl *pacl, int start, int end) {while (!sorted) { sorted =1 ;for (i = start; i < end; i++) { -if (pacl->a_entries[i].e_id - > pacl->a_entries[i+1 ].e_id) { +if (pace_gt (&pacl->a_entries[i], + &pacl->a_entries[i+1 ])) { sorted =0 ; tmp = pacl->a_entries[i]; pacl->a_entries[i] = pacl->a_entries[i+1 ];
@@ -398,7 +410,10 @@ struct posix_ace_state { };struct posix_user_ace_state { -uid_t uid; +union { +kuid_t uid; +kgid_t gid; + };struct posix_ace_state perms; };
@@ -521,7 +536,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->owner.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;for (i=0 ; i < state->users->n; i++) { pace++;
@@ -531,7 +545,7 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) goto out_err;low_mode_from_nfs4 (state->users->aces[i].perms.allow, &pace->e_perm, flags); - pace->e_id = state->users->aces[i].uid; + pace->e_uid = state->users->aces[i].uid;add_to_mask (state, &state->users->aces[i].perms); }
@@ -541,7 +555,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->group.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;add_to_mask (state, &state->group);for (i=0 ; i < state->groups->n; i++) {
@@ -552,14 +565,13 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) goto out_err;low_mode_from_nfs4 (state->groups->aces[i].perms.allow, &pace->e_perm, flags); - pace->e_id = state->groups->aces[i].uid; + pace->e_gid = state->groups->aces[i].gid;add_to_mask (state, &state->groups->aces[i].perms); } pace++; pace->e_tag =ACL_MASK ;low_mode_from_nfs4 (state->mask.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ; pace++; pace->e_tag =ACL_OTHER ;
@@ -567,7 +579,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->other.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;return pacl; out_err:
@@ -587,12 +598,13 @@ static inline void deny_bits(struct posix_ace_state *astate, u32 mask) astate->deny |= mask & ~astate->allow; } -static int find_uid (struct posix_acl_state *state,struct posix_ace_state_array *a,uid_t uid) +static int find_uid (struct posix_acl_state *state,kuid_t uid) { +struct posix_ace_state_array *a = state->users;int i;for (i =0 ; i < a->n; i++) -if (a->aces[i].uid == uid) +if (uid_eq (a->aces[i].uid, uid))return i;/* Not found: */ a->n++;
@@ -603,6 +615,23 @@ static int find_uid(struct posix_acl_state *state, struct posix_ace_state_arrayreturn i; } +static int find_gid (struct posix_acl_state *state,kgid_t gid) +{ +struct posix_ace_state_array *a = state->groups; +int i; + +for (i =0 ; i < a->n; i++) +if (gid_eq (a->aces[i].gid, gid)) +return i; +/* Not found: */ + a->n++; + a->aces[i].gid = gid; + a->aces[i].perms.allow = state->everyone.allow; + a->aces[i].perms.deny = state->everyone.deny; + +return i; +} +static void deny_bits_array (struct posix_ace_state_array *a,u32 mask) {int i;
@@ -636,7 +665,7 @@ static void process_one_v4_ace(struct posix_acl_state *state, }break ;case ACL_USER : - i =find_uid (state, state->users, ace->who); + i =find_uid (state, ace->who_uid);if (ace->type ==NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ) {allow_bits (&state->users->aces[i].perms, mask); }else {
@@ -658,7 +687,7 @@ static void process_one_v4_ace(struct posix_acl_state *state, }break ;case ACL_GROUP : - i =find_uid (state, state->groups, ace->who); + i =find_gid (state, ace->who_gid);if (ace->type ==NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ) {allow_bits (&state->groups->aces[i].perms, mask); }else {
fs/nfsd/nfs4xdr.c +25 -16
86 lines not on this page · raw message
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 {
Signature · 1 line
1.7.5.4
PATCH 69/85 nfsd: Modify nfsd4_cb_sec to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Change uid and gid in struct nfsd4_cb_sec to be of type kuid_t and kgid_t.
In nfsd4_decode_cb_sec when reading uids and gids off the wire convert them to kuids and kgids, and if they don't convert to valid kuids or valid kuids ignore RPC_AUTH_UNIX and don't fill in any of the fields.
--- fs/nfsd/nfs4xdr.c | 13 ++++++++++--- fs/nfsd/state.h | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-)
fs/nfsd/nfs4xdr.c +10 -3
@@ -464,9 +464,16 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_READ32 (dummy);READ_BUF (dummy *4 );if (cbs->flavor == (u32)(-1 )) { - cbs->uid = uid; - cbs->gid = gid; - cbs->flavor =RPC_AUTH_UNIX ; +kuid_t kuid =make_kuid (&init_user_ns, uid); +kgid_t kgid =make_kgid (&init_user_ns, gid); +if (uid_valid (kuid) &&gid_valid (kgid)) { + cbs->uid = kuid; + cbs->gid = kgid; + cbs->flavor =RPC_AUTH_UNIX ; + }else { +dprintk ("RPC_AUTH_UNIX with invalid" +"uid or gid ignoring!\n" ); + } }break ;case RPC_AUTH_GSS :
fs/nfsd/state.h +2 -2
@@ -152,8 +152,8 @@ struct nfsd4_channel_attrs {struct nfsd4_cb_sec {u32 flavor;/* (u32)(-1) used to mean "no valid flavor" */ -u32 uid; -u32 gid; +kuid_t uid; +kgid_t gid; };struct nfsd4_create_session {
Signature · 1 line
1.7.5.4
PATCH 70/85 nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/nfsd/auth.c | 2 +- fs/nfsd/export.c | 22 ++++++++++++++-------- include/linux/nfsd/export.h | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-)
fs/nfsd/auth.c +1 -1
@@ -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); }
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;
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;
Signature · 1 line
1.7.5.4
PATCH 72/85 nfsd: Enable building with user namespaces enabled.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that the kuids and kgids conversion have propogated through net/sunrpc/ and the fs/nfsd/ it is safe to enable building nfsd when user namespaces are enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - depends on NFSD = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
PATCH 73/85 cifs: Override unmappable incoming uids and gids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
The cifs protocol has a 64bit space for uids and gids, while linux only supports a 32bit space today. Instead of silently truncating 64bit cifs ids, replace cifs ids that do not fit in the 32bit linux id space with the default uid and gids for the cifs mount.
--- fs/cifs/inode.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-)
fs/cifs/inode.c +13 -9
@@ -244,15 +244,19 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,break ; } -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); - -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_uid = cifs_sb->mnt_uid; +if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID )) { +u64 id =le64_to_cpu (info->Uid); +if (id < ((uid_t)-1 )) + fattr->cf_uid = id; + } + + fattr->cf_gid = cifs_sb->mnt_gid; +if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID )) { +u64 id =le64_to_cpu (info->Gid); +if (id < ((gid_t)-1 )) + fattr->cf_gid = id; + } fattr->cf_nlink =le64_to_cpu (info->Nlinks); }
Signature · 1 line
1.7.5.4
PATCH 74/85 cifs: Use BUILD_BUG_ON to validate uids and gids are the same size
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
The assumption that sizeof(uid_t) is the same as sizeof(gid_t) is completely reasonable but since we can verify the condition at compile time.
--- fs/cifs/cifsacl.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
fs/cifs/cifsacl.c +1 -0
@@ -297,6 +297,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,* probably a safe assumption but might be better to check based on * sidtype. */ +BUILD_BUG_ON (sizeof (uid_t) !=sizeof (gid_t));if (sidkey->datalen !=sizeof (uid_t)) { rc = -EIO ; cFYI(1, "%s: Downcall contained malformed key "
Signature · 1 line
1.7.5.4
PATCH 76/85 cifs: Use kuids and kgids SID to uid/gid mapping
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Update id_mode_to_cifs_acl to take a kuid_t and a kgid_t.
Replace NO_CHANGE_32 with INVALID_UID and INVALID_GID, and tests for NO_CHANGE_32 with uid_valid and gid_valid.
Carefully unpack the value returned from request_key. memcpy the value into the expected type. The convert the uid/gid into a kuid/kgid. And then only if the result is a valid kuid or kgid update fuid/fgid.
--- fs/cifs/cifsacl.c | 43 +++++++++++++++++++++++++++++-------------- fs/cifs/cifspdu.h | 1 - fs/cifs/cifsproto.h | 2 +- fs/cifs/inode.c | 8 ++++---- 4 files changed, 34 insertions(+), 20 deletions(-)
fs/cifs/cifsacl.c +29 -14
@@ -266,8 +266,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,struct key *sidkey;char *sidstr;const struct cred *saved_cred; -uid_t fuid = cifs_sb->mnt_uid; -gid_t fgid = cifs_sb->mnt_gid; +kuid_t fuid = cifs_sb->mnt_uid; +kgid_t fgid = cifs_sb->mnt_gid;/* * If we have too many subauthorities, then something is really wrong.
@@ -306,10 +306,21 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, goto out_key_put; } -if (sidtype ==SIDOWNER ) -memcpy (&fuid, &sidkey->payload.value,sizeof (uid_t)); -else -memcpy (&fgid, &sidkey->payload.value,sizeof (gid_t)); +if (sidtype ==SIDOWNER ) { +kuid_t uid; +uid_t id; +memcpy (&id, &sidkey->payload.value,sizeof (uid_t)); + uid =make_kuid (&init_user_ns, id); +if (uid_valid (uid)) + fuid = uid; + }else { +kgid_t gid; +gid_t id; +memcpy (&id, &sidkey->payload.value,sizeof (gid_t)); + gid =make_kgid (&init_user_ns, id); +if (gid_valid (gid)) + fgid = gid; + } out_key_put:key_put (sidkey);
@@ -776,7 +787,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;
@@ -808,17 +819,19 @@ 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_valid (uid)) {/* chown */ +uid_t id; 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); + id =from_kuid (&init_user_ns, uid); + rc =id_to_sid (id,SIDOWNER , nowner_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for owner id %d" , - __func__, rc, uid); + __func__, rc, id);kfree (nowner_sid_ptr);return rc; }
@@ -826,17 +839,19 @@ 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_valid (gid)) {/* chgrp */ +gid_t id; 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); + id =from_kgid (&init_user_ns, gid); + rc =id_to_sid (id,SIDGROUP , ngroup_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for group id %d" , - __func__, rc, gid); + __func__, rc, id);kfree (ngroup_sid_ptr);return rc; }
@@ -1004,7 +1019,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/cifspdu.h +0 -1
@@ -277,7 +277,6 @@#define CIFS_NO_HANDLE 0xFFFF#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL -#define NO_CHANGE_32 0xFFFFFFFFUL/* IPC$ in ASCII */ #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
fs/cifs/cifsproto.h +1 -1
@@ -161,7 +161,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 *,
fs/cifs/inode.c +4 -4
@@ -2090,8 +2090,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 =INVALID_UID ; +kgid_t gid =INVALID_GID ;struct inode *inode = direntry->d_inode;struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode);
@@ -2150,7 +2150,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_valid (uid) ||gid_valid (gid)) { rc =id_mode_to_cifs_acl (inode, full_path,NO_CHANGE_64 , uid, gid);if (rc) {
@@ -2174,7 +2174,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 ); +INVALID_UID ,INVALID_GID );if (rc) {cFYI (1 ,"%s: Setting ACL failed with error: %d" , __func__, rc);
Signature · 1 line
1.7.5.4
PATCH 78/85 cifs: Modify struct cifs_unix_set_info_args to hold a kuid_t and a kgid_t
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Use INVALID_UID and INVALID_GID instead of NO_CHANGE_64 to indicate the value should not be changed.
In cifs_fill_unix_set_info convert from kuids and kgids into uids and gids that will fit in FILE_UNIX_BASIC_INFO.
--- fs/cifs/cifsproto.h | 4 ++-- fs/cifs/cifssmb.c | 10 ++++++++-- fs/cifs/dir.c | 18 +++++++++--------- fs/cifs/file.c | 4 ++-- fs/cifs/inode.c | 14 +++++++------- 5 files changed, 28 insertions(+), 22 deletions(-)
fs/cifs/cifsproto.h +2 -2
@@ -305,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 +8 -2
@@ -5819,8 +5819,14 @@ static voidcifs_fill_unix_set_info (FILE_UNIX_BASIC_INFO *data_offset, const struct cifs_unix_set_info_args *args) { +u64 uid =NO_CHANGE_64 , gid =NO_CHANGE_64 ;u64 mode = args->mode; +if (uid_valid (args->uid)) + uid =from_kuid (&init_user_ns, args->uid); +if (gid_valid (args->gid)) + gid =from_kgid (&init_user_ns, args->gid); +/* * Samba server ignores set of file size to zero due to bugs in some * older clients, but we should be precise - we use SetFileSize to
@@ -5833,8 +5839,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/dir.c +9 -9
@@ -342,14 +342,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 =INVALID_UID ;/* no change */ + args.gid =INVALID_GID ;/* no change */ }CIFSSMBUnixSetFileInfo (xid, tcon, &args, fid->netfid, current->tgid);
@@ -588,11 +588,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 =INVALID_UID ;/* no change */ + args.gid =INVALID_GID ;/* no change */ } 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 =INVALID_UID ,/* no change */ + .gid =INVALID_GID ,/* no change */ .ctime =NO_CHANGE_64 , .atime =NO_CHANGE_64 , .mtime =NO_CHANGE_64 ,
fs/cifs/inode.c +7 -7
@@ -1249,14 +1249,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 (); + args.uid =current_fsuid ();if (parent->i_mode &S_ISGID ) - args.gid = (__u64 )parent->i_gid; + args.gid = parent->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 ;/* no change */ + args.gid =INVALID_GID ;/* no change */ } CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, cifs_sb->local_nls,
@@ -2017,12 +2017,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 =INVALID_UID ;/* no change */ if (attrs->ia_valid &ATTR_GID ) args->gid = attrs->ia_gid;else - args->gid =NO_CHANGE_64 ; + args->gid =INVALID_GID ;/* no change */ if (attrs->ia_valid &ATTR_ATIME ) args->atime =cifs_UnixTimeToNT (attrs->ia_atime);
Signature · 1 line
1.7.5.4
PATCH 79/85 cifs: Convert struct tcon_link to use a kuid.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/cifs/cifsglob.h | 2 +- fs/cifs/connect.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-)
fs/cifs/cifsglob.h +1 -1
@@ -837,7 +837,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
fs/cifs/connect.c +6 -6
@@ -3919,7 +3919,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);
@@ -3989,7 +3989,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;
@@ -3997,9 +3997,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;
@@ -4018,7 +4018,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);
@@ -4048,7 +4048,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 ))
Signature · 1 line
1.7.5.4
PATCH 82/85 cifs: Modify struct smb_vol to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Add two helper functions get_option_uid and get_option_gid to handle the work of parsing uid and gids paramaters from the command line and making kuids and kgids out of them.
--- fs/cifs/cifsglob.h | 10 +++++----- fs/cifs/connect.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 15 deletions(-)
fs/cifs/cifsglob.h +5 -5
@@ -399,11 +399,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;
fs/cifs/connect.c +40 -10
93 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH 83/85 cifs: Convert struct cifs_sb_info to use kuids and kgids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/cifs/cifs_fs_sb.h | 8 ++++---- fs/cifs/cifsfs.c | 14 ++++++++++---- fs/cifs/connect.c | 2 +- fs/cifs/misc.c | 2 +- 4 files changed, 16 insertions(+), 10 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/cifsfs.c +10 -4
@@ -376,13 +376,15 @@ 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
@@ -437,9 +439,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/connect.c +1 -1
@@ -2743,7 +2743,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/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 ) {
Signature · 1 line
1.7.5.4
PATCH 84/85 cifs: Convert struct cifs_ses to use a kuid_t and a kgid_t
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/cifs/cifs_spnego.c | 6 ++++-- fs/cifs/cifsglob.h | 4 ++-- fs/cifs/connect.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-)
fs/cifs/cifs_spnego.c +4 -2
@@ -149,10 +149,12 @@ 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/cifsglob.h +2 -2
@@ -702,8 +702,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? */
fs/cifs/connect.c +1 -1
@@ -2271,7 +2271,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 :
Signature · 1 line
1.7.5.4
PATCH 85/85 cifs: Enable building with user namespaces enabled.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1071,7 +1071,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on CIFS = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
PATCH 9/85 9p: Modify the stat structures to use kuid_t and kgid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
9p has thre strucrtures that can encode inode stat information. Modify all of those structures to contain kuid_t and kgid_t values. Modify he wire encoders and decoders of those structures to use 'u' and 'g' instead of 'd' in the format string where uids and gids are present.
This results in all kuid and kgid conversion to and from on the wire values being performed by the same code in protocol.c where the client is known at the time of the conversion.
--- fs/9p/vfs_inode.c | 6 +++--- include/net/9p/9p.h | 14 +++++++------- net/9p/client.c | 18 +++++++++++++----- net/9p/protocol.c | 13 +++++++------ 4 files changed, 30 insertions(+), 21 deletions(-)
fs/9p/vfs_inode.c +3 -3
@@ -228,9 +228,9 @@ v9fs_blank_wstat(struct p9_wstat *wstat) wstat->uid =NULL ; wstat->gid =NULL ; wstat->muid =NULL ; - wstat->n_uid = ~0 ; - wstat->n_gid = ~0 ; - wstat->n_muid = ~0 ; + wstat->n_uid =INVALID_UID ; + wstat->n_gid =INVALID_GID ; + wstat->n_muid =INVALID_UID ; wstat->extension =NULL ; }
include/net/9p/9p.h +7 -7
@@ -407,17 +407,17 @@ struct p9_wstat {char *gid;char *muid;char *extension;/* 9p2000.u extensions */ -u32 n_uid;/* 9p2000.u extensions */ -u32 n_gid;/* 9p2000.u extensions */ -u32 n_muid;/* 9p2000.u extensions */ +kuid_t n_uid;/* 9p2000.u extensions */ +kgid_t n_gid;/* 9p2000.u extensions */ +kuid_t n_muid;/* 9p2000.u extensions */ };struct p9_stat_dotl {u64 st_result_mask;struct p9_qid qid;u32 st_mode; -u32 st_uid; -u32 st_gid; +kuid_t st_uid; +kgid_t st_gid;u64 st_nlink;u64 st_rdev;u64 st_size;
@@ -471,8 +471,8 @@ struct p9_stat_dotl {struct p9_iattr_dotl {u32 valid;u32 mode; -u32 uid; -u32 gid; +kuid_t uid; +kgid_t gid;u64 size;u64 atime_sec;u64 atime_nsec;
net/9p/client.c +13 -5
@@ -1711,7 +1711,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) (unsigned long long )ret->qid.path, ret->qid.version, ret->mode, ret->atime, ret->mtime, (unsigned long long )ret->length, ret->name, ret->uid, ret->gid, ret->muid, ret->extension, - ret->n_uid, ret->n_gid, ret->n_muid); +from_kuid (&init_user_ns, ret->n_uid), +from_kgid (&init_user_ns, ret->n_gid), + from_kuid(&init_user_ns, ret->n_muid));p9_free_req (clnt, req);return ret;
@@ -1765,8 +1767,10 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,"<<< st_btime_sec=%lld st_btime_nsec=%lld\n" "<<< st_gen=%lld st_data_version=%lld" , ret->st_result_mask, ret->qid.type, ret->qid.path, - ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid, - ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize, + ret->qid.version, ret->st_mode, ret->st_nlink, +from_kuid (&init_user_ns, ret->st_uid), +from_kgid (&init_user_ns, ret->st_gid), + ret->st_rdev, ret->st_size, ret->st_blksize, ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
@@ -1829,7 +1833,9 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) (unsigned long long )wst->qid.path, wst->qid.version, wst->mode, wst->atime, wst->mtime, (unsigned long long )wst->length, wst->name, wst->uid, wst->gid, wst->muid, wst->extension, - wst->n_uid, wst->n_gid, wst->n_muid); +from_kuid (&init_user_ns, wst->n_uid), +from_kgid (&init_user_ns, wst->n_gid), + from_kuid(&init_user_ns, wst->n_muid)); req =p9_client_rpc (clnt,P9_TWSTAT ,"dwS" , fid->fid, wst->size+2 , wst);if (IS_ERR (req)) {
@@ -1858,7 +1864,9 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)" valid=%x mode=%x uid=%d gid=%d size=%lld\n" " atime_sec=%lld atime_nsec=%lld\n" " mtime_sec=%lld mtime_nsec=%lld\n" , - p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid, + p9attr->valid, p9attr->mode, +from_kuid (&init_user_ns, p9attr->uid), +from_kgid (&init_user_ns, p9attr->gid), p9attr->size, p9attr->atime_sec, p9attr->atime_nsec, p9attr->mtime_sec, p9attr->mtime_nsec);
net/9p/protocol.c +7 -6
@@ -199,11 +199,12 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, va_arg(ap, struct p9_wstat *);memset (stbuf,0 ,sizeof (struct p9_wstat )); - stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = --1 ; + stbuf->n_uid = stbuf->n_muid =INVALID_UID ; + stbuf->n_gid =INVALID_GID ; + errcode = p9pdu_readf(pdu, proto_version, - "wwdQdddqssss?sddd", + "wwdQdddqssss?sugu", &stbuf->size, &stbuf->type, &stbuf->dev, &stbuf->qid, &stbuf->mode, &stbuf->atime,
@@ -316,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,memset (stbuf,0 ,sizeof (struct p9_stat_dotl )); errcode = p9pdu_readf(pdu, proto_version, - "qQdddqqqqqqqqqqqqqqq", + "qQdugqqqqqqqqqqqqqqq", &stbuf->st_result_mask, &stbuf->qid, &stbuf->st_mode,
@@ -426,7 +427,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, va_arg(ap, const struct p9_wstat *); errcode = p9pdu_writef(pdu, proto_version, - "wwdQdddqssss?sddd", + "wwdQdddqssss?sugu", stbuf->size, stbuf->type, stbuf->dev, &stbuf->qid, stbuf->mode, stbuf->atime,
@@ -504,7 +505,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, struct p9_iattr_dotl *); errcode = p9pdu_writef(pdu, proto_version, - "ddddqqqqq", + "ddugqqqqq", p9attr->valid, p9attr->mode, p9attr->uid,
Signature · 1 line
1.7.5.4
PATCH 10/85 9p: Modify struct 9p_fid to use a kuid_t not a uid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Change struct 9p_fid and it's associated functions to use kuid_t's instead of uid_t.
--- fs/9p/fid.c | 17 +++++++++-------- fs/9p/v9fs.c | 2 +- include/net/9p/client.h | 2 +- 3 files changed, 11 insertions(+), 10 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 +1 -1
@@ -387,7 +387,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 */
include/net/9p/client.h +1 -1
@@ -187,7 +187,7 @@ struct p9_fid {int mode;struct p9_qid qid;u32 iounit; -uid_t uid; +kuid_t uid;void *rdir;
Signature · 1 line
1.7.5.4
PATCH 11/85 9p: Modify struct v9fs_session_info to use a kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Change struct v9fs_session_info and the code that popluates it to use kuids and kgids. When parsing the 9p mount options convert the dfltuid, dflutgid, and the session uid from the current user namespace into kuids and kgids. Modify V9FS_DEFUID and V9FS_DEFGUID to be kuid and kgid values.
--- fs/9p/v9fs.c | 30 +++++++++++++++++++++++++----- fs/9p/v9fs.h | 10 +++++----- 2 files changed, 30 insertions(+), 10 deletions(-)
fs/9p/v9fs.c +25 -5
@@ -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 (current_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 (current_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 (current_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 )) {
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) {
Signature · 1 line
1.7.5.4
PATCH 12/85 9p: Modify v9fs_get_fsgid_for_create to return a kgid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Modify v9fs_get_fsgid_for_create to return a kgid and modify all of the variables that hold the result of v9fs_get_fsgid_for_create to be of type kgid_t.
--- fs/9p/vfs_inode_dotl.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
fs/9p/vfs_inode_dotl.c +5 -5
@@ -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;
@@ -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;
Signature · 1 line
1.7.5.4
PATCH 13/85 9p: Allow building 9p with user namespaces enabled.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Now that the uid_t -> kuid_t, gid_t -> kgid_t conversion has been completed in 9p allow 9p to be built when user namespaces are enabled.
--- init/Kconfig | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
init/Kconfig +0 -4
@@ -1070,11 +1070,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 CIFS = n depends on CODA_FS = n
Signature · 1 line
1.7.5.4
PATCH 14/85 afs: Remove unused structure afs_store_status
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
While looking for kuid_t and kgid_t conversions I found this structure that has never been used since it was added to the kernel in 2007. The obvious for this structure to be used is in xdr_encode_AFS_StoreStatus and that function uses a small handful of local variables instead.
So remove the unnecessary structure to prevent confusion.
--- fs/afs/afs.h | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-)
fs/afs/afs.h +0 -7
@@ -133,13 +133,6 @@ struct afs_file_status {/* * AFS file status change request */ -struct afs_store_status { -u32 mask;/* which bits of the struct are set */ -u32 mtime_client;/* last time client changed data */ -u32 owner;/* owner ID */ -u32 group;/* group ID */ -umode_t mode;/* UNIX mode */ -};#define AFS_SET_MTIME 0x01/* set the mtime */ #define AFS_SET_OWNER 0x02/* set the owner ID */
Signature · 1 line
1.7.5.4
PATCH 15/85 afs: Only allow mounting afs in the intial network namespace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
rxrpc sockets only work in the initial network namespace so it isn't possible to support afs in any other network namespace.
--- fs/afs/super.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
fs/afs/super.c +6 -0
@@ -24,6 +24,8 @@#include <linux/parser.h> #include <linux/statfs.h> #include <linux/sched.h> +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include "internal.h" #define AFS_FS_MAGIC 0x6B414653/* 'kAFS' */
@@ -363,6 +365,10 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,memset (¶ms,0 ,sizeof (params)); + ret = -EINVAL ; +if (current->nsproxy->net_ns != &init_net) + goto error; +/* parse the options and device name */ if (options) { ret =afs_parse_options (¶ms, options, &dev_name);
Signature · 1 line
1.7.5.4
PATCH 16/85 afs: Support interacting with multiple user namespaces
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Modify struct afs_file_status to store owner as a kuid_t and group as a kgid_t.
In xdr_decode_AFSFetchStatus as owner is now a kuid_t and group is now a kgid_t don't use the EXTRACT macro. Instead perform the work of the extract macro explicitly. Read the value with ntohl and convert it to the appropriate type with make_kuid or make_kgid. Test if the value is different from what is stored in status and
update changed. Update the value in status.
In xdr_encode_AFS_StoreStatus call from_kuid or from_kgid as we are computing the on the wire encoding.
Initialize uids with GLOBAL_ROOT_UID instead of 0. Initialize gids with GLOBAL_ROOT_GID instead of 0.
--- 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 */ +kuid_t owner; +kgid_t 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 =make_kuid (&init_user_ns,ntohl (*bp++)); + changed |= !uid_eq (owner, status->owner); + status->owner = 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 =make_kgid (&init_user_ns,ntohl (*bp++)); + changed |= !gid_eq (group, status->group); + status->group = 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
@@ -1071,7 +1071,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on AFS_FS = n depends on CIFS = n depends on CODA_FS = n depends on GFS2_FS = n
Signature · 1 line
1.7.5.4
PATCH 17/85 coda: Restrict coda messages to the initial pid namespace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Remove the slight chance that pids in coda messages will be interpreted in the wrong pid namespace.
- Explicitly send all pids in coda messages in the initial pid namespace.
- Only allow mounts from processes in the initial pid namespace.
- Only allow processes in the initial pid namespace to open the coda character device to communicate with coda.
--- fs/coda/inode.c | 4 ++++ fs/coda/psdev.c | 4 ++++ fs/coda/upcall.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-)
fs/coda/inode.c +4 -0
@@ -20,6 +20,7 @@#include <linux/file.h> #include <linux/vfs.h> #include <linux/slab.h> +#include <linux/pid_namespace.h> #include <asm/uaccess.h>
@@ -157,6 +158,9 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)int error;int idx; +if (task_active_pid_ns (current) != &init_pid_ns) +return -EINVAL ; + idx =get_device_index ((struct coda_mount_data *) data);/* Ignore errors in data, for backward compatibility */
fs/coda/psdev.c +4 -0
@@ -37,6 +37,7 @@#include <linux/list.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/pid_namespace.h> #include <asm/io.h> #include <asm/poll.h> #include <asm/uaccess.h>
@@ -266,6 +267,9 @@ static int coda_psdev_open(struct inode * inode, struct file * file)struct venus_comm *vcp;int idx, err; +if (task_active_pid_ns (current) != &init_pid_ns) +return -EINVAL ; + idx =iminor (inode);if (idx <0 || idx >=MAX_CODADEVS )return -ENODEV ;
fs/coda/upcall.c +2 -2
@@ -50,8 +50,8 @@ static void *alloc_upcall(int opcode, int size)return ERR_PTR (-ENOMEM ); inp->ih.opcode = opcode; - inp->ih.pid = current->pid; - inp->ih.pgid =task_pgrp_nr (current); + inp->ih.pid =task_pid_nr_ns (current, &init_pid_ns); + inp->ih.pgid =task_pgrp_nr_ns (current, &init_pid_ns); inp->ih.uid =current_fsuid ();return (void *)inp;
Signature · 1 line
1.7.5.4
PATCH 18/85 coda: Restrict coda messages to the initial user namespace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Remove the slight chance that uids and gids in coda messages will be interpreted in the wrong user namespace.
- Only allow processes in the initial user namespace to open the coda character device to communicate with coda filesystems.
- Explicitly convert the uids in the coda header into the initial user namespace.
- In coda_vattr_to_attr make kuids and kgids from the initial user namespace uids and gids in struct coda_vattr that just came from userspace.
- In coda_iattr_to_vattr convert kuids and kgids into uids and gids in the intial user namespace and store them in struct coda_vattr for sending to coda userspace programs.
Nothing needs to be changed with mounts as coda does not support being mounted in anything other than the initial user namespace.
--- fs/coda/coda_linux.c | 8 ++++---- fs/coda/psdev.c | 3 +++ fs/coda/upcall.c | 6 +++--- include/linux/coda_psdev.h | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-)
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; + inode->i_uid =make_kuid (&init_user_ns, (uid_t ) attr->va_uid);if (attr->va_gid !=-1 ) - inode->i_gid = (gid_t ) attr->va_gid; + inode->i_gid =make_kgid (&init_user_ns, (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/psdev.c +3 -0
@@ -270,6 +270,9 @@ static int coda_psdev_open(struct inode * inode, struct file * file)if (task_active_pid_ns (current) != &init_pid_ns)return -EINVAL ; +if (current_user_ns () != &init_user_ns) +return -EINVAL ; + idx =iminor (inode);if (idx <0 || idx >=MAX_CODADEVS )return -ENODEV ;
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 =task_pid_nr_ns (current, &init_pid_ns); inp->ih.pgid =task_pgrp_nr_ns (current, &init_pid_ns); - 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,
Signature · 1 line
1.7.5.4
Jan Harkes
maintainerRe: [PATCH review 18/85] coda: Restrict coda messages to the initial user namespace
Quoted 4 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Remove the slight chance that uids and gids in coda messages will be interpreted in the wrong user namespace.
Awesome, I was wondering how to handle uid's from different namespaces cleanly in Coda's userspace daemon without resorting to exporting kuids to userspace.
But this is a much more elegant solution, every namespace that cares about Coda should just run their own mountpoint and userspace daemon.
Jan
Re: [PATCH review 18/85] coda: Restrict coda messages to the initial user namespace
Quoted 6 lines · Jan Harkes
Quoted 4 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Remove the slight chance that uids and gids in coda messages will be interpreted in the wrong user namespace.
Quoted 6 lines
Awesome, I was wondering how to handle uid's from different namespaces cleanly in Coda's userspace daemon without resorting to exporting kuids to userspace.
But this is a much more elegant solution, every namespace that cares about Coda should just run their own mountpoint and userspace daemon.
Do you know if people care enough about coda that they will want to export run coda multiple mountpoint and userspace daemons?
I have never seen anyone running coda so I was suspecting that coda was a filesystem that was gradually fading away.
Eric
PATCH 19/85 coda: Cache permisions in struct coda_inode_info in a kuid_t.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Change c_uid in struct coda_indoe_info from a vuid_t to a kuid_t.
- Initialize c_uid to GLOBAL_ROOT_UID instead of 0.
- Use uid_eq to compare cached kuids.
--- fs/coda/cache.c | 4 ++-- fs/coda/coda_fs_i.h | 2 +- fs/coda/inode.c | 2 +- 3 files changed, 4 insertions(+), 4 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/inode.c +1 -1
@@ -49,7 +49,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;
Signature · 1 line
1.7.5.4
PATCH 20/85 coda: Allow coda to be built when user namespace support is enabled
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that the coda kernel to userspace has been modified to convert between kuids and kgids and uids and gids, and all internal coda structures have be modified to store uids and gids as kuids and kgids it is safe to allow code to be built with user namespace support enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - 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
PATCH 21/85 ocfs2: Handle kuids and kgids in acl/xattr conversions.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Explicitly deal with the different kinds of acls because they need different conversions.
--- fs/ocfs2/acl.c | 31 +++++++++++++++++++++++++++++-- 1 files changed, 29 insertions(+), 2 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; }
Signature · 1 line
1.7.5.4
PATCH 22/85 ocfs2: convert between kuids and kgids and DLM locks
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Convert between uid and gids stored in the on the wire format of dlm locks aka struct ocfs2_meta_lvb and kuids and kgids stored in inode->i_uid and inode->i_gid.
--- fs/ocfs2/dlmglue.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
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,
Signature · 1 line
1.7.5.4
Joel Becker
maintainerRe: [PATCH review 22/85] ocfs2: convert between kuids and kgids and DLM locks
Quoted 29 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Convert between uid and gids stored in the on the wire format of dlm locks aka struct
ocfs2_meta_lvband kuids and kgids stored ininode->i_uidandinode->i_gid.Cc Mark Fasheh <mfasheh-IBi9RG/[email protected]>Cc Joel Becker <[email protected]>--- fs/ocfs2/dlmglue.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)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)); lvb->lvb_imode =cpu_to_be16 (inode->i_mode); lvb->lvb_inlink =cpu_to_be16 (inode->i_nlink); lvb->lvb_iatime_packed =
fs/ocfs2/dlmglue.c static void ocfs2_refresh_inode_from_lvb(struct inode *inode) · line 2102
Quoted 10 lines
fs/ocfs2/dlmglue.c +2
-2@@ -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,
What does this do if two machines with different user namespaces communicate. I think that things go very wrong. Perhaps right now, when ocfs2 is tied to init_user_namespace, we're OK. But as soon as two systems can be in different namespaces, we are broken.
Joel
Quoted 3 lines
Signature · 1 line
1.7.5.4
Signature · 6 lines
"I think it would be a good idea."
- Mahatma Ghandi, when asked what he thought of Western
civilization
http://www.jlbec.org/
[email protected]PATCH 23/85 ocfs2: Convert uid and gids between in core and on disk inodes
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/ocfs2/inode.c | 12 ++++++------ fs/ocfs2/namei.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
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));
Signature · 1 line
1.7.5.4
Joel Becker
maintainerRe: [PATCH review 23/85] ocfs2: Convert uid and gids between in core and on disk inodes
This has the same problem with two machines in different userspace namespaces. Should this be punted to the sysadmin or helped out in the filesystem? Do you define this case as unsupported?
Joel
Quoted 65 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Mark Fasheh <mfasheh-IBi9RG/[email protected]>Cc Joel Becker <[email protected]>--- fs/ocfs2/inode.c | 12 ++++++------ fs/ocfs2/namei.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)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));Signature · 1 line
1.7.5.4
Signature · 6 lines
"Sometimes when reading Goethe I have the paralyzing suspicion
that he is trying to be funny."
- Guy Davenport
http://www.jlbec.org/
[email protected]Re: [PATCH review 23/85] ocfs2: Convert uid and gids between in core and on disk inodes
Quoted 3 lines · Joel Becker
This has the same problem with two machines in different userspace namespaces. Should this be punted to the sysadmin or helped out in the filesystem? Do you define this case as unsupported?
First I define two machines in the same user namespace as two machines with synchronized password files.
As today connecting two machines without synchronizing the password entries is a problem, won't work, and is punted to the sysadmin to make keep from doing something silly.
At the same time I don't want to make it easy to get confused, or cause breakage.
With these patches ocfs2 only still only works in the initial user namespace. I don't set .fs_flags = FS_USERNS_MOUNT in struct filesystem. Which means that while users in other user namespaces can store files on ocfs2, they can't mount ocfs2.
Eric
Re: [PATCH review 23/85] ocfs2: Convert uid and gids between in core and on disk inodes
In reply to Joel BeckerQuoted 3 lines · Joel Becker
This has the same problem with two machines in different userspace namespaces. Should this be punted to the sysadmin or helped out in the filesystem? Do you define this case as unsupported?
First I define two machines in the same user namespace as two machines with synchronized password files.
As today connecting two machines without synchronizing the password entries is a problem, won't work, and is punted to the sysadmin to make keep from doing something silly.
At the same time I don't want to make it easy to get confused, or cause breakage.
With these patches ocfs2 only still only works in the initial user namespace. I don't set .fs_flags = FS_USERNS_MOUNT in struct filesystem. Which means that while users in other user namespaces can store files on ocfs2, they can't mount ocfs2.
Eric
PATCH 24/85 ocfs2: For tracing report the uid and gid values in the initial user namespace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ocfs2/file.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
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));/* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK (inode->i_mode))
Signature · 1 line
1.7.5.4
PATCH 25/85 ocfs2: Compare kuids and kgids using uid_eq and gid_eq
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/ocfs2/file.c | 8 ++++---- fs/ocfs2/refcounttree.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)
fs/ocfs2/file.c +4 -4
@@ -1175,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));
@@ -1191,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/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 ;
Signature · 1 line
1.7.5.4
Joel Becker
maintainerRe: [PATCH review 25/85] ocfs2: Compare kuids and kgids using uid_eq and gid_eq
Quoted 15 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Cc Mark Fasheh <mfasheh-IBi9RG/[email protected]>Cc Joel Becker <[email protected]>--- fs/ocfs2/file.c | 8 ++++---- fs/ocfs2/refcounttree.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)fs/ocfs2/file.c +0
-0
fs/ocfs2/file.c int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) · line 1179
Quoted 7 lines
fs/ocfs2/file.c +2
-2@@ -1175,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))) {
Will the code work if built just before this patch? IOW, does the original comparison (attr->ia_gid != inode->i_gid) work when the system is in the init_user_namespace? If not, then the previous patches are not leaving a functional filesystem.
Joel
Quoted 35 lines
fs/ocfs2/file.c +2
-2/* * 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));@@ -1191,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/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 ;Signature · 1 line
1.7.5.4
Signature · 7 lines
"Where are my angels? Where's my golden one? And where is my hope Now that my heroes are gone?" http://www.jlbec.org/ [email protected]
PATCH 26/85 ocfs2: Enable building with user namespaces enabled
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that ocfs2 has been converted to store uids and gids in kuid_t and kgid_t and all of the conversions have been added to the appropriate places it is safe to allow building and using ocfs2 with user namespace support enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1076,7 +1076,6 @@ config UIDGID_CONVERTED depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n - 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 review 26/85] ocfs2: Enable building with user namespaces enabled
Quoted 19 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that ocfs2 has been converted to store uids and gids in
kuid_tandkgid_tand all of the conversions have been added to the appropriate places it is safe to allow building and using ocfs2 with user namespace support enabled.Cc Mark Fasheh <mfasheh-IBi9RG/[email protected]>Cc Joel Becker <[email protected]>--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)init/Kconfig +0
-0
init/Kconfig config UIDGID_CONVERTED · line 1079
Quoted 4 lines
init/Kconfig +0
-1@@ -1076,7 +1076,6 @@ config UIDGID_CONVERTED depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n - depends on OCFS2_FS = n
Ahh, I can see how this protects the partially applied state. Sorry about that.
Joel
Quoted 6 lines
init/Kconfig +0
-0depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKSSignature · 1 line
1.7.5.4
Signature · 4 lines
"People with narrow minds usually have broad tongues." http://www.jlbec.org/ [email protected]
PATCH 27/85 gfs2: Remove improper checks in gfs2_set_dqblk.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
In set_dqblk it is an error to look at fdq->d_id or fdq->d_flags. Userspace quota applications do not set these fields when calling quotactl(Q_XSETQLIM,...), and the kernel does not set those fields when quota_setquota calls set_dqblk.
gfs2 never looks at fdq->d_id or fdq->d_flags after checking to see if they match the id and type supplied to set_dqblk.
No other linux filesystem in set_dqblk looks at either fdq->d_id or fdq->d_flags.
Therefore remove these bogus checks from gfs2 and allow normal quota setting applications to work.
--- fs/gfs2/quota.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
fs/gfs2/quota.c +0 -6
@@ -1543,13 +1543,9 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,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 ;default :return -EINVAL ;
@@ -1557,8 +1553,6 @@ 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)) -return -EINVAL ; error =qd_get (sdp, type,from_kqid (&init_user_ns, qid), &qd);if (error)
Signature · 1 line
1.7.5.4
PATCH 28/85 gfs2: Split NO_QUOTA_CHANGE inot NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Split NO_QUOTA_CHANGE into NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE so the constants may be well typed.
--- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/inode.c | 10 +++++----- fs/gfs2/quota.c | 4 ++-- fs/gfs2/quota.h | 5 +++-- fs/gfs2/super.c | 2 +- fs/gfs2/xattr.c | 4 ++-- 7 files changed, 15 insertions(+), 14 deletions(-)
fs/gfs2/bmap.c +1 -1
@@ -1098,7 +1098,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
@@ -1849,7 +1849,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/inode.c +5 -5
@@ -548,7 +548,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;
@@ -1589,15 +1589,15 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ngid = attr->ia_gid;if (!(attr->ia_valid &ATTR_UID ) || ouid == nuid) - ouid = nuid =NO_QUOTA_CHANGE ; + ouid = nuid =NO_UID_QUOTA_CHANGE ;if (!(attr->ia_valid &ATTR_GID ) || ogid == ngid) - ogid = ngid =NO_QUOTA_CHANGE ; + 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 (ouid !=NO_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) { error =gfs2_quota_check (ip, nuid, ngid);if (error) goto out_gunlock_q;
@@ -1611,7 +1611,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 (ouid !=NO_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) {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 +2 -2
@@ -524,7 +524,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) ip->i_res->rs_qa_qd_num++; qd++; -if (uid !=NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { +if (uid !=NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { error =qdsb_get (sdp,QUOTA_USER , uid, qd);if (error) goto out;
@@ -532,7 +532,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) qd++; } -if (gid !=NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { +if (gid !=NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { error =qdsb_get (sdp,QUOTA_GROUP , gid, qd);if (error) goto out;
fs/gfs2/quota.h +3 -2
@@ -14,7 +14,8 @@ 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_GIDextern int gfs2_quota_hold (struct gfs2_inode *ip,u32 uid,u32 gid);extern void gfs2_quota_unhold (struct gfs2_inode *ip);
@@ -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 +1 -1
@@ -1429,7 +1429,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/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;
Signature · 1 line
1.7.5.4
PATCH 29/85 gfs2: Report quotas in the caller's user namespace.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
When a quota is queried return the uid or the gid in the mapped into the caller's user namespace. In addition perform the munged version of the mapping so that instead of -1 a value that does not map is reported as the overflowuid or the overflowgid.
--- fs/gfs2/quota.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/gfs2/quota.c +1 -1
@@ -1509,7 +1509,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; 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_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;
Signature · 1 line
1.7.5.4
PATCH 30/85 gfs2: Introduce qd2index
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Both qd_alloc and qd2offset perform the exact same computation
to get an index from a gfs2_quota_data. Make life a little
simpler and factor out this index computation.
--- fs/gfs2/quota.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
fs/gfs2/quota.c +8 -2
@@ -120,11 +120,17 @@ out:return (atomic_read (&qd_lru_count) * sysctl_vfs_cache_pressure) /100 ; } +static u64 qd2index (struct gfs2_quota_data *qd) +{ +return (2 * (u64 )qd->qd_id) + +test_bit (QDF_USER , &qd->qd_flags) ?0 :1 ; +} +static u64 qd2offset (struct gfs2_quota_data *qd) {u64 offset; - offset =2 * (u64 )qd->qd_id + !test_bit (QDF_USER , &qd->qd_flags); + offset =qd2index (qd); offset *=sizeof (struct gfs2_quota );return offset;
@@ -147,7 +153,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, qd->qd_slot =-1 ;INIT_LIST_HEAD (&qd->qd_reclaim); - error =gfs2_glock_get (sdp,2 * (u64 )id + !user, + error =gfs2_glock_get (sdp,qd2index (qd), &gfs2_quota_glops,CREATE , &qd->qd_gl);if (error) goto fail;
Signature · 1 line
1.7.5.4
PATCH 31/85 gfs2: Modify struct gfs2_quota_change_host to use struct kqid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/gfs2/quota.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)
fs/gfs2/quota.c +5 -3
@@ -71,7 +71,7 @@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);
@@ -1200,7 +1200,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)
@@ -1264,7 +1266,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)continue ; error =qd_alloc (sdp, (qc.qc_flags &GFS2_QCF_USER ), - qc.qc_id, &qd); +from_kqid (&init_user_ns, qc.qc_id), &qd);if (error) {brelse (bh); goto fail;
Signature · 1 line
1.7.5.4
PATCH 32/85 gfs2: Modify qdsb_get to take a struct kqid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/gfs2/quota.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
fs/gfs2/quota.c +7 -6
@@ -464,12 +464,13 @@ 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.type ==USRQUOTA ?QUOTA_USER :QUOTA_GROUP , +from_kqid (&init_user_ns, qid), qdp);if (error)return error;
@@ -518,20 +519,20 @@ 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_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { - error =qdsb_get (sdp,QUOTA_USER , uid, qd); + error =qdsb_get (sdp,make_kqid_uid (uid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++;
@@ -539,7 +540,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) }if (gid !=NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { - error =qdsb_get (sdp,QUOTA_GROUP , gid, qd); + error =qdsb_get (sdp,make_kqid_gid (gid), qd);if (error) goto out; ip->i_res->rs_qa_qd_num++;
Signature · 1 line
1.7.5.4
PATCH 33/85 gfs2: Convert gfs2_quota_refresh to take a kqid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- In quota_refresh_user_store convert the user supplied uid into a kqid and pass it to gfs2_quota_refresh.
- In quota_refresh_group_store convert the user supplied gid into a kqid and pass it to gfs2_quota_refresh.
--- fs/gfs2/quota.c | 5 +++-- fs/gfs2/quota.h | 2 +- fs/gfs2/sys.c | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-)
fs/gfs2/quota.c +3 -2
@@ -1177,13 +1177,14 @@ 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.type ==USRQUOTA ?QUOTA_USER :QUOTA_GROUP , +from_kqid (&init_user_ns, qid), &qd);if (error)return error;
fs/gfs2/quota.h +1 -1
@@ -28,7 +28,7 @@ extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, u32 uid, u32 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);
fs/gfs2/sys.c +12 -2
@@ -175,6 +175,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,static ssize_t quota_refresh_user_store (struct gfs2_sbd *sdp,const char *buf,size_t len) { +struct kqid qid;int error;u32 id;
@@ -183,13 +184,18 @@ 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 (current_user_ns (),USRQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }static ssize_t quota_refresh_group_store (struct gfs2_sbd *sdp,const char *buf,size_t len) { +struct kqid qid;int error;u32 id;
@@ -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 (current_user_ns (),GRPQUOTA , id); +if (!qid_valid (qid)) +return -EINVAL ; + + error =gfs2_quota_refresh (sdp, qid);return error ? error : len; }
Signature · 1 line
1.7.5.4
PATCH 34/85 gfs2: Store qd_id in struct gfs2_quota_data as a struct kqid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Change qd_id in struct gfs2_qutoa_data to struct kqid.
- Remove the now unnecessary QDF_USER bit field in qd_flags.
- Propopoage this change through the code generally making things simpler along the way.
--- fs/gfs2/incore.h | 3 +- fs/gfs2/quota.c | 69 +++++++++++++++++++---------------------------------- 2 files changed, 26 insertions(+), 46 deletions(-)
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/quota.c +25 -44
180 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH 35/85 gfs2: Remove the QUOTA_USER and QUOTA_GROUP defines
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Remove the QUOTA_USER and QUOTA_GRUP defines. Remove the last vestigal users of QUOTA_USER and QUOTA_GROUP.
Now that struct kqid is used throughout the gfs2 quota code the need there is to use QUOTA_USER and QUOTA_GROUP and the defines are just extraneous and confusing.
--- fs/gfs2/quota.c | 25 +++++-------------------- 1 files changed, 5 insertions(+), 20 deletions(-)
fs/gfs2/quota.c +5 -20
@@ -65,9 +65,6 @@#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_... */
@@ -1476,18 +1473,14 @@ 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, qid, &qd);
@@ -1499,7 +1492,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; fdq->d_version =FS_DQUOT_VERSION ; - fdq->d_flags = (type ==QUOTA_USER ) ?FS_USER_QUOTA :FS_GROUP_QUOTA ; + 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;
@@ -1526,21 +1519,13 @@ 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 ; -break ; -case GRPQUOTA : - type =QUOTA_GROUP ; -break ; -default : +if ((qid.type !=USRQUOTA ) && + (qid.type !=GRPQUOTA ))return -EINVAL ; - }if (fdq->d_fieldmask & ~GFS2_FIELDMASK )return -EINVAL ;
Signature · 1 line
1.7.5.4
PATCH 36/85 gfs2: Use kuid_t and kgid_t types where appropriate.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/gfs2/inode.c | 3 ++- fs/gfs2/quota.c | 8 ++++---- fs/gfs2/quota.h | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-)
fs/gfs2/inode.c +2 -1
@@ -1580,7 +1580,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;
fs/gfs2/quota.c +4 -4
@@ -492,7 +492,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;
@@ -918,7 +918,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;
@@ -1039,7 +1039,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type)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;
@@ -1088,7 +1088,7 @@ 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;
fs/gfs2/quota.h +4 -4
@@ -17,15 +17,15 @@ struct shrink_control;#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,struct kqid qid);
Signature · 1 line
1.7.5.4
PATCH 37/85 gfs2: Use uid_eq and gid_eq where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Where kuid_t values are compared use uid_eq and where kgid_t values are compared use gid_eq. This is unfortunately necessary because of the type safety that keeps someone from accidentally mixing kuids and kgids with other types.
--- fs/gfs2/acl.c | 2 +- fs/gfs2/inode.c | 19 +++++++++++-------- fs/gfs2/quota.c | 6 ++++-- 3 files changed, 16 insertions(+), 11 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/inode.c +11 -8
@@ -368,10 +368,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip, struct inode *inode) {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 ) && + !uid_eq (dip->i_inode.i_uid,GLOBAL_ROOT_UID )) {if (S_ISDIR (inode->i_mode)) inode->i_mode |=S_ISUID ; -else if (dip->i_inode.i_uid !=current_fsuid ()) +else if (!uid_eq (dip->i_inode.i_uid,current_fsuid ())) inode->i_mode &= ~07111 ; inode->i_uid = dip->i_inode.i_uid; }else
@@ -978,8 +979,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))
@@ -1589,16 +1590,17 @@ 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) +if (!(attr->ia_valid &ATTR_UID ) ||uid_eq (ouid, nuid)) ouid = nuid =NO_UID_QUOTA_CHANGE ; -if (!(attr->ia_valid &ATTR_GID ) || ogid == ngid) +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_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) { +if (!uid_eq (ouid,NO_UID_QUOTA_CHANGE ) || + !gid_eq (ogid,NO_GID_QUOTA_CHANGE )) { error =gfs2_quota_check (ip, nuid, ngid);if (error) goto out_gunlock_q;
@@ -1612,7 +1614,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)if (error) goto out_end_trans; -if (ouid !=NO_UID_QUOTA_CHANGE || ogid !=NO_GID_QUOTA_CHANGE ) { +if (!uid_eq (ouid,NO_UID_QUOTA_CHANGE ) || + !gid_eq (ogid,NO_GID_QUOTA_CHANGE )) {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 +4 -2
@@ -525,7 +525,8 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) ip->i_res->rs_qa_qd_num++; qd++; -if (uid !=NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { +if (!uid_eq (uid,NO_UID_QUOTA_CHANGE ) && + !uid_eq (uid, ip->i_inode.i_uid)) { error =qdsb_get (sdp,make_kqid_uid (uid), qd);if (error) goto out;
@@ -533,7 +534,8 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) qd++; } -if (gid !=NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { +if (!gid_eq (gid,NO_GID_QUOTA_CHANGE ) && + !gid_eq (gid, ip->i_inode.i_gid)) { error =qdsb_get (sdp,make_kqid_gid (gid), qd);if (error) goto out;
Signature · 1 line
1.7.5.4
PATCH 38/85 gfs2: Convert uids and gids between dinodes and vfs inodes.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading dinodes from the disk convert uids and gids into kuids and kgids to store in vfs data structures.
When writing to dinodes to the disk convert kuids and kgids in the in memory structures into plain uids and gids.
For now all on disk data structures are assumed to be stored in the initial user namespace.
--- fs/gfs2/glops.c | 4 ++-- fs/gfs2/inode.c | 4 ++-- fs/gfs2/super.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
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/inode.c +2 -2
@@ -456,8 +456,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip, di->di_num.no_formal_ino =cpu_to_be64 (ip->i_no_formal_ino); di->di_num.no_addr =cpu_to_be64 (ip->i_no_addr); di->di_mode =cpu_to_be32 (ip->i_inode.i_mode); - di->di_uid =cpu_to_be32 (ip->i_inode.i_uid); - di->di_gid =cpu_to_be32 (ip->i_inode.i_gid); + di->di_uid =cpu_to_be32 (i_uid_read (&ip->i_inode)); + di->di_gid =cpu_to_be32 (i_gid_read (&ip->i_inode)); di->di_nlink =0 ; di->di_size =cpu_to_be64 (ip->i_inode.i_size); di->di_blocks =cpu_to_be64 (1 );
fs/gfs2/super.c +2 -2
@@ -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));
Signature · 1 line
1.7.5.4
PATCH 39/85 gfs2: Enable building with user namespaces enabled
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Now that all of the necessary work has been done to push kuids and kgids throughout gfs2 and to convert between kuids and kgids when reading and writing the on disk structures it is safe to enable gfs2 when multiple user namespaces are enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - 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
PATCH 40/85 ncpfs: Support interacting with multiple user namespaces
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
ncpfs does not natively support uids and gids so this conversion was simply a matter of updating the the type of the mounteduid, the uid and the gid on the superblock. Fixing the ioctls that read them, updating the mount option parser and the mount option printer.
--- 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
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - depends on NCP_FS = n depends on NFSD = n depends on NFS_FS = n depends on XFS_FS = n
Signature · 1 line
1.7.5.4
PATCH 41/85 nfs_common: Update the translation between nfsv3 acls linux posix acls
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Use kuid_t and kgit in struct nfsacl_encode_desc.
- Convert from kuids and kgids when generating on the wire values.
- Convert on the wire values to kuids and kgids when read.
- Modify cmp_acl_entry to be type safe comparison on posix acls. Only acls with type ACL_USER and ACL_GROUP can appear more than once and as such need to compare more than their tag.
- The e_id field is being removed from posix acls so don't initialize it.
--- fs/nfs_common/nfsacl.c | 41 ++++++++++++++++++++++++++--------------- 1 files changed, 26 insertions(+), 15 deletions(-)
fs/nfs_common/nfsacl.c +26 -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,22 @@ 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); +if (!uid_valid (entry->e_uid)) +return -EINVAL ; +break ;case ACL_GROUP : + entry->e_gid =make_kgid (&init_user_ns, id); +if (!gid_valid (entry->e_gid)) +return -EINVAL ; +break ; +case ACL_USER_OBJ : +case ACL_GROUP_OBJ :case ACL_OTHER :if (entry->e_perm & ~S_IRWXO )return -EINVAL ;
@@ -190,9 +201,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 +228,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 ; } }
Signature · 1 line
1.7.5.4
PATCH 42/85 sunrpc: Use userns friendly constants.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Instead of (uid_t)0 use GLOBAL_ROOT_UID.
Instead of (gid_t)0 use GLOBAL_ROOT_GID.
Instead of (uid_t)-1 use INVALID_UID
Instead of (gid_t)-1 use INVALID_GID.
Instead of NOGROUP use INVALID_GID.
--- net/sunrpc/auth.c | 4 ++-- net/sunrpc/auth_generic.c | 4 ++-- net/sunrpc/auth_unix.c | 6 +++--- net/sunrpc/svcauth_unix.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-)
net/sunrpc/auth.c +2 -2
@@ -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 +2 -2
@@ -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;
net/sunrpc/auth_unix.c +3 -3
@@ -85,7 +85,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) cred->uc_gids[i] = gid; }if (i <NFS_NGROUPS ) - cred->uc_gids[i] =NOGROUP ; + cred->uc_gids[i] =INVALID_GID ;return &cred->uc_base; }
@@ -137,7 +137,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)return 0 ; }if (groups <NFS_NGROUPS && - cred->uc_gids[groups] !=NOGROUP ) + cred->uc_gids[groups] !=INVALID_GID )return 0 ;return 1 ; }
@@ -166,7 +166,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) *p++ =htonl ((u32 ) cred->uc_uid); *p++ =htonl ((u32 ) cred->uc_gid); hold = p++; -for (i =0 ; i <16 && cred->uc_gids[i] != (gid_t )NOGROUP ; i++) +for (i =0 ; i <16 && cred->uc_gids[i] !=INVALID_GID ; i++) *p++ =htonl ((u32 ) 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 +2 -2
@@ -750,8 +750,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 */
Signature · 1 line
1.7.5.4
PATCH 43/85 sunrpc: Use kuid_t and kgid_t where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Convert variables that store uids and gids to be of type kuid_t and kgid_t instead of type uid_t and gid_t.
--- include/linux/sunrpc/auth.h | 7 ++++--- include/linux/sunrpc/svcauth.h | 4 ++-- net/sunrpc/auth_gss/auth_gss.c | 8 ++++---- net/sunrpc/auth_unix.c | 4 ++-- net/sunrpc/svcauth_unix.c | 8 ++++---- 5 files changed, 16 insertions(+), 15 deletions(-)
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 */
net/sunrpc/auth_gss/auth_gss.c +4 -4
@@ -256,7 +256,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;
@@ -303,7 +303,7 @@ 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) {
@@ -445,7 +445,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;
@@ -475,7 +475,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))
net/sunrpc/auth_unix.c +2 -2
@@ -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
net/sunrpc/svcauth_unix.c +4 -4
@@ -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; };
@@ -475,7 +475,7 @@ 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)
@@ -615,7 +615,7 @@ 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;
@@ -628,7 +628,7 @@ static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid)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;
Signature · 1 line
1.7.5.4
PATCH 44/85 sunrpc: Use uid_eq and gid_eq where appropriate
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When comparing uids use uid_eq instead of ==.
When comparing gids use gid_eq instead of ==.
And unfortunate cost of type safety.
--- net/sunrpc/auth_generic.c | 8 ++++---- net/sunrpc/auth_gss/auth_gss.c | 4 ++-- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/svcauth_unix.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-)
net/sunrpc/auth_generic.c +4 -4
@@ -129,8 +129,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 +147,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 +2 -2
@@ -307,7 +307,7 @@ __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);
@@ -1115,7 +1115,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_unix.c +1 -1
@@ -123,7 +123,7 @@ 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 )
net/sunrpc/svcauth_unix.c +1 -1
@@ -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) {
Signature · 1 line
1.7.5.4
PATCH 45/85 sunrpc: Simplify auth_unix now that everything is a kgid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
In unx_create_cred directly assign gids from acred->group_info to cred->uc_gids.
In unx_match directly compare uc_gids with group_info.
Now that both group_info and unx_cred gids are stored as kgids this is valid and the extra layer of translation can be removed.
--- net/sunrpc/auth_unix.c | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-)
net/sunrpc/auth_unix.c +4 -10
@@ -79,11 +79,8 @@ 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] =INVALID_GID ;
@@ -130,12 +127,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) 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] !=INVALID_GID )return 0 ;
Signature · 1 line
1.7.5.4
PATCH 46/85 sunrpc: Convert kuids and kgids to uids and gids for printing
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When printing kuids and kgids for debugging purpropses convert them to ordinary integers so their values can be fed to the oridnary print functions.
--- net/sunrpc/auth_generic.c | 4 +++- net/sunrpc/auth_gss/auth_gss.c | 13 ++++++++----- net/sunrpc/auth_unix.c | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-)
net/sunrpc/auth_generic.c +3 -1
@@ -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; }
net/sunrpc/auth_gss/auth_gss.c +8 -5
@@ -517,7 +517,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
@@ -549,7 +549,8 @@ 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; }
@@ -562,7 +563,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 ) {
@@ -604,7 +606,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; }
@@ -1059,7 +1061,8 @@ 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;
net/sunrpc/auth_unix.c +2 -1
@@ -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 );
Signature · 1 line
1.7.5.4
PATCH 47/85 sunrpc: Use gid_valid to test for gid != INVALID_GID
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In auth unix there are a couple of places INVALID_GID is used a sentinel to mark the end of uc_gids array. Use gid_valid as a type safe way to verify we have not hit the end of valid data in the array.
--- net/sunrpc/auth_unix.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
net/sunrpc/auth_unix.c +2 -3
@@ -131,8 +131,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)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] !=INVALID_GID ) +if (groups <NFS_NGROUPS &&gid_valid (cred->uc_gids[groups]))return 0 ;return 1 ; }
@@ -161,7 +160,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) *p++ =htonl ((u32 ) cred->uc_uid); *p++ =htonl ((u32 ) cred->uc_gid); hold = p++; -for (i =0 ; i <16 && cred->uc_gids[i] !=INVALID_GID ; i++) +for (i =0 ; i <16 &&gid_valid (cred->uc_gids[i]); i++) *p++ =htonl ((u32 ) cred->uc_gids[i]); *hold =htonl (p - hold -1 );/* gid array length */ *base =htonl ((p - base -1 ) <<2 );/* cred length */
Signature · 1 line
1.7.5.4
PATCH 48/85 sunrpc: Update gss uid to security context mapping.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use from_kuid when generating the on the wire uid values.
- Use make_kuid when reading on the wire values.
In gss_encode_v0_msg, since the uid in gss_upcall_msg is now a kuid_t generate the necessary uid_t value on the stack copy it into gss_msg->databuf where it can safely live until the message is no longer needed.
--- net/sunrpc/auth_gss/auth_gss.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)
net/sunrpc/auth_gss/auth_gss.c +15 -5
@@ -395,8 +395,11 @@ gss_upcall_callback(struct rpc_task *task)static void gss_encode_v0_msg (struct gss_upcall_msg *gss_msg) { - gss_msg->msg.data = &gss_msg->uid; - gss_msg->msg.len =sizeof (gss_msg->uid); +uid_t uid =from_kuid (&init_user_ns, gss_msg->uid); +memcpy (gss_msg->databuf, &uid,sizeof (uid)); + gss_msg->msg.data = gss_msg->databuf; + gss_msg->msg.len =sizeof (uid); +BUG_ON (sizeof (uid) >UPCALL_BUF_LEN ); } static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
@@ -409,7 +412,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);
@@ -620,7 +623,8 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)struct gss_upcall_msg *gss_msg;struct rpc_pipe *pipe =RPC_I (filp->f_dentry->d_inode)->pipe;struct gss_cl_ctx *ctx; -uid_t uid; +uid_t id; +kuid_t uid;ssize_t err = -EFBIG ;if (mlen >MSG_BUF_MAXSIZE )
@@ -635,12 +639,18 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) goto err; end = (const void *)((char *)buf + mlen); - p =simple_get_bytes (buf, end, &uid,sizeof (uid)); + p =simple_get_bytes (buf, end, &id,sizeof (id));if (IS_ERR (p)) { err =PTR_ERR (p); goto err; } + uid =make_kuid (&init_user_ns, id); +if (!uid_valid (uid)) { + err = -EINVAL ; + goto err; + } + err = -ENOMEM ; ctx =gss_alloc_context ();if (ctx ==NULL )
Signature · 1 line
1.7.5.4
Re: [PATCH review 48/85] sunrpc: Update gss uid to security context mapping.
Quoted 9 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use
from_kuidwhen generating the on the wire uid values.
- Usemake_kuidwhen reading on the wire values.In
gss_encode_v0_msg, since the uid ingss_upcall_msgis now akuid_tgenerate the necessaryuid_tvalue on the stack copy it intogss_msg->databufwhere it can safely live until the message is no longer needed.
Apologies, I haven't been following the user namespace work.
If I understand correctly, you're expecting the id's seen in nfs protocol messages to be the same as the id's seen in the initial user namespace.
Why is that right, and not, say, the user namespace in which the mount was originally performed? (Just asking, I honestly haven't thought about it before.)
Also:
Quoted 5 lines
net/sunrpc/auth_gss/auth_gss.c +0
-0
net/sunrpc/auth_gss/auth_gss.c gss_upcall_callback(struct rpc_task *task) · line 402
Quoted 10 lines
net/sunrpc/auth_gss/auth_gss.c +5
-2@@ -395,8 +395,11 @@ gss_upcall_callback(struct rpc_task *task)static void gss_encode_v0_msg (struct gss_upcall_msg *gss_msg) { - gss_msg->msg.data = &gss_msg->uid; - gss_msg->msg.len =sizeof (gss_msg->uid); +uid_t uid =from_kuid (&init_user_ns, gss_msg->uid); +memcpy (gss_msg->databuf, &uid,sizeof (uid)); + gss_msg->msg.data = gss_msg->databuf; + gss_msg->msg.len =sizeof (uid); +BUG_ON (sizeof (uid) >UPCALL_BUF_LEN );
This message is going to gssd, not to the server. Should it be encoded for whatever namespace gssd lives in?
--b.
Quoted 45 lines
net/sunrpc/auth_gss/auth_gss.c +10
-3} static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,@@ -409,7 +412,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);@@ -620,7 +623,8 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)struct gss_upcall_msg *gss_msg;struct rpc_pipe *pipe =RPC_I (filp->f_dentry->d_inode)->pipe;struct gss_cl_ctx *ctx; -uid_t uid; +uid_t id; +kuid_t uid;ssize_t err = -EFBIG ;if (mlen >MSG_BUF_MAXSIZE )@@ -635,12 +639,18 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) goto err; end = (const void *)((char *)buf + mlen); - p =simple_get_bytes (buf, end, &uid,sizeof (uid)); + p =simple_get_bytes (buf, end, &id,sizeof (id));if (IS_ERR (p)) { err =PTR_ERR (p); goto err; } + uid =make_kuid (&init_user_ns, id); +if (!uid_valid (uid)) { + err = -EINVAL ; + goto err; + } + err = -ENOMEM ; ctx =gss_alloc_context ();if (ctx ==NULL )Signature · 1 line
1.7.5.4
Re: [PATCH review 48/85] sunrpc: Update gss uid to security context mapping.
Quoted 13 lines · J. Bruce Fields
Quoted 9 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use
from_kuidwhen generating the on the wire uid values.
- Usemake_kuidwhen reading on the wire values.In
gss_encode_v0_msg, since the uid ingss_upcall_msgis now akuid_tgenerate the necessaryuid_tvalue on the stack copy it intogss_msg->databufwhere it can safely live until the message is no longer needed.Apologies, I haven't been following the user namespace work.
Quoted 7 lines
If I understand correctly, you're expecting the id's seen in nfs protocol messages to be the same as the id's seen in the initial user namespace.
Why is that right, and not, say, the user namespace in which the mount was originally performed? (Just asking, I honestly haven't thought about it before.)
Actually my expectation is the user namespace was originally performed in. Currently nfs doesn't support being mounted in anything other than the initial user namespace.
Quoted 8 lines
Also:
Quoted 6 lines
net/sunrpc/auth_gss/auth_gss.c +0
-0@@ -395,8 +395,11 @@ gss_upcall_callback(struct rpc_task *task)
Quoted 12 lines
net/sunrpc/auth_gss/auth_gss.c gss_upcall_callback(struct rpc_task *task) · line 402
Quoted 9 lines
net/sunrpc/auth_gss/auth_gss.c +5
-2static void gss_encode_v0_msg (struct gss_upcall_msg *gss_msg) { - gss_msg->msg.data = &gss_msg->uid; - gss_msg->msg.len =sizeof (gss_msg->uid); +uid_t uid =from_kuid (&init_user_ns, gss_msg->uid); +memcpy (gss_msg->databuf, &uid,sizeof (uid)); + gss_msg->msg.data = gss_msg->databuf; + gss_msg->msg.len =sizeof (uid); +BUG_ON (sizeof (uid) >UPCALL_BUF_LEN );This message is going to gssd, not to the server. Should it be encoded for whatever namespace gssd lives in?
Good basic question. The immediate answer is that right now I only support these things living in user namespace the filesystem was mounted in, aka the initial user namespace.
There are a handful of things ioctls, and a quota call or two that I will translate into the callers user namespace. For network filesystems and their specialized helpers it would be lossy and unnecessarily complex to support arbitrary pieces living in different user namespaces. Historically unix has had syncrhonized password databases to ensure even multiple machines effectively had the same user namespace.
The really important step for me is to have the kernel using kuid_t and kgid_t throughout and only converting when talking outside of the kernel (disk, filesystem on disk data structures, network).
With that step I can enable user namespaces and the various filesystems. And even if the filesystem itself is restricted to just one user namespace, the users who read and write files on that filesystem won't be.
A next step for the filesystems where this is interesting is to support a user who is not the global root mounting the filesystem and having the filesystem speak in ids in the user namespace that the filesystem was mounted in. That takes a little bit of connecting the dots of which user namespace goes where, and it takes a little bit of confidence that the kernel won't fall over if an evil server sends us deliberately bad protocol messages. I suspect at some point someone will want to figure all of that out for nfs, certainly there has been work to figure that out for network namespaces.
For now though I am happy to have kuid_t and kgid_t pushed down everywhere they should be.
Eric
Re: [PATCH review 48/85] sunrpc: Update gss uid to security context mapping.
Quoted 78 lines · Eric W. Biederman
Quoted 13 lines · J. Bruce Fields
Quoted 9 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use
from_kuidwhen generating the on the wire uid values.
- Usemake_kuidwhen reading on the wire values.In
gss_encode_v0_msg, since the uid ingss_upcall_msgis now akuid_tgenerate the necessaryuid_tvalue on the stack copy it intogss_msg->databufwhere it can safely live until the message is no longer needed.Apologies, I haven't been following the user namespace work.
Quoted 7 lines
If I understand correctly, you're expecting the id's seen in nfs protocol messages to be the same as the id's seen in the initial user namespace.
Why is that right, and not, say, the user namespace in which the mount was originally performed? (Just asking, I honestly haven't thought about it before.)
Actually my expectation is the user namespace was originally performed in. Currently nfs doesn't support being mounted in anything other than the initial user namespace.
Quoted 8 lines
Also:
Quoted 6 lines
net/sunrpc/auth_gss/auth_gss.c +0
-0@@ -395,8 +395,11 @@ gss_upcall_callback(struct rpc_task *task)Quoted 12 lines
net/sunrpc/auth_gss/auth_gss.c gss_upcall_callback(struct rpc_task *task) · line 402
Quoted 9 lines
net/sunrpc/auth_gss/auth_gss.c +5
-2static void gss_encode_v0_msg (struct gss_upcall_msg *gss_msg) { - gss_msg->msg.data = &gss_msg->uid; - gss_msg->msg.len =sizeof (gss_msg->uid); +uid_t uid =from_kuid (&init_user_ns, gss_msg->uid); +memcpy (gss_msg->databuf, &uid,sizeof (uid)); + gss_msg->msg.data = gss_msg->databuf; + gss_msg->msg.len =sizeof (uid); +BUG_ON (sizeof (uid) >UPCALL_BUF_LEN );This message is going to gssd, not to the server. Should it be encoded for whatever namespace gssd lives in?
Good basic question. The immediate answer is that right now I only support these things living in user namespace the filesystem was mounted in, aka the initial user namespace.
There are a handful of things ioctls, and a quota call or two that I will translate into the callers user namespace. For network filesystems and their specialized helpers it would be lossy and unnecessarily complex to support arbitrary pieces living in different user namespaces. Historically unix has had syncrhonized password databases to ensure even multiple machines effectively had the same user namespace.
The really important step for me is to have the kernel using
kuid_tandkgid_tthroughout and only converting when talking outside of the kernel (disk, filesystem on disk data structures, network).With that step I can enable user namespaces and the various filesystems. And even if the filesystem itself is restricted to just one user namespace, the users who read and write files on that filesystem won't be.
A next step for the filesystems where this is interesting is to support a user who is not the global root mounting the filesystem and having the filesystem speak in ids in the user namespace that the filesystem was mounted in. That takes a little bit of connecting the dots of which user namespace goes where, and it takes a little bit of confidence that the kernel won't fall over if an evil server sends us deliberately bad protocol messages. I suspect at some point someone will want to figure all of that out for nfs, certainly there has been work to figure that out for network namespaces.
Quoted 2 lines
For now though I am happy to have
kuid_tandkgid_tpushed down everywhere they should be.
OK, makes sense, thanks for the explanation.--b.
PATCH 49/85 sunrpc: Update svcgss xdr handle to rpsec_contect cache
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
For each received uid call make_kuid and validate the result. For each received gid call make_kgid and validate the result.
--- net/sunrpc/auth_gss/svcauth_gss.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)
net/sunrpc/auth_gss/svcauth_gss.c +13 -5
@@ -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,7 @@ 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 == -EINVAL ) goto out;if (rv == -ENOENT )
@@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd,else {int N , i; +/* uid */ + rsci.cred.cr_uid =make_kuid (&init_user_ns, id); +if (!uid_valid (rsci.cred.cr_uid)) + goto out; +/* 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 */
@@ -467,11 +476,10 @@ static int rsc_parse(struct cache_detail *cd,/* gid's */ status = -EINVAL ;for (i=0 ; i<N ; i++) { -gid_t gid;kgid_t kgid; -if (get_int (&mesg, &gid)) +if (get_int (&mesg, &id)) goto out; - kgid =make_kgid (&init_user_ns, gid); + kgid =make_kgid (&init_user_ns, id);if (!gid_valid (kgid)) goto out;GROUP_AT (rsci.cred.cr_group_info, i) = kgid;
Signature · 1 line
1.7.5.4
Re: [PATCH review 49/85] sunrpc: Update svcgss xdr handle to rpsec_contect cache
Quoted 39 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
For each received uid call
make_kuidand validate the result. For each received gid callmake_kgidand validate the result.Cc "J. Bruce Fields" <[email protected]>Cc Trond Myklebust <[email protected]>--- net/sunrpc/auth_gss/svcauth_gss.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)net/sunrpc/auth_gss/svcauth_gss.c +4
-1@@ -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,7 @@ 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 == -EINVAL ) goto out;if (rv == -ENOENT )@@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd,else {int N , i; +/* uid */ + rsci.cred.cr_uid =make_kuid (&init_user_ns, id);
net/sunrpc/auth_gss/svcauth_gss.c static int rsc_parse(struct cache_detail *cd, · line 466
Quoted 10 lines
net/sunrpc/auth_gss/svcauth_gss.c +7
-1+if (!uid_valid (rsci.cred.cr_uid)) + goto out; +/* 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;
krb5 mounts started failing for me as of this patch (upstream as 683428fae8c73d7d7da0fa2e0b6beb4d8df4e808), and I believe the problem is these uid/gid_valid checks: if I recall correctly, gssd uses -1 uid/gid values to indicate "authentication succeeded, but treat this user as anonymous". We delay mapping -1 id's to the (configurable-per-export) anonymous id's till fs/nfsd/auth.c:nfsd_setuser():
if (uid_eq(new->fsuid, INVALID_UID)) new->fsuid = exp->ex_anon_uid; if (gid_eq(new->fsgid, INVALID_GID)) new->fsgid = exp->ex_anon_gid;
(We wouldn't be able to do that earlier because we don't know the export yet.)
Confirmed that the following fixes the regression.
Eric, any objection to removing those checks?
--b.
net/sunrpc/auth_gss/svcauth_gss.c +0 -4
@@ -449,15 +449,11 @@ static int rsc_parse(struct cache_detail *cd,/* uid */ rsci.cred.cr_uid =make_kuid (&init_user_ns, id); -if (!uid_valid (rsci.cred.cr_uid)) - goto out;/* 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 */ if (get_int (&mesg, &N ))
Re: [PATCH review 49/85] sunrpc: Update svcgss xdr handle to rpsec_contect cache
Quoted 2 lines · J. Bruce Fields
krb5 mounts started failing for me as of this patch (upstream as
683428fae8c73d7d7da0fa2e0b6beb4d8df4e808),
Ouch!
Quoted 11 lines
and I believe the problem is
these uid/gid_valid checks: if I recall correctly, gssd uses -1 uid/gid values to indicate "authentication succeeded, but treat this user as anonymous". We delay mapping -1 id's to the (configurable-per-export) anonymous id's till fs/nfsd/auth.c:nfsd_setuser():if (uid_eq(new->fsuid, INVALID_UID)) new->fsuid = exp->ex_anon_uid; if (gid_eq(new->fsgid, INVALID_GID)) new->fsgid = exp->ex_anon_gid;
Quoted 6 lines
(We wouldn't be able to do that earlier because we don't know the export yet.)
Confirmed that the following fixes the regression.
Eric, any objection to removing those checks?
Not strongly. As long as we have the uid ang gid valid checks in there somewhere before we start using these uids and gids much. This does seems to be the case of using out of range uids and gids to mean out of range uids and gids.
In the description of my original patch before I split it up, I noted that one of the small dangers might be that I had added some possibly unneceessary uid and gid valid checks. So it seems I had even considered this slight possibility once and noted that there was a slight chance we might have to remove a few of these.
It would be nice to have a comment to say that we expect this to happen so people don't start wondering why there are missing checks on this path.
There is also a gid_valid check in the secondary uids. It looks like we should keep that as we don't have any checks for invalid gids in nfsd_setuser. Is that possibly an oversight in nfsd_setuser?
Also looking towards a future in which all of these things don't reside in the initial user namespace. Is mapping any out of range uid to INVALID_UID and then into ex_anon_uid the always the right thing to do?
Or is -1 a very special case in this instance. In which case we probably want checks that look like:
if (-1 == id) {
rsci.cred.cr_uid = INVALID_UID;
} else {
rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
if (!uid_valid(rsci.cred.cr_uid))
goto out;
}Eric
Quoted 20 lines
net/sunrpc/auth_gss/svcauth_gss.c +0
-4@@ -449,15 +449,11 @@ static int rsc_parse(struct cache_detail *cd,/* uid */ rsci.cred.cr_uid =make_kuid (&init_user_ns, id); -if (!uid_valid (rsci.cred.cr_uid)) - goto out;/* 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 */ if (get_int (&mesg, &N ))
Re: [PATCH review 49/85] sunrpc: Update svcgss xdr handle to rpsec_contect cache
Quoted 31 lines · Eric W. Biederman
Quoted 2 lines · J. Bruce Fields
krb5 mounts started failing for me as of this patch (upstream as
683428fae8c73d7d7da0fa2e0b6beb4d8df4e808),Ouch!
Quoted 11 lines
and I believe the problem is
these uid/gid_valid checks: if I recall correctly, gssd uses -1 uid/gid values to indicate "authentication succeeded, but treat this user as anonymous". We delay mapping -1 id's to the (configurable-per-export) anonymous id's till fs/nfsd/auth.c:nfsd_setuser():if (uid_eq(new->fsuid, INVALID_UID)) new->fsuid = exp->ex_anon_uid; if (gid_eq(new->fsgid, INVALID_GID)) new->fsgid = exp->ex_anon_gid;Quoted 6 lines
(We wouldn't be able to do that earlier because we don't know the export yet.)
Confirmed that the following fixes the regression.
Eric, any objection to removing those checks?
Not strongly. As long as we have the uid ang gid valid checks in there somewhere before we start using these uids and gids much. This does seems to be the case of using out of range uids and gids to mean out of range uids and gids.
Quoted 5 lines
In the description of my original patch before I split it up, I noted that one of the small dangers might be that I had added some possibly unneceessary uid and gid valid checks. So it seems I had even considered this slight possibility once and noted that there was a slight chance we might have to remove a few of these.
Ah, I should have seen that and checked that, my bad.
Quoted 3 lines
It would be nice to have a comment to say that we expect this to happen so people don't start wondering why there are missing checks on this path.
OK--something like the appended?
Quoted 3 lines
There is also a
gid_validcheck in the secondary uids. It looks like we should keep that as we don't have any checks for invalid gids innfsd_setuser. Is that possibly an oversight innfsd_setuser?
Honestly I don't think anyone's thought that through....
But it would seem odd to pass down an "anonymous" supplementary gid--why not just leave it off the list instead?
(BTW, dumb question: is it legal for userspace to use a uid -1? And was it illegal before the user namespace patches?)
Quoted 6 lines
Also looking towards a future in which all of these things don't reside in the initial user namespace. Is mapping any out of range uid to
INVALID_UIDand then intoex_anon_uidthe always the right thing to do?Or is -1 a very special case in this instance. In which case we probably want checks that look like:
svcgssd should pass down either -1 or a valid uid, so I don't think we're committed to any particular handling of invalid id's other than -1--whatever's easiest.
--b.
commit d78f5cd062edb400190521e9540b042b4805875b
Author: J. Bruce Fields <[email protected]> Date: Mon Mar 4 08:44:01 2013 -0500
nfsd: fix krb5 handling of anonymous principals
krb5 mounts started failing as of 683428fae8c73d7d7da0fa2e0b6beb4d8df4e808 "sunrpc: Update svcgss xdr handle to rpsec_contect cache".
The problem is that mounts are usually done with some host principal which isn't normally mapped to any user, in which case svcgssd passes down uid -1, which the kernel is then expected to map to the export-specific anonymous uid or gid.
The new uid_valid/gid_valid checks were therefore causing that downcall to fail.
(Note the regression may not have been seen with older userspace that tended to map unknown principals to an anonymous id on their own rather than leaving it to the kernel.)
net/sunrpc/auth_gss/svcauth_gss.c +8 -4
@@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,else {int N , i; +/* +* NOTE: we don't check uid_valid() or gid_valid(): instead, +* -1 id's are later mapped to the (export-specific) +* anonymous id by nfsd_setuser. +* +* (But supplementary gid's get no such special +* treatment so are checked for validity here.) +*/ /* uid */ rsci.cred.cr_uid =make_kuid (&init_user_ns, id); -if (!uid_valid (rsci.cred.cr_uid)) - goto out;/* 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 */ if (get_int (&mesg, &N ))
Eric W. Biederman
Reviewed-byRe: [PATCH review 49/85] sunrpc: Update svcgss xdr handle to rpsec_contect cache
Quoted 9 lines · J. Bruce Fields
Quoted 8 lines · Eric W. Biederman
"J. Bruce Fields" <[email protected]> writes:
Not strongly. As long as we have the uid ang gid valid checks in there somewhere before we start using these uids and gids much. This does seems to be the case of using out of range uids and gids to mean out of range uids and gids.
Quoted 7 lines
Quoted 5 lines
In the description of my original patch before I split it up, I noted that one of the small dangers might be that I had added some possibly unneceessary uid and gid valid checks. So it seems I had even considered this slight possibility once and noted that there was a slight chance we might have to remove a few of these.
Ah, I should have seen that and checked that, my bad.
I think that text was lost when I split my nfs patch into all of those patches so I don't expect you ever saw that text.
Quoted 5 lines
Quoted 3 lines
It would be nice to have a comment to say that we expect this to happen so people don't start wondering why there are missing checks on this path.
OK--something like the appended?
It looks good to me.
Quoted 5 lines
Quoted 3 lines
There is also a
gid_validcheck in the secondary uids. It looks like we should keep that as we don't have any checks for invalid gids innfsd_setuser. Is that possibly an oversight innfsd_setuser?Honestly I don't think anyone's thought that through....
I try and take these moments of that's weird to spark the thinking of things through. Just in case there is something important was overlooked.
Quoted 2 lines
But it would seem odd to pass down an "anonymous" supplementary gid--why not just leave it off the list instead?
True.
Quoted 2 lines
(BTW, dumb question: is it legal for userspace to use a uid -1? And was it illegal before the user namespace patches?)
It is now impossible and thus illegal for userspace to use a uid value of -1. Previously to use a uid of -1 you had to jump through hoops as some system calls would allow it (setuid) and some system calls special cased the value of -1 (setresuid). Which mean using a uid value of -1 was while possible but a bad idea because various things would break in strange ways.
Quoted 10 lines
Quoted 6 lines
Also looking towards a future in which all of these things don't reside in the initial user namespace. Is mapping any out of range uid to
INVALID_UIDand then intoex_anon_uidthe always the right thing to do?Or is -1 a very special case in this instance. In which case we probably want checks that look like:
svcgssd should pass down either -1 or a valid uid, so I don't think we're committed to any particular handling of invalid id's other than -1--whatever's easiest.
Sounds good. I won't worry about them in future development then.
Quoted 15 lines
commit
d78f5cd062edb400190521e9540b042b4805875bAuthor: J. Bruce Fields <[email protected]> Date: Mon Mar 4 08:44:01 2013 -0500nfsd: fix krb5 handling of anonymous principals
krb5 mounts started failing as of
683428fae8c73d7d7da0fa2e0b6beb4d8df4e808"sunrpc: Update svcgss xdr handle torpsec_contectcache".The problem is that mounts are usually done with some host principal which isn't normally mapped to any user, in which case svcgssd passes down uid -1, which the kernel is then expected to map to the export-specific anonymous uid or gid.
Quoted 8 lines
The new uid_valid/gid_valid checks were therefore causing that downcall to fail.
(Note the regression may not have been seen with older userspace that tended to map unknown principals to an anonymous id on their own rather than leaving it to the kernel.)
Signed-off-by J. Bruce Fields <[email protected]>
Quoted 30 lines
net/sunrpc/auth_gss/svcauth_gss.c +8
-4@@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,else {int N , i; +/* +* NOTE: we don't check uid_valid() or gid_valid(): instead, +* -1 id's are later mapped to the (export-specific) +* anonymous id by nfsd_setuser. +* +* (But supplementary gid's get no such special +* treatment so are checked for validity here.) +*/ /* uid */ rsci.cred.cr_uid =make_kuid (&init_user_ns, id); -if (!uid_valid (rsci.cred.cr_uid)) - goto out;/* 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 */ if (get_int (&mesg, &N ))
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH review 49/85] sunrpc: Update svcgss xdr handle to rpsec_contect cache
Quoted 2 lines · J. Bruce Fields
krb5 mounts started failing for me as of this patch (upstream as
683428fae8c73d7d7da0fa2e0b6beb4d8df4e808),
Ouch!
Quoted 11 lines
and I believe the problem is
these uid/gid_valid checks: if I recall correctly, gssd uses -1 uid/gid values to indicate "authentication succeeded, but treat this user as anonymous". We delay mapping -1 id's to the (configurable-per-export) anonymous id's till fs/nfsd/auth.c:nfsd_setuser():if (uid_eq(new->fsuid, INVALID_UID)) new->fsuid = exp->ex_anon_uid; if (gid_eq(new->fsgid, INVALID_GID)) new->fsgid = exp->ex_anon_gid;
Quoted 6 lines
(We wouldn't be able to do that earlier because we don't know the export yet.)
Confirmed that the following fixes the regression.
Eric, any objection to removing those checks?
Not strongly. As long as we have the uid ang gid valid checks in there somewhere before we start using these uids and gids much. This does seems to be the case of using out of range uids and gids to mean out of range uids and gids.
In the description of my original patch before I split it up, I noted that one of the small dangers might be that I had added some possibly unneceessary uid and gid valid checks. So it seems I had even considered this slight possibility once and noted that there was a slight chance we might have to remove a few of these.
It would be nice to have a comment to say that we expect this to happen so people don't start wondering why there are missing checks on this path.
There is also a gid_valid check in the secondary uids. It looks like we should keep that as we don't have any checks for invalid gids in nfsd_setuser. Is that possibly an oversight in nfsd_setuser?
Also looking towards a future in which all of these things don't reside in the initial user namespace. Is mapping any out of range uid to INVALID_UID and then into ex_anon_uid the always the right thing to do?
Or is -1 a very special case in this instance. In which case we probably want checks that look like:
if (-1 == id) {
rsci.cred.cr_uid = INVALID_UID;
} else {
rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
if (!uid_valid(rsci.cred.cr_uid))
goto out;
}Eric
Quoted 20 lines
net/sunrpc/auth_gss/svcauth_gss.c +0
-4@@ -449,15 +449,11 @@ static int rsc_parse(struct cache_detail *cd,/* uid */ rsci.cred.cr_uid =make_kuid (&init_user_ns, id); -if (!uid_valid (rsci.cred.cr_uid)) - goto out;/* 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 */ if (get_int (&mesg, &N ))
PATCH 50/85 sunrpc: Hash uids by first computing their value in the initial userns
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In svcauth_unix introduce a helper unix_gid_hash as otherwise the expresion to generate the hash value is just too long.
--- net/sunrpc/auth.c | 2 +- net/sunrpc/svcauth_unix.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-)
net/sunrpc/auth.c +1 -1
@@ -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) {
net/sunrpc/svcauth_unix.c +7 -2
@@ -419,6 +419,11 @@ struct unix_gid {struct group_info *gi; }; +static int unix_gid_hash (kuid_t uid) +{ +return hash_long (from_kuid (&init_user_ns, uid),GID_HASHBITS ); +} +static void unix_gid_put (struct kref *kref) { struct cache_head *item = container_of(kref, struct cache_head, ref);
@@ -530,7 +535,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 )); +unix_gid_hash (uid));if (!ch) err = -ENOMEM ;else {
@@ -621,7 +626,7 @@ static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)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,unix_gid_hash (uid));if (ch) return container_of(ch, struct unix_gid, h);else
Signature · 1 line
1.7.5.4
PATCH 51/85 sunrpc: Properly encode kuids and kgids in RPC_AUTH_UNIX credentials
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When writing kuids onto the wire first map them into the initial user namespace.
When writing kgids onto the wire first map them into the initial user namespace.
--- net/sunrpc/auth_unix.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
net/sunrpc/auth_unix.c +3 -3
@@ -157,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 &&gid_valid (cred->uc_gids[i]); i++) - *p++ =htonl ((u32 ) cred->uc_gids[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 */
Signature · 1 line
1.7.5.4
PATCH 52/85 sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through svc_process_common, and svc_set_client and down into svcauth_unix_set_client if it is of type RPC_AUTH_NULL or RPC_AUTH_UNIX.
svcauth_unix_set_client then looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
--- net/sunrpc/svcauth_unix.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)
net/sunrpc/svcauth_unix.c +9 -5
@@ -470,7 +470,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' ; }
@@ -486,7 +486,8 @@ 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;
@@ -498,9 +499,12 @@ 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);
@@ -554,7 +558,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 = &init_user_ns;struct unix_gid *ug;int i;int glen;
@@ -570,7 +574,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" );
Signature · 1 line
1.7.5.4
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.
Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
--b.
Quoted 66 lines
Cc "J. Bruce Fields" <[email protected]>Cc Trond Myklebust <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- net/sunrpc/svcauth_unix.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)net/sunrpc/svcauth_unix.c +9
-5@@ -470,7 +470,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' ; }@@ -486,7 +486,8 @@ 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;@@ -498,9 +499,12 @@ 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);@@ -554,7 +558,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 = &init_user_ns;struct unix_gid *ug;int i;int glen;@@ -570,7 +574,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" );Signature · 1 line
1.7.5.4
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that net->user_ns is what we want as it will be shared by all users in network namespace I presume.
Eric
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 44 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Quoted 8 lines
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.
Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
--b.
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes. net->user_ns is the user namespace the network namespace was created in. And it is the user namespace that is used in test like ns_capable(net->user_ns, CAP_NET_ADMIN) to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.
Could you double check my understanding of the code?
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace. But because they are mounts they are still limited to the initial user namespace.
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
lockd is started by either the nfs server or the nfs client.
There are no other sunrpc servers in the kernel.
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user)
return -ESORRY_CHARLEY;Eric
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 68 lines · Eric W. Biederman
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes.
net->user_nsis the user namespace the network namespace was created in. And it is the user namespace that is used in test likens_capable(net->user_ns, CAP_NET_ADMIN)to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.Could you double check my understanding of the code?
Quoted 7 lines
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace.
We're talking about the server side here, not the client, so I'm not sure what you mean by "nfs mounts". The nfs server does use various pseudofilesystems ("proc", "nfsd"), and those can be mounted outside the initial network namespace.
The server can receive rpc requests over network interfaces outside the initial network namespace, sure. The server doesn't perform mounts on behalf of clients, though, it just accesses previously mounted filesystems on clients' behalf.
Quoted 2 lines
But because they are mounts they are
still limited to the initial user namespace.
OK, so that's just a limitation on any mount whatsoever for now. I'm catching on, slowly, thanks!
Quoted 3 lines
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<[email protected]>
and followups. That should make it for 3.9, I just need to review them....
Quoted 4 lines
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
Yes.
Quoted 3 lines
lockd is started by either the nfs server or the nfs client.
There are no other sunrpc servers in the kernel.
There are a couple callback services on the NFS client--those should be associated with nfs mounts in some obvious way. There's a confusing ACL service that's really just an appendage of NFSv2/v3 service.
I think we're fine.
Quoted 6 lines
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user) return -ESORRY_CHARLEY;
I think you're right.
So for now it's safely confined to one user namespace, and I think we understand approximately what to do if we want to support nfsd's in user namespace in the future. (Mainly, make sure nfsd and proc can be mounted in them and then most things will be determined by the user_ns of the network namespace associated with a given rpc.)
--b.
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 74 lines · J. Bruce Fields
Quoted 73 lines · Eric W. Biederman
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes.
net->user_nsis the user namespace the network namespace was created in. And it is the user namespace that is used in test likens_capable(net->user_ns, CAP_NET_ADMIN)to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.Could you double check my understanding of the code?
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Quoted 7 lines
Quoted 2 lines
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace.
We're talking about the server side here, not the client, so I'm not sure what you mean by "nfs mounts". The nfs server does use various pseudofilesystems ("proc", "nfsd"), and those can be mounted outside the initial network namespace.
Actually I was seeing that nfs clients were starting lockd. So I was just reasoning here that anything that came from a nfs client was ultimately in the user namespace of that client, which is ultimately limited by the client out.
Quoted 4 lines
The server can receive rpc requests over network interfaces outside the initial network namespace, sure. The server doesn't perform mounts on behalf of clients, though, it just accesses previously mounted filesystems on clients' behalf.
But nfsd_init_socks only creates sockets in a single network namespace, and today we pass only &init_net.
Quoted 5 lines
Quoted 2 lines
But because they are mounts they are
still limited to the initial user namespace.OK, so that's just a limitation on any mount whatsoever for now. I'm catching on, slowly, thanks!
If you set in struct filesystem .fs_flags = FS_USERNS_MOUNT your filesystem can be mounted outside of the initial user namespace. But since that takes extra work and because unprivileged users are allowed to create user namespaces and perform the mounts by default it is off.
Quoted 8 lines
Quoted 3 lines
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<20130201125210.3257.46454.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]>
and followups. That should make it for 3.9, I just need to review them....
Ok that is interesting.
There is an interesting corner case here where an unprivileged user can create a user namespace and then can create a network namespace. Depending on how we interpret things when Stanislaves patches reach there we might have to add:
if (net->user_ns != &init_user_ns)
-EINVAL
Somewhere appropriate.
Quoted 9 lines
Quoted 4 lines
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
Yes.
Quoted 2 lines
lockd is started by either the nfs server or the nfs client.
Quoted 7 lines
Quoted 1 line
There are no other sunrpc servers in the kernel.
There are a couple callback services on the NFS client--those should be associated with nfs mounts in some obvious way. There's a confusing ACL service that's really just an appendage of NFSv2/v3 service.
I think we're fine.
Thanks.
Quoted 7 lines
Quoted 6 lines
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user) return -ESORRY_CHARLEY;
Quoted 7 lines
I think you're right.
So for now it's safely confined to one user namespace, and I think we understand approximately what to do if we want to support nfsd's in user namespace in the future. (Mainly, make sure nfsd and proc can be mounted in them and then most things will be determined by the
user_nsof the network namespace associated with a given rpc.)
For 3.9 the list of filesystems mountable outside the initial user namespace is: mqueuefs, tmpfs, ramfs, devpts, sysfs, and proc.
I am a touch concerned about /proc/fs/nfsd/exports after my patches and Stanislavs patches both come in. As I think that will allow for cases where net->user_ns != &init_userns. But we can cross that bridge when we come to it.
Eric
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
14.02.2013 03:22, Eric W. Biederman пишет:
Quoted 163 lines
Quoted 74 lines · J. Bruce Fields
Quoted 73 lines · Eric W. Biederman
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes.
net->user_nsis the user namespace the network namespace was created in. And it is the user namespace that is used in test likens_capable(net->user_ns, CAP_NET_ADMIN)to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.Could you double check my understanding of the code?
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Quoted 7 lines
Quoted 2 lines
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace.
We're talking about the server side here, not the client, so I'm not sure what you mean by "nfs mounts". The nfs server does use various pseudofilesystems ("proc", "nfsd"), and those can be mounted outside the initial network namespace.
Actually I was seeing that nfs clients were starting lockd. So I was just reasoning here that anything that came from a nfs client was ultimately in the user namespace of that client, which is ultimately limited by the client out.
Quoted 4 lines
The server can receive rpc requests over network interfaces outside the initial network namespace, sure. The server doesn't perform mounts on behalf of clients, though, it just accesses previously mounted filesystems on clients' behalf.
But
nfsd_init_socksonly creates sockets in a single network namespace, and today we pass only&init_net.Quoted 5 lines
Quoted 2 lines
But because they are mounts they are
still limited to the initial user namespace.OK, so that's just a limitation on any mount whatsoever for now. I'm catching on, slowly, thanks!
If you set in struct filesystem .fs_flags =
FS_USERNS_MOUNTyour filesystem can be mounted outside of the initial user namespace. But since that takes extra work and because unprivileged users are allowed to create user namespaces and perform the mounts by default it is off.Quoted 8 lines
Quoted 3 lines
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<[email protected]>
and followups. That should make it for 3.9, I just need to review them....Ok that is interesting.
There is an interesting corner case here where an unprivileged user can create a user namespace and then can create a network namespace. Depending on how we interpret things when Stanislaves patches reach there we might have to add:
if (
net->user_ns!=&init_user_ns)
-EINVALSomewhere appropriate.
Quoted 9 lines
Quoted 4 lines
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
Yes.
Quoted 2 lines
lockd is started by either the nfs server or the nfs client.
Quoted 7 lines
Quoted 1 line
There are no other sunrpc servers in the kernel.
There are a couple callback services on the NFS client--those should be associated with nfs mounts in some obvious way. There's a confusing ACL service that's really just an appendage of NFSv2/v3 service.
I think we're fine.
Thanks.
Quoted 7 lines
Quoted 6 lines
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user) return -ESORRY_CHARLEY;Quoted 7 lines
I think you're right.
So for now it's safely confined to one user namespace, and I think we understand approximately what to do if we want to support nfsd's in user namespace in the future. (Mainly, make sure nfsd and proc can be mounted in them and then most things will be determined by the
user_nsof the network namespace associated with a given rpc.)
Quoted 8 lines
For 3.9 the list of filesystems mountable outside the initial user namespace is: mqueuefs, tmpfs, ramfs, devpts, sysfs, and proc.
I am a touch concerned about
/proc/fs/nfsd/exportsafter my patches and Stanislavs patches both come in. As I think that will allow for cases wherenet->user_ns!=&init_userns. But we can cross that bridge when we come to it.
Hmmm...
Maybe I'm missing the point of user namespaces, but since NFS kernel server is controlled via NFSd file system write calls, maybe it would be better to add:
.fs_flags = FS_USERNS_MOUNT
to it and add check:
+ if (net->user_ns != current_user_ns())
+ return -EINVAL;
No?
Quoted 2 lines
Eric
Signature · 2 lines
Best regards, Stanislav Kinsbursky
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 13 lines · Stanislav Kinsbursky
14.02.2013 03:22, Eric W. Biederman пишет:
Hmmm...
Maybe I'm missing the point of user namespaces, but since NFS kernel server is controlled via NFSd file system write calls, maybe it would be better to add:.fs_flags =
FS_USERNS_MOUNTto it and add check:
(quoted diff) +2
-0+ if (net->user_ns != current_user_ns()) + return -EINVAL;
Quoted 1 line
No?
Not really. The immediate goal is to just use kuid_t and kgid_t instead of uid_t and gid_t throughout the kernel. That ensures someone hasn't missed a case and is getting a uid in one namespace confused with a uid in another. And that is needed to make it safe to enable nfs and nfsd support when user namespace support is enabled in the kernel.
So at the basic level I have made the assumption that all nfs activity happens in the initial user namespace and have made conversions to/from the initial user namespace throughout the nfs and nfsd code.
We can add FS_USERNS_MOUNT when we are ready to support running in multiple user namespaces. For now not allowing mounts outside of the initial user namespace ensures that the nfs client code is always in the initial user namespace and that the nfs server code is always dealing with ids in the initial user namespace.
Stanislav even with your pending patches it won't be possible to mount a nfsd whre net->user_ns != init_userns. So no bugs will result in the combination of our patches. The one case I was worried about was fs/nfs/exports. But since that is read-only it creates no problems.
The big things user namespaces allow (besides uid and gid mapping) is a context where unprivileged users can create containers. Those containers can mount and unmount filesystems and have a root user. But that root users does not have global uid == 0, nor does that root user have any global capabilities. The root user only has capabilities over objects created in that user namespace. Which can include network namespaces etc.
Now all of that said and done when we do start supporting user namespaces in nfs (something that looks comparitively simple after your recent work to make nfs and nfsd network namespace aware) I expect the mount for nfsd and nfs will want to do:
if (net->user_ns != current_user_ns())
return -EINVAL;I can't see any other cases actually making sense. If we are in an ancestor user namespace of net->user_ns we are ok permission wise but totally we are in a totally confused state with respect to which permission to talk. If we are in a descendent user namespace we should not have the permissions to potentially dangerous things.
Which should make for a very very simple conversion when to get nfs running in multiple user namespaces for 3.10 as we can just replace &init_net with net->user_ns everywhere.
Eric
_______________________________________________
Containers mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/containers
A message that is not in the archive (sent off-list or not yet received): 87ip5vn6iv.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
14.02.2013 03:22, Eric W. Biederman пишет:
Quoted 163 lines
Quoted 74 lines · J. Bruce Fields
Quoted 73 lines · Eric W. Biederman
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes.
net->user_nsis the user namespace the network namespace was created in. And it is the user namespace that is used in test likens_capable(net->user_ns, CAP_NET_ADMIN)to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.Could you double check my understanding of the code?
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Quoted 7 lines
Quoted 2 lines
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace.
We're talking about the server side here, not the client, so I'm not sure what you mean by "nfs mounts". The nfs server does use various pseudofilesystems ("proc", "nfsd"), and those can be mounted outside the initial network namespace.
Actually I was seeing that nfs clients were starting lockd. So I was just reasoning here that anything that came from a nfs client was ultimately in the user namespace of that client, which is ultimately limited by the client out.
Quoted 4 lines
The server can receive rpc requests over network interfaces outside the initial network namespace, sure. The server doesn't perform mounts on behalf of clients, though, it just accesses previously mounted filesystems on clients' behalf.
But
nfsd_init_socksonly creates sockets in a single network namespace, and today we pass only&init_net.Quoted 5 lines
Quoted 2 lines
But because they are mounts they are
still limited to the initial user namespace.OK, so that's just a limitation on any mount whatsoever for now. I'm catching on, slowly, thanks!
If you set in struct filesystem .fs_flags =
FS_USERNS_MOUNTyour filesystem can be mounted outside of the initial user namespace. But since that takes extra work and because unprivileged users are allowed to create user namespaces and perform the mounts by default it is off.Quoted 8 lines
Quoted 3 lines
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<[email protected]>
and followups. That should make it for 3.9, I just need to review them....Ok that is interesting.
There is an interesting corner case here where an unprivileged user can create a user namespace and then can create a network namespace. Depending on how we interpret things when Stanislaves patches reach there we might have to add:
if (
net->user_ns!=&init_user_ns)
-EINVALSomewhere appropriate.
Quoted 9 lines
Quoted 4 lines
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
Yes.
Quoted 2 lines
lockd is started by either the nfs server or the nfs client.
Quoted 7 lines
Quoted 1 line
There are no other sunrpc servers in the kernel.
There are a couple callback services on the NFS client--those should be associated with nfs mounts in some obvious way. There's a confusing ACL service that's really just an appendage of NFSv2/v3 service.
I think we're fine.
Thanks.
Quoted 7 lines
Quoted 6 lines
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user) return -ESORRY_CHARLEY;Quoted 7 lines
I think you're right.
So for now it's safely confined to one user namespace, and I think we understand approximately what to do if we want to support nfsd's in user namespace in the future. (Mainly, make sure nfsd and proc can be mounted in them and then most things will be determined by the
user_nsof the network namespace associated with a given rpc.)
Quoted 8 lines
For 3.9 the list of filesystems mountable outside the initial user namespace is: mqueuefs, tmpfs, ramfs, devpts, sysfs, and proc.
I am a touch concerned about
/proc/fs/nfsd/exportsafter my patches and Stanislavs patches both come in. As I think that will allow for cases wherenet->user_ns!=&init_userns. But we can cross that bridge when we come to it.
Hmmm...
Maybe I'm missing the point of user namespaces, but since NFS kernel server is controlled via NFSd file system write calls, maybe it would be better to add:
.fs_flags = FS_USERNS_MOUNT
to it and add check:
+ if (net->user_ns != current_user_ns())
+ return -EINVAL;
No?
Quoted 2 lines
Eric
Signature · 6 lines
Best regards, Stanislav Kinsbursky _______________________________________________ Containers mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/containers
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
In reply to Eric W. BiedermanQuoted 19 lines · Eric W. Biederman
Quoted 9 lines · J. Bruce Fields
Quoted 3 lines · Eric W. Biederman
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<20130201125210.3257.46454.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]>
and followups. That should make it for 3.9, I just need to review them....Ok that is interesting.
There is an interesting corner case here where an unprivileged user can create a user namespace and then can create a network namespace. Depending on how we interpret things when Stanislaves patches reach there we might have to add:
Quoted 4 lines
if (
net->user_ns!=&init_user_ns)
-EINVALSomewhere appropriate.
I'm assuming that's something that's needed only in kernels that have *both* Stanislav's patches and yours.
I've committed his patches to
git://linux-nfs.org/~bfields/linux.git for-3.9
which should also get pulled into next. Let me know if there's another patch I should take.
Quoted 4 lines
I am a touch concerned about
/proc/fs/nfsd/exportsafter my patches and Stanislavs patches both come in. As I think that will allow for cases wherenet->user_ns!=&init_userns. But we can cross that bridge when we come to it.
OK, let me know of anything I can do to make your life easier....
--b.
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 8 lines · J. Bruce Fields
On Wed, Feb 13, 2013 at 03:22:32PM -0800, Eric W. Biederman wrote:
I've committed his patches to
git://linux-nfs.org/~bfields/linux.git for-3.9which should also get pulled into next. Let me know if there's another patch I should take.
I don't currently see any problems.
My changes are now in:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git for-next
So we will get whatever linux-next testing there is.
Quoted 6 lines
Quoted 4 lines
I am a touch concerned about
/proc/fs/nfsd/exportsafter my patches and Stanislavs patches both come in. As I think that will allow for cases wherenet->user_ns!=&init_userns. But we can cross that bridge when we come to it.OK, let me know of anything I can do to make your life easier....
/proc/fs/nfsd/exports is read-only so it turns out not be be a problem.
That we can not mount nfs or the nfsd control filesystem outside of init_userns prevents any other problems. Details are in my conversation with Stanislav.
Eric
p.s. It would be nice if /proc/fs/nfsd/exports became a symlink to /proc/net/nfsd/exports so the code didn't have to use current to figure out how to do the right thing.
p.p.s Full user namespace support probably isn't much more than using net->user_ns and adding the FS_USERNS_MOUNT flag.
A message that is not in the archive (sent off-list or not yet received): 8738wzq1z6.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 68 lines · Eric W. Biederman
Quoted 49 lines · J. Bruce Fields
Quoted 48 lines · Eric W. Biederman
Quoted 18 lines · J. Bruce Fields
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
Quoted 4 lines
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Perhaps I have the description a little scrambled. The short version is that to start I only support the initial network namespace.
If I haven't succeeded it is my intent to initially limit the servers to the initial user namespace as well. I should see if I can figure that out.
Quoted 11 lines
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
Ideally yes. I read through the caches enough to figure out where there user space interfaces were, and to make certain we had conversions to/from kuids and kgids.
Quoted 8 lines
Quoted 4 lines
I haven't looked at what user namespace makes sense for these caches. For this cache my first guess is that
net->user_nsis what we want as it will be shared by all users in network namespace I presume.Oh, I didn't know about net->user_ns--so each network namespace is associated with a single user namespace, great, that simplifies life. Yes, that sounds exactly right.
Yes.
net->user_nsis the user namespace the network namespace was created in. And it is the user namespace that is used in test likens_capable(net->user_ns, CAP_NET_ADMIN)to see if you are allowed to manipulate the network namespace. So looks like exactly what we want for that cache.Could you double check my understanding of the code?
Quoted 7 lines
I want to be certain that I can't _yet_ start an sunrpc server process outside of the initial user namespace. While writing an earlier reply I realized that I hadn't thought about where sunrpc server processes come from.
Reading through the code it looks like we can have nfs mounts outside of the initial network namespace.
We're talking about the server side here, not the client, so I'm not sure what you mean by "nfs mounts". The nfs server does use various pseudofilesystems ("proc", "nfsd"), and those can be mounted outside the initial network namespace.
The server can receive rpc requests over network interfaces outside the initial network namespace, sure. The server doesn't perform mounts on behalf of clients, though, it just accesses previously mounted filesystems on clients' behalf.
Quoted 2 lines
But because they are mounts they are
still limited to the initial user namespace.
OK, so that's just a limitation on any mount whatsoever for now. I'm catching on, slowly, thanks!
Quoted 3 lines
Now looking at the nfs server, seems to be hard coded to only start in the initial network namespace despite almost having support for starting in more.
Right, Stanislav's got 4 more patches that should finish the job; see
http://mid.gmane.org/<20130201125210.3257.46454.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]>
and followups. That should make it for 3.9, I just need to review them....
Quoted 4 lines
Even more the nfs server is controlled and started through the "nfsd" filesystem. Which has to be mounted before you can start the server. So you can only start the server through a mount in the initial user namespace.
Yes.
Quoted 3 lines
lockd is started by either the nfs server or the nfs client.
There are no other sunrpc servers in the kernel.
There are a couple callback services on the NFS client--those should be associated with nfs mounts in some obvious way. There's a confusing ACL service that's really just an appendage of NFSv2/v3 service.
I think we're fine.
Quoted 6 lines
I think all of that is enough to reasonably claim that you can't have any sunrpc server processes outside of the initial user namespace. But if I am wrong I would to find an appropriate spot to put in a line that says:
if (current_user_ns() != &init_user) return -ESORRY_CHARLEY;
I think you're right.
So for now it's safely confined to one user namespace, and I think we understand approximately what to do if we want to support nfsd's in user namespace in the future. (Mainly, make sure nfsd and proc can be mounted in them and then most things will be determined by the user_ns of the network namespace associated with a given rpc.)
--b.
A message that is not in the archive (sent off-list or not yet received): 1360777934-5663-52-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH review 52/85] sunrpc: Properly encode kuids and kgids in auth.unix.gid rpc pipe upcalls.
Quoted 12 lines · Eric W. Biederman
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When a new rpc connection is established with an in-kernel server, the traffic passes through
svc_process_common, andsvc_set_clientand down intosvcauth_unix_set_clientif it is of typeRPC_AUTH_NULLorRPC_AUTH_UNIX.
svcauth_unix_set_clientthen looks at the uid of the credential we have assigned to the incomming client and if we don't have the groups already cached makes an upcall to get a list of groups that the client can use.
Quoted 4 lines
The upcall encodes send a rpc message to user space encoding the uid of the user whose groups we want to know. Encode the kuid of the user in the initial user namespace as nfs mounts can only happen today in the initial user namespace.
OK, I didn't know that.
(Though I'm unclear how it should matter to the server what user namespace the client is in?)
Quoted 8 lines
When a reply to an upcall comes in convert interpret the uid and gid values from the rpc pipe as uids and gids in the initial user namespace and convert them into kuids and kgids before processing them further.
When reading proc files listing the uid to gid list cache convert the kuids and kgids from into uids and gids the initial user namespace. As we are displaying server internal details it makes sense to display these values from the servers perspective.
All of these caches are already per-network-namespace. Ideally wouldn't we also like to associate a user namespace with each cache somehow?
--b.
Quoted 66 lines
Cc "J. Bruce Fields" <[email protected]>Cc Trond Myklebust <[email protected]>--- net/sunrpc/svcauth_unix.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)net/sunrpc/svcauth_unix.c +9
-5@@ -470,7 +470,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' ; }@@ -486,7 +486,8 @@ 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;@@ -498,9 +499,12 @@ 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);@@ -554,7 +558,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 = &init_user_ns;struct unix_gid *ug;int i;int glen;@@ -570,7 +574,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" );Signature · 1 line
1.7.5.4
PATCH 53/85 sunrpc: Properly decode kuids and kgids in RPC_AUTH_UNIX credentials
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
When reading kuids from the wire map them into the initial user namespace, and validate the mapping succeded.
When reading kgids from the wire map them into the initial user namespace, and validate the mapping succeded.
--- net/sunrpc/svcauth_unix.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
net/sunrpc/svcauth_unix.c +4 -2
@@ -821,8 +821,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
PATCH 54/85 nfs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring alloc
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/nfs/idmap.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
fs/nfs/idmap.c +2 -1
@@ -193,7 +193,8 @@ static int nfs_idmap_init_keyring(void)if (!cred)return -ENOMEM ; - keyring =keyring_alloc (".id_resolver" ,0 ,0 , cred, + keyring =keyring_alloc (".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 ,NULL );
Signature · 1 line
1.7.5.4
PATCH 55/85 nfs: Convert struct nfs_fattr to Use kuid_t and kgid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- include/linux/nfs_xdr.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
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 {
Signature · 1 line
1.7.5.4
PATCH 56/85 nfs: Convert idmap to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Convert nfs_map_name_to_uid to return a kuid_t value. Convert nfs_map_name_to_gid to return a kgid_t value. Convert nfs_map_uid_to_name to take a kuid_t paramater. Convert nfs_map_gid_to_name to take a kgid_t paramater.
Tweak nfs_fattr_map_owner_to_name to use a kuid_t intermediate value. Tweak nfs_fattr_map_group_to_name to use a kgid_t intermediate value.
Which makes these functions properly handle kuids and kgids, including erroring of the generated kuid or kgid is invalid.
--- fs/nfs/idmap.c | 50 ++++++++++++++++++++++++++++++-------------- include/linux/nfs_idmap.h | 9 ++++--- 2 files changed, 39 insertions(+), 20 deletions(-)
fs/nfs/idmap.c +34 -16
@@ -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;
@@ -837,43 +837,61 @@ 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); +if (ret ==0 ) { + *uid =make_kuid (&init_user_ns, id); +if (!uid_valid (*uid)) + ret = -ERANGE ; + } +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)) + ret =nfs_idmap_lookup_id (name, namelen,"gid" , &id, idmap); +if (ret ==0 ) { + *gid =make_kgid (&init_user_ns, id); +if (!gid_valid (*gid)) + ret = -ERANGE ; + } +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 ; +__u32 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 ; +__u32 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; }
include/linux/nfs_idmap.h +5 -4
@@ -36,6 +36,7 @@#ifndef NFS_IDMAP_H #define NFS_IDMAP_H +#include <linux/uidgid.h> #include <uapi/linux/nfs_idmap.h>
@@ -67,10 +68,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 */
Signature · 1 line
1.7.5.4
PATCH 57/85 nfs: Convert nfs2xdr to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
Add an additional failure mode for incoming uid or gids that are invalid.
--- fs/nfs/nfs2xdr.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-)
fs/nfs/nfs2xdr.c +15 -4
@@ -290,8 +290,13 @@ 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++)); +if (!uid_valid (fattr->uid)) + goto out_uid; + fattr->gid =make_kgid (&init_user_ns,be32_to_cpup (p++)); +if (!gid_valid (fattr->gid)) + goto out_gid; + fattr->size =be32_to_cpup (p++); fattr->du.nfs2.blocksize =be32_to_cpup (p++);
@@ -313,6 +318,12 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) fattr->change_attr =nfs_timespec_to_change_attr (&fattr->ctime);return 0 ; +out_uid: +dprintk ("NFS: returned invalid uid\n" ); +return -EINVAL ; +out_gid: +dprintk ("NFS: returned invalid gid\n" ); +return -EINVAL ; out_overflow:print_overflow_msg (__func__, xdr);return -EIO ;
@@ -351,11 +362,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 )
Signature · 1 line
1.7.5.4
PATCH 58/85 nfs: Convert nfs3xdr to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
Add an additional failure mode incoming for uids or gids that are invalid.
--- fs/nfs/nfs3xdr.c | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-)
fs/nfs/nfs3xdr.c +14 -4
@@ -592,13 +592,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;
@@ -657,8 +657,12 @@ 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++)); +if (!uid_valid (fattr->uid)) + goto out_uid; + fattr->gid =make_kgid (&init_user_ns,be32_to_cpup (p++)); +if (!gid_valid (fattr->gid)) + goto out_gid; p =xdr_decode_size3 (p, &fattr->size); p =xdr_decode_size3 (p, &fattr->du.nfs3.used);
@@ -675,6 +679,12 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) fattr->valid |=NFS_ATTR_FATTR_V3 ;return 0 ; +out_uid: +dprintk ("NFS: returned invalid uid\n" ); +return -EINVAL ; +out_gid: +dprintk ("NFS: returned invalid gid\n" ); +return -EINVAL ; out_overflow:print_overflow_msg (__func__, xdr);return -EIO ;
Signature · 1 line
1.7.5.4
PATCH 59/85 nfs: Convert nfs4xdr to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
When printing kuids and kgids convert them to values in the initial user namespace then use normal printf formats.
--- fs/nfs/nfs4xdr.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-)
fs/nfs/nfs4xdr.c +8 -8
@@ -1002,7 +1002,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 ;
@@ -1014,7 +1014,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);
Signature · 1 line
1.7.5.4
PATCH 60/85 nfs: kuid and kgid conversions for nfs/inode.c
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use uid_eq and gid_eq when comparing kuids and kgids.
- Use make_kuid(&init_user_ns, -2) and make_kgid(&init_user_ns, -2) as the initial uid and gid on nfs inodes, instead of using the typeunsafe value of -2.
--- fs/nfs/inode.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
fs/nfs/inode.c +6 -6
@@ -332,8 +332,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 ; + inode->i_uid =make_kuid (&init_user_ns,-2 ); + inode->i_gid =make_kgid (&init_user_ns,-2 ); inode->i_blocks =0 ;memset (nfsi->cookieverf,0 ,sizeof (nfsi->cookieverf)); nfsi->write_io =0 ;
@@ -1009,9 +1009,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? */
@@ -1440,7 +1440,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; }
@@ -1451,7 +1451,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; }
Signature · 1 line
1.7.5.4
PATCH 61/85 nfs: Enable building with user namespaces enabled.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Now that the kuids and kgids conversion have propogated through net/sunrpc/ and the fs/nfs/ it is safe to enable building nfs when user namespaces are enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1073,7 +1073,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n depends on NFSD = n - depends on NFS_FS = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
PATCH 62/85 nfsd: Remove declaration of nonexistent nfs4_acl_permisison
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/nfsd/acl.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
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
Signature · 1 line
1.7.5.4
PATCH 63/85 nfsd: idmap use u32 not uid_t as the intermediate type
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
u32 and uid_t have the same size and semantics so this change should have no operational effect. This just removes the WTF factor when looking at variables that hold both uids and gids whos type is uid_t.
--- fs/nfsd/nfs4idmap.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
fs/nfsd/nfs4idmap.c +6 -6
@@ -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);
Signature · 1 line
1.7.5.4
PATCH 64/85 nfsd: Convert idmap to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Convert nfsd_map_name_to_uid to return a kuid_t value. Convert nfsd_map_name_to_gid to return a kgid_t value. Convert nfsd_map_uid_to_name to take a kuid_t parameter. Convert nfsd_map_gid_to_name to take a kgid_t paramater.
--- fs/nfsd/idmap.h | 8 ++++---- fs/nfsd/nfs4idmap.c | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-)
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/nfs4idmap.c +20 -6
@@ -625,26 +625,40 @@ do_id_to_name(struct svc_rqst *rqstp, int type, u32 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); +if (!uid_valid (*uid)) + status = nfserr_badowner; +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); +if (!gid_valid (*gid)) + status = nfserr_badowner; +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); }
Signature · 1 line
1.7.5.4
PATCH 65/85 nfsd: Remove nfsd_luid, nfsd_lgid, nfsd_ruid and nfsd_rgid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
These trivial macros that don't currently do anything are the last vestiages of an old attempt at uid mapping that was removed from the kernel in September of 2002. Remove them to make it clear what the code is currently doing.
--- fs/nfsd/auth.h | 6 ------ fs/nfsd/nfs3xdr.c | 4 ++-- fs/nfsd/nfsxdr.c | 4 ++-- 3 files changed, 4 insertions(+), 10 deletions(-)
fs/nfsd/auth.h +0 -6
@@ -1,6 +1,5 @@/* * nfsd-specific authentication stuff. -* uid/gid mapping not yet implemented. * * Copyright (C) 1995, 1996 Olaf Kirch <[email protected]> */
@@ -8,11 +7,6 @@#ifndef LINUX_NFSD_AUTH_H #define LINUX_NFSD_AUTH_H -#define nfsd_luid (rq, uid) ((u32)(uid)) -#define nfsd_lgid (rq, gid) ((u32)(gid)) -#define nfsd_ruid (rq, uid) ((u32)(uid)) -#define nfsd_rgid (rq, gid) ((u32)(gid)) -/* * Set the current process's fsuid/fsgid etc to those of the NFS * client user
fs/nfsd/nfs3xdr.c +2 -2
@@ -167,8 +167,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 ) stat->uid); + *p++ =htonl ((u32 ) stat->gid);if (S_ISLNK (stat->mode) && stat->size >NFS3_MAXPATHLEN ) { p =xdr_encode_hyper (p, (u64 )NFS3_MAXPATHLEN ); }else {
fs/nfsd/nfsxdr.c +2 -2
@@ -151,8 +151,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 ) stat->uid); + *p++ =htonl ((u32 ) stat->gid);if (S_ISLNK (type) && stat->size >NFS_MAXPATHLEN ) { *p++ =htonl (NFS_MAXPATHLEN );
Signature · 1 line
1.7.5.4
PATCH 66/85 nfsd: Convert nfs3xdr to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
--- fs/nfsd/nfs3xdr.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
fs/nfsd/nfs3xdr.c +8 -6
@@ -105,12 +105,14 @@ decode_sattr3(__be32 *p, struct iattr *iap) iap->ia_mode =ntohl (*p++); }if (*p++) { - iap->ia_valid |=ATTR_UID ; - iap->ia_uid =ntohl (*p++); + iap->ia_uid =make_kuid (&init_user_ns,ntohl (*p++)); +if (uid_valid (iap->ia_uid)) + iap->ia_valid |=ATTR_UID ; }if (*p++) { - iap->ia_valid |=ATTR_GID ; - iap->ia_gid =ntohl (*p++); + iap->ia_gid =make_kgid (&init_user_ns,ntohl (*p++)); +if (gid_valid (iap->ia_gid)) + iap->ia_valid |=ATTR_GID ; }if (*p++) {u64 newsize;
@@ -167,8 +169,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 ) stat->uid); - *p++ =htonl ((u32 ) stat->gid); + *p++ =htonl ((u32 )from_kuid (&init_user_ns, stat->uid)); + *p++ =htonl ((u32 )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 {
Signature · 1 line
1.7.5.4
PATCH 67/85 nfsd: Convert nfsxdr to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
When reading uids and gids off the wire convert them to kuids and kgids. If the conversion results in an invalid result don't set the ATTR_UID or ATTR_GID.
When putting kuids and kgids onto the wire first convert them to uids and gids the other side will understand.
--- fs/nfsd/nfsxdr.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
fs/nfsd/nfsxdr.c +8 -6
@@ -100,12 +100,14 @@ decode_sattr(__be32 *p, struct iattr *iap) iap->ia_mode = tmp; }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 (uid_valid (iap->ia_uid)) + iap->ia_valid |=ATTR_UID ; }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 (gid_valid (iap->ia_gid)) + iap->ia_valid |=ATTR_GID ; }if ((tmp =ntohl (*p++)) != (u32)-1 ) { iap->ia_valid |=ATTR_SIZE ;
@@ -151,8 +153,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 ) stat->uid); - *p++ =htonl ((u32 ) stat->gid); + *p++ =htonl ((u32 )from_kuid (&init_user_ns, stat->uid)); + *p++ =htonl ((u32 )from_kgid (&init_user_ns, stat->gid));if (S_ISLNK (type) && stat->size >NFS_MAXPATHLEN ) { *p++ =htonl (NFS_MAXPATHLEN );
Signature · 1 line
1.7.5.4
PATCH 68/85 nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
In struct nfs4_ace remove the member who and replace it with an anonymous union holding who_uid and who_gid. Allowing typesafe storage uids and gids.
Add a helper pace_gt for sorting posix_acl_entries.
In struct posix_user_ace_state to replace uid with a union of kuid_t uid and kgid_t gid.
Remove all initializations of the deprecated posic_acl_entry e_id field. Which is not present when user namespaces are enabled.
Split find_uid into two functions find_uid and find_gid that work in a typesafe manner.
In nfs4xdr update nfsd4_encode_fattr to deal with the changes in struct nfs4_ace.
Rewrite nfsd4_encode_name to take a kuid_t and a kgid_t instead of a generic id and flag if it is a group or a uid. Replace the group flag with a test for a valid gid.
Modify nfsd4_encode_user to take a kuid_t and call the modifed nfsd4_encode_name.
Modify nfsd4_encode_group to take a kgid_t and call the modified nfsd4_encode_name.
Modify nfsd4_encode_aclname to take an ace instead of taking the fields of an ace broken out. This allows it to detect if the ace is for a user or a group and to pass the appropriate value while still being typesafe.
--- fs/nfsd/nfs4acl.c | 63 ++++++++++++++++++++++++++++++++++++------------- fs/nfsd/nfs4xdr.c | 41 +++++++++++++++++++------------ include/linux/nfs4.h | 6 ++++- 3 files changed, 76 insertions(+), 34 deletions(-)
fs/nfsd/nfs4acl.c +46 -17
@@ -264,7 +264,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->flag = eflag; ace->access_mask =deny_mask_from_posix (deny, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_uid = pa->e_uid; ace++; acl->naces++; }
@@ -273,7 +273,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->access_mask =mask_from_posix (pa->e_perm & pas.mask, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_uid = pa->e_uid; ace++; acl->naces++; pa++;
@@ -300,7 +300,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->access_mask =mask_from_posix (pa->e_perm & pas.mask, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_gid = pa->e_gid; ace++; acl->naces++; pa++;
@@ -329,7 +329,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, ace->flag = eflag |NFS4_ACE_IDENTIFIER_GROUP ; ace->access_mask =deny_mask_from_posix (deny, flags); ace->whotype =NFS4_ACL_WHO_NAMED ; - ace->who = pa->e_id; + ace->who_gid = pa->e_gid; ace++; acl->naces++; }
@@ -345,6 +345,18 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, acl->naces++; } +static bool +pace_gt (struct posix_acl_entry *pace1,struct posix_acl_entry *pace2) +{ +if (pace1->e_tag != pace2->e_tag) +return pace1->e_tag > pace2->e_tag; +if (pace1->e_tag ==ACL_USER ) +return uid_gt (pace1->e_uid, pace2->e_uid); +if (pace1->e_tag ==ACL_GROUP ) +return gid_gt (pace1->e_gid, pace2->e_gid); +return false; +} +static void sort_pacl_range (struct posix_acl *pacl,int start,int end) {int sorted =0 , i;
@@ -355,8 +367,8 @@ sort_pacl_range(struct posix_acl *pacl, int start, int end) {while (!sorted) { sorted =1 ;for (i = start; i < end; i++) { -if (pacl->a_entries[i].e_id - > pacl->a_entries[i+1 ].e_id) { +if (pace_gt (&pacl->a_entries[i], + &pacl->a_entries[i+1 ])) { sorted =0 ; tmp = pacl->a_entries[i]; pacl->a_entries[i] = pacl->a_entries[i+1 ];
@@ -398,7 +410,10 @@ struct posix_ace_state { };struct posix_user_ace_state { -uid_t uid; +union { +kuid_t uid; +kgid_t gid; + };struct posix_ace_state perms; };
@@ -521,7 +536,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->owner.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;for (i=0 ; i < state->users->n; i++) { pace++;
@@ -531,7 +545,7 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) goto out_err;low_mode_from_nfs4 (state->users->aces[i].perms.allow, &pace->e_perm, flags); - pace->e_id = state->users->aces[i].uid; + pace->e_uid = state->users->aces[i].uid;add_to_mask (state, &state->users->aces[i].perms); }
@@ -541,7 +555,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->group.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;add_to_mask (state, &state->group);for (i=0 ; i < state->groups->n; i++) {
@@ -552,14 +565,13 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) goto out_err;low_mode_from_nfs4 (state->groups->aces[i].perms.allow, &pace->e_perm, flags); - pace->e_id = state->groups->aces[i].uid; + pace->e_gid = state->groups->aces[i].gid;add_to_mask (state, &state->groups->aces[i].perms); } pace++; pace->e_tag =ACL_MASK ;low_mode_from_nfs4 (state->mask.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ; pace++; pace->e_tag =ACL_OTHER ;
@@ -567,7 +579,6 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)if (error) goto out_err;low_mode_from_nfs4 (state->other.allow, &pace->e_perm, flags); - pace->e_id =ACL_UNDEFINED_ID ;return pacl; out_err:
@@ -587,12 +598,13 @@ static inline void deny_bits(struct posix_ace_state *astate, u32 mask) astate->deny |= mask & ~astate->allow; } -static int find_uid (struct posix_acl_state *state,struct posix_ace_state_array *a,uid_t uid) +static int find_uid (struct posix_acl_state *state,kuid_t uid) { +struct posix_ace_state_array *a = state->users;int i;for (i =0 ; i < a->n; i++) -if (a->aces[i].uid == uid) +if (uid_eq (a->aces[i].uid, uid))return i;/* Not found: */ a->n++;
@@ -603,6 +615,23 @@ static int find_uid(struct posix_acl_state *state, struct posix_ace_state_arrayreturn i; } +static int find_gid (struct posix_acl_state *state,kgid_t gid) +{ +struct posix_ace_state_array *a = state->groups; +int i; + +for (i =0 ; i < a->n; i++) +if (gid_eq (a->aces[i].gid, gid)) +return i; +/* Not found: */ + a->n++; + a->aces[i].gid = gid; + a->aces[i].perms.allow = state->everyone.allow; + a->aces[i].perms.deny = state->everyone.deny; + +return i; +} +static void deny_bits_array (struct posix_ace_state_array *a,u32 mask) {int i;
@@ -636,7 +665,7 @@ static void process_one_v4_ace(struct posix_acl_state *state, }break ;case ACL_USER : - i =find_uid (state, state->users, ace->who); + i =find_uid (state, ace->who_uid);if (ace->type ==NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ) {allow_bits (&state->users->aces[i].perms, mask); }else {
@@ -658,7 +687,7 @@ static void process_one_v4_ace(struct posix_acl_state *state, }break ;case ACL_GROUP : - i =find_uid (state, state->groups, ace->who); + i =find_gid (state, ace->who_gid);if (ace->type ==NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ) {allow_bits (&state->groups->aces[i].perms, mask); }else {
fs/nfsd/nfs4xdr.c +25 -16
86 lines not on this page · raw message
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 {
Signature · 1 line
1.7.5.4
PATCH 69/85 nfsd: Modify nfsd4_cb_sec to use kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Change uid and gid in struct nfsd4_cb_sec to be of type kuid_t and kgid_t.
In nfsd4_decode_cb_sec when reading uids and gids off the wire convert them to kuids and kgids, and if they don't convert to valid kuids or valid kuids ignore RPC_AUTH_UNIX and don't fill in any of the fields.
--- fs/nfsd/nfs4xdr.c | 13 ++++++++++--- fs/nfsd/state.h | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-)
fs/nfsd/nfs4xdr.c +10 -3
@@ -464,9 +464,16 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_READ32 (dummy);READ_BUF (dummy *4 );if (cbs->flavor == (u32)(-1 )) { - cbs->uid = uid; - cbs->gid = gid; - cbs->flavor =RPC_AUTH_UNIX ; +kuid_t kuid =make_kuid (&init_user_ns, uid); +kgid_t kgid =make_kgid (&init_user_ns, gid); +if (uid_valid (kuid) &&gid_valid (kgid)) { + cbs->uid = kuid; + cbs->gid = kgid; + cbs->flavor =RPC_AUTH_UNIX ; + }else { +dprintk ("RPC_AUTH_UNIX with invalid" +"uid or gid ignoring!\n" ); + } }break ;case RPC_AUTH_GSS :
fs/nfsd/state.h +2 -2
@@ -152,8 +152,8 @@ struct nfsd4_channel_attrs {struct nfsd4_cb_sec {u32 flavor;/* (u32)(-1) used to mean "no valid flavor" */ -u32 uid; -u32 gid; +kuid_t uid; +kgid_t gid; };struct nfsd4_create_session {
Signature · 1 line
1.7.5.4
PATCH 70/85 nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/nfsd/auth.c | 2 +- fs/nfsd/export.c | 22 ++++++++++++++-------- include/linux/nfsd/export.h | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-)
fs/nfsd/auth.c +1 -1
@@ -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); }
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;
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;
Signature · 1 line
1.7.5.4
PATCH 71/85 nfsd: Properly compare and initialize kuids and kgids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Use uid_eq(uid, GLOBAL_ROOT_UID) instead of !uid.
Use gid_eq(gid, GLOBAL_ROOT_GID) instead of !gid.
Use uid_eq(uid, INVALID_UID) instead of uid == -1
Use gid_eq(uid, INVALID_GID) instead of gid == -1
Use uid = GLOBAL_ROOT_UID instead of uid = 0;
Use gid = GLOBAL_ROOT_GID instead of gid = 0;
Use !uid_eq(uid1, uid2) instead of uid1 != uid2.
Use !gid_eq(gid1, gid2) instead of gid1 != gid2.
Use uid_eq(uid1, uid2) instead of uid1 == uid2.
--- fs/nfsd/auth.c | 10 +++++----- fs/nfsd/nfs4recover.c | 4 ++-- fs/nfsd/nfs4state.c | 6 +++--- fs/nfsd/vfs.c | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-)
fs/nfsd/auth.c +5 -5
@@ -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);
@@ -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/nfs4recover.c +2 -2
@@ -73,8 +73,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
@@ -1202,7 +1202,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; }
@@ -1227,8 +1227,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/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 */
@@ -1205,7 +1205,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 );
@@ -2150,7 +2150,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} */
Signature · 1 line
1.7.5.4
PATCH 72/85 nfsd: Enable building with user namespaces enabled.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Now that the kuids and kgids conversion have propogated through net/sunrpc/ and the fs/nfsd/ it is safe to enable building nfsd when user namespaces are enabled.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1072,7 +1072,6 @@ config UIDGID_CONVERTED # Filesystems depends on CIFS = n - depends on NFSD = n depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS
Signature · 1 line
1.7.5.4
PATCH 73/85 cifs: Override unmappable incoming uids and gids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
The cifs protocol has a 64bit space for uids and gids, while linux only supports a 32bit space today. Instead of silently truncating 64bit cifs ids, replace cifs ids that do not fit in the 32bit linux id space with the default uid and gids for the cifs mount.
--- fs/cifs/inode.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-)
fs/cifs/inode.c +13 -9
@@ -244,15 +244,19 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,break ; } -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); - -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_uid = cifs_sb->mnt_uid; +if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_UID )) { +u64 id =le64_to_cpu (info->Uid); +if (id < ((uid_t)-1 )) + fattr->cf_uid = id; + } + + fattr->cf_gid = cifs_sb->mnt_gid; +if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_OVERR_GID )) { +u64 id =le64_to_cpu (info->Gid); +if (id < ((gid_t)-1 )) + fattr->cf_gid = id; + } fattr->cf_nlink =le64_to_cpu (info->Nlinks); }
Signature · 1 line
1.7.5.4
PATCH 74/85 cifs: Use BUILD_BUG_ON to validate uids and gids are the same size
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
The assumption that sizeof(uid_t) is the same as sizeof(gid_t) is completely reasonable but since we can verify the condition at compile time.
--- fs/cifs/cifsacl.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
fs/cifs/cifsacl.c +1 -0
@@ -297,6 +297,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,* probably a safe assumption but might be better to check based on * sidtype. */ +BUILD_BUG_ON (sizeof (uid_t) !=sizeof (gid_t));if (sidkey->datalen !=sizeof (uid_t)) { rc = -EIO ; cFYI(1, "%s: Downcall contained malformed key "
Signature · 1 line
1.7.5.4
PATCH 75/85 cifs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring_alloc
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
keyring_alloc has been updated to take a kuid_t and kgid_t so pass GLOBAL_ROOT_UID instead of 0 for the uid and GLOBAL_ROOT_GID instead of 0 for the gid.
--- fs/cifs/cifsacl.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
fs/cifs/cifsacl.c +2 -1
@@ -347,7 +347,8 @@ init_cifs_idmap(void)if (!cred)return -ENOMEM ; - keyring =keyring_alloc (".cifs_idmap" ,0 ,0 , cred, + keyring =keyring_alloc (".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 ,NULL );
Signature · 1 line
1.7.5.4
PATCH 76/85 cifs: Use kuids and kgids SID to uid/gid mapping
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Update id_mode_to_cifs_acl to take a kuid_t and a kgid_t.
Replace NO_CHANGE_32 with INVALID_UID and INVALID_GID, and tests for NO_CHANGE_32 with uid_valid and gid_valid.
Carefully unpack the value returned from request_key. memcpy the value into the expected type. The convert the uid/gid into a kuid/kgid. And then only if the result is a valid kuid or kgid update fuid/fgid.
--- fs/cifs/cifsacl.c | 43 +++++++++++++++++++++++++++++-------------- fs/cifs/cifspdu.h | 1 - fs/cifs/cifsproto.h | 2 +- fs/cifs/inode.c | 8 ++++---- 4 files changed, 34 insertions(+), 20 deletions(-)
fs/cifs/cifsacl.c +29 -14
@@ -266,8 +266,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,struct key *sidkey;char *sidstr;const struct cred *saved_cred; -uid_t fuid = cifs_sb->mnt_uid; -gid_t fgid = cifs_sb->mnt_gid; +kuid_t fuid = cifs_sb->mnt_uid; +kgid_t fgid = cifs_sb->mnt_gid;/* * If we have too many subauthorities, then something is really wrong.
@@ -306,10 +306,21 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, goto out_key_put; } -if (sidtype ==SIDOWNER ) -memcpy (&fuid, &sidkey->payload.value,sizeof (uid_t)); -else -memcpy (&fgid, &sidkey->payload.value,sizeof (gid_t)); +if (sidtype ==SIDOWNER ) { +kuid_t uid; +uid_t id; +memcpy (&id, &sidkey->payload.value,sizeof (uid_t)); + uid =make_kuid (&init_user_ns, id); +if (uid_valid (uid)) + fuid = uid; + }else { +kgid_t gid; +gid_t id; +memcpy (&id, &sidkey->payload.value,sizeof (gid_t)); + gid =make_kgid (&init_user_ns, id); +if (gid_valid (gid)) + fgid = gid; + } out_key_put:key_put (sidkey);
@@ -776,7 +787,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;
@@ -808,17 +819,19 @@ 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_valid (uid)) {/* chown */ +uid_t id; 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); + id =from_kuid (&init_user_ns, uid); + rc =id_to_sid (id,SIDOWNER , nowner_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for owner id %d" , - __func__, rc, uid); + __func__, rc, id);kfree (nowner_sid_ptr);return rc; }
@@ -826,17 +839,19 @@ 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_valid (gid)) {/* chgrp */ +gid_t id; 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); + id =from_kgid (&init_user_ns, gid); + rc =id_to_sid (id,SIDGROUP , ngroup_sid_ptr);if (rc) {cFYI (1 ,"%s: Mapping error %d for group id %d" , - __func__, rc, gid); + __func__, rc, id);kfree (ngroup_sid_ptr);return rc; }
@@ -1004,7 +1019,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/cifspdu.h +0 -1
@@ -277,7 +277,6 @@#define CIFS_NO_HANDLE 0xFFFF#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL -#define NO_CHANGE_32 0xFFFFFFFFUL/* IPC$ in ASCII */ #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
fs/cifs/cifsproto.h +1 -1
@@ -161,7 +161,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 *,
fs/cifs/inode.c +4 -4
@@ -2090,8 +2090,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 =INVALID_UID ; +kgid_t gid =INVALID_GID ;struct inode *inode = direntry->d_inode;struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode);
@@ -2150,7 +2150,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_valid (uid) ||gid_valid (gid)) { rc =id_mode_to_cifs_acl (inode, full_path,NO_CHANGE_64 , uid, gid);if (rc) {
@@ -2174,7 +2174,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 ); +INVALID_UID ,INVALID_GID );if (rc) {cFYI (1 ,"%s: Setting ACL failed with error: %d" , __func__, rc);
Signature · 1 line
1.7.5.4
PATCH 77/85 cifs: Convert from a kuid before printing current_fsuid
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/cifs/cifsproto.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
fs/cifs/cifsproto.h +2 -1
@@ -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; \ })
Signature · 1 line
1.7.5.4
PATCH 78/85 cifs: Modify struct cifs_unix_set_info_args to hold a kuid_t and a kgid_t
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Use INVALID_UID and INVALID_GID instead of NO_CHANGE_64 to indicate the value should not be changed.
In cifs_fill_unix_set_info convert from kuids and kgids into uids and gids that will fit in FILE_UNIX_BASIC_INFO.
--- fs/cifs/cifsproto.h | 4 ++-- fs/cifs/cifssmb.c | 10 ++++++++-- fs/cifs/dir.c | 18 +++++++++--------- fs/cifs/file.c | 4 ++-- fs/cifs/inode.c | 14 +++++++------- 5 files changed, 28 insertions(+), 22 deletions(-)
fs/cifs/cifsproto.h +2 -2
@@ -305,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 +8 -2
@@ -5819,8 +5819,14 @@ static voidcifs_fill_unix_set_info (FILE_UNIX_BASIC_INFO *data_offset, const struct cifs_unix_set_info_args *args) { +u64 uid =NO_CHANGE_64 , gid =NO_CHANGE_64 ;u64 mode = args->mode; +if (uid_valid (args->uid)) + uid =from_kuid (&init_user_ns, args->uid); +if (gid_valid (args->gid)) + gid =from_kgid (&init_user_ns, args->gid); +/* * Samba server ignores set of file size to zero due to bugs in some * older clients, but we should be precise - we use SetFileSize to
@@ -5833,8 +5839,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/dir.c +9 -9
@@ -342,14 +342,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 =INVALID_UID ;/* no change */ + args.gid =INVALID_GID ;/* no change */ }CIFSSMBUnixSetFileInfo (xid, tcon, &args, fid->netfid, current->tgid);
@@ -588,11 +588,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 =INVALID_UID ;/* no change */ + args.gid =INVALID_GID ;/* no change */ } 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 =INVALID_UID ,/* no change */ + .gid =INVALID_GID ,/* no change */ .ctime =NO_CHANGE_64 , .atime =NO_CHANGE_64 , .mtime =NO_CHANGE_64 ,
fs/cifs/inode.c +7 -7
@@ -1249,14 +1249,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 (); + args.uid =current_fsuid ();if (parent->i_mode &S_ISGID ) - args.gid = (__u64 )parent->i_gid; + args.gid = parent->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 ;/* no change */ + args.gid =INVALID_GID ;/* no change */ } CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, cifs_sb->local_nls,
@@ -2017,12 +2017,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 =INVALID_UID ;/* no change */ if (attrs->ia_valid &ATTR_GID ) args->gid = attrs->ia_gid;else - args->gid =NO_CHANGE_64 ; + args->gid =INVALID_GID ;/* no change */ if (attrs->ia_valid &ATTR_ATIME ) args->atime =cifs_UnixTimeToNT (attrs->ia_atime);
Signature · 1 line
1.7.5.4