2012-11-20 12:42:39

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 0/12] Final userns conversions


This patchset contain the basic user namespace changes for filesystems
that have needed nontrivial work. Along with the 2 patches that depend
on these changes.

I belive these patches to be correct for allowing the remaining
filesystems to work in the presence of user namespaces. At the same
time I would like to give all of these much deeper scrutiny, just
because there is so much going on. Unfortunately these patches
individually are not obviously correct.

Since I won't have much time until after Thanksgiving and because the
merge window is looming I figure I will put these changes out there and
let people see I am looking at these changes, and see if anyone happens
to spot anything.

If I can figure out how to responsibly get these changes into linux-next
I want to get these changes into linux-next so that user namespace bugs
show up in allyesconfig builds.

For people who want to see what else I am cooking my git tree is at:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git

Eric W. Biederman (12):
userns: Support 9p interacting with multiple user namespaces
userns: Convert afs to use kuid/kgid where appropriate
userns: Convert ceph to use kuid/kgid where appropriate
userns: Convert cifs to use kuid/kgid where appropriate
userns: Convert coda's to use kuid/kgid where appropriate
userns: Convert gfs2 to use kuid/kgid where appropriate
userns: Convert ncpfs to use kuid and kgid where appropriate
userns: Convert nfs and nfsd to use kuid/kgid where appropriate
userns: Convert ocfs2 to use kuid and kgid where appropriate
userns: Convert xfs to use kuid/kgid/kprojid where appropriate
userns: Now that everything has been converted remove the unnecessary infrastructure
userns: Remove the EXPERMINTAL kconfig tag

fs/9p/fid.c | 17 +++--
fs/9p/v9fs.c | 34 ++++++++--
fs/9p/v9fs.h | 10 ++--
fs/9p/vfs_inode.c | 8 +-
fs/9p/vfs_inode_dotl.c | 22 +++---
fs/afs/afs.h | 4 +-
fs/afs/fsclient.c | 14 +++-
fs/afs/inode.c | 6 +-
fs/ceph/caps.c | 16 ++--
fs/ceph/inode.c | 18 +++---
fs/ceph/mds_client.c | 4 +-
fs/ceph/super.h | 4 +-
fs/cifs/cifs_fs_sb.h | 8 +-
fs/cifs/cifs_spnego.c | 4 +-
fs/cifs/cifsacl.c | 115 +++++++++++++++++++++++++--------
fs/cifs/cifsacl.h | 16 ++++-
fs/cifs/cifsfs.c | 12 ++-
fs/cifs/cifsglob.h | 22 +++---
fs/cifs/cifspdu.h | 2 +
fs/cifs/cifsproto.h | 9 ++-
fs/cifs/cifssmb.c | 11 +++-
fs/cifs/connect.c | 58 +++++++++++++----
fs/cifs/dir.c | 18 +++---
fs/cifs/file.c | 8 +-
fs/cifs/inode.c | 28 ++++----
fs/cifs/misc.c | 2 +-
fs/coda/cache.c | 4 +-
fs/coda/coda_fs_i.h | 2 +-
fs/coda/coda_linux.c | 8 +-
fs/coda/inode.c | 2 +-
fs/coda/upcall.c | 6 +-
fs/gfs2/acl.c | 2 +-
fs/gfs2/bmap.c | 2 +-
fs/gfs2/dir.c | 2 +-
fs/gfs2/glops.c | 4 +-
fs/gfs2/incore.h | 3 +-
fs/gfs2/inode.c | 36 ++++++-----
fs/gfs2/quota.c | 128 ++++++++++++++++---------------------
fs/gfs2/quota.h | 15 ++--
fs/gfs2/super.c | 6 +-
fs/gfs2/sys.c | 14 ++++-
fs/gfs2/xattr.c | 4 +-
fs/ncpfs/inode.c | 55 ++++++++++------
fs/ncpfs/ioctl.c | 25 ++++---
fs/ncpfs/ncp_fs_sb.h | 6 +-
fs/nfs/idmap.c | 45 ++++++++-----
fs/nfs/inode.c | 12 ++--
fs/nfs/nfs2xdr.c | 8 +-
fs/nfs/nfs3xdr.c | 8 +-
fs/nfs/nfs4xdr.c | 16 ++--
fs/nfs_common/nfsacl.c | 37 ++++++----
fs/nfsd/acl.h | 2 -
fs/nfsd/auth.c | 12 ++--
fs/nfsd/export.c | 22 ++++--
fs/nfsd/idmap.h | 8 +-
fs/nfsd/nfs3xdr.c | 9 ++-
fs/nfsd/nfs4acl.c | 63 +++++++++++++-----
fs/nfsd/nfs4idmap.c | 34 ++++++----
fs/nfsd/nfs4recover.c | 4 +-
fs/nfsd/nfs4state.c | 6 +-
fs/nfsd/nfs4xdr.c | 42 ++++++++-----
fs/nfsd/nfsxdr.c | 9 ++-
fs/nfsd/vfs.c | 8 +-
fs/ocfs2/acl.c | 31 ++++++++-
fs/ocfs2/dlmglue.c | 8 +-
fs/ocfs2/file.c | 11 ++--
fs/ocfs2/inode.c | 12 ++--
fs/ocfs2/namei.c | 4 +-
fs/ocfs2/refcounttree.c | 2 +-
fs/xfs/xfs_acl.c | 23 ++++++-
fs/xfs/xfs_dquot.c | 36 +++++++----
fs/xfs/xfs_dquot.h | 5 +-
fs/xfs/xfs_inode.c | 33 ++++++----
fs/xfs/xfs_inode.h | 32 ++--------
fs/xfs/xfs_ioctl.c | 23 +++++--
fs/xfs/xfs_iops.c | 18 +++---
fs/xfs/xfs_itable.c | 8 +-
fs/xfs/xfs_qm.c | 87 +++++++++++++------------
fs/xfs/xfs_qm.h | 4 +-
fs/xfs/xfs_qm_bhv.c | 3 +-
fs/xfs/xfs_qm_syscalls.c | 24 ++++---
fs/xfs/xfs_quota.h | 4 +-
fs/xfs/xfs_quotaops.c | 20 +-----
fs/xfs/xfs_rename.c | 2 +-
fs/xfs/xfs_trans_dquot.c | 6 +--
fs/xfs/xfs_utils.c | 2 +-
fs/xfs/xfs_utils.h | 2 +-
fs/xfs/xfs_vnodeops.c | 14 ++--
include/linux/coda_psdev.h | 2 +-
include/linux/nfs4.h | 6 ++-
include/linux/nfs_idmap.h | 10 ++--
include/linux/nfs_xdr.h | 4 +-
include/linux/nfsd/export.h | 4 +-
include/linux/posix_acl.h | 3 -
include/linux/projid.h | 15 ----
include/linux/sunrpc/auth.h | 7 +-
include/linux/sunrpc/svcauth.h | 4 +-
include/linux/uidgid.h | 22 ------
include/net/9p/client.h | 12 ++--
init/Kconfig | 40 +-----------
net/9p/client.c | 28 +++++----
net/sunrpc/auth.c | 6 +-
net/sunrpc/auth_generic.c | 16 +++--
net/sunrpc/auth_gss/auth_gss.c | 33 ++++++----
net/sunrpc/auth_gss/svcauth_gss.c | 14 ++++-
net/sunrpc/auth_unix.c | 36 ++++------
net/sunrpc/svcauth_unix.c | 40 +++++++-----
107 files changed, 1035 insertions(+), 820 deletions(-)


2012-11-20 12:44:03

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 01/12] userns: Support 9p interacting with multiple user namespaces

From: "Eric W. Biederman" <[email protected]>

Use kuid_t and kgid_t in struct v9fs_session_info and struct 9p_fid.

Cc: Eric Van Hensbergen <[email protected]>
Cc: Ron Minnich <[email protected]>
Cc: Latchesar Ionkov <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/9p/fid.c | 17 +++++++++--------
fs/9p/v9fs.c | 34 +++++++++++++++++++++++++++-------
fs/9p/v9fs.h | 10 +++++-----
fs/9p/vfs_inode.c | 8 ++++----
fs/9p/vfs_inode_dotl.c | 22 +++++++++++-----------
include/net/9p/client.h | 12 ++++++------
init/Kconfig | 4 ----
net/9p/client.c | 28 ++++++++++++++++------------
8 files changed, 78 insertions(+), 57 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index da8eefb..afd4724 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -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;
/*
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index d934f04..1c750ab 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -161,7 +161,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
ret = r;
continue;
}
- v9ses->dfltuid = option;
+ v9ses->dfltuid = make_kuid(&init_user_ns, option);
+ if (!uid_valid(v9ses->dfltuid)) {
+ p9_debug(P9_DEBUG_ERROR,
+ "uid field, but not a uid?\n");
+ ret = -EINVAL;
+ continue;
+ }
break;
case Opt_dfltgid:
r = match_int(&args[0], &option);
@@ -171,7 +177,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
ret = r;
continue;
}
- v9ses->dfltgid = option;
+ v9ses->dfltgid = make_kgid(&init_user_ns, option);
+ if (!gid_valid(v9ses->dfltgid)) {
+ p9_debug(P9_DEBUG_ERROR,
+ "gid field, but not a gid?\n");
+ ret = -EINVAL;
+ continue;
+ }
break;
case Opt_afid:
r = match_int(&args[0], &option);
@@ -248,8 +260,9 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
else if (strcmp(s, "client") == 0) {
v9ses->flags |= V9FS_ACCESS_CLIENT;
} else {
+ uid_t uid;
v9ses->flags |= V9FS_ACCESS_SINGLE;
- v9ses->uid = simple_strtoul(s, &e, 10);
+ uid = simple_strtoul(s, &e, 10);
if (*e != '\0') {
ret = -EINVAL;
pr_info("Unknown access argument %s\n",
@@ -257,6 +270,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
kfree(s);
goto free_and_return;
}
+ v9ses->uid = make_kuid(&init_user_ns, uid);
+ if (!uid_valid(v9ses->uid)) {
+ ret = -EINVAL;
+ pr_info("Uknown uid %s\n", s);
+ kfree(s);
+ goto free_and_return;
+ }
}

kfree(s);
@@ -319,7 +339,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
list_add(&v9ses->slist, &v9fs_sessionlist);
spin_unlock(&v9fs_sessionlist_lock);

- v9ses->uid = ~0;
+ v9ses->uid = INVALID_UID;
v9ses->dfltuid = V9FS_DEFUID;
v9ses->dfltgid = V9FS_DEFGID;

@@ -364,7 +384,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,

v9ses->flags &= ~V9FS_ACCESS_MASK;
v9ses->flags |= V9FS_ACCESS_ANY;
- v9ses->uid = ~0;
+ v9ses->uid = INVALID_UID;
}
if (!v9fs_proto_dotl(v9ses) ||
!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
@@ -375,7 +395,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
v9ses->flags &= ~V9FS_ACL_MASK;
}

- fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
+ fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID,
v9ses->aname);
if (IS_ERR(fid)) {
retval = PTR_ERR(fid);
@@ -387,7 +407,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
fid->uid = v9ses->uid;
else
- fid->uid = ~0;
+ fid->uid = INVALID_UID;

#ifdef CONFIG_9P_FSCACHE
/* register the session for caching */
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 34c59f1..a8e127c 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -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)
{
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 890bed5..2c0f777 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1137,10 +1137,10 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)

if (v9fs_proto_dotu(v9ses)) {
if (iattr->ia_valid & ATTR_UID)
- wstat.n_uid = iattr->ia_uid;
+ wstat.n_uid = from_kuid(&init_user_ns, iattr->ia_uid);

if (iattr->ia_valid & ATTR_GID)
- wstat.n_gid = iattr->ia_gid;
+ wstat.n_gid = from_kgid(&init_user_ns, iattr->ia_gid);
}

/* Write all dirty data */
@@ -1191,8 +1191,8 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
inode->i_gid = v9ses->dfltgid;

if (v9fs_proto_dotu(v9ses)) {
- inode->i_uid = stat->n_uid;
- inode->i_gid = stat->n_gid;
+ i_uid_write(inode, stat->n_uid);
+ i_gid_write(inode, stat->n_gid);
}
if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 4089554..e8695df 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -57,7 +57,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
* group of the new file system object.
*/

-static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
+static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
{
BUG_ON(dir_inode == NULL);

@@ -246,7 +246,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
int *opened)
{
int err = 0;
- gid_t gid;
+ kgid_t gid;
umode_t mode;
char *name = NULL;
struct p9_qid qid;
@@ -391,7 +391,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
int err;
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL;
- gid_t gid;
+ kgid_t gid;
char *name;
umode_t mode;
struct inode *inode;
@@ -576,8 +576,8 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)

p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid);
p9attr.mode = iattr->ia_mode;
- p9attr.uid = iattr->ia_uid;
- p9attr.gid = iattr->ia_gid;
+ p9attr.uid = from_kuid(&init_user_ns, iattr->ia_uid);
+ p9attr.gid = from_kgid(&init_user_ns, iattr->ia_gid);
p9attr.size = iattr->ia_size;
p9attr.atime_sec = iattr->ia_atime.tv_sec;
p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
@@ -635,8 +635,8 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
inode->i_ctime.tv_sec = stat->st_ctime_sec;
inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
- inode->i_uid = stat->st_uid;
- inode->i_gid = stat->st_gid;
+ i_uid_write(inode, stat->st_uid);
+ i_gid_write(inode, stat->st_gid);
set_nlink(inode, stat->st_nlink);

mode = stat->st_mode & S_IALLUGO;
@@ -659,9 +659,9 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
}
if (stat->st_result_mask & P9_STATS_UID)
- inode->i_uid = stat->st_uid;
+ i_uid_write(inode, stat->st_uid);
if (stat->st_result_mask & P9_STATS_GID)
- inode->i_gid = stat->st_gid;
+ i_gid_write(inode, stat->st_gid);
if (stat->st_result_mask & P9_STATS_NLINK)
set_nlink(inode, stat->st_nlink);
if (stat->st_result_mask & P9_STATS_MODE) {
@@ -692,7 +692,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
const char *symname)
{
int err;
- gid_t gid;
+ kgid_t gid;
char *name;
struct p9_qid qid;
struct inode *inode;
@@ -832,7 +832,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
dev_t rdev)
{
int err;
- gid_t gid;
+ kgid_t gid;
char *name;
umode_t mode;
struct v9fs_session_info *v9ses;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index fc9b90b..4d05d94 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -187,7 +187,7 @@ struct p9_fid {
int mode;
struct p9_qid qid;
u32 iounit;
- uid_t uid;
+ kuid_t uid;

void *rdir;

@@ -220,17 +220,17 @@ void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
void p9_client_begin_disconnect(struct p9_client *clnt);
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
- char *uname, u32 n_uname, char *aname);
+ char *uname, kuid_t n_uname, char *aname);
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
char **wnames, int clone);
int p9_client_open(struct p9_fid *fid, int mode);
int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
char *extension);
int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname);
-int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid,
+int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, kgid_t gid,
struct p9_qid *qid);
int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
- gid_t gid, struct p9_qid *qid);
+ kgid_t gid, struct p9_qid *qid);
int p9_client_clunk(struct p9_fid *fid);
int p9_client_fsync(struct p9_fid *fid, int datasync);
int p9_client_remove(struct p9_fid *fid);
@@ -250,9 +250,9 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
u64 request_mask);

int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode,
- dev_t rdev, gid_t gid, struct p9_qid *);
+ dev_t rdev, kgid_t gid, struct p9_qid *);
int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
- gid_t gid, struct p9_qid *);
+ kgid_t gid, struct p9_qid *);
int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
diff --git a/init/Kconfig b/init/Kconfig
index 38c1a1d..35c1b89 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -998,11 +998,7 @@ config UIDGID_CONVERTED
bool
default y

- # Networking
- depends on NET_9P = n
-
# Filesystems
- depends on 9P_FS = n
depends on AFS_FS = n
depends on CEPH_FS = n
depends on CIFS = n
diff --git a/net/9p/client.c b/net/9p/client.c
index 34d4176..25d58f4 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1100,7 +1100,7 @@ void p9_client_begin_disconnect(struct p9_client *clnt)
EXPORT_SYMBOL(p9_client_begin_disconnect);

struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
- char *uname, u32 n_uname, char *aname)
+ char *uname, kuid_t n_uname, char *aname)
{
int err = 0;
struct p9_req_t *req;
@@ -1118,7 +1118,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
}

req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
- afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
+ afid ? afid->fid : P9_NOFID, uname, aname,
+ from_kuid(&init_user_ns, n_uname));
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
@@ -1270,7 +1271,7 @@ error:
EXPORT_SYMBOL(p9_client_open);

int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
- gid_t gid, struct p9_qid *qid)
+ kgid_t gid, struct p9_qid *qid)
{
int err = 0;
struct p9_client *clnt;
@@ -1279,14 +1280,16 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,

p9_debug(P9_DEBUG_9P,
">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
- ofid->fid, name, flags, mode, gid);
+ ofid->fid, name, flags, mode,
+ from_kgid(&init_user_ns, gid));
clnt = ofid->clnt;

if (ofid->mode != -1)
return -EINVAL;

req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags,
- mode, gid);
+ mode,
+ from_kgid(&init_user_ns, gid));
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
@@ -1358,7 +1361,7 @@ error:
}
EXPORT_SYMBOL(p9_client_fcreate);

-int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
+int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, kgid_t gid,
struct p9_qid *qid)
{
int err = 0;
@@ -1370,7 +1373,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
clnt = dfid->clnt;

req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt,
- gid);
+ from_kgid(&init_user_ns, gid));
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
@@ -2106,7 +2109,7 @@ error:
EXPORT_SYMBOL(p9_client_readdir);

int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
- dev_t rdev, gid_t gid, struct p9_qid *qid)
+ dev_t rdev, kgid_t gid, struct p9_qid *qid)
{
int err;
struct p9_client *clnt;
@@ -2117,7 +2120,8 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
"minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode,
- MAJOR(rdev), MINOR(rdev), gid);
+ MAJOR(rdev), MINOR(rdev),
+ from_kgid(&init_user_ns, gid));
if (IS_ERR(req))
return PTR_ERR(req);

@@ -2137,7 +2141,7 @@ error:
EXPORT_SYMBOL(p9_client_mknod_dotl);

int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
- gid_t gid, struct p9_qid *qid)
+ kgid_t gid, struct p9_qid *qid)
{
int err;
struct p9_client *clnt;
@@ -2146,9 +2150,9 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
err = 0;
clnt = fid->clnt;
p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
- fid->fid, name, mode, gid);
+ fid->fid, name, mode, from_kgid(&init_user_ns, gid));
req = p9_client_rpc(clnt, P9_TMKDIR, "dsdd", fid->fid, name, mode,
- gid);
+ from_kgid(&init_user_ns, gid));
if (IS_ERR(req))
return PTR_ERR(req);

--
1.7.5.4

2012-11-20 12:44:09

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 02/12] userns: Convert afs to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: David Howells <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/afs/afs.h | 4 ++--
fs/afs/fsclient.c | 14 ++++++++++----
fs/afs/inode.c | 6 +++---
init/Kconfig | 1 -
4 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index c548aa3..ba7ac7b 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -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 */
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index b960ff0..eecbf4b 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -42,6 +42,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
umode_t mode;
u64 data_version, size;
u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
+ u32 owner;
+ u32 group;

#define EXTRACT(DST) \
do { \
@@ -56,7 +58,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
size = ntohl(*bp++);
data_version = ntohl(*bp++);
EXTRACT(status->author);
- EXTRACT(status->owner);
+ owner = from_kuid(&init_user_ns, status->owner);
+ EXTRACT(owner);
+ status->owner = make_kuid(&init_user_ns, owner);
EXTRACT(status->caller_access); /* call ticket dependent */
EXTRACT(status->anon_access);
EXTRACT(status->mode);
@@ -65,7 +69,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
bp++; /* seg size */
status->mtime_client = ntohl(*bp++);
status->mtime_server = ntohl(*bp++);
- EXTRACT(status->group);
+ group = from_kgid(&init_user_ns, status->group);
+ EXTRACT(group);
+ status->group = make_kgid(&init_user_ns, group);
bp++; /* sync counter */
data_version |= (u64) ntohl(*bp++) << 32;
EXTRACT(status->lock_count);
@@ -181,12 +187,12 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)

if (attr->ia_valid & ATTR_UID) {
mask |= AFS_SET_OWNER;
- owner = attr->ia_uid;
+ owner = from_kuid(&init_user_ns, attr->ia_uid);
}

if (attr->ia_valid & ATTR_GID) {
mask |= AFS_SET_GROUP;
- group = attr->ia_gid;
+ group = from_kgid(&init_user_ns, attr->ia_gid);
}

if (attr->ia_valid & ATTR_MODE) {
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 95cffd3..789bc25 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -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;
diff --git a/init/Kconfig b/init/Kconfig
index 35c1b89..dfa391d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on AFS_FS = n
depends on CEPH_FS = n
depends on CIFS = n
depends on CODA_FS = n
--
1.7.5.4

2012-11-20 12:44:16

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: Sage Weil <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/ceph/caps.c | 16 ++++++++--------
fs/ceph/inode.c | 18 +++++++++---------
fs/ceph/mds_client.c | 4 ++--
fs/ceph/super.h | 4 ++--
init/Kconfig | 1 -
5 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 3251e9c..ee29cc6 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -928,7 +928,7 @@ static int send_cap_msg(struct ceph_mds_session *session,
u64 size, u64 max_size,
struct timespec *mtime, struct timespec *atime,
u64 time_warp_seq,
- uid_t uid, gid_t gid, umode_t mode,
+ kuid_t uid, kgid_t gid, umode_t mode,
u64 xattr_version,
struct ceph_buffer *xattrs_buf,
u64 follows)
@@ -972,8 +972,8 @@ static int send_cap_msg(struct ceph_mds_session *session,
ceph_encode_timespec(&fc->atime, atime);
fc->time_warp_seq = cpu_to_le32(time_warp_seq);

- fc->uid = cpu_to_le32(uid);
- fc->gid = cpu_to_le32(gid);
+ fc->uid = cpu_to_le32(from_kuid(&init_user_ns, uid));
+ fc->gid = cpu_to_le32(from_kgid(&init_user_ns, gid));
fc->mode = cpu_to_le32(mode);

fc->xattr_version = cpu_to_le64(xattr_version);
@@ -1079,8 +1079,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
struct timespec mtime, atime;
int wake = 0;
umode_t mode;
- uid_t uid;
- gid_t gid;
+ kuid_t uid;
+ kgid_t gid;
struct ceph_mds_session *session;
u64 xattr_version = 0;
struct ceph_buffer *xattr_blob = NULL;
@@ -2353,10 +2353,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,

if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
inode->i_mode = le32_to_cpu(grant->mode);
- inode->i_uid = le32_to_cpu(grant->uid);
- inode->i_gid = le32_to_cpu(grant->gid);
+ i_uid_write(inode, le32_to_cpu(grant->uid));
+ i_gid_write(inode, le32_to_cpu(grant->gid));
dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
- inode->i_uid, inode->i_gid);
+ i_uid_read(inode), i_gid_read(inode));
}

if ((issued & CEPH_CAP_LINK_EXCL) == 0)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index ba95eea..195b7fd 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -612,10 +612,10 @@ static int fill_inode(struct inode *inode,

if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
inode->i_mode = le32_to_cpu(info->mode);
- inode->i_uid = le32_to_cpu(info->uid);
- inode->i_gid = le32_to_cpu(info->gid);
+ i_uid_write(inode, le32_to_cpu(info->uid));
+ i_gid_write(inode, le32_to_cpu(info->gid));
dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
- inode->i_uid, inode->i_gid);
+ i_uid_read(inode), i_gid_read(inode));
}

if ((issued & CEPH_CAP_LINK_EXCL) == 0)
@@ -1562,26 +1562,26 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)

if (ia_valid & ATTR_UID) {
dout("setattr %p uid %d -> %d\n", inode,
- inode->i_uid, attr->ia_uid);
+ i_uid_read(inode), from_kuid(&init_user_ns, attr->ia_uid));
if (issued & CEPH_CAP_AUTH_EXCL) {
inode->i_uid = attr->ia_uid;
dirtied |= CEPH_CAP_AUTH_EXCL;
} else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 ||
- attr->ia_uid != inode->i_uid) {
- req->r_args.setattr.uid = cpu_to_le32(attr->ia_uid);
+ !uid_eq(attr->ia_uid, inode->i_uid)) {
+ req->r_args.setattr.uid = cpu_to_le32(from_kuid(&init_user_ns, attr->ia_uid));
mask |= CEPH_SETATTR_UID;
release |= CEPH_CAP_AUTH_SHARED;
}
}
if (ia_valid & ATTR_GID) {
dout("setattr %p gid %d -> %d\n", inode,
- inode->i_gid, attr->ia_gid);
+ i_gid_read(inode), from_kgid(&init_user_ns, attr->ia_gid));
if (issued & CEPH_CAP_AUTH_EXCL) {
inode->i_gid = attr->ia_gid;
dirtied |= CEPH_CAP_AUTH_EXCL;
} else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 ||
- attr->ia_gid != inode->i_gid) {
- req->r_args.setattr.gid = cpu_to_le32(attr->ia_gid);
+ !gid_eq(attr->ia_gid, inode->i_gid)) {
+ req->r_args.setattr.gid = cpu_to_le32(from_kgid(&init_user_ns, attr->ia_gid));
mask |= CEPH_SETATTR_GID;
release |= CEPH_CAP_AUTH_SHARED;
}
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 1bcf712..59e45fe 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -578,8 +578,8 @@ static void __register_request(struct ceph_mds_client *mdsc,
ceph_mdsc_get_request(req);
__insert_request(mdsc, req);

- req->r_uid = current_fsuid();
- req->r_gid = current_fsgid();
+ req->r_uid = from_kuid(&init_user_ns, current_fsuid());
+ req->r_gid = from_kgid(&init_user_ns, current_fsgid());

if (dir) {
struct ceph_inode_info *ci = ceph_inode(dir);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 66ebe72..f053bbd 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -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;
diff --git a/init/Kconfig b/init/Kconfig
index dfa391d..cb2c46a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on CEPH_FS = n
depends on CIFS = n
depends on CODA_FS = n
depends on GFS2_FS = n
--
1.7.5.4

2012-11-20 12:44:28

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 05/12] userns: Convert coda's to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: Jan Harkes <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/coda/cache.c | 4 ++--
fs/coda/coda_fs_i.h | 2 +-
fs/coda/coda_linux.c | 8 ++++----
fs/coda/inode.c | 2 +-
fs/coda/upcall.c | 6 +++---
include/linux/coda_psdev.h | 2 +-
init/Kconfig | 1 -
7 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 958ae0e..1da168c 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -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);

diff --git a/fs/coda/coda_fs_i.h b/fs/coda/coda_fs_i.h
index b24fdfd..c640752 100644
--- a/fs/coda/coda_fs_i.h
+++ b/fs/coda/coda_fs_i.h
@@ -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;
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 854ace7..38a0a6e 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -100,9 +100,9 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_mode != (u_short) -1)
inode->i_mode = attr->va_mode | inode_type;
if (attr->va_uid != -1)
- inode->i_uid = (uid_t) attr->va_uid;
+ i_uid_write(inode, (uid_t) attr->va_uid);
if (attr->va_gid != -1)
- inode->i_gid = (gid_t) attr->va_gid;
+ i_gid_write(inode, (gid_t) attr->va_gid);
if (attr->va_nlink != -1)
set_nlink(inode, attr->va_nlink);
if (attr->va_size != -1)
@@ -171,10 +171,10 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
vattr->va_mode = iattr->ia_mode;
}
if ( valid & ATTR_UID ) {
- vattr->va_uid = (vuid_t) iattr->ia_uid;
+ vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
}
if ( valid & ATTR_GID ) {
- vattr->va_gid = (vgid_t) iattr->ia_gid;
+ vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
}
if ( valid & ATTR_SIZE ) {
vattr->va_size = iattr->ia_size;
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index be2aa49..19a8018 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -48,7 +48,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
return NULL;
memset(&ei->c_fid, 0, sizeof(struct CodaFid));
ei->c_flags = 0;
- ei->c_uid = 0;
+ ei->c_uid = GLOBAL_ROOT_UID;
ei->c_cached_perm = 0;
spin_lock_init(&ei->c_lock);
return &ei->vfs_inode;
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 0c68fd3..efbc665 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -52,7 +52,7 @@ static void *alloc_upcall(int opcode, int size)
inp->ih.opcode = opcode;
inp->ih.pid = current->pid;
inp->ih.pgid = task_pgrp_nr(current);
- inp->ih.uid = current_fsuid();
+ inp->ih.uid = from_kuid(&init_user_ns, current_fsuid());

return (void*)inp;
}
@@ -157,7 +157,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
}

int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
- vuid_t uid)
+ kuid_t uid)
{
union inputArgs *inp;
union outputArgs *outp;
@@ -166,7 +166,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
insize = SIZE(release);
UPARG(CODA_CLOSE);

- inp->ih.uid = uid;
+ inp->ih.uid = from_kuid(&init_user_ns, uid);
inp->coda_close.VFid = *fid;
inp->coda_close.flags = flags;

diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
index 8031d6e..5b8721e 100644
--- a/include/linux/coda_psdev.h
+++ b/include/linux/coda_psdev.h
@@ -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,
diff --git a/init/Kconfig b/init/Kconfig
index 58959ea..2573664 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on CODA_FS = n
depends on GFS2_FS = n
depends on NCP_FS = n
depends on NFSD = n
--
1.7.5.4

2012-11-20 12:44:42

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 06/12] userns: Convert gfs2 to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

- Use struct kqid to hold the identifier of in core quota objects
- Use qid.type uniformly for all in core quota type computation.
- kill QDF_USER
- kill QUOTA_USER and QUOTA_GROUP

Cc: Steven Whitehouse <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/gfs2/acl.c | 2 +-
fs/gfs2/bmap.c | 2 +-
fs/gfs2/dir.c | 2 +-
fs/gfs2/glops.c | 4 +-
fs/gfs2/incore.h | 3 +-
fs/gfs2/inode.c | 36 ++++++++-------
fs/gfs2/quota.c | 128 +++++++++++++++++++++++------------------------------
fs/gfs2/quota.h | 15 +++---
fs/gfs2/super.c | 6 +-
fs/gfs2/sys.c | 14 +++++-
fs/gfs2/xattr.c | 4 +-
init/Kconfig | 1 -
12 files changed, 106 insertions(+), 111 deletions(-)

diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index f850020..f69ac0a 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -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;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 1fd3ae2..ce2316b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1052,7 +1052,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
if (error)
return error;

- error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (error)
return error;

diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 259b088..5a9f574 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1854,7 +1854,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
if (!ht)
return -ENOMEM;

- error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ error = gfs2_quota_hold(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (error)
goto out;

diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 32cc4fd..f3033f6 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -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));
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 3d469d3..4fccb6c 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -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;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 381893c..bf60354 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -365,13 +365,13 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
}

static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
- unsigned int *uid, unsigned int *gid)
+ kuid_t *uid, kgid_t *gid)
{
if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
- (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
+ (dip->i_inode.i_mode & S_ISUID) && i_uid_read(&dip->i_inode)) {
if (S_ISDIR(*mode))
*mode |= S_ISUID;
- else if (dip->i_inode.i_uid != current_fsuid())
+ else if (!uid_eq(dip->i_inode.i_uid, current_fsuid()))
*mode &= ~07111;
*uid = dip->i_inode.i_uid;
} else
@@ -444,7 +444,7 @@ static void gfs2_init_dir(struct buffer_head *dibh,

static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
const struct gfs2_inum_host *inum, umode_t mode,
- unsigned int uid, unsigned int gid,
+ kuid_t uid, kgid_t gid,
const u64 *generation, dev_t dev, const char *symname,
unsigned size, struct buffer_head **bhp)
{
@@ -462,8 +462,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
di->di_num.no_addr = cpu_to_be64(inum->no_addr);
di->di_mode = cpu_to_be32(mode);
- di->di_uid = cpu_to_be32(uid);
- di->di_gid = cpu_to_be32(gid);
+ di->di_uid = cpu_to_be32(from_kuid(&init_user_ns, uid));
+ di->di_gid = cpu_to_be32(from_kgid(&init_user_ns, gid));
di->di_nlink = 0;
di->di_size = cpu_to_be64(size);
di->di_blocks = cpu_to_be64(1);
@@ -517,7 +517,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
unsigned int size, struct buffer_head **bhp)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
- unsigned int uid, gid;
+ kuid_t uid;
+ kgid_t gid;
int error;

munge_mode_uid_gid(dip, &mode, &uid, &gid);
@@ -558,7 +559,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
if (error)
return error;

- error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ error = gfs2_quota_lock(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (error)
goto fail;

@@ -955,8 +956,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
return -EPERM;

if ((dip->i_inode.i_mode & S_ISVTX) &&
- dip->i_inode.i_uid != current_fsuid() &&
- ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
+ !uid_eq(dip->i_inode.i_uid, current_fsuid()) &&
+ !uid_eq(ip->i_inode.i_uid, current_fsuid()) && !capable(CAP_FOWNER))
return -EPERM;

if (IS_APPEND(&dip->i_inode))
@@ -1571,7 +1572,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
- u32 ouid, ogid, nuid, ngid;
+ kuid_t ouid, nuid;
+ kgid_t ogid, ngid;
int error;

ouid = inode->i_uid;
@@ -1579,16 +1581,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
nuid = attr->ia_uid;
ngid = attr->ia_gid;

- if (!(attr->ia_valid & ATTR_UID) || ouid == nuid)
- ouid = nuid = NO_QUOTA_CHANGE;
- if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
- ogid = ngid = NO_QUOTA_CHANGE;
+ if (!(attr->ia_valid & ATTR_UID) || uid_eq(ouid, nuid))
+ ouid = nuid = NO_UID_QUOTA_CHANGE;
+ if (!(attr->ia_valid & ATTR_GID) || gid_eq(ogid, ngid))
+ ogid = ngid = NO_GID_QUOTA_CHANGE;

error = gfs2_quota_lock(ip, nuid, ngid);
if (error)
return error;

- if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
+ if (uid_valid(ouid) || gid_valid(ogid)) {
error = gfs2_quota_check(ip, nuid, ngid);
if (error)
goto out_gunlock_q;
@@ -1602,7 +1604,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
if (error)
goto out_end_trans;

- if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
+ if (uid_valid(ouid) || gid_valid(ogid)) {
u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
gfs2_quota_change(ip, -blocks, ouid, ogid);
gfs2_quota_change(ip, blocks, nuid, ngid);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 40c4b0d..f2353b5 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -65,19 +65,22 @@
#include "inode.h"
#include "util.h"

-#define QUOTA_USER 1
-#define QUOTA_GROUP 0
-
struct gfs2_quota_change_host {
u64 qc_change;
u32 qc_flags; /* GFS2_QCF_... */
- u32 qc_id;
+ struct kqid qc_id;
};

static LIST_HEAD(qd_lru_list);
static atomic_t qd_lru_count = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(qd_lru_lock);

+static u64 gfs2_qid_number(struct kqid qid)
+{
+ return (2 * (u64)from_kqid(&init_user_ns, qid)) +
+ (qid.type == USRQUOTA) ? 0 : 1;
+}
+
int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
{
struct gfs2_quota_data *qd;
@@ -124,13 +127,13 @@ static u64 qd2offset(struct gfs2_quota_data *qd)
{
u64 offset;

- offset = 2 * (u64)qd->qd_id + !test_bit(QDF_USER, &qd->qd_flags);
+ offset = gfs2_qid_number(qd->qd_id);
offset *= sizeof(struct gfs2_quota);

return offset;
}

-static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
+static int qd_alloc(struct gfs2_sbd *sdp, struct kqid qid,
struct gfs2_quota_data **qdp)
{
struct gfs2_quota_data *qd;
@@ -141,13 +144,11 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
return -ENOMEM;

atomic_set(&qd->qd_count, 1);
- qd->qd_id = id;
- if (user)
- set_bit(QDF_USER, &qd->qd_flags);
+ qd->qd_id = qid;
qd->qd_slot = -1;
INIT_LIST_HEAD(&qd->qd_reclaim);

- error = gfs2_glock_get(sdp, 2 * (u64)id + !user,
+ error = gfs2_glock_get(sdp, gfs2_qid_number(qid),
&gfs2_quota_glops, CREATE, &qd->qd_gl);
if (error)
goto fail;
@@ -161,8 +162,8 @@ fail:
return error;
}

-static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
- struct gfs2_quota_data **qdp)
+static int qd_get(struct gfs2_sbd *sdp,
+ struct kqid qid, struct gfs2_quota_data **qdp)
{
struct gfs2_quota_data *qd = NULL, *new_qd = NULL;
int error, found;
@@ -173,8 +174,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
found = 0;
spin_lock(&qd_lru_lock);
list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
- if (qd->qd_id == id &&
- !test_bit(QDF_USER, &qd->qd_flags) == !user) {
+ if (qid_eq(qd->qd_id, qid)) {
if (!atomic_read(&qd->qd_count) &&
!list_empty(&qd->qd_reclaim)) {
/* Remove it from reclaim list */
@@ -208,7 +208,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
return 0;
}

- error = qd_alloc(sdp, user, id, &new_qd);
+ error = qd_alloc(sdp, qid, &new_qd);
if (error)
return error;
}
@@ -458,12 +458,12 @@ static void qd_unlock(struct gfs2_quota_data *qd)
qd_put(qd);
}

-static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id,
+static int qdsb_get(struct gfs2_sbd *sdp, struct kqid qid,
struct gfs2_quota_data **qdp)
{
int error;

- error = qd_get(sdp, user, id, qdp);
+ error = qd_get(sdp, qid, qdp);
if (error)
return error;

@@ -491,7 +491,7 @@ static void qdsb_put(struct gfs2_quota_data *qd)
qd_put(qd);
}

-int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
+int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_quota_data **qd;
@@ -509,28 +509,28 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return 0;

- error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd);
+ error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd);
if (error)
goto out;
ip->i_res->rs_qa_qd_num++;
qd++;

- error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd);
+ error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd);
if (error)
goto out;
ip->i_res->rs_qa_qd_num++;
qd++;

- if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) {
- error = qdsb_get(sdp, QUOTA_USER, uid, qd);
+ if (uid_valid(uid) && !uid_eq(uid, ip->i_inode.i_uid)) {
+ error = qdsb_get(sdp, make_kqid_uid(uid), qd);
if (error)
goto out;
ip->i_res->rs_qa_qd_num++;
qd++;
}

- if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) {
- error = qdsb_get(sdp, QUOTA_GROUP, gid, qd);
+ if (gid_valid(gid) && !gid_eq(gid, ip->i_inode.i_gid)) {
+ error = qdsb_get(sdp, make_kqid_gid(gid), qd);
if (error)
goto out;
ip->i_res->rs_qa_qd_num++;
@@ -564,18 +564,10 @@ static int sort_qd(const void *a, const void *b)
const struct gfs2_quota_data *qd_a = *(const struct gfs2_quota_data **)a;
const struct gfs2_quota_data *qd_b = *(const struct gfs2_quota_data **)b;

- if (!test_bit(QDF_USER, &qd_a->qd_flags) !=
- !test_bit(QDF_USER, &qd_b->qd_flags)) {
- if (test_bit(QDF_USER, &qd_a->qd_flags))
- return -1;
- else
- return 1;
- }
- if (qd_a->qd_id < qd_b->qd_id)
+ if (qid_lt(qd_a->qd_id, qd_b->qd_id))
return -1;
- if (qd_a->qd_id > qd_b->qd_id)
+ if (qid_lt(qd_b->qd_id, qd_a->qd_id))
return 1;
-
return 0;
}

@@ -592,9 +584,9 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
if (!test_bit(QDF_CHANGE, &qd->qd_flags)) {
qc->qc_change = 0;
qc->qc_flags = 0;
- if (test_bit(QDF_USER, &qd->qd_flags))
+ if (qd->qd_id.type == USRQUOTA)
qc->qc_flags = cpu_to_be32(GFS2_QCF_USER);
- qc->qc_id = cpu_to_be32(qd->qd_id);
+ qc->qc_id = cpu_to_be32(from_kqid(&init_user_ns, qd->qd_id));
}

x = be64_to_cpu(qc->qc_change) + change;
@@ -922,7 +914,7 @@ fail:
return error;
}

-int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
+int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_quota_data *qd;
@@ -1037,19 +1029,20 @@ static int print_message(struct gfs2_quota_data *qd, char *type)

printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n",
sdp->sd_fsname, type,
- (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",
- qd->qd_id);
+ (qd->qd_id.type == USRQUOTA) ? "user" : "group",
+ from_kqid(&init_user_ns, qd->qd_id));

return 0;
}

-int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
+int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_quota_data *qd;
s64 value;
unsigned int x;
int error = 0;
+ int user;

if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
return 0;
@@ -1060,8 +1053,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
qd = ip->i_res->rs_qa_qd[x];

- if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
- (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))))
+ user = (qd->qd_id.type == USRQUOTA);
+ if (!((user && uid_eq(qd->qd_id.uid, uid)) ||
+ (!user && gid_eq(qd->qd_id.gid, gid))))
continue;

value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
@@ -1071,10 +1065,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)

if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
print_message(qd, "exceeded");
- quota_send_warning(make_kqid(&init_user_ns,
- test_bit(QDF_USER, &qd->qd_flags) ?
- USRQUOTA : GRPQUOTA,
- qd->qd_id),
+ quota_send_warning(qd->qd_id,
sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN);

error = -EDQUOT;
@@ -1084,10 +1075,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
time_after_eq(jiffies, qd->qd_last_warn +
gfs2_tune_get(sdp,
gt_quota_warn_period) * HZ)) {
- quota_send_warning(make_kqid(&init_user_ns,
- test_bit(QDF_USER, &qd->qd_flags) ?
- USRQUOTA : GRPQUOTA,
- qd->qd_id),
+ quota_send_warning(qd->qd_id,
sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
error = print_message(qd, "warning");
qd->qd_last_warn = jiffies;
@@ -1098,10 +1086,11 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
}

void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
- u32 uid, u32 gid)
+ kuid_t uid, kgid_t gid)
{
struct gfs2_quota_data *qd;
unsigned int x;
+ int user;

if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
return;
@@ -1111,8 +1100,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
qd = ip->i_res->rs_qa_qd[x];

- if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
- (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) {
+ user = (qd->qd_id.type == USRQUOTA);
+ if ((user && uid_eq(qd->qd_id.uid, uid)) ||
+ (!user && gid_eq(qd->qd_id.gid, gid))) {
do_qc(qd, change);
}
}
@@ -1167,13 +1157,13 @@ static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
return gfs2_quota_sync(sb, type);
}

-int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
+int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid)
{
struct gfs2_quota_data *qd;
struct gfs2_holder q_gh;
int error;

- error = qd_get(sdp, user, id, &qd);
+ error = qd_get(sdp, qid, &qd);
if (error)
return error;

@@ -1191,7 +1181,9 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *

qc->qc_change = be64_to_cpu(str->qc_change);
qc->qc_flags = be32_to_cpu(str->qc_flags);
- qc->qc_id = be32_to_cpu(str->qc_id);
+ qc->qc_id = make_kqid(&init_user_ns,
+ (qc->qc_flags & GFS2_QCF_USER)?USRQUOTA:GRPQUOTA,
+ be32_to_cpu(str->qc_id));
}

int gfs2_quota_init(struct gfs2_sbd *sdp)
@@ -1254,8 +1246,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
if (!qc.qc_change)
continue;

- error = qd_alloc(sdp, (qc.qc_flags & GFS2_QCF_USER),
- qc.qc_id, &qd);
+ error = qd_alloc(sdp, qc.qc_id, &qd);
if (error) {
brelse(bh);
goto fail;
@@ -1482,21 +1473,17 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
struct gfs2_quota_data *qd;
struct gfs2_holder q_gh;
int error;
- int type;

memset(fdq, 0, sizeof(struct fs_disk_quota));

if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return -ESRCH; /* Crazy XFS error code */

- if (qid.type == USRQUOTA)
- type = QUOTA_USER;
- else if (qid.type == GRPQUOTA)
- type = QUOTA_GROUP;
- else
+ if ((qid.type != USRQUOTA) &&
+ (qid.type != GRPQUOTA))
return -EINVAL;

- error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
+ error = qd_get(sdp, qid, &qd);
if (error)
return error;
error = do_glock(qd, FORCE, &q_gh);
@@ -1505,8 +1492,8 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,

qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
fdq->d_version = FS_DQUOT_VERSION;
- fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
- fdq->d_id = from_kqid(&init_user_ns, qid);
+ fdq->d_flags = (qid.type == USRQUOTA) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
+ fdq->d_id = from_kqid_munged(current_user_ns(), qid);
fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
@@ -1532,19 +1519,16 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
int alloc_required;
loff_t offset;
int error;
- int type;

if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return -ESRCH; /* Crazy XFS error code */

switch(qid.type) {
case USRQUOTA:
- type = QUOTA_USER;
if (fdq->d_flags != FS_USER_QUOTA)
return -EINVAL;
break;
case GRPQUOTA:
- type = QUOTA_GROUP;
if (fdq->d_flags != FS_GROUP_QUOTA)
return -EINVAL;
break;
@@ -1554,10 +1538,10 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,

if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
return -EINVAL;
- if (fdq->d_id != from_kqid(&init_user_ns, qid))
+ if (!qid_eq(make_kqid(current_user_ns(), qid.type, fdq->d_id), qid))
return -EINVAL;

- error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
+ error = qd_get(sdp, qid, &qd);
if (error)
return error;

diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index f25d98b..4f5e6e4 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -14,20 +14,21 @@ struct gfs2_inode;
struct gfs2_sbd;
struct shrink_control;

-#define NO_QUOTA_CHANGE ((u32)-1)
+#define NO_UID_QUOTA_CHANGE INVALID_UID
+#define NO_GID_QUOTA_CHANGE INVALID_GID

-extern int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
extern void gfs2_quota_unhold(struct gfs2_inode *ip);

-extern int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
extern void gfs2_quota_unlock(struct gfs2_inode *ip);

-extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
- u32 uid, u32 gid);
+ kuid_t uid, kgid_t gid);

extern int gfs2_quota_sync(struct super_block *sb, int type);
-extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
+extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid);

extern int gfs2_quota_init(struct gfs2_sbd *sdp);
extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
@@ -41,7 +42,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
int ret;
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return 0;
- ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (ret)
return ret;
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index bc73726..b4340b8 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -721,8 +721,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
- str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
- str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+ str->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
+ str->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -1428,7 +1428,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
if (error)
return error;

- error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (error)
return error;

diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 8056b7b..0153040 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -176,6 +176,7 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
size_t len)
{
int error;
+ struct kqid qid;
u32 id;

if (!capable(CAP_SYS_ADMIN))
@@ -183,7 +184,11 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,

id = simple_strtoul(buf, NULL, 0);

- error = gfs2_quota_refresh(sdp, 1, id);
+ qid = make_kqid(&init_user_ns, USRQUOTA, id);
+ if (!qid_valid(qid))
+ return -EINVAL;
+
+ error = gfs2_quota_refresh(sdp, qid);
return error ? error : len;
}

@@ -191,6 +196,7 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
size_t len)
{
int error;
+ struct kqid qid;
u32 id;

if (!capable(CAP_SYS_ADMIN))
@@ -198,7 +204,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,

id = simple_strtoul(buf, NULL, 0);

- error = gfs2_quota_refresh(sdp, 0, id);
+ qid = make_kqid(&init_user_ns, GRPQUOTA, id);
+ if (!qid_valid(qid))
+ return -EINVAL;
+
+ error = gfs2_quota_refresh(sdp, qid);
return error ? error : len;
}

diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index db330e5..342f93e 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -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;

diff --git a/init/Kconfig b/init/Kconfig
index 2573664..53b61cd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on GFS2_FS = n
depends on NCP_FS = n
depends on NFSD = n
depends on NFS_FS = n
--
1.7.5.4

2012-11-20 12:44:53

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 08/12] userns: Convert nfs and nfsd to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Changed as many fields as practical to be kuid_t and kgid_t. With
the result that we create kuids and kgids in the network decodes
and we change out of kuids and kgids in the network encoders.

The one slight exception to this is the name to id mapping
where we use a plane unsigned integer as the key, instead of
a kuid_t or a kgid_t. Using a plain integer is necessary to
prevent duplication of all of the mapping state.

This one was a little tricky as nfs has some special cases where
INVALID_UID aka -1 is used to indicate that the uid does not have a
mapping and where 2^16 -2 is used to talk about nobody or the
overflowuid, and similary for gids.

I believe I have converted everything correctly, but if I have not in
the worst case there will be a place or two where a uid_valid or a
gid_valid check will need to be removed.

Cc: Trond Myklebust <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/nfs/idmap.c | 45 ++++++++++++++++----------
fs/nfs/inode.c | 12 +++---
fs/nfs/nfs2xdr.c | 8 ++--
fs/nfs/nfs3xdr.c | 8 ++--
fs/nfs/nfs4xdr.c | 16 +++++-----
fs/nfs_common/nfsacl.c | 37 +++++++++++++---------
fs/nfsd/acl.h | 2 -
fs/nfsd/auth.c | 12 +++---
fs/nfsd/export.c | 22 ++++++++-----
fs/nfsd/idmap.h | 8 ++--
fs/nfsd/nfs3xdr.c | 9 +++--
fs/nfsd/nfs4acl.c | 63 +++++++++++++++++++++++++++----------
fs/nfsd/nfs4idmap.c | 34 +++++++++++++-------
fs/nfsd/nfs4recover.c | 4 +-
fs/nfsd/nfs4state.c | 6 ++--
fs/nfsd/nfs4xdr.c | 42 +++++++++++++++---------
fs/nfsd/nfsxdr.c | 9 +++--
fs/nfsd/vfs.c | 8 ++--
include/linux/nfs4.h | 6 +++-
include/linux/nfs_idmap.h | 10 +++---
include/linux/nfs_xdr.h | 4 +-
include/linux/nfsd/export.h | 4 +-
include/linux/sunrpc/auth.h | 7 ++--
include/linux/sunrpc/svcauth.h | 4 +-
init/Kconfig | 2 -
net/sunrpc/auth.c | 6 ++--
net/sunrpc/auth_generic.c | 16 +++++----
net/sunrpc/auth_gss/auth_gss.c | 33 ++++++++++++-------
net/sunrpc/auth_gss/svcauth_gss.c | 14 +++++++-
net/sunrpc/auth_unix.c | 36 +++++++++------------
net/sunrpc/svcauth_unix.c | 40 ++++++++++++++---------
31 files changed, 312 insertions(+), 215 deletions(-)

diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 9cc4a3f..d3f3669 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -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_fattr
static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr)
{
struct nfs4_string *group = fattr->group_name;
- __u32 gid;
+ kgid_t gid;

if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME))
return false;
@@ -193,7 +193,8 @@ static int nfs_idmap_init_keyring(void)
if (!cred)
return -ENOMEM;

- keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
+ keyring = key_alloc(&key_type_keyring, ".id_resolver",
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ,
KEY_ALLOC_NOT_IN_QUOTA);
@@ -840,43 +841,53 @@ idmap_release_pipe(struct inode *inode)
nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
}

-int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
{
struct idmap *idmap = server->nfs_client->cl_idmap;
+ __u32 id = -1;
+ int ret = 0;

- if (nfs_map_string_to_numeric(name, namelen, uid))
- return 0;
- return nfs_idmap_lookup_id(name, namelen, "uid", uid, idmap);
+ if (!nfs_map_string_to_numeric(name, namelen, &id))
+ ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
+ *uid = make_kuid(&init_user_ns, id);
+ return ret;
}

-int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid)
+int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
{
struct idmap *idmap = server->nfs_client->cl_idmap;
+ __u32 id = -1;
+ int ret = 0;

- if (nfs_map_string_to_numeric(name, namelen, gid))
- return 0;
- return nfs_idmap_lookup_id(name, namelen, "gid", gid, idmap);
+ if (!nfs_map_string_to_numeric(name, namelen, &id))
+ nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
+ *gid = make_kgid(&init_user_ns, id);
+ return ret;
}

-int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
+int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
{
struct idmap *idmap = server->nfs_client->cl_idmap;
int ret = -EINVAL;
+ unsigned int id;

+ id = from_kuid(&init_user_ns, uid);
if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
- ret = nfs_idmap_lookup_name(uid, "user", buf, buflen, idmap);
+ ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
if (ret < 0)
- ret = nfs_map_numeric_to_string(uid, buf, buflen);
+ ret = nfs_map_numeric_to_string(id, buf, buflen);
return ret;
}
-int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
+int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
{
struct idmap *idmap = server->nfs_client->cl_idmap;
int ret = -EINVAL;
+ unsigned int id;

+ id = from_kgid(&init_user_ns, gid);
if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
- ret = nfs_idmap_lookup_name(gid, "group", buf, buflen, idmap);
+ ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
if (ret < 0)
- ret = nfs_map_numeric_to_string(gid, buf, buflen);
+ ret = nfs_map_numeric_to_string(id, buf, buflen);
return ret;
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5c7325c..cbb6210 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -323,8 +323,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode->i_version = 0;
inode->i_size = 0;
clear_nlink(inode);
- inode->i_uid = -2;
- inode->i_gid = -2;
+ i_uid_write(inode, -2);
+ i_gid_write(inode, -2);
inode->i_blocks = 0;
memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
nfsi->write_io = 0;
@@ -993,9 +993,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
/* Have any file permissions changed? */
if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO))
invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
- if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && inode->i_uid != fattr->uid)
+ if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid))
invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
- if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && inode->i_gid != fattr->gid)
+ if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && !gid_eq(inode->i_gid, fattr->gid))
invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;

/* Has the link count changed? */
@@ -1422,7 +1422,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
| NFS_INO_REVAL_FORCED);

if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
- if (inode->i_uid != fattr->uid) {
+ if (!uid_eq(inode->i_uid, fattr->uid)) {
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
inode->i_uid = fattr->uid;
}
@@ -1433,7 +1433,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
| NFS_INO_REVAL_FORCED);

if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
- if (inode->i_gid != fattr->gid) {
+ if (!gid_eq(inode->i_gid, fattr->gid)) {
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
inode->i_gid = fattr->gid;
}
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index d04f0df..d7ef144 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -291,8 +291,8 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)

fattr->mode = be32_to_cpup(p++);
fattr->nlink = be32_to_cpup(p++);
- fattr->uid = be32_to_cpup(p++);
- fattr->gid = be32_to_cpup(p++);
+ fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
+ fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));
fattr->size = be32_to_cpup(p++);
fattr->du.nfs2.blocksize = be32_to_cpup(p++);

@@ -352,11 +352,11 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
else
*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
if (attr->ia_valid & ATTR_UID)
- *p++ = cpu_to_be32(attr->ia_uid);
+ *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
else
*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
if (attr->ia_valid & ATTR_GID)
- *p++ = cpu_to_be32(attr->ia_gid);
+ *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
else
*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
if (attr->ia_valid & ATTR_SIZE)
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 6cbe894..c6a7f49 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -594,13 +594,13 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)

if (attr->ia_valid & ATTR_UID) {
*p++ = xdr_one;
- *p++ = cpu_to_be32(attr->ia_uid);
+ *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
} else
*p++ = xdr_zero;

if (attr->ia_valid & ATTR_GID) {
*p++ = xdr_one;
- *p++ = cpu_to_be32(attr->ia_gid);
+ *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
} else
*p++ = xdr_zero;

@@ -659,8 +659,8 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)

fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
fattr->nlink = be32_to_cpup(p++);
- fattr->uid = be32_to_cpup(p++);
- fattr->gid = be32_to_cpup(p++);
+ fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
+ fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));

p = xdr_decode_size3(p, &fattr->size);
p = xdr_decode_size3(p, &fattr->du.nfs3.used);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 40836ee..135ac67 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -999,7 +999,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
if (owner_namelen < 0) {
dprintk("nfs: couldn't resolve uid %d to string\n",
- iap->ia_uid);
+ from_kuid(&init_user_ns, iap->ia_uid));
/* XXX */
strcpy(owner_name, "nobody");
owner_namelen = sizeof("nobody") - 1;
@@ -1011,7 +1011,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
if (owner_grouplen < 0) {
dprintk("nfs: couldn't resolve gid %d to string\n",
- iap->ia_gid);
+ from_kgid(&init_user_ns, iap->ia_gid));
strcpy(owner_group, "nobody");
owner_grouplen = sizeof("nobody") - 1;
/* goto out; */
@@ -3778,14 +3778,14 @@ out_overflow:
}

static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
- const struct nfs_server *server, uint32_t *uid,
+ const struct nfs_server *server, kuid_t *uid,
struct nfs4_string *owner_name)
{
uint32_t len;
__be32 *p;
int ret = 0;

- *uid = -2;
+ *uid = make_kuid(&init_user_ns, -2);
if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
return -EIO;
if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
@@ -3813,7 +3813,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
__func__, len);
bitmap[1] &= ~FATTR4_WORD1_OWNER;
}
- dprintk("%s: uid=%d\n", __func__, (int)*uid);
+ dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid));
return ret;
out_overflow:
print_overflow_msg(__func__, xdr);
@@ -3821,14 +3821,14 @@ out_overflow:
}

static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
- const struct nfs_server *server, uint32_t *gid,
+ const struct nfs_server *server, kgid_t *gid,
struct nfs4_string *group_name)
{
uint32_t len;
__be32 *p;
int ret = 0;

- *gid = -2;
+ *gid = make_kgid(&init_user_ns, -2);
if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
return -EIO;
if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
@@ -3856,7 +3856,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
__func__, len);
bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
}
- dprintk("%s: gid=%d\n", __func__, (int)*gid);
+ dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid));
return ret;
out_overflow:
print_overflow_msg(__func__, xdr);
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
index 6940439..698b8d0 100644
--- a/fs/nfs_common/nfsacl.c
+++ b/fs/nfs_common/nfsacl.c
@@ -38,8 +38,8 @@ struct nfsacl_encode_desc {
unsigned int count;
struct posix_acl *acl;
int typeflag;
- uid_t uid;
- gid_t gid;
+ kuid_t uid;
+ kgid_t gid;
};

struct nfsacl_simple_acl {
@@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
*p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
switch(entry->e_tag) {
case ACL_USER_OBJ:
- *p++ = htonl(nfsacl_desc->uid);
+ *p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid));
break;
case ACL_GROUP_OBJ:
- *p++ = htonl(nfsacl_desc->gid);
+ *p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid));
break;
case ACL_USER:
+ *p++ = htonl(from_kuid(&init_user_ns, entry->e_uid));
+ break;
case ACL_GROUP:
- *p++ = htonl(entry->e_id);
+ *p++ = htonl(from_kgid(&init_user_ns, entry->e_gid));
break;
default: /* Solaris depends on that! */
*p++ = 0;
@@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
(struct nfsacl_decode_desc *) desc;
__be32 *p = elem;
struct posix_acl_entry *entry;
+ unsigned int id;

if (!nfsacl_desc->acl) {
if (desc->array_len > NFS_ACL_MAX_ENTRIES)
@@ -160,14 +163,18 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)

entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
- entry->e_id = ntohl(*p++);
+ id = ntohl(*p++);
entry->e_perm = ntohl(*p++);

switch(entry->e_tag) {
- case ACL_USER_OBJ:
case ACL_USER:
- case ACL_GROUP_OBJ:
+ entry->e_uid = make_kuid(&init_user_ns, id);
+ break;
case ACL_GROUP:
+ entry->e_gid = make_kgid(&init_user_ns, id);
+ break;
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
case ACL_OTHER:
if (entry->e_perm & ~S_IRWXO)
return -EINVAL;
@@ -190,9 +197,13 @@ cmp_acl_entry(const void *x, const void *y)

if (a->e_tag != b->e_tag)
return a->e_tag - b->e_tag;
- else if (a->e_id > b->e_id)
+ else if ((a->e_tag == ACL_USER) && uid_gt(a->e_uid, b->e_uid))
+ return 1;
+ else if ((a->e_tag == ACL_USER) && uid_lt(a->e_uid, b->e_uid))
+ return -1;
+ else if ((a->e_tag == ACL_GROUP) && gid_gt(a->e_gid, b->e_gid))
return 1;
- else if (a->e_id < b->e_id)
+ else if ((a->e_tag == ACL_GROUP) && gid_lt(a->e_gid, b->e_gid))
return -1;
else
return 0;
@@ -213,22 +224,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
cmp_acl_entry, NULL);

- /* Clear undefined identifier fields and find the ACL_GROUP_OBJ
- and ACL_MASK entries. */
+ /* Find the ACL_GROUP_OBJ and ACL_MASK entries. */
FOREACH_ACL_ENTRY(pa, acl, pe) {
switch(pa->e_tag) {
case ACL_USER_OBJ:
- pa->e_id = ACL_UNDEFINED_ID;
break;
case ACL_GROUP_OBJ:
- pa->e_id = ACL_UNDEFINED_ID;
group_obj = pa;
break;
case ACL_MASK:
mask = pa;
/* fall through */
case ACL_OTHER:
- pa->e_id = ACL_UNDEFINED_ID;
break;
}
}
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 34e5c40..8b186a4 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -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
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 34a10d7..839dcd7 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -47,9 +47,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
if (!gi)
goto oom;
} else if (flags & NFSEXP_ROOTSQUASH) {
- if (!new->fsuid)
+ if (uid_eq(new->fsuid, GLOBAL_ROOT_UID))
new->fsuid = exp->ex_anon_uid;
- if (!new->fsgid)
+ if (gid_eq(new->fsgid, GLOBAL_ROOT_GID))
new->fsgid = exp->ex_anon_gid;

gi = groups_alloc(rqgi->ngroups);
@@ -58,7 +58,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)

for (i = 0; i < rqgi->ngroups; i++) {
if (gid_eq(GLOBAL_ROOT_GID, GROUP_AT(rqgi, i)))
- GROUP_AT(gi, i) = make_kgid(&init_user_ns, exp->ex_anon_gid);
+ GROUP_AT(gi, i) = exp->ex_anon_gid;
else
GROUP_AT(gi, i) = GROUP_AT(rqgi, i);
}
@@ -66,9 +66,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
gi = get_group_info(rqgi);
}

- if (new->fsuid == (uid_t) -1)
+ if (uid_eq(new->fsuid, INVALID_UID))
new->fsuid = exp->ex_anon_uid;
- if (new->fsgid == (gid_t) -1)
+ if (gid_eq(new->fsgid, INVALID_GID))
new->fsgid = exp->ex_anon_gid;

ret = set_groups(new, gi);
@@ -76,7 +76,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
if (ret < 0)
goto error;

- if (new->fsuid)
+ if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID))
new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
else
new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index a3946cf..e8c28e8 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -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;
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h
index 9d513ef..bf95f6b 100644
--- a/fs/nfsd/idmap.h
+++ b/fs/nfsd/idmap.h
@@ -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 */
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 43f46cd..349d793 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -7,6 +7,7 @@
*/

#include <linux/namei.h>
+#include <linux/user_namespace.h>
#include "xdr3.h"
#include "auth.h"

@@ -104,11 +105,11 @@ decode_sattr3(__be32 *p, struct iattr *iap)
}
if (*p++) {
iap->ia_valid |= ATTR_UID;
- iap->ia_uid = ntohl(*p++);
+ iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++));
}
if (*p++) {
iap->ia_valid |= ATTR_GID;
- iap->ia_gid = ntohl(*p++);
+ iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++));
}
if (*p++) {
u64 newsize;
@@ -165,8 +166,8 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
*p++ = htonl((u32) stat->mode);
*p++ = htonl((u32) stat->nlink);
- *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
- *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+ *p++ = htonl((u32) nfsd_ruid(rqstp, from_kuid(&init_user_ns, stat->uid)));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, from_kgid(&init_user_ns, stat->gid)));
if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
} else {
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 9c51aff..8a50b3c 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -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_array
return 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 {
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index a1f10c0..40e2d89 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(nfs4_disable_idmapping,
struct ent {
struct cache_head h;
int type; /* User / Group */
- uid_t id;
+ u32 id;
char name[IDMAP_NAMESZ];
char authname[IDMAP_NAMESZ];
};
@@ -540,7 +540,7 @@ rqst_authname(struct svc_rqst *rqstp)

static __be32
idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
- uid_t *id)
+ u32 *id)
{
struct ent *item, key = {
.type = type,
@@ -564,7 +564,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
}

static int
-idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
+idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
{
struct ent *item, key = {
.id = id,
@@ -587,7 +587,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
}

static bool
-numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
+numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id)
{
int ret;
char buf[11];
@@ -603,7 +603,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
}

static __be32
-do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
+do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id)
{
if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
if (numeric_name_to_id(rqstp, type, name, namelen, id))
@@ -616,7 +616,7 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
}

static int
-do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
+do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
{
if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
return sprintf(name, "%u", id);
@@ -625,26 +625,36 @@ do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)

__be32
nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
- __u32 *id)
+ kuid_t *uid)
{
- return do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
+ __be32 status;
+ __u32 id = -1;
+ status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id);
+ *uid = make_kuid(&init_user_ns, id);
+ return status;
}

__be32
nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
- __u32 *id)
+ kgid_t *gid)
{
- return do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
+ __be32 status;
+ __u32 id = -1;
+ status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
+ *gid = make_kgid(&init_user_ns, id);
+ return status;
}

int
-nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
+nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name)
{
+ __u32 id = from_kuid(&init_user_ns, uid);
return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
}

int
-nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
+nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name)
{
+ __u32 id = from_kgid(&init_user_ns, gid);
return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 43295d4..72d4a26 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -75,8 +75,8 @@ nfs4_save_creds(const struct cred **original_creds)
if (!new)
return -ENOMEM;

- new->fsuid = 0;
- new->fsgid = 0;
+ new->fsuid = GLOBAL_ROOT_UID;
+ new->fsgid = GLOBAL_ROOT_GID;
*original_creds = override_creds(new);
put_cred(new);
return 0;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d0237f8..7bef25f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1211,7 +1211,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
if (g1->ngroups != g2->ngroups)
return false;
for (i=0; i<g1->ngroups; i++)
- if (GROUP_AT(g1, i) != GROUP_AT(g2, i))
+ if (!gid_eq(GROUP_AT(g1, i), GROUP_AT(g2, i)))
return false;
return true;
}
@@ -1236,8 +1236,8 @@ static bool
same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
{
if ((is_gss_cred(cr1) != is_gss_cred(cr2))
- || (cr1->cr_uid != cr2->cr_uid)
- || (cr1->cr_gid != cr2->cr_gid)
+ || (!uid_eq(cr1->cr_uid, cr2->cr_uid))
+ || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
return false;
if (cr1->cr_principal == cr2->cr_principal)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fd548d1..690dbf5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -292,13 +292,13 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
status = nfs_ok;
if (ace->whotype != NFS4_ACL_WHO_NAMED)
- ace->who = 0;
+ ;
else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
status = nfsd_map_name_to_gid(argp->rqstp,
- buf, dummy32, &ace->who);
+ buf, dummy32, &ace->who_gid);
else
status = nfsd_map_name_to_uid(argp->rqstp,
- buf, dummy32, &ace->who);
+ buf, dummy32, &ace->who_uid);
if (status)
return status;
}
@@ -1954,7 +1954,7 @@ static u32 nfs4_file_type(umode_t mode)
}

static __be32
-nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid,
__be32 **p, int *buflen)
{
int status;
@@ -1963,10 +1963,10 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
return nfserr_resource;
if (whotype != NFS4_ACL_WHO_NAMED)
status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
- else if (group)
- status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
+ else if (gid_valid(gid))
+ status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1));
else
- status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
+ status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1));
if (status < 0)
return nfserrno(status);
*p = xdr_encode_opaque(*p, NULL, status);
@@ -1976,22 +1976,34 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
}

static inline __be32
-nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
+nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen)
{
- return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
+ return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID,
+ p, buflen);
}

static inline __be32
-nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
+nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen)
{
- return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
+ return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group,
+ p, buflen);
}

static inline __be32
-nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
__be32 **p, int *buflen)
{
- return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
+ kuid_t uid = INVALID_UID;
+ kgid_t gid = INVALID_GID;
+
+ if (ace->whotype == NFS4_ACL_WHO_NAMED) {
+ if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
+ gid = ace->who_gid;
+ else
+ uid = ace->who_uid;
+ }
+ return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, gid,
+ p, buflen);
}

#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
@@ -2235,9 +2247,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
WRITE32(ace->type);
WRITE32(ace->flag);
WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
- status = nfsd4_encode_aclname(rqstp, ace->whotype,
- ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
- &p, &buflen);
+ status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen);
if (status == nfserr_resource)
goto out_resource;
if (status)
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 65ec595..109140d 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -4,6 +4,7 @@
* Copyright (C) 1995, 1996 Olaf Kirch <[email protected]>
*/

+#include <linux/user_namespace.h>
#include "xdr.h"
#include "auth.h"

@@ -101,11 +102,11 @@ decode_sattr(__be32 *p, struct iattr *iap)
}
if ((tmp = ntohl(*p++)) != (u32)-1) {
iap->ia_valid |= ATTR_UID;
- iap->ia_uid = tmp;
+ iap->ia_uid = make_kuid(&init_user_ns, tmp);
}
if ((tmp = ntohl(*p++)) != (u32)-1) {
iap->ia_valid |= ATTR_GID;
- iap->ia_gid = tmp;
+ iap->ia_gid = make_kgid(&init_user_ns, tmp);
}
if ((tmp = ntohl(*p++)) != (u32)-1) {
iap->ia_valid |= ATTR_SIZE;
@@ -151,8 +152,8 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
*p++ = htonl(nfs_ftypes[type >> 12]);
*p++ = htonl((u32) stat->mode);
*p++ = htonl((u32) stat->nlink);
- *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
- *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+ *p++ = htonl((u32) nfsd_ruid(rqstp, from_kuid(&init_user_ns, stat->uid)));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, from_kgid(&init_user_ns, stat->gid)));

if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
*p++ = htonl(NFS_MAXPATHLEN);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c120b48..e7f96a0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -401,8 +401,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,

/* Revoke setuid/setgid on chown */
if (!S_ISDIR(inode->i_mode) &&
- (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) ||
- ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid))) {
+ (((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
+ ((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
iap->ia_valid |= ATTR_KILL_PRIV;
if (iap->ia_valid & ATTR_MODE) {
/* we're setting mode too, just clear the s*id bits */
@@ -1221,7 +1221,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
* send along the gid on create when it tries to implement
* setgid directories via NFS:
*/
- if (current_fsuid() != 0)
+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
iap->ia_valid &= ~(ATTR_UID|ATTR_GID);
if (iap->ia_valid)
return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
@@ -2160,7 +2160,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
* with NFSv3.
*/
if ((acc & NFSD_MAY_OWNER_OVERRIDE) &&
- inode->i_uid == current_fsuid())
+ uid_eq(inode->i_uid, current_fsuid()))
return 0;

/* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e111fa4..7b8fc73 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -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 {
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index 2dcef3a..d568a6a 100644
--- a/include/linux/nfs_idmap.h
+++ b/include/linux/nfs_idmap.h
@@ -36,9 +36,9 @@
#ifndef NFS_IDMAP_H
#define NFS_IDMAP_H

+#include <linux/uidgid.h>
#include <uapi/linux/nfs_idmap.h>

-
/* Forward declaration to make this header independent of others */
struct nfs_client;
struct nfs_server;
@@ -67,10 +67,10 @@ void nfs_fattr_init_names(struct nfs_fattr *fattr,
void nfs_fattr_free_names(struct nfs_fattr *);
void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *);

-int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *);
-int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t);
-int nfs_map_gid_to_group(const struct nfs_server *, __u32, char *, size_t);
+int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, kuid_t *);
+int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, kgid_t *);
+int nfs_map_uid_to_name(const struct nfs_server *, kuid_t, char *, size_t);
+int nfs_map_gid_to_group(const struct nfs_server *, kgid_t, char *, size_t);

extern unsigned int nfs_idmap_cache_timeout;
#endif /* NFS_IDMAP_H */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a73ea89..4d11786 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -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 {
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 24c1392..7898c99 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -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;
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index f25ba92..58fda1c 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -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 */
};
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index dd74084..ff374ab 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -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 */
diff --git a/init/Kconfig b/init/Kconfig
index 433e6e0..1bcc523 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,8 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on NFSD = n
- depends on NFS_FS = n
depends on OCFS2_FS = n
depends on XFS_FS = n

diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index b5c067b..392adc4 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -412,7 +412,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
*entry, *new;
unsigned int nr;

- nr = hash_long(acred->uid, cache->hashbits);
+ nr = hash_long(from_kuid(&init_user_ns, acred->uid), cache->hashbits);

rcu_read_lock();
hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
@@ -519,8 +519,8 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
{
struct rpc_auth *auth = task->tk_client->cl_auth;
struct auth_cred acred = {
- .uid = 0,
- .gid = 0,
+ .uid = GLOBAL_ROOT_UID,
+ .gid = GLOBAL_ROOT_GID,
};

dprintk("RPC: %5u looking up %s cred\n",
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 6ed6f20..b6badaf 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -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_GID

struct generic_cred {
struct rpc_cred gc_base;
@@ -96,7 +96,9 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)

dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
gcred->acred.machine_cred ? "machine" : "generic",
- gcred, acred->uid, acred->gid);
+ gcred,
+ from_kuid(&init_user_ns, acred->uid),
+ from_kgid(&init_user_ns, acred->gid));
return &gcred->gc_base;
}

@@ -129,8 +131,8 @@ machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flag
{
if (!gcred->acred.machine_cred ||
gcred->acred.principal != acred->principal ||
- gcred->acred.uid != acred->uid ||
- gcred->acred.gid != acred->gid)
+ !uid_eq(gcred->acred.uid, acred->uid) ||
+ !gid_eq(gcred->acred.gid, acred->gid))
return 0;
return 1;
}
@@ -147,8 +149,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
if (acred->machine_cred)
return machine_cred_match(acred, gcred, flags);

- if (gcred->acred.uid != acred->uid ||
- gcred->acred.gid != acred->gid ||
+ if (!uid_eq(gcred->acred.uid, acred->uid) ||
+ !gid_eq(gcred->acred.gid, acred->gid) ||
gcred->acred.machine_cred != 0)
goto out_nomatch;

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 909dc0c..16e5fda 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -247,7 +247,7 @@ err:

struct gss_upcall_msg {
atomic_t count;
- uid_t uid;
+ kuid_t uid;
struct rpc_pipe_msg msg;
struct list_head list;
struct gss_auth *auth;
@@ -294,11 +294,11 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
}

static struct gss_upcall_msg *
-__gss_find_upcall(struct rpc_pipe *pipe, uid_t uid)
+__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid)
{
struct gss_upcall_msg *pos;
list_for_each_entry(pos, &pipe->in_downcall, list) {
- if (pos->uid != uid)
+ if (!uid_eq(pos->uid, uid))
continue;
atomic_inc(&pos->count);
dprintk("RPC: %s found msg %p\n", __func__, pos);
@@ -400,7 +400,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,

gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ",
mech->gm_name,
- gss_msg->uid);
+ from_kuid(&init_user_ns, gss_msg->uid));
p += gss_msg->msg.len;
if (clnt->cl_principal) {
len = sprintf(p, "target=%s ", clnt->cl_principal);
@@ -436,7 +436,7 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,

static struct gss_upcall_msg *
gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
- uid_t uid, const char *service_name)
+ kuid_t uid, const char *service_name)
{
struct gss_upcall_msg *gss_msg;
int vers;
@@ -466,7 +466,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
struct gss_cred *gss_cred = container_of(cred,
struct gss_cred, gc_base);
struct gss_upcall_msg *gss_new, *gss_msg;
- uid_t uid = cred->cr_uid;
+ kuid_t uid = cred->cr_uid;

gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal);
if (IS_ERR(gss_new))
@@ -508,7 +508,7 @@ gss_refresh_upcall(struct rpc_task *task)
int err = 0;

dprintk("RPC: %5u %s for uid %u\n",
- task->tk_pid, __func__, cred->cr_uid);
+ task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid));
gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
if (PTR_ERR(gss_msg) == -EAGAIN) {
/* XXX: warning on the first, under the assumption we
@@ -540,7 +540,7 @@ gss_refresh_upcall(struct rpc_task *task)
gss_release_msg(gss_msg);
out:
dprintk("RPC: %5u %s for uid %u result %d\n",
- task->tk_pid, __func__, cred->cr_uid, err);
+ task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid), err);
return err;
}

@@ -553,7 +553,8 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
DEFINE_WAIT(wait);
int err = 0;

- dprintk("RPC: %s for uid %u\n", __func__, cred->cr_uid);
+ dprintk("RPC: %s for uid %u\n",
+ __func__, from_kuid(&init_user_ns, cred->cr_uid));
retry:
gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
if (PTR_ERR(gss_msg) == -EAGAIN) {
@@ -595,7 +596,7 @@ out_intr:
gss_release_msg(gss_msg);
out:
dprintk("RPC: %s for uid %u result %d\n",
- __func__, cred->cr_uid, err);
+ __func__, from_kuid(&init_user_ns, cred->cr_uid), err);
return err;
}

@@ -610,6 +611,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe;
struct gss_cl_ctx *ctx;
uid_t uid;
+ kuid_t kuid;
ssize_t err = -EFBIG;

if (mlen > MSG_BUF_MAXSIZE)
@@ -629,6 +631,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
err = PTR_ERR(p);
goto err;
}
+ kuid = make_kuid(&init_user_ns, uid);
+ if (!uid_valid(kuid)) {
+ err = -EINVAL;
+ goto err;
+ }

err = -ENOMEM;
ctx = gss_alloc_context();
@@ -638,7 +645,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
err = -ENOENT;
/* Find a matching upcall */
spin_lock(&pipe->lock);
- gss_msg = __gss_find_upcall(pipe, uid);
+ gss_msg = __gss_find_upcall(pipe, kuid);
if (gss_msg == NULL) {
spin_unlock(&pipe->lock);
goto err_put_ctx;
@@ -1050,7 +1057,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
int err = -ENOMEM;

dprintk("RPC: %s for uid %d, flavor %d\n",
- __func__, acred->uid, auth->au_flavor);
+ __func__, from_kuid(&init_user_ns, acred->uid), auth->au_flavor);

if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
goto out_err;
@@ -1106,7 +1113,7 @@ out:
}
if (gss_cred->gc_principal != NULL)
return 0;
- return rc->cr_uid == acred->uid;
+ return uid_eq(rc->cr_uid, acred->uid);
}

/*
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 73e9573..ae3ec09 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -418,6 +418,7 @@ static int rsc_parse(struct cache_detail *cd,
{
/* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */
char *buf = mesg;
+ int id;
int len, rv;
struct rsc rsci, *rscp = NULL;
time_t expiry;
@@ -444,7 +445,12 @@ static int rsc_parse(struct cache_detail *cd,
goto out;

/* uid, or NEGATIVE */
- rv = get_int(&mesg, &rsci.cred.cr_uid);
+ rv = get_int(&mesg, &id);
+ if (rv == 0) {
+ rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
+ if (!uid_valid(rsci.cred.cr_uid))
+ goto out;
+ }
if (rv == -EINVAL)
goto out;
if (rv == -ENOENT)
@@ -453,7 +459,11 @@ static int rsc_parse(struct cache_detail *cd,
int N, i;

/* gid */
- if (get_int(&mesg, &rsci.cred.cr_gid))
+ if (get_int(&mesg, &id))
+ goto out;
+
+ rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
+ if (!gid_valid(rsci.cred.cr_gid))
goto out;

/* number of additional gid's */
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 52c5abd..dc37021 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -18,8 +18,8 @@

struct unx_cred {
struct rpc_cred uc_base;
- gid_t uc_gid;
- gid_t uc_gids[NFS_NGROUPS];
+ kgid_t uc_gid;
+ kgid_t uc_gids[NFS_NGROUPS];
};
#define uc_uid uc_base.cr_uid

@@ -65,7 +65,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
unsigned int i;

dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
- acred->uid, acred->gid);
+ from_kuid(&init_user_ns, acred->uid),
+ from_kgid(&init_user_ns, acred->gid));

if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS)))
return ERR_PTR(-ENOMEM);
@@ -79,13 +80,10 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
groups = NFS_NGROUPS;

cred->uc_gid = acred->gid;
- for (i = 0; i < groups; i++) {
- gid_t gid;
- gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i));
- cred->uc_gids[i] = gid;
- }
+ for (i = 0; i < groups; i++)
+ cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
if (i < NFS_NGROUPS)
- cred->uc_gids[i] = NOGROUP;
+ cred->uc_gids[i] = INVALID_GID;

return &cred->uc_base;
}
@@ -123,21 +121,17 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
unsigned int i;


- if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
+ if (!uid_eq(cred->uc_uid, acred->uid) || !gid_eq(cred->uc_gid, acred->gid))
return 0;

if (acred->group_info != NULL)
groups = acred->group_info->ngroups;
if (groups > NFS_NGROUPS)
groups = NFS_NGROUPS;
- for (i = 0; i < groups ; i++) {
- gid_t gid;
- gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i));
- if (cred->uc_gids[i] != gid)
+ for (i = 0; i < groups ; i++)
+ if (!gid_eq(cred->uc_gids[i], GROUP_AT(acred->group_info, i)))
return 0;
- }
- if (groups < NFS_NGROUPS &&
- cred->uc_gids[groups] != NOGROUP)
+ if (groups < NFS_NGROUPS && gid_valid(cred->uc_gids[groups]))
return 0;
return 1;
}
@@ -163,11 +157,11 @@ unx_marshal(struct rpc_task *task, __be32 *p)
*/
p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);

- *p++ = htonl((u32) cred->uc_uid);
- *p++ = htonl((u32) cred->uc_gid);
+ *p++ = htonl((u32) from_kuid(&init_user_ns, cred->uc_uid));
+ *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gid));
hold = p++;
- for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
- *p++ = htonl((u32) cred->uc_gids[i]);
+ for (i = 0; i < 16 && gid_valid(cred->uc_gids[i]); i++)
+ *p++ = htonl((u32) from_kgid(&init_user_ns, cred->uc_gids[i]));
*hold = htonl(p - hold - 1); /* gid array length */
*base = htonl((p - base - 1) << 2); /* cred length */

diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4d01292..59a4985 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -415,7 +415,7 @@ svcauth_unix_info_release(struct svc_xprt *xpt)

struct unix_gid {
struct cache_head h;
- uid_t uid;
+ kuid_t uid;
struct group_info *gi;
};

@@ -433,7 +433,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
{
struct unix_gid *orig = container_of(corig, struct unix_gid, h);
struct unix_gid *new = container_of(cnew, struct unix_gid, h);
- return orig->uid == new->uid;
+ return uid_eq(orig->uid, new->uid);
}
static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
{
@@ -465,7 +465,7 @@ static void unix_gid_request(struct cache_detail *cd,
char tuid[20];
struct unix_gid *ug = container_of(h, struct unix_gid, h);

- snprintf(tuid, 20, "%u", ug->uid);
+ snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
qword_add(bpp, blen, tuid);
(*bpp)[-1] = '\n';
}
@@ -475,13 +475,14 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request);
}

-static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid);
+static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);

static int unix_gid_parse(struct cache_detail *cd,
char *mesg, int mlen)
{
/* uid expiry Ngid gid0 gid1 ... gidN-1 */
- int uid;
+ int id;
+ kuid_t uid;
int gids;
int rv;
int i;
@@ -493,9 +494,14 @@ static int unix_gid_parse(struct cache_detail *cd,
return -EINVAL;
mesg[mlen-1] = 0;

- rv = get_int(&mesg, &uid);
+ rv = get_int(&mesg, &id);
if (rv)
return -EINVAL;
+
+ uid = make_kuid(&init_user_ns, id);
+ if (!uid_valid(uid))
+ return -EINVAL;
+
ug.uid = uid;

expiry = get_expiry(&mesg);
@@ -530,7 +536,7 @@ static int unix_gid_parse(struct cache_detail *cd,
ug.h.expiry_time = expiry;
ch = sunrpc_cache_update(cd,
&ug.h, &ugp->h,
- hash_long(uid, GID_HASHBITS));
+ hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS));
if (!ch)
err = -ENOMEM;
else {
@@ -549,7 +555,7 @@ static int unix_gid_show(struct seq_file *m,
struct cache_detail *cd,
struct cache_head *h)
{
- struct user_namespace *user_ns = current_user_ns();
+ struct user_namespace *user_ns = seq_user_ns(m);
struct unix_gid *ug;
int i;
int glen;
@@ -565,7 +571,7 @@ static int unix_gid_show(struct seq_file *m,
else
glen = 0;

- seq_printf(m, "%u %d:", ug->uid, glen);
+ seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
for (i = 0; i < glen; i++)
seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i)));
seq_printf(m, "\n");
@@ -615,20 +621,20 @@ void unix_gid_cache_destroy(struct net *net)
cache_destroy_net(cd, net);
}

-static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid)
+static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
{
struct unix_gid ug;
struct cache_head *ch;

ug.uid = uid;
- ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS));
+ ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS));
if (ch)
return container_of(ch, struct unix_gid, h);
else
return NULL;
}

-static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
+static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
{
struct unix_gid *ug;
struct group_info *gi;
@@ -750,8 +756,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
}

/* Signal that mapping to nobody uid/gid is required */
- cred->cr_uid = (uid_t) -1;
- cred->cr_gid = (gid_t) -1;
+ cred->cr_uid = INVALID_UID;
+ cred->cr_gid = INVALID_GID;
cred->cr_group_info = groups_alloc(0);
if (cred->cr_group_info == NULL)
return SVC_CLOSE; /* kmalloc failure - client must retry */
@@ -812,8 +818,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */
argv->iov_len -= slen*4;

- cred->cr_uid = svc_getnl(argv); /* uid */
- cred->cr_gid = svc_getnl(argv); /* gid */
+ cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
+ cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
+ if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid))
+ goto badcred;
slen = svc_getnl(argv); /* gids length */
if (slen > 16 || (len -= (slen + 2)*4) < 0)
goto badcred;
--
1.7.5.4

2012-11-20 12:45:00

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate

From: "Eric W. Biederman" <[email protected]>

- Modify the incore inode to use kuid_t, kgid_t and kprojid_t.
- Remove xfs_get_projid and xfs_set_projid with projid being stored
in a single field they are unnecessary.
- Add dq_id (a struct kqid) to struct xfs_dquot to retain the incore
version of the quota identifiers.
- Pass struct kquid all of the way into xfs_qm_dqgetn and xfs_qm_dqread,
and move xfs_quota_type into xfs_dquot.c from xfs_quotaops.c to support
this change.

Cc: Ben Myers <[email protected]>
Cc: Alex Elder <[email protected]>
Cc: Dave Chinner <[email protected]>
Signed-off-by: "Eric W. Biederman" <[email protected]>
---
fs/xfs/xfs_acl.c | 23 ++++++++++--
fs/xfs/xfs_dquot.c | 36 +++++++++++++------
fs/xfs/xfs_dquot.h | 5 ++-
fs/xfs/xfs_inode.c | 33 ++++++++++-------
fs/xfs/xfs_inode.h | 32 +++--------------
fs/xfs/xfs_ioctl.c | 23 +++++++++---
fs/xfs/xfs_iops.c | 18 +++++-----
fs/xfs/xfs_itable.c | 8 ++--
fs/xfs/xfs_qm.c | 87 ++++++++++++++++++++++++---------------------
fs/xfs/xfs_qm.h | 4 +-
fs/xfs/xfs_qm_bhv.c | 3 +-
fs/xfs/xfs_qm_syscalls.c | 24 +++++++------
fs/xfs/xfs_quota.h | 4 +-
fs/xfs/xfs_quotaops.c | 20 +---------
fs/xfs/xfs_rename.c | 2 +-
fs/xfs/xfs_trans_dquot.c | 6 +---
fs/xfs/xfs_utils.c | 2 +-
fs/xfs/xfs_utils.h | 2 +-
fs/xfs/xfs_vnodeops.c | 14 ++++----
init/Kconfig | 1 -
20 files changed, 179 insertions(+), 168 deletions(-)

diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 1d32f1d..ca2aade 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -64,14 +64,17 @@ xfs_acl_from_disk(struct xfs_acl *aclp)

switch (acl_e->e_tag) {
case ACL_USER:
+ acl_e->e_uid = make_kuid(&init_user_ns,
+ be32_to_cpu(ace->ae_id));
+ break;
case ACL_GROUP:
- acl_e->e_id = be32_to_cpu(ace->ae_id);
+ acl_e->e_gid = make_kgid(&init_user_ns,
+ be32_to_cpu(ace->ae_id));
break;
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
- acl_e->e_id = ACL_UNDEFINED_ID;
break;
default:
goto fail;
@@ -97,8 +100,20 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl)
acl_e = &acl->a_entries[i];

ace->ae_tag = cpu_to_be32(acl_e->e_tag);
- ace->ae_id = cpu_to_be32(acl_e->e_id);
ace->ae_perm = cpu_to_be16(acl_e->e_perm);
+ switch(acl_e->e_tag) {
+ case ACL_USER:
+ ace->ae_id = cpu_to_be32(
+ from_kuid(&init_user_ns, acl_e->e_uid));
+ break;
+ case ACL_GROUP:
+ ace->ae_id = cpu_to_be32(
+ from_kgid(&init_user_ns, acl_e->e_gid));
+ break;
+ default:
+ ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID);
+ break;
+ }
}
}

@@ -355,7 +370,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
return -EINVAL;
if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
return value ? -EACCES : 0;
- if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
+ if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_FOWNER))
return -EPERM;

if (!value)
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index bf27fcc..428926c 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -63,6 +63,19 @@ static struct kmem_zone *xfs_qm_dqzone;

static struct lock_class_key xfs_dquot_other_class;

+STATIC int
+xfs_quota_type(int type)
+{
+ switch (type) {
+ case USRQUOTA:
+ return XFS_DQ_USER;
+ case GRPQUOTA:
+ return XFS_DQ_GROUP;
+ default:
+ return XFS_DQ_PROJ;
+ }
+}
+
/*
* This is called to free all the memory associated with a dquot
*/
@@ -480,8 +493,7 @@ xfs_qm_dqtobp(
int
xfs_qm_dqread(
struct xfs_mount *mp,
- xfs_dqid_t id,
- uint type,
+ struct kqid id,
uint flags,
struct xfs_dquot **O_dqpp)
{
@@ -495,8 +507,9 @@ xfs_qm_dqread(

dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP);

- dqp->dq_flags = type;
- dqp->q_core.d_id = cpu_to_be32(id);
+ dqp->dq_id = id;
+ dqp->dq_flags = xfs_quota_type(id.type);
+ dqp->q_core.d_id = cpu_to_be32(from_kqid(&init_user_ns, id));
dqp->q_mount = mp;
INIT_LIST_HEAD(&dqp->q_lru);
mutex_init(&dqp->q_qlock);
@@ -514,7 +527,7 @@ xfs_qm_dqread(
* Make sure group quotas have a different lock class than user
* quotas.
*/
- if (!(type & XFS_DQ_USER))
+ if (id.type != USRQUOTA)
lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);

XFS_STATS_INC(xs_qm_dquot);
@@ -614,12 +627,12 @@ int
xfs_qm_dqget(
xfs_mount_t *mp,
xfs_inode_t *ip, /* locked inode (optional) */
- xfs_dqid_t id, /* uid/projid/gid depending on type */
- uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
+ struct kqid id, /* uid/projid/gid depending on type */
uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
{
struct xfs_quotainfo *qi = mp->m_quotainfo;
+ uint type = xfs_quota_type(id.type);
struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
struct xfs_dquot *dqp;
int error;
@@ -651,7 +664,7 @@ xfs_qm_dqget(

restart:
mutex_lock(&qi->qi_tree_lock);
- dqp = radix_tree_lookup(tree, id);
+ dqp = radix_tree_lookup(tree, from_kqid(&init_user_ns, id));
if (dqp) {
xfs_dqlock(dqp);
if (dqp->dq_flags & XFS_DQ_FREEING) {
@@ -683,7 +696,7 @@ restart:
if (ip)
xfs_iunlock(ip, XFS_ILOCK_EXCL);

- error = xfs_qm_dqread(mp, id, type, flags, &dqp);
+ error = xfs_qm_dqread(mp, id, flags, &dqp);

if (ip)
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -714,7 +727,7 @@ restart:
}

mutex_lock(&qi->qi_tree_lock);
- error = -radix_tree_insert(tree, id, dqp);
+ error = -radix_tree_insert(tree, from_kqid(&init_user_ns, id), dqp);
if (unlikely(error)) {
WARN_ON(error != EEXIST);

@@ -990,8 +1003,7 @@ xfs_dqlock2(
{
if (d1 && d2) {
ASSERT(d1 != d2);
- if (be32_to_cpu(d1->q_core.d_id) >
- be32_to_cpu(d2->q_core.d_id)) {
+ if (qid_lt(d2->dq_id, d1->dq_id)) {
mutex_lock(&d2->q_qlock);
mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED);
} else {
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 7d20af2..1f19b87 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -36,6 +36,7 @@ struct xfs_trans;
* The incore dquot structure
*/
typedef struct xfs_dquot {
+ struct kqid dq_id; /* Quota identifier */
uint dq_flags; /* various flags (XFS_DQ_*) */
struct list_head q_lru; /* global free list of dquots */
struct xfs_mount*q_mount; /* filesystem this relates to */
@@ -138,7 +139,7 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
XFS_DQ_TO_QINF(dqp)->qi_gquotaip)

-extern int xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
+extern int xfs_qm_dqread(struct xfs_mount *, struct kqid,
uint, struct xfs_dquot **);
extern void xfs_qm_dqdestroy(xfs_dquot_t *);
extern int xfs_qm_dqflush(struct xfs_dquot *, struct xfs_buf **);
@@ -148,7 +149,7 @@ extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,
extern void xfs_qm_adjust_dqlimits(xfs_mount_t *,
xfs_disk_dquot_t *);
extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
- xfs_dqid_t, uint, uint, xfs_dquot_t **);
+ struct kqid, uint, xfs_dquot_t **);
extern void xfs_qm_dqput(xfs_dquot_t *);

extern void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 2778258..3656b88 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -570,11 +570,12 @@ xfs_dinode_from_disk(
to->di_version = from ->di_version;
to->di_format = from->di_format;
to->di_onlink = be16_to_cpu(from->di_onlink);
- to->di_uid = be32_to_cpu(from->di_uid);
- to->di_gid = be32_to_cpu(from->di_gid);
+ to->di_uid = make_kuid(&init_user_ns, be32_to_cpu(from->di_uid));
+ to->di_gid = make_kgid(&init_user_ns, be32_to_cpu(from->di_gid));
to->di_nlink = be32_to_cpu(from->di_nlink);
- to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
- to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
+ to->di_projid = make_kprojid(&init_user_ns,
+ be16_to_cpu(from->di_projid_lo) |
+ (be16_to_cpu(from->di_projid_hi) << 16));
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_flushiter = be16_to_cpu(from->di_flushiter);
to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
@@ -601,16 +602,18 @@ xfs_dinode_to_disk(
xfs_dinode_t *to,
xfs_icdinode_t *from)
{
+ projid_t projid = from_kprojid(&init_user_ns, from->di_projid);
+
to->di_magic = cpu_to_be16(from->di_magic);
to->di_mode = cpu_to_be16(from->di_mode);
to->di_version = from ->di_version;
to->di_format = from->di_format;
to->di_onlink = cpu_to_be16(from->di_onlink);
- to->di_uid = cpu_to_be32(from->di_uid);
- to->di_gid = cpu_to_be32(from->di_gid);
+ to->di_uid = cpu_to_be32(from_kuid(&init_user_ns, from->di_uid));
+ to->di_gid = cpu_to_be32(from_kgid(&init_user_ns, from->di_gid));
to->di_nlink = cpu_to_be32(from->di_nlink);
- to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
- to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
+ to->di_projid_lo = cpu_to_be16(projid & 0xffff);
+ to->di_projid_hi = cpu_to_be16(projid >> 16);
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_flushiter = cpu_to_be16(from->di_flushiter);
to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
@@ -778,7 +781,7 @@ xfs_iread(
if (ip->i_d.di_version == 1) {
ip->i_d.di_nlink = ip->i_d.di_onlink;
ip->i_d.di_onlink = 0;
- xfs_set_projid(ip, 0);
+ ip->i_d.di_projid = make_kprojid(&init_user_ns, 0);
}

ip->i_delayed_blks = 0;
@@ -884,7 +887,7 @@ xfs_ialloc(
umode_t mode,
xfs_nlink_t nlink,
xfs_dev_t rdev,
- prid_t prid,
+ kprojid_t prid,
int okalloc,
xfs_buf_t **ialloc_context,
xfs_inode_t **ipp)
@@ -927,7 +930,7 @@ xfs_ialloc(
ASSERT(ip->i_d.di_nlink == nlink);
ip->i_d.di_uid = current_fsuid();
ip->i_d.di_gid = current_fsgid();
- xfs_set_projid(ip, prid);
+ ip->i_d.di_projid = prid;
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));

/*
@@ -948,7 +951,8 @@ xfs_ialloc(
/*
* Project ids won't be stored on disk if we are using a version 1 inode.
*/
- if ((prid != 0) && (ip->i_d.di_version == 1))
+ if (!projid_eq(prid, make_kprojid(&init_user_ns, 0)) &&
+ (ip->i_d.di_version == 1))
xfs_bump_ino_vers2(tp, ip);

if (pip && XFS_INHERIT_GID(pip)) {
@@ -965,7 +969,7 @@ xfs_ialloc(
*/
if ((irix_sgid_inherit) &&
(ip->i_d.di_mode & S_ISGID) &&
- (!in_group_p((gid_t)ip->i_d.di_gid))) {
+ (!in_group_p(ip->i_d.di_gid))) {
ip->i_d.di_mode &= ~S_ISGID;
}

@@ -2554,7 +2558,8 @@ xfs_iflush_int(
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
memset(&(dip->di_pad[0]), 0,
sizeof(dip->di_pad));
- ASSERT(xfs_get_projid(ip) == 0);
+ ASSERT(projid_eq(ip->i_d.di_projid,
+ make_kprojid(&init_user_ns, 0)));
}
}

diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 94b32f9..973b252 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -120,8 +120,8 @@ typedef struct xfs_ictimestamp {
} xfs_ictimestamp_t;

/*
- * NOTE: This structure must be kept identical to struct xfs_dinode
- * in xfs_dinode.h except for the endianness annotations.
+ * NOTE: This structure must contain all of the same informationas struct xfs_dinode
+ * in xfs_dinode.h except in core format.
*/
typedef struct xfs_icdinode {
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
@@ -129,11 +129,10 @@ typedef struct xfs_icdinode {
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */
- __uint32_t di_uid; /* owner's user id */
- __uint32_t di_gid; /* owner's group id */
+ kuid_t di_uid; /* owner's user id */
+ kgid_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
- __uint16_t di_projid_lo; /* lower part of owner's project id */
- __uint16_t di_projid_hi; /* higher part of owner's project id */
+ kprojid_t di_projid; /* project id */
__uint8_t di_pad[6]; /* unused, zeroed space */
__uint16_t di_flushiter; /* incremented on flush */
xfs_ictimestamp_t di_atime; /* time last accessed */
@@ -355,25 +354,6 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags)
}

/*
- * Project quota id helpers (previously projid was 16bit only
- * and using two 16bit values to hold new 32bit projid was chosen
- * to retain compatibility with "old" filesystems).
- */
-static inline prid_t
-xfs_get_projid(struct xfs_inode *ip)
-{
- return (prid_t)ip->i_d.di_projid_hi << 16 | ip->i_d.di_projid_lo;
-}
-
-static inline void
-xfs_set_projid(struct xfs_inode *ip,
- prid_t projid)
-{
- ip->i_d.di_projid_hi = (__uint16_t) (projid >> 16);
- ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
-}
-
-/*
* In-core inode flags.
*/
#define XFS_IRECLAIM (1 << 0) /* started reclaiming this inode */
@@ -514,7 +494,7 @@ void xfs_inode_free(struct xfs_inode *ip);
* xfs_inode.c prototypes.
*/
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t,
- xfs_nlink_t, xfs_dev_t, prid_t, int,
+ xfs_nlink_t, xfs_dev_t, kprojid_t, int,
struct xfs_buf **, xfs_inode_t **);

uint xfs_ip2xflags(struct xfs_inode *);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 8305f2a..434892e 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -814,7 +814,7 @@ xfs_ioc_fsgetxattr(
xfs_ilock(ip, XFS_ILOCK_SHARED);
fa.fsx_xflags = xfs_ip2xflags(ip);
fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
- fa.fsx_projid = xfs_get_projid(ip);
+ fa.fsx_projid = from_kprojid_munged(current_user_ns(), ip->i_d.di_projid);

if (attr) {
if (ip->i_afp) {
@@ -924,6 +924,7 @@ xfs_ioctl_setattr(
struct xfs_dquot *gdqp = NULL;
struct xfs_dquot *olddquot = NULL;
int code;
+ kprojid_t projid = INVALID_PROJID;

trace_xfs_ioctl_setattr(ip);

@@ -940,6 +941,15 @@ xfs_ioctl_setattr(
return XFS_ERROR(EINVAL);

/*
+ * Verify the specifid project id is valid.
+ */
+ if (mask & FSX_PROJID) {
+ projid = make_kprojid(current_user_ns(), fa->fsx_projid);
+ if (!projid_valid(projid))
+ return XFS_ERROR(EINVAL);
+ }
+
+ /*
* If disk quotas is on, we make sure that the dquots do exist on disk,
* before we start any other transactions. Trying to do this later
* is messy. We don't care to take a readlock to look at the ids
@@ -949,7 +959,7 @@ xfs_ioctl_setattr(
*/
if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
- ip->i_d.di_gid, fa->fsx_projid,
+ ip->i_d.di_gid, projid,
XFS_QMOPT_PQUOTA, &udqp, &gdqp);
if (code)
return code;
@@ -974,7 +984,8 @@ xfs_ioctl_setattr(
* to the file owner ID, except in cases where the
* CAP_FSETID capability is applicable.
*/
- if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
+ if (!uid_eq(current_fsuid(), ip->i_d.di_uid) &&
+ !capable(CAP_FOWNER)) {
code = XFS_ERROR(EPERM);
goto error_return;
}
@@ -985,7 +996,7 @@ xfs_ioctl_setattr(
if (mask & FSX_PROJID) {
if (XFS_IS_QUOTA_RUNNING(mp) &&
XFS_IS_PQUOTA_ON(mp) &&
- xfs_get_projid(ip) != fa->fsx_projid) {
+ !projid_eq(ip->i_d.di_projid, projid)) {
ASSERT(tp);
code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
capable(CAP_FOWNER) ?
@@ -1103,12 +1114,12 @@ xfs_ioctl_setattr(
* Change the ownerships and register quota modifications
* in the transaction.
*/
- if (xfs_get_projid(ip) != fa->fsx_projid) {
+ if (!projid_eq(ip->i_d.di_projid, projid)) {
if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
olddquot = xfs_qm_vop_chown(tp, ip,
&ip->i_gdquot, gdqp);
}
- xfs_set_projid(ip, fa->fsx_projid);
+ ip->i_d.di_projid = projid;

/*
* We may have to rev the inode as well as
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 4e00cf0..ff80a0d 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -465,8 +465,8 @@ xfs_setattr_nonsize(
int mask = iattr->ia_valid;
xfs_trans_t *tp;
int error;
- uid_t uid = 0, iuid = 0;
- gid_t gid = 0, igid = 0;
+ kuid_t uid = GLOBAL_ROOT_UID, iuid = GLOBAL_ROOT_UID;
+ kgid_t gid = GLOBAL_ROOT_GID, igid = GLOBAL_ROOT_GID;
struct xfs_dquot *udqp = NULL, *gdqp = NULL;
struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL;

@@ -515,7 +515,7 @@ xfs_setattr_nonsize(
*/
ASSERT(udqp == NULL);
ASSERT(gdqp == NULL);
- error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
+ error = xfs_qm_vop_dqalloc(ip, uid, gid, ip->i_d.di_projid,
qflags, &udqp, &gdqp);
if (error)
return error;
@@ -548,8 +548,8 @@ xfs_setattr_nonsize(
* going to change.
*/
if (XFS_IS_QUOTA_RUNNING(mp) &&
- ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
- (XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
+ ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) ||
+ (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) {
ASSERT(tp);
error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
capable(CAP_FOWNER) ?
@@ -579,7 +579,7 @@ xfs_setattr_nonsize(
* Change the ownerships and register quota modifications
* in the transaction.
*/
- if (iuid != uid) {
+ if (!uid_eq(iuid, uid)) {
if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) {
ASSERT(mask & ATTR_UID);
ASSERT(udqp);
@@ -589,7 +589,7 @@ xfs_setattr_nonsize(
ip->i_d.di_uid = uid;
inode->i_uid = uid;
}
- if (igid != gid) {
+ if (!gid_eq(igid, gid)) {
if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
ASSERT(!XFS_IS_PQUOTA_ON(mp));
ASSERT(mask & ATTR_GID);
@@ -1151,8 +1151,8 @@ xfs_setup_inode(

inode->i_mode = ip->i_d.di_mode;
set_nlink(inode, ip->i_d.di_nlink);
- inode->i_uid = ip->i_d.di_uid;
- inode->i_gid = ip->i_d.di_gid;
+ inode->i_uid = ip->i_d.di_uid;
+ inode->i_gid = ip->i_d.di_gid;

switch (inode->i_mode & S_IFMT) {
case S_IFBLK:
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 01d10a6..541fdd4 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -90,12 +90,12 @@ xfs_bulkstat_one_int(
* further change.
*/
buf->bs_nlink = dic->di_nlink;
- buf->bs_projid_lo = dic->di_projid_lo;
- buf->bs_projid_hi = dic->di_projid_hi;
+ buf->bs_projid_lo = from_kprojid(current_user_ns(), dic->di_projid) & 0xffff;
+ buf->bs_projid_hi = from_kprojid(current_user_ns(), dic->di_projid) >> 16;
buf->bs_ino = ino;
buf->bs_mode = dic->di_mode;
- buf->bs_uid = dic->di_uid;
- buf->bs_gid = dic->di_gid;
+ buf->bs_uid = from_kuid(&init_user_ns, dic->di_uid);
+ buf->bs_gid = from_kgid(&init_user_ns, dic->di_gid);
buf->bs_size = dic->di_size;
buf->bs_atime.tv_sec = dic->di_atime.t_sec;
buf->bs_atime.tv_nsec = dic->di_atime.t_nsec;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 2e86fa0..0f39a95 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -366,8 +366,7 @@ xfs_qm_unmount_quotas(
STATIC int
xfs_qm_dqattach_one(
xfs_inode_t *ip,
- xfs_dqid_t id,
- uint type,
+ struct kqid id,
uint doalloc,
xfs_dquot_t *udqhint, /* hint */
xfs_dquot_t **IO_idqpp)
@@ -396,7 +395,7 @@ xfs_qm_dqattach_one(
* the user dquot.
*/
if (udqhint) {
- ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
+ ASSERT(id.type == GRPQUOTA || id.type == PRJQUOTA);
xfs_dqlock(udqhint);

/*
@@ -407,7 +406,7 @@ xfs_qm_dqattach_one(
* hold the ilock.
*/
dqp = udqhint->q_gdquot;
- if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
+ if (dqp && qid_eq(dqp->dq_id, id)) {
ASSERT(*IO_idqpp == NULL);

*IO_idqpp = xfs_qm_dqhold(dqp);
@@ -431,7 +430,7 @@ xfs_qm_dqattach_one(
* disk and we didn't ask it to allocate;
* ESRCH if quotas got turned off suddenly.
*/
- error = xfs_qm_dqget(ip->i_mount, ip, id, type,
+ error = xfs_qm_dqget(ip->i_mount, ip, id,
doalloc | XFS_QMOPT_DOWARN, &dqp);
if (error)
return error;
@@ -515,7 +514,7 @@ xfs_qm_dqattach_locked(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));

if (XFS_IS_UQUOTA_ON(mp)) {
- error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER,
+ error = xfs_qm_dqattach_one(ip, make_kqid_uid(ip->i_d.di_uid),
flags & XFS_QMOPT_DQALLOC,
NULL, &ip->i_udquot);
if (error)
@@ -526,10 +525,10 @@ xfs_qm_dqattach_locked(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
if (XFS_IS_OQUOTA_ON(mp)) {
error = XFS_IS_GQUOTA_ON(mp) ?
- xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+ xfs_qm_dqattach_one(ip, make_kqid_gid(ip->i_d.di_gid),
flags & XFS_QMOPT_DQALLOC,
ip->i_udquot, &ip->i_gdquot) :
- xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
+ xfs_qm_dqattach_one(ip, make_kqid_projid(ip->i_d.di_projid),
flags & XFS_QMOPT_DQALLOC,
ip->i_udquot, &ip->i_gdquot);
/*
@@ -673,10 +672,12 @@ xfs_qm_init_quotainfo(
* Since we may not have done a quotacheck by this point, just read
* the dquot without attaching it to any hashtables or lists.
*/
- error = xfs_qm_dqread(mp, 0,
- XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
- (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
- XFS_DQ_PROJ),
+ error = xfs_qm_dqread(mp,
+ make_kqid(&init_user_ns,
+ XFS_IS_UQUOTA_RUNNING(mp) ? USRQUOTA :
+ (XFS_IS_GQUOTA_RUNNING(mp) ? GRPQUOTA :
+ PRJQUOTA),
+ 0),
XFS_QMOPT_DOWARN, &dqp);
if (!error) {
xfs_disk_dquot_t *ddqp = &dqp->q_core;
@@ -776,7 +777,9 @@ xfs_qm_qino_alloc(
return error;
}

- error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
+ error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
+ make_kprojid(&init_user_ns, 0),
+ 1, ip, &committed);
if (error) {
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
XFS_TRANS_ABORT);
@@ -1011,8 +1014,7 @@ out:
STATIC int
xfs_qm_quotacheck_dqadjust(
struct xfs_inode *ip,
- xfs_dqid_t id,
- uint type,
+ struct kqid id,
xfs_qcnt_t nblks,
xfs_qcnt_t rtblks)
{
@@ -1020,7 +1022,7 @@ xfs_qm_quotacheck_dqadjust(
struct xfs_dquot *dqp;
int error;

- error = xfs_qm_dqget(mp, ip, id, type,
+ error = xfs_qm_dqget(mp, ip, id,
XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp);
if (error) {
/*
@@ -1155,22 +1157,25 @@ xfs_qm_dqusage_adjust(
* and quotaoffs don't race. (Quotachecks happen at mount time only).
*/
if (XFS_IS_UQUOTA_ON(mp)) {
- error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid,
- XFS_DQ_USER, nblks, rtblks);
+ error = xfs_qm_quotacheck_dqadjust(ip,
+ make_kqid_uid(ip->i_d.di_uid),
+ nblks, rtblks);
if (error)
goto error0;
}

if (XFS_IS_GQUOTA_ON(mp)) {
- error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid,
- XFS_DQ_GROUP, nblks, rtblks);
+ error = xfs_qm_quotacheck_dqadjust(ip,
+ make_kqid_gid(ip->i_d.di_gid),
+ nblks, rtblks);
if (error)
goto error0;
}

if (XFS_IS_PQUOTA_ON(mp)) {
- error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip),
- XFS_DQ_PROJ, nblks, rtblks);
+ error = xfs_qm_quotacheck_dqadjust(ip,
+ make_kqid_projid(ip->i_d.di_projid),
+ nblks, rtblks);
if (error)
goto error0;
}
@@ -1434,7 +1439,7 @@ xfs_qm_dqfree_one(

mutex_lock(&qi->qi_tree_lock);
radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
- be32_to_cpu(dqp->q_core.d_id));
+ from_kqid(&init_user_ns, dqp->dq_id));

qi->qi_dquots--;
mutex_unlock(&qi->qi_tree_lock);
@@ -1613,9 +1618,9 @@ xfs_qm_write_sb_changes(
int
xfs_qm_vop_dqalloc(
struct xfs_inode *ip,
- uid_t uid,
- gid_t gid,
- prid_t prid,
+ kuid_t uid,
+ kgid_t gid,
+ kprojid_t prid,
uint flags,
struct xfs_dquot **O_udqpp,
struct xfs_dquot **O_gdqpp)
@@ -1648,7 +1653,7 @@ xfs_qm_vop_dqalloc(

uq = gq = NULL;
if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
- if (ip->i_d.di_uid != uid) {
+ if (!uid_eq(ip->i_d.di_uid, uid)) {
/*
* What we need is the dquot that has this uid, and
* if we send the inode to dqget, the uid of the inode
@@ -1659,8 +1664,8 @@ xfs_qm_vop_dqalloc(
* holding ilock.
*/
xfs_iunlock(ip, lockflags);
- if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
- XFS_DQ_USER,
+ if ((error = xfs_qm_dqget(mp, NULL,
+ make_kqid_uid(uid),
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
&uq))) {
@@ -1683,10 +1688,10 @@ xfs_qm_vop_dqalloc(
}
}
if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
- if (ip->i_d.di_gid != gid) {
+ if (!gid_eq(ip->i_d.di_gid, gid)) {
xfs_iunlock(ip, lockflags);
- if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
- XFS_DQ_GROUP,
+ if ((error = xfs_qm_dqget(mp, NULL,
+ make_kqid_gid(gid),
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
&gq))) {
@@ -1703,10 +1708,10 @@ xfs_qm_vop_dqalloc(
gq = xfs_qm_dqhold(ip->i_gdquot);
}
} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
- if (xfs_get_projid(ip) != prid) {
+ if (!projid_eq(ip->i_d.di_projid, prid)) {
xfs_iunlock(ip, lockflags);
- if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
- XFS_DQ_PROJ,
+ if ((error = xfs_qm_dqget(mp, NULL,
+ make_kqid_projid(prid),
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
&gq))) {
@@ -1804,7 +1809,7 @@ xfs_qm_vop_chown_reserve(
XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;

if (XFS_IS_UQUOTA_ON(mp) && udqp &&
- ip->i_d.di_uid != (uid_t)be32_to_cpu(udqp->q_core.d_id)) {
+ !uid_eq(ip->i_d.di_uid, udqp->dq_id.uid)) {
delblksudq = udqp;
/*
* If there are delayed allocation blocks, then we have to
@@ -1818,12 +1823,12 @@ xfs_qm_vop_chown_reserve(
}
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
- xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
+ !projid_eq(ip->i_d.di_projid, gdqp->dq_id.projid))
prjflags = XFS_QMOPT_ENOSPC;

if (prjflags ||
(XFS_IS_GQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
+ !gid_eq(ip->i_d.di_gid, gdqp->dq_id.gid))) {
delblksgdq = gdqp;
if (delblks) {
ASSERT(ip->i_gdquot);
@@ -1907,7 +1912,7 @@ xfs_qm_vop_create_dqattach(
if (udqp) {
ASSERT(ip->i_udquot == NULL);
ASSERT(XFS_IS_UQUOTA_ON(mp));
- ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
+ ASSERT(uid_eq(ip->i_d.di_uid, udqp->dq_id.uid));

ip->i_udquot = xfs_qm_dqhold(udqp);
xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
@@ -1916,8 +1921,8 @@ xfs_qm_vop_create_dqattach(
ASSERT(ip->i_gdquot == NULL);
ASSERT(XFS_IS_OQUOTA_ON(mp));
ASSERT((XFS_IS_GQUOTA_ON(mp) ?
- ip->i_d.di_gid : xfs_get_projid(ip)) ==
- be32_to_cpu(gdqp->q_core.d_id));
+ gid_eq(ip->i_d.di_gid, gdqp->dq_id.gid) :
+ projid_eq(ip->i_d.di_projid, gdqp->dq_id.projid)));

ip->i_gdquot = xfs_qm_dqhold(gdqp);
xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 44b858b..ce478dc 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -114,9 +114,9 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);

/* quota ops */
extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
-extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
+extern int xfs_qm_scall_getquota(xfs_mount_t *, struct kqid,
fs_disk_quota_t *);
-extern int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
+extern int xfs_qm_scall_setqlim(xfs_mount_t *, struct kqid,
fs_disk_quota_t *);
extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 6b39115..e82f48b 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -79,7 +79,8 @@ xfs_qm_statvfs(
xfs_mount_t *mp = ip->i_mount;
xfs_dquot_t *dqp;

- if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
+ if (!xfs_qm_dqget(mp, NULL, make_kqid_projid(ip->i_d.di_projid),
+ 0, &dqp)) {
xfs_fill_statvfs_from_dquot(statp, dqp);
xfs_qm_dqput(dqp);
}
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 858a3b1..5b98821 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -472,8 +472,7 @@ xfs_qm_scall_getqstat(
int
xfs_qm_scall_setqlim(
xfs_mount_t *mp,
- xfs_dqid_t id,
- uint type,
+ struct kqid id,
fs_disk_quota_t *newlim)
{
struct xfs_quotainfo *q = mp->m_quotainfo;
@@ -482,6 +481,7 @@ xfs_qm_scall_setqlim(
xfs_trans_t *tp;
int error;
xfs_qcnt_t hard, soft;
+ bool root_qid;

if (newlim->d_fieldmask & ~XFS_DQ_MASK)
return EINVAL;
@@ -495,6 +495,9 @@ xfs_qm_scall_setqlim(
return (error);
}

+ /* Are we setting the root users quota? */
+ root_qid = qid_eq(id, make_kqid(&init_user_ns, id.type, 0));
+
/*
* We don't want to race with a quotaoff so take the quotaoff lock.
* (We don't hold an inode lock, so there's nothing else to stop
@@ -507,7 +510,7 @@ xfs_qm_scall_setqlim(
* Get the dquot (locked), and join it to the transaction.
* Allocate the dquot if this doesn't exist.
*/
- if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) {
+ if ((error = xfs_qm_dqget(mp, NULL, id, XFS_QMOPT_DQALLOC, &dqp))) {
xfs_trans_cancel(tp, XFS_TRANS_ABORT);
ASSERT(error != ENOENT);
goto out_unlock;
@@ -527,7 +530,7 @@ xfs_qm_scall_setqlim(
if (hard == 0 || hard >= soft) {
ddq->d_blk_hardlimit = cpu_to_be64(hard);
ddq->d_blk_softlimit = cpu_to_be64(soft);
- if (id == 0) {
+ if (root_qid) {
q->qi_bhardlimit = hard;
q->qi_bsoftlimit = soft;
}
@@ -543,7 +546,7 @@ xfs_qm_scall_setqlim(
if (hard == 0 || hard >= soft) {
ddq->d_rtb_hardlimit = cpu_to_be64(hard);
ddq->d_rtb_softlimit = cpu_to_be64(soft);
- if (id == 0) {
+ if (root_qid) {
q->qi_rtbhardlimit = hard;
q->qi_rtbsoftlimit = soft;
}
@@ -560,7 +563,7 @@ xfs_qm_scall_setqlim(
if (hard == 0 || hard >= soft) {
ddq->d_ino_hardlimit = cpu_to_be64(hard);
ddq->d_ino_softlimit = cpu_to_be64(soft);
- if (id == 0) {
+ if (root_qid) {
q->qi_ihardlimit = hard;
q->qi_isoftlimit = soft;
}
@@ -578,7 +581,7 @@ xfs_qm_scall_setqlim(
if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);

- if (id == 0) {
+ if (root_qid) {
/*
* Timelimits for the super user set the relative time
* the other users can be over quota for this file system.
@@ -716,8 +719,7 @@ error0:
int
xfs_qm_scall_getquota(
struct xfs_mount *mp,
- xfs_dqid_t id,
- uint type,
+ struct kqid id,
struct fs_disk_quota *dst)
{
struct xfs_dquot *dqp;
@@ -728,7 +730,7 @@ xfs_qm_scall_getquota(
* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
* exist, we'll get ENOENT back.
*/
- error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp);
+ error = xfs_qm_dqget(mp, NULL, id, 0, &dqp);
if (error)
return error;

@@ -744,7 +746,7 @@ xfs_qm_scall_getquota(
memset(dst, 0, sizeof(*dst));
dst->d_version = FS_DQUOT_VERSION;
dst->d_flags = xfs_qm_export_qtype_flags(dqp->q_core.d_flags);
- dst->d_id = be32_to_cpu(dqp->q_core.d_id);
+ dst->d_id = from_kqid_munged(current_user_ns(), dqp->dq_id);
dst->d_blk_hardlimit =
XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
dst->d_blk_softlimit =
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index b50ec5b..f48f801 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -311,7 +311,7 @@ extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
struct xfs_mount *, struct xfs_dquot *,
struct xfs_dquot *, long, long, uint);

-extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint,
+extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t, kprojid_t, uint,
struct xfs_dquot **, struct xfs_dquot **);
extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *);
@@ -332,7 +332,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);

#else
static inline int
-xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid,
+xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t uid, kgid_t gid, kprojid_t prid,
uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp)
{
*udqp = NULL;
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 71926d6..4d88faa 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -27,20 +27,6 @@
#include "xfs_qm.h"
#include <linux/quota.h>

-
-STATIC int
-xfs_quota_type(int type)
-{
- switch (type) {
- case USRQUOTA:
- return XFS_DQ_USER;
- case GRPQUOTA:
- return XFS_DQ_GROUP;
- default:
- return XFS_DQ_PROJ;
- }
-}
-
STATIC int
xfs_fs_get_xstate(
struct super_block *sb,
@@ -107,8 +93,7 @@ xfs_fs_get_dqblk(
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;

- return -xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
- xfs_quota_type(qid.type), fdq);
+ return -xfs_qm_scall_getquota(mp, qid, fdq);
}

STATIC int
@@ -126,8 +111,7 @@ xfs_fs_set_dqblk(
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;

- return -xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
- xfs_quota_type(qid.type), fdq);
+ return -xfs_qm_scall_setqlim(mp, qid, fdq);
}

const struct quotactl_ops xfs_quotactl_operations = {
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 30ff5f4..b919704 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -171,7 +171,7 @@ xfs_rename(
* tree quota mechanism would be circumvented.
*/
if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
- (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
+ !projid_eq(target_dp->i_d.di_projid, src_ip->i_d.di_projid))) {
error = XFS_ERROR(EXDEV);
goto error_return;
}
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 0c7fa54..9a65ca6 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -578,11 +578,7 @@ xfs_quota_warn(
/* no warnings for project quotas - we just return ENOSPC later */
if (dqp->dq_flags & XFS_DQ_PROJ)
return;
- quota_send_warning(make_kqid(&init_user_ns,
- (dqp->dq_flags & XFS_DQ_USER) ?
- USRQUOTA : GRPQUOTA,
- be32_to_cpu(dqp->q_core.d_id)),
- mp->m_super->s_dev, type);
+ quota_send_warning(dqp->dq_id, mp->m_super->s_dev, type);
}

/*
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 0025c78..f0a9f1d 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -54,7 +54,7 @@ xfs_dir_ialloc(
umode_t mode,
xfs_nlink_t nlink,
xfs_dev_t rdev,
- prid_t prid, /* project id */
+ kprojid_t prid, /* project id */
int okalloc, /* ok to allocate new space */
xfs_inode_t **ipp, /* pointer to inode; it will be
locked. */
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index 5eeab46..7757f7c 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -19,7 +19,7 @@
#define __XFS_UTILS_H__

extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, umode_t, xfs_nlink_t,
- xfs_dev_t, prid_t, int, xfs_inode_t **, int *);
+ xfs_dev_t, kprojid_t, int, xfs_inode_t **, int *);
extern int xfs_droplink(xfs_trans_t *, xfs_inode_t *);
extern int xfs_bumplink(xfs_trans_t *, xfs_inode_t *);
extern void xfs_bump_ino_vers2(xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 2a5c6373..efc2420 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -727,7 +727,7 @@ xfs_create(
boolean_t unlock_dp_on_error = B_FALSE;
uint cancel_flags;
int committed;
- prid_t prid;
+ kprojid_t prid;
struct xfs_dquot *udqp = NULL;
struct xfs_dquot *gdqp = NULL;
uint resblks;
@@ -740,9 +740,9 @@ xfs_create(
return XFS_ERROR(EIO);

if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
- prid = xfs_get_projid(dp);
+ prid = dp->i_d.di_projid;
else
- prid = XFS_PROJID_DEFAULT;
+ prid = make_kprojid(&init_user_ns, XFS_PROJID_DEFAULT);

/*
* Make sure that we have allocated dquot(s) on disk.
@@ -1304,7 +1304,7 @@ xfs_link(
* the tree quota mechanism could be circumvented.
*/
if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
- (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
+ !projid_eq(tdp->i_d.di_projid, sip->i_d.di_projid))) {
error = XFS_ERROR(EXDEV);
goto error_return;
}
@@ -1378,7 +1378,7 @@ xfs_symlink(
int byte_cnt;
int n;
xfs_buf_t *bp;
- prid_t prid;
+ kprojid_t prid;
struct xfs_dquot *udqp, *gdqp;
uint resblks;

@@ -1401,9 +1401,9 @@ xfs_symlink(

udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
- prid = xfs_get_projid(dp);
+ prid = dp->i_d.di_projid;
else
- prid = XFS_PROJID_DEFAULT;
+ prid = make_kprojid(&init_user_ns, XFS_PROJID_DEFAULT);

/*
* Make sure that we have allocated dquot(s) on disk.
diff --git a/init/Kconfig b/init/Kconfig
index ee7e5b6..fb5e192 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on XFS_FS = n

config UIDGID_STRICT_TYPE_CHECKS
bool "Require conversions between uid/gids and their internal representation"
--
1.7.5.4

2012-11-20 12:45:44

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: Mark Fasheh <[email protected]>
Cc: Joel Becker <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/ocfs2/acl.c | 31 +++++++++++++++++++++++++++++--
fs/ocfs2/dlmglue.c | 8 ++++----
fs/ocfs2/file.c | 11 ++++++-----
fs/ocfs2/inode.c | 12 ++++++------
fs/ocfs2/namei.c | 4 ++--
fs/ocfs2/refcounttree.c | 2 +-
init/Kconfig | 1 -
7 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 260b162..8a40457 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -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;
}
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 4f7795f..f99af1c 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -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,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 5a4ee77..dc19b69 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
(unsigned long long)OCFS2_I(inode)->ip_blkno,
dentry->d_name.len, dentry->d_name.name,
attr->ia_valid, attr->ia_mode,
- attr->ia_uid, attr->ia_gid);
+ from_kuid(&init_user_ns, attr->ia_uid),
+ from_kgid(&init_user_ns, attr->ia_gid));

/* ensuring we don't even attempt to truncate a symlink */
if (S_ISLNK(inode->i_mode))
@@ -1174,14 +1175,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
}
}

- if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
- (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+ if ((attr->ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) ||
+ (attr->ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) {
/*
* Gather pointers to quota structures so that allocation /
* freeing of quota structures happens here and not inside
* dquot_transfer() where we have problems with lock ordering
*/
- if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
+ if (attr->ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
@@ -1190,7 +1191,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
goto bail_unlock;
}
}
- if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
+ if (attr->ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid)
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index d89e08a..f87f9bd 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -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;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f1fd074..04ee1b5 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -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));
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 30a0550..934a4ac 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -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;
diff --git a/init/Kconfig b/init/Kconfig
index 1bcc523..ee7e5b6 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on OCFS2_FS = n
depends on XFS_FS = n

config UIDGID_STRICT_TYPE_CHECKS
--
1.7.5.4

2012-11-20 12:44:40

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 07/12] userns: Convert ncpfs to use kuid and kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: Petr Vandrovec <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/ncpfs/inode.c | 55 ++++++++++++++++++++++++++++++--------------------
fs/ncpfs/ioctl.c | 25 ++++++++++++----------
fs/ncpfs/ncp_fs_sb.h | 6 ++--
init/Kconfig | 1 -
4 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index d7e9fe7..3dd2cfd 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -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) &&
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 6958adf..d44318d 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -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
diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h
index 54cc0cd..c51b2c5 100644
--- a/fs/ncpfs/ncp_fs_sb.h
+++ b/fs/ncpfs/ncp_fs_sb.h
@@ -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;
diff --git a/init/Kconfig b/init/Kconfig
index 53b61cd..433e6e0 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on NCP_FS = n
depends on NFSD = n
depends on NFS_FS = n
depends on OCFS2_FS = n
--
1.7.5.4

2012-11-20 12:46:35

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate

From: "Eric W. Biederman" <[email protected]>

Cc: Steve French <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/cifs/cifs_fs_sb.h | 8 ++--
fs/cifs/cifs_spnego.c | 4 +-
fs/cifs/cifsacl.c | 115 ++++++++++++++++++++++++++++++++++++------------
fs/cifs/cifsacl.h | 16 ++++++-
fs/cifs/cifsfs.c | 12 +++--
fs/cifs/cifsglob.h | 22 +++++-----
fs/cifs/cifspdu.h | 2 +
fs/cifs/cifsproto.h | 9 ++--
fs/cifs/cifssmb.c | 11 ++++-
fs/cifs/connect.c | 58 +++++++++++++++++++------
fs/cifs/dir.c | 18 ++++----
fs/cifs/file.c | 8 ++--
fs/cifs/inode.c | 28 ++++++------
fs/cifs/misc.c | 2 +-
init/Kconfig | 1 -
15 files changed, 213 insertions(+), 101 deletions(-)

diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index c865bfd..37e4a72 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -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;
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 086f381..014a4c2 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -149,10 +149,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
goto out;

dp = description + strlen(description);
- sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
+ sprintf(dp, ";uid=0x%x", from_kuid_munged(&init_user_ns, sesInfo->linux_uid));

dp = description + strlen(description);
- sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
+ sprintf(dp, ";creduid=0x%x", from_kuid_munged(&init_user_ns, sesInfo->cred_uid));

if (sesInfo->user_name) {
dp = description + strlen(description);
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index fc783e2..0f8b920 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -44,6 +44,55 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };

const struct cred *root_cred;

+static inline struct cifs_id kuid_to_cid(kuid_t uid)
+{
+ struct cifs_id cid;
+ cid.type = SIDOWNER;
+ cid.uid = uid;
+ return cid;
+}
+
+static inline struct cifs_id kgid_to_cid(kgid_t gid)
+{
+ struct cifs_id cid;
+ cid.type = SIDGROUP;
+ cid.gid = gid;
+ return cid;
+}
+
+static unsigned long from_cid(struct user_namespace *user_ns, struct cifs_id cid)
+{
+ switch (cid.type) {
+ case SIDOWNER:
+ return from_kuid(user_ns, cid.uid);
+ case SIDGROUP:
+ return from_kgid(user_ns, cid.gid);
+ default:
+ BUG();
+ }
+}
+
+static bool cid_lt(struct cifs_id left, struct cifs_id right)
+{
+ if (left.type < right.type)
+ return true;
+ if (left.type > right.type)
+ return false;
+ switch (left.type) {
+ case SIDOWNER:
+ return uid_lt(left.uid, right.uid);
+ case SIDGROUP:
+ return gid_lt(left.gid, right.gid);
+ default:
+ BUG();
+ }
+}
+
+static inline bool cid_gt(struct cifs_id left, struct cifs_id right)
+{
+ return cid_lt(right, left);
+}
+
static void
shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
int *nr_del)
@@ -105,7 +154,7 @@ cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
}

static void
-sid_rb_insert(struct rb_root *root, unsigned long cid,
+sid_rb_insert(struct rb_root *root, struct cifs_id cid,
struct cifs_sid_id **psidid, char *typestr)
{
char *strptr;
@@ -117,11 +166,11 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,
while (node) {
lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
parent = node;
- if (cid > lsidid->id) {
+ if (cid_gt(cid, lsidid->id)) {
linkto = &(node->rb_left);
node = node->rb_left;
}
- if (cid < lsidid->id) {
+ if (cid_lt(cid, lsidid->id)) {
linkto = &(node->rb_right);
node = node->rb_right;
}
@@ -133,7 +182,7 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,

sprintf((*psidid)->sidstr, "%s", typestr);
strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
- sprintf(strptr, "%ld", cid);
+ sprintf(strptr, "%ld", from_cid(&init_user_ns, cid));

clear_bit(SID_ID_PENDING, &(*psidid)->state);
clear_bit(SID_ID_MAPPED, &(*psidid)->state);
@@ -143,16 +192,16 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,
}

static struct cifs_sid_id *
-sid_rb_search(struct rb_root *root, unsigned long cid)
+sid_rb_search(struct rb_root *root, struct cifs_id cid)
{
struct rb_node *node = root->rb_node;
struct cifs_sid_id *lsidid;

while (node) {
lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
- if (cid > lsidid->id)
+ if (cid_gt(cid, lsidid->id))
node = node->rb_left;
- else if (cid < lsidid->id)
+ else if (cid_lt(cid, lsidid->id))
node = node->rb_right;
else /* node found */
return lsidid;
@@ -292,7 +341,7 @@ sidid_pending_wait(void *unused)
}

static int
-id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
+id_to_sid(struct cifs_id cid, struct cifs_sid *ssid)
{
int rc = 0;
struct key *sidkey;
@@ -302,10 +351,10 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
struct rb_root *cidtree;
spinlock_t *cidlock;

- if (sidtype == SIDOWNER) {
+ if (cid.type == SIDOWNER) {
cidlock = &siduidlock;
cidtree = &uidtree;
- } else if (sidtype == SIDGROUP) {
+ } else if (cid.type == SIDGROUP) {
cidlock = &sidgidlock;
cidtree = &gidtree;
} else
@@ -336,7 +385,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
} else {
psidid = npsidid;
sid_rb_insert(cidtree, cid, &psidid,
- sidtype == SIDOWNER ? "oi:" : "gi:");
+ cid.type == SIDOWNER ? "oi:" : "gi:");
++psidid->refcount;
spin_unlock(cidlock);
}
@@ -410,7 +459,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
struct cifs_fattr *fattr, uint sidtype)
{
int rc;
- unsigned long cid;
+ struct cifs_id cid;
struct key *idkey;
const struct cred *saved_cred;
struct cifs_sid_id *psidid, *npsidid;
@@ -418,11 +467,11 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
spinlock_t *cidlock;

if (sidtype == SIDOWNER) {
- cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
+ cid = kuid_to_cid(cifs_sb->mnt_uid); /* default uid, in case upcall fails */
cidlock = &siduidlock;
cidtree = &uidtree;
} else if (sidtype == SIDGROUP) {
- cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
+ cid = kgid_to_cid(cifs_sb->mnt_gid); /* default gid, in case upcall fails */
cidlock = &sidgidlock;
cidtree = &gidtree;
} else
@@ -471,7 +520,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
* any fields of the node after a reference is put .
*/
if (test_bit(SID_ID_MAPPED, &psidid->state)) {
- cid = psidid->id;
+ //cid = psidid->id;
psidid->time = jiffies; /* update ts for accessing */
goto sid_to_id_out;
}
@@ -485,8 +534,13 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
if (IS_ERR(idkey))
cFYI(1, "%s: Can't map SID to an id", __func__);
else {
- cid = *(unsigned long *)idkey->payload.value;
- psidid->id = cid;
+ u32 id;
+ id = *(u32 *)idkey->payload.value;
+ psidid->id.type = sidtype;
+ if (sidtype == SIDOWNER)
+ psidid->id.uid = make_kuid(&init_user_ns, id);
+ else
+ psidid->id.gid = make_kgid(&init_user_ns, id);
set_bit(SID_ID_MAPPED, &psidid->state);
key_put(idkey);
kfree(psidid->sidstr);
@@ -510,10 +564,10 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,

sid_to_id_out:
--psidid->refcount; /* decremented without spinlock */
- if (sidtype == SIDOWNER)
- fattr->cf_uid = cid;
+ if (cid.type == SIDOWNER)
+ fattr->cf_uid = cid.uid;
else
- fattr->cf_gid = cid;
+ fattr->cf_gid = cid.gid;

return 0;
}
@@ -537,7 +591,8 @@ init_cifs_idmap(void)
if (!cred)
return -ENOMEM;

- keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
+ keyring = key_alloc(&key_type_keyring, ".cifs_idmap",
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ,
KEY_ALLOC_NOT_IN_QUOTA);
@@ -1074,7 +1129,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,

/* Convert permission bits from mode to equivalent CIFS ACL */
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
- __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
+ __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
{
int rc = 0;
__u32 dacloffset;
@@ -1106,17 +1161,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
*aclflag = CIFS_ACL_DACL;
} else {
memcpy(pnntsd, pntsd, secdesclen);
- if (uid != NO_CHANGE_32) { /* chown */
+ if (!uid_eq(uid, NO_CHANGE_UID)) { /* chown */
owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
le32_to_cpu(pnntsd->osidoffset));
nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
GFP_KERNEL);
if (!nowner_sid_ptr)
return -ENOMEM;
- rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
+ rc = id_to_sid(kuid_to_cid(uid), nowner_sid_ptr);
if (rc) {
cFYI(1, "%s: Mapping error %d for owner id %d",
- __func__, rc, uid);
+ __func__, rc,
+ from_kuid(&init_user_ns, uid));
kfree(nowner_sid_ptr);
return rc;
}
@@ -1125,17 +1181,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
kfree(nowner_sid_ptr);
*aclflag = CIFS_ACL_OWNER;
}
- if (gid != NO_CHANGE_32) { /* chgrp */
+ if (!gid_eq(gid, NO_CHANGE_GID)) { /* chgrp */
group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
le32_to_cpu(pnntsd->gsidoffset));
ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
GFP_KERNEL);
if (!ngroup_sid_ptr)
return -ENOMEM;
- rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
+ rc = id_to_sid(kgid_to_cid(gid), ngroup_sid_ptr);
if (rc) {
cFYI(1, "%s: Mapping error %d for group id %d",
- __func__, rc, gid);
+ __func__, rc,
+ from_kgid(&init_user_ns, gid));
kfree(ngroup_sid_ptr);
return rc;
}
@@ -1304,7 +1361,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
/* Convert mode bits to an ACL so we can update the ACL on the server */
int
id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
- uid_t uid, gid_t gid)
+ kuid_t uid, kgid_t gid)
{
int rc = 0;
int aclflag = CIFS_ACL_DACL; /* default flag to set */
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 5c902c7..233c576 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -39,8 +39,10 @@
#define ACCESS_ALLOWED 0
#define ACCESS_DENIED 1

-#define SIDOWNER 1
-#define SIDGROUP 2
+enum sidtype {
+ SIDOWNER = 1,
+ SIDGROUP = 2,
+};
#define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */

#define SID_ID_MAPPED 0
@@ -83,9 +85,17 @@ struct cifs_wksid {
char sidname[SIDNAMELENGTH];
} __attribute__((packed));

+struct cifs_id {
+ enum sidtype type;
+ union {
+ kuid_t uid;
+ kgid_t gid;
+ };
+};
+
struct cifs_sid_id {
unsigned int refcount; /* increment with spinlock, decrement without */
- unsigned long id;
+ struct cifs_id id;
unsigned long time;
unsigned long state;
char *sidstr;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e7931cc..0a4740b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -377,13 +377,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
(int)(srcaddr->sa_family));
}

- seq_printf(s, ",uid=%u", cifs_sb->mnt_uid);
+ seq_printf(s, ",uid=%u", from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
seq_printf(s, ",forceuid");
else
seq_printf(s, ",noforceuid");

- seq_printf(s, ",gid=%u", cifs_sb->mnt_gid);
+ seq_printf(s, ",gid=%u", from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
seq_printf(s, ",forcegid");
else
@@ -438,9 +438,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
seq_printf(s, ",noperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
- seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid);
+ seq_printf(s, ",backupuid=%u",
+ from_kuid_munged(&init_user_ns,
+ cifs_sb->mnt_backupuid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
- seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid);
+ seq_printf(s, ",backupgid=%u",
+ from_kgid_munged(&init_user_ns,
+ cifs_sb->mnt_backupgid));

seq_printf(s, ",rsize=%u", cifs_sb->rsize);
seq_printf(s, ",wsize=%u", cifs_sb->wsize);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f5af252..97f1683 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -400,11 +400,11 @@ struct smb_vol {
char *iocharset; /* local code page for mapping to and from Unicode */
char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
- uid_t cred_uid;
- uid_t linux_uid;
- gid_t linux_gid;
- uid_t backupuid;
- gid_t backupgid;
+ kuid_t cred_uid;
+ kuid_t linux_uid;
+ kgid_t linux_gid;
+ kuid_t backupuid;
+ kgid_t backupgid;
umode_t file_mode;
umode_t dir_mode;
unsigned secFlg;
@@ -703,8 +703,8 @@ struct cifs_ses {
char *serverNOS; /* name of network operating system of server */
char *serverDomain; /* security realm of server */
__u64 Suid; /* remote smb uid */
- uid_t linux_uid; /* overriding owner of files on the mount */
- uid_t cred_uid; /* owner of credentials */
+ kuid_t linux_uid; /* overriding owner of files on the mount */
+ kuid_t cred_uid; /* owner of credentials */
unsigned int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
@@ -838,7 +838,7 @@ struct cifs_tcon {
*/
struct tcon_link {
struct rb_node tl_rbnode;
- uid_t tl_uid;
+ kuid_t tl_uid;
unsigned long tl_flags;
#define TCON_LINK_MASTER 0
#define TCON_LINK_PENDING 1
@@ -931,7 +931,7 @@ struct cifsFileInfo {
struct list_head tlist; /* pointer to next fid owned by tcon */
struct list_head flist; /* next fid (file instance) for this inode */
struct cifs_fid_locks *llist; /* brlocks held by this fid */
- unsigned int uid; /* allows finding which FileInfo structure */
+ kuid_t uid; /* allows finding which FileInfo structure */
__u32 pid; /* process id who opened file */
struct cifs_fid fid; /* file id from remote */
/* BB add lock scope info here if needed */ ;
@@ -1259,8 +1259,8 @@ struct cifs_fattr {
u64 cf_eof;
u64 cf_bytes;
u64 cf_createtime;
- uid_t cf_uid;
- gid_t cf_gid;
+ kuid_t cf_uid;
+ kgid_t cf_gid;
umode_t cf_mode;
dev_t cf_rdev;
unsigned int cf_nlink;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b9d59a9..2ede310 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -278,6 +278,8 @@

#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
#define NO_CHANGE_32 0xFFFFFFFFUL
+#define NO_CHANGE_UID INVALID_UID
+#define NO_CHANGE_GID INVALID_GID

/* IPC$ in ASCII */
#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 5144e9f..27b268a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -46,7 +46,8 @@ extern void _free_xid(unsigned int);
({ \
unsigned int __xid = _get_xid(); \
cFYI(1, "CIFS VFS: in %s as Xid: %u with uid: %d", \
- __func__, __xid, current_fsuid()); \
+ __func__, __xid, \
+ from_kuid(&init_user_ns, current_fsuid())); \
__xid; \
})

@@ -161,7 +162,7 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr, struct inode *inode,
const char *path, const __u16 *pfid);
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
- uid_t, gid_t);
+ kuid_t, kgid_t);
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
const char *, u32 *);
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
@@ -304,8 +305,8 @@ struct cifs_unix_set_info_args {
__u64 atime;
__u64 mtime;
__u64 mode;
- __u64 uid;
- __u64 gid;
+ kuid_t uid;
+ kgid_t gid;
dev_t device;
};

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 76d0d29..6b88d47 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -5820,6 +5820,13 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
const struct cifs_unix_set_info_args *args)
{
u64 mode = args->mode;
+ __u64 uid;
+ __u64 gid;
+
+ uid = uid_eq(args->uid, NO_CHANGE_UID) ? NO_CHANGE_64:
+ (__u64)from_kuid(&init_user_ns, args->uid);
+ gid = gid_eq(args->gid, NO_CHANGE_GID) ? NO_CHANGE_64:
+ (__u64)from_kgid(&init_user_ns, args->gid);

/*
* Samba server ignores set of file size to zero due to bugs in some
@@ -5833,8 +5840,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
data_offset->LastStatusChange = cpu_to_le64(args->ctime);
data_offset->LastAccessTime = cpu_to_le64(args->atime);
data_offset->LastModificationTime = cpu_to_le64(args->mtime);
- data_offset->Uid = cpu_to_le64(args->uid);
- data_offset->Gid = cpu_to_le64(args->gid);
+ data_offset->Uid = cpu_to_le64(uid);
+ data_offset->Gid = cpu_to_le64(gid);
/* better to leave device as zero when it is */
data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5c670b9..dab3cf1 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1108,6 +1108,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
char *string = NULL;
char *tmp_end, *value;
char delim;
+ kuid_t uid;
+ kgid_t gid;

separator[0] = ',';
separator[1] = 0;
@@ -1361,7 +1363,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
__func__);
goto cifs_parse_mount_err;
}
- vol->backupuid = option;
+ uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(uid)) {
+ cERROR(1, "%s: Invalid backupuid value",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->backupuid = uid;
vol->backupuid_specified = true;
break;
case Opt_backupgid:
@@ -1370,7 +1378,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
__func__);
goto cifs_parse_mount_err;
}
- vol->backupgid = option;
+ gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(gid)) {
+ cERROR(1, "%s: Invalid backupgid value",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->backupgid = gid;
vol->backupgid_specified = true;
break;
case Opt_uid:
@@ -1379,7 +1393,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
__func__);
goto cifs_parse_mount_err;
}
- vol->linux_uid = option;
+ uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(uid)) {
+ cERROR(1, "%s: Invalid uid value",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->linux_uid = uid;
uid_specified = true;
break;
case Opt_cruid:
@@ -1388,7 +1408,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
__func__);
goto cifs_parse_mount_err;
}
- vol->cred_uid = option;
+ uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(uid)) {
+ cERROR(1, "%s: Invalid cruid value",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->cred_uid = uid;
break;
case Opt_gid:
if (get_option_ul(args, &option)) {
@@ -1396,7 +1422,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
__func__);
goto cifs_parse_mount_err;
}
- vol->linux_gid = option;
+ gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(gid)) {
+ cERROR(1, "%s: Invalid gid value",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->linux_gid = gid;
gid_specified = true;
break;
case Opt_file_mode:
@@ -2203,7 +2235,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
{
switch (ses->server->secType) {
case Kerberos:
- if (vol->cred_uid != ses->cred_uid)
+ if (!uid_eq(vol->cred_uid, ses->cred_uid))
return 0;
break;
default:
@@ -2692,7 +2724,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
if (new->rsize && new->rsize < old->rsize)
return 0;

- if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
+ if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
return 0;

if (old->mnt_file_mode != new->mnt_file_mode ||
@@ -3910,7 +3942,7 @@ cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
}

static struct cifs_tcon *
-cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
{
int rc;
struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
@@ -3980,7 +4012,7 @@ cifs_sb_tcon_pending_wait(void *unused)

/* find and return a tlink with given uid */
static struct tcon_link *
-tlink_rb_search(struct rb_root *root, uid_t uid)
+tlink_rb_search(struct rb_root *root, kuid_t uid)
{
struct rb_node *node = root->rb_node;
struct tcon_link *tlink;
@@ -3988,9 +4020,9 @@ tlink_rb_search(struct rb_root *root, uid_t uid)
while (node) {
tlink = rb_entry(node, struct tcon_link, tl_rbnode);

- if (tlink->tl_uid > uid)
+ if (uid_gt(tlink->tl_uid, uid))
node = node->rb_left;
- else if (tlink->tl_uid < uid)
+ else if (uid_lt(tlink->tl_uid, uid))
node = node->rb_right;
else
return tlink;
@@ -4009,7 +4041,7 @@ tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
parent = *new;

- if (tlink->tl_uid > new_tlink->tl_uid)
+ if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
new = &((*new)->rb_left);
else
new = &((*new)->rb_right);
@@ -4039,7 +4071,7 @@ struct tcon_link *
cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
{
int ret;
- uid_t fsuid = current_fsuid();
+ kuid_t fsuid = current_fsuid();
struct tcon_link *tlink, *newtlink;

if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 7c0a812..d2c4062 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -310,14 +310,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,

*created |= FILE_CREATED;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64) current_fsuid();
+ args.uid = current_fsuid();
if (inode->i_mode & S_ISGID)
- args.gid = (__u64) inode->i_gid;
+ args.gid = inode->i_gid;
else
- args.gid = (__u64) current_fsgid();
+ args.gid = current_fsgid();
} else {
- args.uid = NO_CHANGE_64;
- args.gid = NO_CHANGE_64;
+ args.uid = NO_CHANGE_UID;
+ args.gid = NO_CHANGE_GID;
}
CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
current->tgid);
@@ -547,11 +547,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
.device = device_number,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64) current_fsuid();
- args.gid = (__u64) current_fsgid();
+ args.uid = current_fsuid();
+ args.gid = current_fsgid();
} else {
- args.uid = NO_CHANGE_64;
- args.gid = NO_CHANGE_64;
+ args.uid = NO_CHANGE_UID;
+ args.gid = NO_CHANGE_GID;
}
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
cifs_sb->local_nls,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index edb25b4..603863c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -487,8 +487,8 @@ int cifs_open(struct inode *inode, struct file *file)
*/
struct cifs_unix_set_info_args args = {
.mode = inode->i_mode,
- .uid = NO_CHANGE_64,
- .gid = NO_CHANGE_64,
+ .uid = NO_CHANGE_UID,
+ .gid = NO_CHANGE_GID,
.ctime = NO_CHANGE_64,
.atime = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
@@ -1631,7 +1631,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
- if (fsuid_only && open_file->uid != current_fsuid())
+ if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
if (!open_file->invalidHandle) {
@@ -1684,7 +1684,7 @@ refind_writable:
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (!any_available && open_file->pid != current->tgid)
continue;
- if (fsuid_only && open_file->uid != current_fsuid())
+ if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
if (!open_file->invalidHandle) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index afdff79..c43bfa2 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -247,12 +247,12 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
fattr->cf_uid = cifs_sb->mnt_uid;
else
- fattr->cf_uid = le64_to_cpu(info->Uid);
+ fattr->cf_uid = make_kuid(&init_user_ns, le64_to_cpu(info->Uid));

if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
fattr->cf_gid = cifs_sb->mnt_gid;
else
- fattr->cf_gid = le64_to_cpu(info->Gid);
+ fattr->cf_gid = make_kgid(&init_user_ns, le64_to_cpu(info->Gid));

fattr->cf_nlink = le64_to_cpu(info->Nlinks);
}
@@ -1245,14 +1245,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
.device = 0,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64)current_fsuid();
- if (parent->i_mode & S_ISGID)
- args.gid = (__u64)parent->i_gid;
+ args.uid = current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ args.gid = inode->i_gid;
else
- args.gid = (__u64)current_fsgid();
+ args.gid = current_fsgid();
} else {
- args.uid = NO_CHANGE_64;
- args.gid = NO_CHANGE_64;
+ args.uid = INVALID_UID;
+ args.gid = INVALID_GID;
}
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
cifs_sb->local_nls,
@@ -2012,12 +2012,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_UID)
args->uid = attrs->ia_uid;
else
- args->uid = NO_CHANGE_64;
+ args->uid = NO_CHANGE_UID;

if (attrs->ia_valid & ATTR_GID)
args->gid = attrs->ia_gid;
else
- args->gid = NO_CHANGE_64;
+ args->gid = NO_CHANGE_GID;

if (attrs->ia_valid & ATTR_ATIME)
args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
@@ -2085,8 +2085,8 @@ static int
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
{
unsigned int xid;
- uid_t uid = NO_CHANGE_32;
- gid_t gid = NO_CHANGE_32;
+ kuid_t uid = NO_CHANGE_UID;
+ kgid_t gid = NO_CHANGE_GID;
struct inode *inode = direntry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
@@ -2145,7 +2145,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)

#ifdef CONFIG_CIFS_ACL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
- if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
+ if (!uid_eq(uid, NO_CHANGE_UID) || !gid_eq(gid, NO_CHANGE_GID)) {
rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
uid, gid);
if (rc) {
@@ -2169,7 +2169,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
#ifdef CONFIG_CIFS_ACL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
rc = id_mode_to_cifs_acl(inode, full_path, mode,
- NO_CHANGE_32, NO_CHANGE_32);
+ NO_CHANGE_UID, NO_CHANGE_GID);
if (rc) {
cFYI(1, "%s: Setting ACL failed with error: %d",
__func__, rc);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 3a00c0d..1b15bf8 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -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) {
diff --git a/init/Kconfig b/init/Kconfig
index cb2c46a..58959ea 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -999,7 +999,6 @@ config UIDGID_CONVERTED
default y

# Filesystems
- depends on CIFS = n
depends on CODA_FS = n
depends on GFS2_FS = n
depends on NCP_FS = n
--
1.7.5.4

2012-11-20 12:47:08

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 11/12] userns: Now that everything has been converted remove the unnecessary infrastructure

From: "Eric W. Biederman" <[email protected]>

In particular kill UIDGID_CONVERTED and UIDGID_STRICT_TYPE_CHECKS
and have the code treat them as always true.

Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
include/linux/posix_acl.h | 3 ---
include/linux/projid.h | 15 ---------------
include/linux/uidgid.h | 22 ----------------------
init/Kconfig | 23 -----------------------
4 files changed, 0 insertions(+), 63 deletions(-)

diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 7931efe..f0f7746 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -39,9 +39,6 @@ struct posix_acl_entry {
union {
kuid_t e_uid;
kgid_t e_gid;
-#ifndef CONFIG_UIDGID_STRICT_TYPE_CHECKS
- unsigned int e_id;
-#endif
};
};

diff --git a/include/linux/projid.h b/include/linux/projid.h
index 36517b9..8c1f2c5 100644
--- a/include/linux/projid.h
+++ b/include/linux/projid.h
@@ -18,8 +18,6 @@ extern struct user_namespace init_user_ns;

typedef __kernel_uid32_t projid_t;

-#ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS
-
typedef struct {
projid_t val;
} kprojid_t;
@@ -31,19 +29,6 @@ static inline projid_t __kprojid_val(kprojid_t projid)

#define KPROJIDT_INIT(value) (kprojid_t){ value }

-#else
-
-typedef projid_t kprojid_t;
-
-static inline projid_t __kprojid_val(kprojid_t projid)
-{
- return projid;
-}
-
-#define KPROJIDT_INIT(value) ((kprojid_t) value )
-
-#endif
-
#define INVALID_PROJID KPROJIDT_INIT(-1)
#define OVERFLOW_PROJID 65534

diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h
index 8e522cbc..2d1f9b6 100644
--- a/include/linux/uidgid.h
+++ b/include/linux/uidgid.h
@@ -17,8 +17,6 @@
struct user_namespace;
extern struct user_namespace init_user_ns;

-#ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS
-
typedef struct {
uid_t val;
} kuid_t;
@@ -41,26 +39,6 @@ static inline gid_t __kgid_val(kgid_t gid)
return gid.val;
}

-#else
-
-typedef uid_t kuid_t;
-typedef gid_t kgid_t;
-
-static inline uid_t __kuid_val(kuid_t uid)
-{
- return uid;
-}
-
-static inline gid_t __kgid_val(kgid_t gid)
-{
- return gid;
-}
-
-#define KUIDT_INIT(value) ((kuid_t) value )
-#define KGIDT_INIT(value) ((kgid_t) value )
-
-#endif
-
#define GLOBAL_ROOT_UID KUIDT_INIT(0)
#define GLOBAL_ROOT_GID KGIDT_INIT(0)

diff --git a/init/Kconfig b/init/Kconfig
index fb5e192..6c93bd8 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -963,9 +963,6 @@ config IPC_NS
config USER_NS
bool "User namespace (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on UIDGID_CONVERTED
- select UIDGID_STRICT_TYPE_CHECKS
-
default n
help
This allows containers, i.e. vservers, to use user namespaces
@@ -990,26 +987,6 @@ config NET_NS

endif # NAMESPACES

-config UIDGID_CONVERTED
- # True if all of the selected software conmponents are known
- # to have uid_t and gid_t converted to kuid_t and kgid_t
- # where appropriate and are otherwise safe to use with
- # the user namespace.
- bool
- default y
-
- # Filesystems
-
-config UIDGID_STRICT_TYPE_CHECKS
- bool "Require conversions between uid/gids and their internal representation"
- depends on UIDGID_CONVERTED
- default n
- help
- While the nececessary conversions are being added to all subsystems this option allows
- the code to continue to build for unconverted subsystems.
-
- Say Y here if you want the strict type checking enabled
-
config SCHED_AUTOGROUP
bool "Automatic process group scheduling"
select EVENTFD
--
1.7.5.4

2012-11-20 12:47:06

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH RFC 12/12] userns: Remove the EXPERMINTAL kconfig tag

From: "Eric W. Biederman" <[email protected]>

While there is more work to be done in the form of allowing
more to happen when you have root inside of a user namespace
there is nothing experimental about them.

Signed-off-by: "Eric W. Biederman" <[email protected]>
---
init/Kconfig | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index 6c93bd8..cfd2789 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -961,8 +961,7 @@ config IPC_NS
different IPC objects in different namespaces.

config USER_NS
- bool "User namespace (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "User namespace"
default n
help
This allows containers, i.e. vservers, to use user namespaces
--
1.7.5.4

2012-11-20 16:48:03

by Sage Weil

[permalink] [raw]
Subject: Re: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate

On Tue, 20 Nov 2012, Eric W. Biederman wrote:
> From: "Eric W. Biederman" <[email protected]>
>
> Cc: Sage Weil <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>

Acked-by: Sage Weil <[email protected]>

Do you want me to take this via the ceph tree?

sage


> ---
> fs/ceph/caps.c | 16 ++++++++--------
> fs/ceph/inode.c | 18 +++++++++---------
> fs/ceph/mds_client.c | 4 ++--
> fs/ceph/super.h | 4 ++--
> init/Kconfig | 1 -
> 5 files changed, 21 insertions(+), 22 deletions(-)
>
> diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
> index 3251e9c..ee29cc6 100644
> --- a/fs/ceph/caps.c
> +++ b/fs/ceph/caps.c
> @@ -928,7 +928,7 @@ static int send_cap_msg(struct ceph_mds_session *session,
> u64 size, u64 max_size,
> struct timespec *mtime, struct timespec *atime,
> u64 time_warp_seq,
> - uid_t uid, gid_t gid, umode_t mode,
> + kuid_t uid, kgid_t gid, umode_t mode,
> u64 xattr_version,
> struct ceph_buffer *xattrs_buf,
> u64 follows)
> @@ -972,8 +972,8 @@ static int send_cap_msg(struct ceph_mds_session *session,
> ceph_encode_timespec(&fc->atime, atime);
> fc->time_warp_seq = cpu_to_le32(time_warp_seq);
>
> - fc->uid = cpu_to_le32(uid);
> - fc->gid = cpu_to_le32(gid);
> + fc->uid = cpu_to_le32(from_kuid(&init_user_ns, uid));
> + fc->gid = cpu_to_le32(from_kgid(&init_user_ns, gid));
> fc->mode = cpu_to_le32(mode);
>
> fc->xattr_version = cpu_to_le64(xattr_version);
> @@ -1079,8 +1079,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
> struct timespec mtime, atime;
> int wake = 0;
> umode_t mode;
> - uid_t uid;
> - gid_t gid;
> + kuid_t uid;
> + kgid_t gid;
> struct ceph_mds_session *session;
> u64 xattr_version = 0;
> struct ceph_buffer *xattr_blob = NULL;
> @@ -2353,10 +2353,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
>
> if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
> inode->i_mode = le32_to_cpu(grant->mode);
> - inode->i_uid = le32_to_cpu(grant->uid);
> - inode->i_gid = le32_to_cpu(grant->gid);
> + i_uid_write(inode, le32_to_cpu(grant->uid));
> + i_gid_write(inode, le32_to_cpu(grant->gid));
> dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
> - inode->i_uid, inode->i_gid);
> + i_uid_read(inode), i_gid_read(inode));
> }
>
> if ((issued & CEPH_CAP_LINK_EXCL) == 0)
> diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
> index ba95eea..195b7fd 100644
> --- a/fs/ceph/inode.c
> +++ b/fs/ceph/inode.c
> @@ -612,10 +612,10 @@ static int fill_inode(struct inode *inode,
>
> if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
> inode->i_mode = le32_to_cpu(info->mode);
> - inode->i_uid = le32_to_cpu(info->uid);
> - inode->i_gid = le32_to_cpu(info->gid);
> + i_uid_write(inode, le32_to_cpu(info->uid));
> + i_gid_write(inode, le32_to_cpu(info->gid));
> dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
> - inode->i_uid, inode->i_gid);
> + i_uid_read(inode), i_gid_read(inode));
> }
>
> if ((issued & CEPH_CAP_LINK_EXCL) == 0)
> @@ -1562,26 +1562,26 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
>
> if (ia_valid & ATTR_UID) {
> dout("setattr %p uid %d -> %d\n", inode,
> - inode->i_uid, attr->ia_uid);
> + i_uid_read(inode), from_kuid(&init_user_ns, attr->ia_uid));
> if (issued & CEPH_CAP_AUTH_EXCL) {
> inode->i_uid = attr->ia_uid;
> dirtied |= CEPH_CAP_AUTH_EXCL;
> } else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 ||
> - attr->ia_uid != inode->i_uid) {
> - req->r_args.setattr.uid = cpu_to_le32(attr->ia_uid);
> + !uid_eq(attr->ia_uid, inode->i_uid)) {
> + req->r_args.setattr.uid = cpu_to_le32(from_kuid(&init_user_ns, attr->ia_uid));
> mask |= CEPH_SETATTR_UID;
> release |= CEPH_CAP_AUTH_SHARED;
> }
> }
> if (ia_valid & ATTR_GID) {
> dout("setattr %p gid %d -> %d\n", inode,
> - inode->i_gid, attr->ia_gid);
> + i_gid_read(inode), from_kgid(&init_user_ns, attr->ia_gid));
> if (issued & CEPH_CAP_AUTH_EXCL) {
> inode->i_gid = attr->ia_gid;
> dirtied |= CEPH_CAP_AUTH_EXCL;
> } else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 ||
> - attr->ia_gid != inode->i_gid) {
> - req->r_args.setattr.gid = cpu_to_le32(attr->ia_gid);
> + !gid_eq(attr->ia_gid, inode->i_gid)) {
> + req->r_args.setattr.gid = cpu_to_le32(from_kgid(&init_user_ns, attr->ia_gid));
> mask |= CEPH_SETATTR_GID;
> release |= CEPH_CAP_AUTH_SHARED;
> }
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index 1bcf712..59e45fe 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -578,8 +578,8 @@ static void __register_request(struct ceph_mds_client *mdsc,
> ceph_mdsc_get_request(req);
> __insert_request(mdsc, req);
>
> - req->r_uid = current_fsuid();
> - req->r_gid = current_fsgid();
> + req->r_uid = from_kuid(&init_user_ns, current_fsuid());
> + req->r_gid = from_kgid(&init_user_ns, current_fsgid());
>
> if (dir) {
> struct ceph_inode_info *ci = ceph_inode(dir);
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index 66ebe72..f053bbd 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -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;
> diff --git a/init/Kconfig b/init/Kconfig
> index dfa391d..cb2c46a 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -999,7 +999,6 @@ config UIDGID_CONVERTED
> default y
>
> # Filesystems
> - depends on CEPH_FS = n
> depends on CIFS = n
> depends on CODA_FS = n
> depends on GFS2_FS = n
> --
> 1.7.5.4
>
>

2012-11-20 17:16:16

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH RFC 03/12] userns: Convert ceph to use kuid/kgid where appropriate

Sage Weil <[email protected]> writes:

> On Tue, 20 Nov 2012, Eric W. Biederman wrote:
>> From: "Eric W. Biederman" <[email protected]>
>>
>> Cc: Sage Weil <[email protected]>
>> Acked-by: Serge Hallyn <[email protected]>
>> Signed-off-by: Eric W. Biederman <[email protected]>
>
> Acked-by: Sage Weil <[email protected]>
>
> Do you want me to take this via the ceph tree?

If you have reviewed the changes, understand them and don't have
problems with them, having the changes go through your tree would be
great.

Eric

2012-11-20 17:23:01

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate

Steve French <[email protected]> writes:

> Do you have a pointer to the background on kuid/kgid

You might try this lwn article
https://lwn.net/Articles/491310/

In a nutshell each user namespace has it's own view of uid_t and gid_t
values. Those values are mapped into kernel internal kuid_t and kgid_t
values. Then user space interfaces convert from kuid_t and kgid_t when
read from userspace.

The initial user namespace as a 1-1 identity mapping between kuid_t and
uid_t values.

kuid_t and kgid_t are not assignment compatible with uid_t and gid_t so
that if the conversions are left out a compile error results.

My strategy is to push kuid_t and kgid_t values as deeply into the
kernel data structures as possible so that there is a high propbability
that when we get it wrong a compile error will happen.

Eric

2012-11-20 23:55:31

by Dave Chinner

[permalink] [raw]
Subject: Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate

On Tue, Nov 20, 2012 at 04:43:38AM -0800, Eric W. Biederman wrote:
> From: "Eric W. Biederman" <[email protected]>
>
> - Modify the incore inode to use kuid_t, kgid_t and kprojid_t.
> - Remove xfs_get_projid and xfs_set_projid with projid being stored
> in a single field they are unnecessary.
> - Add dq_id (a struct kqid) to struct xfs_dquot to retain the incore
> version of the quota identifiers.
> - Pass struct kquid all of the way into xfs_qm_dqgetn and xfs_qm_dqread,
> and move xfs_quota_type into xfs_dquot.c from xfs_quotaops.c to support
> this change.
>
> Cc: Ben Myers <[email protected]>
> Cc: Alex Elder <[email protected]>
> Cc: Dave Chinner <[email protected]>
> Signed-off-by: "Eric W. Biederman" <[email protected]>
> ---
.....

> @@ -614,12 +627,12 @@ int
> xfs_qm_dqget(
> xfs_mount_t *mp,
> xfs_inode_t *ip, /* locked inode (optional) */
> - xfs_dqid_t id, /* uid/projid/gid depending on type */
> - uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
> + struct kqid id, /* uid/projid/gid depending on type */
> uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
> xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
> {
> struct xfs_quotainfo *qi = mp->m_quotainfo;
> + uint type = xfs_quota_type(id.type);

uint type = xfs_quota_type(id.type);

....

> diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
> index 7d20af2..1f19b87 100644
> --- a/fs/xfs/xfs_dquot.h
> +++ b/fs/xfs/xfs_dquot.h
> @@ -36,6 +36,7 @@ struct xfs_trans;
> * The incore dquot structure
> */
> typedef struct xfs_dquot {
> + struct kqid dq_id; /* Quota identifier */
> uint dq_flags; /* various flags (XFS_DQ_*) */
> struct list_head q_lru; /* global free list of dquots */
> struct xfs_mount*q_mount; /* filesystem this relates to */

Can you place new entries at the end of the structure, please?

> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 2778258..3656b88 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -570,11 +570,12 @@ xfs_dinode_from_disk(
> to->di_version = from ->di_version;
> to->di_format = from->di_format;
> to->di_onlink = be16_to_cpu(from->di_onlink);
> - to->di_uid = be32_to_cpu(from->di_uid);
> - to->di_gid = be32_to_cpu(from->di_gid);
> + to->di_uid = make_kuid(&init_user_ns, be32_to_cpu(from->di_uid));
> + to->di_gid = make_kgid(&init_user_ns, be32_to_cpu(from->di_gid));

You can't do this, because the incore inode structure is written
directly to the log. This is effectively an on-disk format change.

> to->di_nlink = be32_to_cpu(from->di_nlink);
> - to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
> - to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
> + to->di_projid = make_kprojid(&init_user_ns,
> + be16_to_cpu(from->di_projid_lo) |
> + (be16_to_cpu(from->di_projid_hi) << 16));

As is this. I won't comment on all the other problems that stem from
changing this structure, apart from....

> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 94b32f9..973b252 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -120,8 +120,8 @@ typedef struct xfs_ictimestamp {
> } xfs_ictimestamp_t;
>
> /*
> - * NOTE: This structure must be kept identical to struct xfs_dinode
> - * in xfs_dinode.h except for the endianness annotations.
> + * NOTE: This structure must contain all of the same informationas struct xfs_dinode
> + * in xfs_dinode.h except in core format.

.... noting that you even read the comment that says the incore
inode must remain identical to struct xfs_dinode. Changing the
comment doesn't make the change correct. :/

> */
> typedef struct xfs_icdinode {
> __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
> @@ -129,11 +129,10 @@ typedef struct xfs_icdinode {
> __int8_t di_version; /* inode version */
> __int8_t di_format; /* format of di_c data */
> __uint16_t di_onlink; /* old number of links to file */
> - __uint32_t di_uid; /* owner's user id */
> - __uint32_t di_gid; /* owner's group id */
> + kuid_t di_uid; /* owner's user id */
> + kgid_t di_gid; /* owner's group id */
> __uint32_t di_nlink; /* number of links to file */
> - __uint16_t di_projid_lo; /* lower part of owner's project id */
> - __uint16_t di_projid_hi; /* higher part of owner's project id */
> + kprojid_t di_projid; /* project id */

Basically, you cannot replace these with your new structure because
it changes the layout of the structure, and because it is written
directly into the journal it is an on-disk format change. We might
be able to work around that, but there's a high bar that needs to be
passed before this sort of change canbe made.

The question I have is why do you need to make changes this deeply
to the filesystem? We already pass the {type, id} tuple throughout
the code, and it really only needs to be translated from the special
{kuid_t/kguid_t/kprojid_t, namespace} notation once at entry to the
filesystem.

You are not changing anything on disk or how {type, id} is being
interpreted by the filesystem, so do you really need to propagate
the namespace changes this far down to the low-level filesystem
uid/gid/prid management code? I do not see why it is necessary,
especially as doing so opens several large, smelly cans of worms
that are going to require significant verification effort.

> @@ -1151,8 +1151,8 @@ xfs_setup_inode(
>
> inode->i_mode = ip->i_d.di_mode;
> set_nlink(inode, ip->i_d.di_nlink);
> - inode->i_uid = ip->i_d.di_uid;
> - inode->i_gid = ip->i_d.di_gid;
> + inode->i_uid = ip->i_d.di_uid;
> + inode->i_gid = ip->i_d.di_gid;

You've already added the special structures to the struct inode, so
perhaps that's where the XFS uid/gid on-disk values need to be
translated.
>
> switch (inode->i_mode & S_IFMT) {
> case S_IFBLK:
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 01d10a6..541fdd4 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -90,12 +90,12 @@ xfs_bulkstat_one_int(
> * further change.
> */
> buf->bs_nlink = dic->di_nlink;
> - buf->bs_projid_lo = dic->di_projid_lo;
> - buf->bs_projid_hi = dic->di_projid_hi;
> + buf->bs_projid_lo = from_kprojid(current_user_ns(), dic->di_projid) & 0xffff;
> + buf->bs_projid_hi = from_kprojid(current_user_ns(), dic->di_projid) >> 16;

Another question: why are you using current_user_ns() for project
IDs, but:

> buf->bs_ino = ino;
> buf->bs_mode = dic->di_mode;
> - buf->bs_uid = dic->di_uid;
> - buf->bs_gid = dic->di_gid;
> + buf->bs_uid = from_kuid(&init_user_ns, dic->di_uid);
> + buf->bs_gid = from_kgid(&init_user_ns, dic->di_gid);

init_user_ns for uid/gid?

As it is, I think that even just using namespaces here is wrong -
bulkstat is for filesystem utilities to get the information that is
on disk as efficiently as possible. e.g. xfsdump wants the exact
information in the inode on disk for backup purposes, not what some
random namespace thinks is valid. i.e. if there's projid set on the
inode, it must be reported *unchanged* to xfsdump so that when it is
restored it has the same value on disk.

Hmmm, that also means that using current_user_ns() for setting the
project id is also problematic, because that's what xfs_restore uses
and it has to be written unmolested to the inode.

IOWs, this set of changes is not something that can be done with a
simple search-and-replace, and certainly not a change that can be
asserted to be "obviously correct". That means you're going to need
to write new xfstests for xfsdump/restore to validate that they
correctly backup and restore filesystems in the presence of multiple
namespaces.

> @@ -776,7 +777,9 @@ xfs_qm_qino_alloc(
> return error;
> }
>
> - error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
> + error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
> + make_kprojid(&init_user_ns, 0),
> + 1, ip, &committed);

This sort of thing just makes me cringe. This is all internal
project ID management that has nothing to do with namespaces. It's
for project ID's that are inherited from the parent inode, and as
such we do not care one bit what the namespace is. Internal
passing of project IDs like this this should not be converted at
all as it has nothing at all to do with the namespaces.

Overall, I think this patch needs to be broken up into several
steps. The first is to propagate the new structures into the VFS
entry points of the filesystem, one to convert the quota entry points,
another to convert the generic ACL code, another to convert the
ioctl entry points. At that point, XFS supports namespaces fully,
and it should be possible to review and test the changes sanely.

>From there, targetted patches can drive the kernel structures inward
from the entry points where it makes sense to do so (e.g. common
places that the quota entry points call that take a type/id pair).
The last thing that should happen is internal structures be
converted from type/id pairs to the kernel types if it makes sense
to do so and it makes the code simpler and easier to read....

Cheers,

Dave.
--
Dave Chinner
[email protected]

2012-11-21 00:10:01

by Dave Chinner

[permalink] [raw]
Subject: Re: [PATCH RFC 0/12] Final userns conversions

On Tue, Nov 20, 2012 at 04:42:16AM -0800, Eric W. Biederman wrote:
>
> This patchset contain the basic user namespace changes for filesystems
> that have needed nontrivial work. Along with the 2 patches that depend
> on these changes.
>
> I belive these patches to be correct for allowing the remaining
> filesystems to work in the presence of user namespaces. At the same
> time I would like to give all of these much deeper scrutiny, just
> because there is so much going on. Unfortunately these patches
> individually are not obviously correct.
>
> Since I won't have much time until after Thanksgiving and because the
> merge window is looming I figure I will put these changes out there and
> let people see I am looking at these changes, and see if anyone happens
> to spot anything.

The XFS stuff is non-trivial, causes on-disk format changes and
likely breaks xfsdump/xfsrestore, so the XFS patch is a no-go until
that is sorted out.

Given the short time until the merge window and that the XFS patch
needs to be significantly revised, it's already too late for the XFS
changes to be considered for the 3.8 merge window. Hence I'd
suggest that you are going to be targeting 3.9 for the XFS changes.

> If I can figure out how to responsibly get these changes into linux-next
> I want to get these changes into linux-next so that user namespace bugs
> show up in allyesconfig builds.

The XFS changes definitely need to be staged through the XFS tree
given the complexity of the changes, the amount of validation that
is required. Also, it is likely that there are significant conflicts
against changes already staged for 3.8, so getting it upstream
through the XFS tree is the only option that I'd consider
acceptible...

Cheers,

Dave.
--
Dave Chinner
[email protected]

2012-11-21 19:51:24

by Joel Becker

[permalink] [raw]
Subject: Re: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate

On Tue, Nov 20, 2012 at 04:43:37AM -0800, Eric W. Biederman wrote:
> --- a/fs/ocfs2/file.c
> +++ b/fs/ocfs2/file.c
> @@ -1116,7 +1116,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
> (unsigned long long)OCFS2_I(inode)->ip_blkno,
> dentry->d_name.len, dentry->d_name.name,
> attr->ia_valid, attr->ia_mode,
> - attr->ia_uid, attr->ia_gid);
> + from_kuid(&init_user_ns, attr->ia_uid),
> + from_kgid(&init_user_ns, attr->ia_gid));

Dear Eric,
I have a similar question about init_user_ns to Dave. As far as
I can tell, using init_user_ns here means we'll never get translations
based on the current process namespace. It just so happens that
include/linux/user_namespace.h doesn't allow new namespaces yet, but I
can't see why we would propagate that knowledge elsewhere.
Is there some magic about when init_user_ns should be used
regardless?

Joel

--

Brain: I shall pollute the water supply with this DNAdefibuliser,
turning everyone into mindless slaves.
Pinky: What about the people who drink bottled water?
Brain: Pinky, people who pay 5 dollars for a bottle of water are
already mindless slaves.

http://www.jlbec.org/
[email protected]

2012-11-21 19:52:55

by Joel Becker

[permalink] [raw]
Subject: Re: [PATCH RFC 10/12] userns: Convert xfs to use kuid/kgid/kprojid where appropriate

On Wed, Nov 21, 2012 at 10:55:24AM +1100, Dave Chinner wrote:
> > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> > index 2778258..3656b88 100644
> > --- a/fs/xfs/xfs_inode.c
> > +++ b/fs/xfs/xfs_inode.c
> > @@ -570,11 +570,12 @@ xfs_dinode_from_disk(
> > to->di_version = from ->di_version;
> > to->di_format = from->di_format;
> > to->di_onlink = be16_to_cpu(from->di_onlink);
> > - to->di_uid = be32_to_cpu(from->di_uid);
> > - to->di_gid = be32_to_cpu(from->di_gid);
> > + to->di_uid = make_kuid(&init_user_ns, be32_to_cpu(from->di_uid));
> > + to->di_gid = make_kgid(&init_user_ns, be32_to_cpu(from->di_gid));
>
> You can't do this, because the incore inode structure is written
> directly to the log. This is effectively an on-disk format change.

Yeah, I don't get this either. Over in ocfs2, you do the
correct thing, translating at the boundary from ocfs2_dinode to struct
inode.

Joel

--

"I always thought the hardest questions were those I could not answer.
Now I know they are the ones I can never ask."
- Charlie Watkins

http://www.jlbec.org/
[email protected]

2012-11-21 19:59:46

by Joel Becker

[permalink] [raw]
Subject: Re: [PATCH RFC 09/12] userns: Convert ocfs2 to use kuid and kgid where appropriate

On Tue, Nov 20, 2012 at 04:43:37AM -0800, Eric W. Biederman wrote:
> diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
> index 260b162..8a40457 100644
> --- a/fs/ocfs2/acl.c
> +++ b/fs/ocfs2/acl.c
> @@ -65,7 +65,20 @@ static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size)
>
> acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
> acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
> - acl->a_entries[n].e_id = le32_to_cpu(entry->e_id);
> + switch(acl->a_entries[n].e_tag) {
> + case ACL_USER:
> + acl->a_entries[n].e_uid =
> + make_kuid(&init_user_ns,
> + le32_to_cpu(entry->e_id));
> + break;

Stupid question: do you consider disjoint namespaces on multiple
machines to be a problem? Remember that ocfs2 is a cluster filesystem.
If I have uid 100 on machine A in the default namespace, and then I
mount the filesystem on machine B with uid 100 in a different namespace,
what happens? I presume that both can access as the same nominal uid,
and configuring this correctly is left as an exercise to the namespace
administrator?

> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 4f7795f..f99af1c 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -2045,8 +2045,8 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
> lvb->lvb_version = OCFS2_LVB_VERSION;
> lvb->lvb_isize = cpu_to_be64(i_size_read(inode));
> lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters);
> - lvb->lvb_iuid = cpu_to_be32(inode->i_uid);
> - lvb->lvb_igid = cpu_to_be32(inode->i_gid);
> + lvb->lvb_iuid = cpu_to_be32(i_uid_read(inode));
> + lvb->lvb_igid = cpu_to_be32(i_gid_read(inode));

I have the reverse question here. Are we guaranteed that the
on-disk uid/gid will not change regardless of the namespace? That is,
if I create a file on machine A in init_user_ns as uid 100, then access
it over on machine B in some other namespace with a user-visible uid of
100, will the wire be passing 100 in both directions? This absolutely
must be true for the cluster communication to work.

Joel


--

Life's Little Instruction Book #80

"Slow dance"

http://www.jlbec.org/
[email protected]

2012-11-22 22:23:03

by Steven Whitehouse

[permalink] [raw]
Subject: Re: [PATCH RFC 06/12] userns: Convert gfs2 to use kuid/kgid where appropriate

Hi,

On Tue, 2012-11-20 at 04:43 -0800, Eric W. Biederman wrote:
> From: "Eric W. Biederman" <[email protected]>
>
> - Use struct kqid to hold the identifier of in core quota objects
> - Use qid.type uniformly for all in core quota type computation.
> - kill QDF_USER
> - kill QUOTA_USER and QUOTA_GROUP
>

There are some GFS2 changes in linux-next for merging shortly which are
likely to conflict with your changes in inode.c, but otherwise this
looks ok to me. I don't think that it will be very tricky to fix up the
conflicts.

I've not actually tested this, but it looks ok having read through it.
I'm also copying in Abhi since he looks after quotas in GFS2,

Steve.


> Cc: Steven Whitehouse <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>
> ---
> fs/gfs2/acl.c | 2 +-
> fs/gfs2/bmap.c | 2 +-
> fs/gfs2/dir.c | 2 +-
> fs/gfs2/glops.c | 4 +-
> fs/gfs2/incore.h | 3 +-
> fs/gfs2/inode.c | 36 ++++++++-------
> fs/gfs2/quota.c | 128 +++++++++++++++++++++++------------------------------
> fs/gfs2/quota.h | 15 +++---
> fs/gfs2/super.c | 6 +-
> fs/gfs2/sys.c | 14 +++++-
> fs/gfs2/xattr.c | 4 +-
> init/Kconfig | 1 -
> 12 files changed, 106 insertions(+), 111 deletions(-)
>
> diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
> index f850020..f69ac0a 100644
> --- a/fs/gfs2/acl.c
> +++ b/fs/gfs2/acl.c
> @@ -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;
> diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
> index 1fd3ae2..ce2316b 100644
> --- a/fs/gfs2/bmap.c
> +++ b/fs/gfs2/bmap.c
> @@ -1052,7 +1052,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
> if (error)
> return error;
>
> - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
> + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
> if (error)
> return error;
>
> diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
> index 259b088..5a9f574 100644
> --- a/fs/gfs2/dir.c
> +++ b/fs/gfs2/dir.c
> @@ -1854,7 +1854,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
> if (!ht)
> return -ENOMEM;
>
> - error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
> + error = gfs2_quota_hold(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
> if (error)
> goto out;
>
> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
> index 32cc4fd..f3033f6 100644
> --- a/fs/gfs2/glops.c
> +++ b/fs/gfs2/glops.c
> @@ -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));
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 3d469d3..4fccb6c 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -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;
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 381893c..bf60354 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -365,13 +365,13 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
> }
>
> static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
> - unsigned int *uid, unsigned int *gid)
> + kuid_t *uid, kgid_t *gid)
> {
> if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
> - (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
> + (dip->i_inode.i_mode & S_ISUID) && i_uid_read(&dip->i_inode)) {
> if (S_ISDIR(*mode))
> *mode |= S_ISUID;
> - else if (dip->i_inode.i_uid != current_fsuid())
> + else if (!uid_eq(dip->i_inode.i_uid, current_fsuid()))
> *mode &= ~07111;
> *uid = dip->i_inode.i_uid;
> } else
> @@ -444,7 +444,7 @@ static void gfs2_init_dir(struct buffer_head *dibh,
>
> static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
> const struct gfs2_inum_host *inum, umode_t mode,
> - unsigned int uid, unsigned int gid,
> + kuid_t uid, kgid_t gid,
> const u64 *generation, dev_t dev, const char *symname,
> unsigned size, struct buffer_head **bhp)
> {
> @@ -462,8 +462,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
> di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
> di->di_num.no_addr = cpu_to_be64(inum->no_addr);
> di->di_mode = cpu_to_be32(mode);
> - di->di_uid = cpu_to_be32(uid);
> - di->di_gid = cpu_to_be32(gid);
> + di->di_uid = cpu_to_be32(from_kuid(&init_user_ns, uid));
> + di->di_gid = cpu_to_be32(from_kgid(&init_user_ns, gid));
> di->di_nlink = 0;
> di->di_size = cpu_to_be64(size);
> di->di_blocks = cpu_to_be64(1);
> @@ -517,7 +517,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
> unsigned int size, struct buffer_head **bhp)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
> - unsigned int uid, gid;
> + kuid_t uid;
> + kgid_t gid;
> int error;
>
> munge_mode_uid_gid(dip, &mode, &uid, &gid);
> @@ -558,7 +559,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
> if (error)
> return error;
>
> - error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
> + error = gfs2_quota_lock(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
> if (error)
> goto fail;
>
> @@ -955,8 +956,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
> return -EPERM;
>
> if ((dip->i_inode.i_mode & S_ISVTX) &&
> - dip->i_inode.i_uid != current_fsuid() &&
> - ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
> + !uid_eq(dip->i_inode.i_uid, current_fsuid()) &&
> + !uid_eq(ip->i_inode.i_uid, current_fsuid()) && !capable(CAP_FOWNER))
> return -EPERM;
>
> if (IS_APPEND(&dip->i_inode))
> @@ -1571,7 +1572,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
> {
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_sbd *sdp = GFS2_SB(inode);
> - u32 ouid, ogid, nuid, ngid;
> + kuid_t ouid, nuid;
> + kgid_t ogid, ngid;
> int error;
>
> ouid = inode->i_uid;
> @@ -1579,16 +1581,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
> nuid = attr->ia_uid;
> ngid = attr->ia_gid;
>
> - if (!(attr->ia_valid & ATTR_UID) || ouid == nuid)
> - ouid = nuid = NO_QUOTA_CHANGE;
> - if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
> - ogid = ngid = NO_QUOTA_CHANGE;
> + if (!(attr->ia_valid & ATTR_UID) || uid_eq(ouid, nuid))
> + ouid = nuid = NO_UID_QUOTA_CHANGE;
> + if (!(attr->ia_valid & ATTR_GID) || gid_eq(ogid, ngid))
> + ogid = ngid = NO_GID_QUOTA_CHANGE;
>
> error = gfs2_quota_lock(ip, nuid, ngid);
> if (error)
> return error;
>
> - if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
> + if (uid_valid(ouid) || gid_valid(ogid)) {
> error = gfs2_quota_check(ip, nuid, ngid);
> if (error)
> goto out_gunlock_q;
> @@ -1602,7 +1604,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
> if (error)
> goto out_end_trans;
>
> - if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
> + if (uid_valid(ouid) || gid_valid(ogid)) {
> u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
> gfs2_quota_change(ip, -blocks, ouid, ogid);
> gfs2_quota_change(ip, blocks, nuid, ngid);
> diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> index 40c4b0d..f2353b5 100644
> --- a/fs/gfs2/quota.c
> +++ b/fs/gfs2/quota.c
> @@ -65,19 +65,22 @@
> #include "inode.h"
> #include "util.h"
>
> -#define QUOTA_USER 1
> -#define QUOTA_GROUP 0
> -
> struct gfs2_quota_change_host {
> u64 qc_change;
> u32 qc_flags; /* GFS2_QCF_... */
> - u32 qc_id;
> + struct kqid qc_id;
> };
>
> static LIST_HEAD(qd_lru_list);
> static atomic_t qd_lru_count = ATOMIC_INIT(0);
> static DEFINE_SPINLOCK(qd_lru_lock);
>
> +static u64 gfs2_qid_number(struct kqid qid)
> +{
> + return (2 * (u64)from_kqid(&init_user_ns, qid)) +
> + (qid.type == USRQUOTA) ? 0 : 1;
> +}
> +
> int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
> {
> struct gfs2_quota_data *qd;
> @@ -124,13 +127,13 @@ static u64 qd2offset(struct gfs2_quota_data *qd)
> {
> u64 offset;
>
> - offset = 2 * (u64)qd->qd_id + !test_bit(QDF_USER, &qd->qd_flags);
> + offset = gfs2_qid_number(qd->qd_id);
> offset *= sizeof(struct gfs2_quota);
>
> return offset;
> }
>
> -static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
> +static int qd_alloc(struct gfs2_sbd *sdp, struct kqid qid,
> struct gfs2_quota_data **qdp)
> {
> struct gfs2_quota_data *qd;
> @@ -141,13 +144,11 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
> return -ENOMEM;
>
> atomic_set(&qd->qd_count, 1);
> - qd->qd_id = id;
> - if (user)
> - set_bit(QDF_USER, &qd->qd_flags);
> + qd->qd_id = qid;
> qd->qd_slot = -1;
> INIT_LIST_HEAD(&qd->qd_reclaim);
>
> - error = gfs2_glock_get(sdp, 2 * (u64)id + !user,
> + error = gfs2_glock_get(sdp, gfs2_qid_number(qid),
> &gfs2_quota_glops, CREATE, &qd->qd_gl);
> if (error)
> goto fail;
> @@ -161,8 +162,8 @@ fail:
> return error;
> }
>
> -static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
> - struct gfs2_quota_data **qdp)
> +static int qd_get(struct gfs2_sbd *sdp,
> + struct kqid qid, struct gfs2_quota_data **qdp)
> {
> struct gfs2_quota_data *qd = NULL, *new_qd = NULL;
> int error, found;
> @@ -173,8 +174,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
> found = 0;
> spin_lock(&qd_lru_lock);
> list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
> - if (qd->qd_id == id &&
> - !test_bit(QDF_USER, &qd->qd_flags) == !user) {
> + if (qid_eq(qd->qd_id, qid)) {
> if (!atomic_read(&qd->qd_count) &&
> !list_empty(&qd->qd_reclaim)) {
> /* Remove it from reclaim list */
> @@ -208,7 +208,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
> return 0;
> }
>
> - error = qd_alloc(sdp, user, id, &new_qd);
> + error = qd_alloc(sdp, qid, &new_qd);
> if (error)
> return error;
> }
> @@ -458,12 +458,12 @@ static void qd_unlock(struct gfs2_quota_data *qd)
> qd_put(qd);
> }
>
> -static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id,
> +static int qdsb_get(struct gfs2_sbd *sdp, struct kqid qid,
> struct gfs2_quota_data **qdp)
> {
> int error;
>
> - error = qd_get(sdp, user, id, qdp);
> + error = qd_get(sdp, qid, qdp);
> if (error)
> return error;
>
> @@ -491,7 +491,7 @@ static void qdsb_put(struct gfs2_quota_data *qd)
> qd_put(qd);
> }
>
> -int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
> +int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_quota_data **qd;
> @@ -509,28 +509,28 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
> if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
> return 0;
>
> - error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd);
> + error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd);
> if (error)
> goto out;
> ip->i_res->rs_qa_qd_num++;
> qd++;
>
> - error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd);
> + error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd);
> if (error)
> goto out;
> ip->i_res->rs_qa_qd_num++;
> qd++;
>
> - if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) {
> - error = qdsb_get(sdp, QUOTA_USER, uid, qd);
> + if (uid_valid(uid) && !uid_eq(uid, ip->i_inode.i_uid)) {
> + error = qdsb_get(sdp, make_kqid_uid(uid), qd);
> if (error)
> goto out;
> ip->i_res->rs_qa_qd_num++;
> qd++;
> }
>
> - if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) {
> - error = qdsb_get(sdp, QUOTA_GROUP, gid, qd);
> + if (gid_valid(gid) && !gid_eq(gid, ip->i_inode.i_gid)) {
> + error = qdsb_get(sdp, make_kqid_gid(gid), qd);
> if (error)
> goto out;
> ip->i_res->rs_qa_qd_num++;
> @@ -564,18 +564,10 @@ static int sort_qd(const void *a, const void *b)
> const struct gfs2_quota_data *qd_a = *(const struct gfs2_quota_data **)a;
> const struct gfs2_quota_data *qd_b = *(const struct gfs2_quota_data **)b;
>
> - if (!test_bit(QDF_USER, &qd_a->qd_flags) !=
> - !test_bit(QDF_USER, &qd_b->qd_flags)) {
> - if (test_bit(QDF_USER, &qd_a->qd_flags))
> - return -1;
> - else
> - return 1;
> - }
> - if (qd_a->qd_id < qd_b->qd_id)
> + if (qid_lt(qd_a->qd_id, qd_b->qd_id))
> return -1;
> - if (qd_a->qd_id > qd_b->qd_id)
> + if (qid_lt(qd_b->qd_id, qd_a->qd_id))
> return 1;
> -
> return 0;
> }
>
> @@ -592,9 +584,9 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
> if (!test_bit(QDF_CHANGE, &qd->qd_flags)) {
> qc->qc_change = 0;
> qc->qc_flags = 0;
> - if (test_bit(QDF_USER, &qd->qd_flags))
> + if (qd->qd_id.type == USRQUOTA)
> qc->qc_flags = cpu_to_be32(GFS2_QCF_USER);
> - qc->qc_id = cpu_to_be32(qd->qd_id);
> + qc->qc_id = cpu_to_be32(from_kqid(&init_user_ns, qd->qd_id));
> }
>
> x = be64_to_cpu(qc->qc_change) + change;
> @@ -922,7 +914,7 @@ fail:
> return error;
> }
>
> -int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
> +int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_quota_data *qd;
> @@ -1037,19 +1029,20 @@ static int print_message(struct gfs2_quota_data *qd, char *type)
>
> printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n",
> sdp->sd_fsname, type,
> - (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",
> - qd->qd_id);
> + (qd->qd_id.type == USRQUOTA) ? "user" : "group",
> + from_kqid(&init_user_ns, qd->qd_id));
>
> return 0;
> }
>
> -int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
> +int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
> {
> struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
> struct gfs2_quota_data *qd;
> s64 value;
> unsigned int x;
> int error = 0;
> + int user;
>
> if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
> return 0;
> @@ -1060,8 +1053,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
> for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
> qd = ip->i_res->rs_qa_qd[x];
>
> - if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
> - (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))))
> + user = (qd->qd_id.type == USRQUOTA);
> + if (!((user && uid_eq(qd->qd_id.uid, uid)) ||
> + (!user && gid_eq(qd->qd_id.gid, gid))))
> continue;
>
> value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
> @@ -1071,10 +1065,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
>
> if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
> print_message(qd, "exceeded");
> - quota_send_warning(make_kqid(&init_user_ns,
> - test_bit(QDF_USER, &qd->qd_flags) ?
> - USRQUOTA : GRPQUOTA,
> - qd->qd_id),
> + quota_send_warning(qd->qd_id,
> sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN);
>
> error = -EDQUOT;
> @@ -1084,10 +1075,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
> time_after_eq(jiffies, qd->qd_last_warn +
> gfs2_tune_get(sdp,
> gt_quota_warn_period) * HZ)) {
> - quota_send_warning(make_kqid(&init_user_ns,
> - test_bit(QDF_USER, &qd->qd_flags) ?
> - USRQUOTA : GRPQUOTA,
> - qd->qd_id),
> + quota_send_warning(qd->qd_id,
> sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
> error = print_message(qd, "warning");
> qd->qd_last_warn = jiffies;
> @@ -1098,10 +1086,11 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
> }
>
> void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
> - u32 uid, u32 gid)
> + kuid_t uid, kgid_t gid)
> {
> struct gfs2_quota_data *qd;
> unsigned int x;
> + int user;
>
> if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
> return;
> @@ -1111,8 +1100,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
> for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
> qd = ip->i_res->rs_qa_qd[x];
>
> - if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
> - (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) {
> + user = (qd->qd_id.type == USRQUOTA);
> + if ((user && uid_eq(qd->qd_id.uid, uid)) ||
> + (!user && gid_eq(qd->qd_id.gid, gid))) {
> do_qc(qd, change);
> }
> }
> @@ -1167,13 +1157,13 @@ static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
> return gfs2_quota_sync(sb, type);
> }
>
> -int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
> +int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid)
> {
> struct gfs2_quota_data *qd;
> struct gfs2_holder q_gh;
> int error;
>
> - error = qd_get(sdp, user, id, &qd);
> + error = qd_get(sdp, qid, &qd);
> if (error)
> return error;
>
> @@ -1191,7 +1181,9 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *
>
> qc->qc_change = be64_to_cpu(str->qc_change);
> qc->qc_flags = be32_to_cpu(str->qc_flags);
> - qc->qc_id = be32_to_cpu(str->qc_id);
> + qc->qc_id = make_kqid(&init_user_ns,
> + (qc->qc_flags & GFS2_QCF_USER)?USRQUOTA:GRPQUOTA,
> + be32_to_cpu(str->qc_id));
> }
>
> int gfs2_quota_init(struct gfs2_sbd *sdp)
> @@ -1254,8 +1246,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
> if (!qc.qc_change)
> continue;
>
> - error = qd_alloc(sdp, (qc.qc_flags & GFS2_QCF_USER),
> - qc.qc_id, &qd);
> + error = qd_alloc(sdp, qc.qc_id, &qd);
> if (error) {
> brelse(bh);
> goto fail;
> @@ -1482,21 +1473,17 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
> struct gfs2_quota_data *qd;
> struct gfs2_holder q_gh;
> int error;
> - int type;
>
> memset(fdq, 0, sizeof(struct fs_disk_quota));
>
> if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
> return -ESRCH; /* Crazy XFS error code */
>
> - if (qid.type == USRQUOTA)
> - type = QUOTA_USER;
> - else if (qid.type == GRPQUOTA)
> - type = QUOTA_GROUP;
> - else
> + if ((qid.type != USRQUOTA) &&
> + (qid.type != GRPQUOTA))
> return -EINVAL;
>
> - error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
> + error = qd_get(sdp, qid, &qd);
> if (error)
> return error;
> error = do_glock(qd, FORCE, &q_gh);
> @@ -1505,8 +1492,8 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
>
> qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
> fdq->d_version = FS_DQUOT_VERSION;
> - fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
> - fdq->d_id = from_kqid(&init_user_ns, qid);
> + fdq->d_flags = (qid.type == USRQUOTA) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
> + fdq->d_id = from_kqid_munged(current_user_ns(), qid);
> fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
> fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
> fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
> @@ -1532,19 +1519,16 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
> int alloc_required;
> loff_t offset;
> int error;
> - int type;
>
> if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
> return -ESRCH; /* Crazy XFS error code */
>
> switch(qid.type) {
> case USRQUOTA:
> - type = QUOTA_USER;
> if (fdq->d_flags != FS_USER_QUOTA)
> return -EINVAL;
> break;
> case GRPQUOTA:
> - type = QUOTA_GROUP;
> if (fdq->d_flags != FS_GROUP_QUOTA)
> return -EINVAL;
> break;
> @@ -1554,10 +1538,10 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
>
> if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
> return -EINVAL;
> - if (fdq->d_id != from_kqid(&init_user_ns, qid))
> + if (!qid_eq(make_kqid(current_user_ns(), qid.type, fdq->d_id), qid))
> return -EINVAL;
>
> - error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
> + error = qd_get(sdp, qid, &qd);
> if (error)
> return error;
>
> diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
> index f25d98b..4f5e6e4 100644
> --- a/fs/gfs2/quota.h
> +++ b/fs/gfs2/quota.h
> @@ -14,20 +14,21 @@ struct gfs2_inode;
> struct gfs2_sbd;
> struct shrink_control;
>
> -#define NO_QUOTA_CHANGE ((u32)-1)
> +#define NO_UID_QUOTA_CHANGE INVALID_UID
> +#define NO_GID_QUOTA_CHANGE INVALID_GID
>
> -extern int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid);
> +extern int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
> extern void gfs2_quota_unhold(struct gfs2_inode *ip);
>
> -extern int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid);
> +extern int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
> extern void gfs2_quota_unlock(struct gfs2_inode *ip);
>
> -extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
> +extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
> extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
> - u32 uid, u32 gid);
> + kuid_t uid, kgid_t gid);
>
> extern int gfs2_quota_sync(struct super_block *sb, int type);
> -extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
> +extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid);
>
> extern int gfs2_quota_init(struct gfs2_sbd *sdp);
> extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
> @@ -41,7 +42,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
> int ret;
> if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
> return 0;
> - ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
> + ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
> if (ret)
> return ret;
> if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
> diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
> index bc73726..b4340b8 100644
> --- a/fs/gfs2/super.c
> +++ b/fs/gfs2/super.c
> @@ -721,8 +721,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
> str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
> str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
> str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
> - str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
> - str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
> + str->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
> + str->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
> str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
> str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
> str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
> @@ -1428,7 +1428,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
> if (error)
> return error;
>
> - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
> + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
> if (error)
> return error;
>
> diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
> index 8056b7b..0153040 100644
> --- a/fs/gfs2/sys.c
> +++ b/fs/gfs2/sys.c
> @@ -176,6 +176,7 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
> size_t len)
> {
> int error;
> + struct kqid qid;
> u32 id;
>
> if (!capable(CAP_SYS_ADMIN))
> @@ -183,7 +184,11 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
>
> id = simple_strtoul(buf, NULL, 0);
>
> - error = gfs2_quota_refresh(sdp, 1, id);
> + qid = make_kqid(&init_user_ns, USRQUOTA, id);
> + if (!qid_valid(qid))
> + return -EINVAL;
> +
> + error = gfs2_quota_refresh(sdp, qid);
> return error ? error : len;
> }
>
> @@ -191,6 +196,7 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
> size_t len)
> {
> int error;
> + struct kqid qid;
> u32 id;
>
> if (!capable(CAP_SYS_ADMIN))
> @@ -198,7 +204,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
>
> id = simple_strtoul(buf, NULL, 0);
>
> - error = gfs2_quota_refresh(sdp, 0, id);
> + qid = make_kqid(&init_user_ns, GRPQUOTA, id);
> + if (!qid_valid(qid))
> + return -EINVAL;
> +
> + error = gfs2_quota_refresh(sdp, qid);
> return error ? error : len;
> }
>
> diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
> index db330e5..342f93e 100644
> --- a/fs/gfs2/xattr.c
> +++ b/fs/gfs2/xattr.c
> @@ -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;
>
> diff --git a/init/Kconfig b/init/Kconfig
> index 2573664..53b61cd 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -999,7 +999,6 @@ config UIDGID_CONVERTED
> default y
>
> # Filesystems
> - depends on GFS2_FS = n
> depends on NCP_FS = n
> depends on NFSD = n
> depends on NFS_FS = n

2012-11-25 12:47:38

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH RFC 04/12] userns: Convert cifs to use kuid/kgid where appropriate

On Tue, 20 Nov 2012 04:43:32 -0800
"Eric W. Biederman" <[email protected]> wrote:

> From: "Eric W. Biederman" <[email protected]>
>
> Cc: Steve French <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>
> ---
> fs/cifs/cifs_fs_sb.h | 8 ++--
> fs/cifs/cifs_spnego.c | 4 +-
> fs/cifs/cifsacl.c | 115 ++++++++++++++++++++++++++++++++++++------------
> fs/cifs/cifsacl.h | 16 ++++++-
> fs/cifs/cifsfs.c | 12 +++--
> fs/cifs/cifsglob.h | 22 +++++-----
> fs/cifs/cifspdu.h | 2 +
> fs/cifs/cifsproto.h | 9 ++--
> fs/cifs/cifssmb.c | 11 ++++-
> fs/cifs/connect.c | 58 +++++++++++++++++++------
> fs/cifs/dir.c | 18 ++++----
> fs/cifs/file.c | 8 ++--
> fs/cifs/inode.c | 28 ++++++------
> fs/cifs/misc.c | 2 +-
> init/Kconfig | 1 -
> 15 files changed, 213 insertions(+), 101 deletions(-)
>
> diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
> index c865bfd..37e4a72 100644
> --- a/fs/cifs/cifs_fs_sb.h
> +++ b/fs/cifs/cifs_fs_sb.h
> @@ -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;
> diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
> index 086f381..014a4c2 100644
> --- a/fs/cifs/cifs_spnego.c
> +++ b/fs/cifs/cifs_spnego.c
> @@ -149,10 +149,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
> goto out;
>
> dp = description + strlen(description);
> - sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
> + sprintf(dp, ";uid=0x%x", from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
>
> dp = description + strlen(description);
> - sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
> + sprintf(dp, ";creduid=0x%x", from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
>
> if (sesInfo->user_name) {
> dp = description + strlen(description);
> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
> index fc783e2..0f8b920 100644
> --- a/fs/cifs/cifsacl.c
> +++ b/fs/cifs/cifsacl.c
> @@ -44,6 +44,55 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
>
> const struct cred *root_cred;
>
> +static inline struct cifs_id kuid_to_cid(kuid_t uid)
> +{
> + struct cifs_id cid;
> + cid.type = SIDOWNER;
> + cid.uid = uid;
> + return cid;
> +}
> +
> +static inline struct cifs_id kgid_to_cid(kgid_t gid)
> +{
> + struct cifs_id cid;
> + cid.type = SIDGROUP;
> + cid.gid = gid;
> + return cid;
> +}
> +
> +static unsigned long from_cid(struct user_namespace *user_ns, struct cifs_id cid)
> +{
> + switch (cid.type) {
> + case SIDOWNER:
> + return from_kuid(user_ns, cid.uid);
> + case SIDGROUP:
> + return from_kgid(user_ns, cid.gid);
> + default:
> + BUG();
> + }
> +}
> +
> +static bool cid_lt(struct cifs_id left, struct cifs_id right)
> +{
> + if (left.type < right.type)
> + return true;
> + if (left.type > right.type)
> + return false;
> + switch (left.type) {
> + case SIDOWNER:
> + return uid_lt(left.uid, right.uid);
> + case SIDGROUP:
> + return gid_lt(left.gid, right.gid);
> + default:
> + BUG();
> + }
> +}
> +
> +static inline bool cid_gt(struct cifs_id left, struct cifs_id right)
> +{
> + return cid_lt(right, left);
> +}
> +
> static void
> shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
> int *nr_del)
> @@ -105,7 +154,7 @@ cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
> }
>
> static void
> -sid_rb_insert(struct rb_root *root, unsigned long cid,
> +sid_rb_insert(struct rb_root *root, struct cifs_id cid,
> struct cifs_sid_id **psidid, char *typestr)
> {
> char *strptr;
> @@ -117,11 +166,11 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,
> while (node) {
> lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
> parent = node;
> - if (cid > lsidid->id) {
> + if (cid_gt(cid, lsidid->id)) {
> linkto = &(node->rb_left);
> node = node->rb_left;
> }
> - if (cid < lsidid->id) {
> + if (cid_lt(cid, lsidid->id)) {
> linkto = &(node->rb_right);
> node = node->rb_right;
> }
> @@ -133,7 +182,7 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,
>
> sprintf((*psidid)->sidstr, "%s", typestr);
> strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
> - sprintf(strptr, "%ld", cid);
> + sprintf(strptr, "%ld", from_cid(&init_user_ns, cid));
>
> clear_bit(SID_ID_PENDING, &(*psidid)->state);
> clear_bit(SID_ID_MAPPED, &(*psidid)->state);
> @@ -143,16 +192,16 @@ sid_rb_insert(struct rb_root *root, unsigned long cid,
> }
>
> static struct cifs_sid_id *
> -sid_rb_search(struct rb_root *root, unsigned long cid)
> +sid_rb_search(struct rb_root *root, struct cifs_id cid)
> {
> struct rb_node *node = root->rb_node;
> struct cifs_sid_id *lsidid;
>
> while (node) {
> lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
> - if (cid > lsidid->id)
> + if (cid_gt(cid, lsidid->id))
> node = node->rb_left;
> - else if (cid < lsidid->id)
> + else if (cid_lt(cid, lsidid->id))
> node = node->rb_right;
> else /* node found */
> return lsidid;
> @@ -292,7 +341,7 @@ sidid_pending_wait(void *unused)
> }
>
> static int
> -id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
> +id_to_sid(struct cifs_id cid, struct cifs_sid *ssid)
> {
> int rc = 0;
> struct key *sidkey;
> @@ -302,10 +351,10 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
> struct rb_root *cidtree;
> spinlock_t *cidlock;
>
> - if (sidtype == SIDOWNER) {
> + if (cid.type == SIDOWNER) {
> cidlock = &siduidlock;
> cidtree = &uidtree;
> - } else if (sidtype == SIDGROUP) {
> + } else if (cid.type == SIDGROUP) {
> cidlock = &sidgidlock;
> cidtree = &gidtree;
> } else
> @@ -336,7 +385,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
> } else {
> psidid = npsidid;
> sid_rb_insert(cidtree, cid, &psidid,
> - sidtype == SIDOWNER ? "oi:" : "gi:");
> + cid.type == SIDOWNER ? "oi:" : "gi:");
> ++psidid->refcount;
> spin_unlock(cidlock);
> }
> @@ -410,7 +459,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
> struct cifs_fattr *fattr, uint sidtype)
> {
> int rc;
> - unsigned long cid;
> + struct cifs_id cid;
> struct key *idkey;
> const struct cred *saved_cred;
> struct cifs_sid_id *psidid, *npsidid;
> @@ -418,11 +467,11 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
> spinlock_t *cidlock;
>
> if (sidtype == SIDOWNER) {
> - cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
> + cid = kuid_to_cid(cifs_sb->mnt_uid); /* default uid, in case upcall fails */
> cidlock = &siduidlock;
> cidtree = &uidtree;
> } else if (sidtype == SIDGROUP) {
> - cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
> + cid = kgid_to_cid(cifs_sb->mnt_gid); /* default gid, in case upcall fails */
> cidlock = &sidgidlock;
> cidtree = &gidtree;
> } else
> @@ -471,7 +520,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
> * any fields of the node after a reference is put .
> */
> if (test_bit(SID_ID_MAPPED, &psidid->state)) {
> - cid = psidid->id;
> + //cid = psidid->id;
> psidid->time = jiffies; /* update ts for accessing */
> goto sid_to_id_out;
> }
> @@ -485,8 +534,13 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
> if (IS_ERR(idkey))
> cFYI(1, "%s: Can't map SID to an id", __func__);
> else {
> - cid = *(unsigned long *)idkey->payload.value;
> - psidid->id = cid;
> + u32 id;
> + id = *(u32 *)idkey->payload.value;
> + psidid->id.type = sidtype;
> + if (sidtype == SIDOWNER)
> + psidid->id.uid = make_kuid(&init_user_ns, id);
> + else
> + psidid->id.gid = make_kgid(&init_user_ns, id);
> set_bit(SID_ID_MAPPED, &psidid->state);
> key_put(idkey);
> kfree(psidid->sidstr);
> @@ -510,10 +564,10 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
>
> sid_to_id_out:
> --psidid->refcount; /* decremented without spinlock */
> - if (sidtype == SIDOWNER)
> - fattr->cf_uid = cid;
> + if (cid.type == SIDOWNER)
> + fattr->cf_uid = cid.uid;
> else
> - fattr->cf_gid = cid;
> + fattr->cf_gid = cid.gid;
>
> return 0;
> }
> @@ -537,7 +591,8 @@ init_cifs_idmap(void)
> if (!cred)
> return -ENOMEM;
>
> - keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
> + keyring = key_alloc(&key_type_keyring, ".cifs_idmap",
> + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ,
> KEY_ALLOC_NOT_IN_QUOTA);
> @@ -1074,7 +1129,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
>
> /* Convert permission bits from mode to equivalent CIFS ACL */
> static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
> - __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
> + __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
> {
> int rc = 0;
> __u32 dacloffset;
> @@ -1106,17 +1161,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
> *aclflag = CIFS_ACL_DACL;
> } else {
> memcpy(pnntsd, pntsd, secdesclen);
> - if (uid != NO_CHANGE_32) { /* chown */
> + if (!uid_eq(uid, NO_CHANGE_UID)) { /* chown */
> owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
> le32_to_cpu(pnntsd->osidoffset));
> nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
> GFP_KERNEL);
> if (!nowner_sid_ptr)
> return -ENOMEM;
> - rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
> + rc = id_to_sid(kuid_to_cid(uid), nowner_sid_ptr);
> if (rc) {
> cFYI(1, "%s: Mapping error %d for owner id %d",
> - __func__, rc, uid);
> + __func__, rc,
> + from_kuid(&init_user_ns, uid));
> kfree(nowner_sid_ptr);
> return rc;
> }
> @@ -1125,17 +1181,18 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
> kfree(nowner_sid_ptr);
> *aclflag = CIFS_ACL_OWNER;
> }
> - if (gid != NO_CHANGE_32) { /* chgrp */
> + if (!gid_eq(gid, NO_CHANGE_GID)) { /* chgrp */
> group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
> le32_to_cpu(pnntsd->gsidoffset));
> ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
> GFP_KERNEL);
> if (!ngroup_sid_ptr)
> return -ENOMEM;
> - rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
> + rc = id_to_sid(kgid_to_cid(gid), ngroup_sid_ptr);
> if (rc) {
> cFYI(1, "%s: Mapping error %d for group id %d",
> - __func__, rc, gid);
> + __func__, rc,
> + from_kgid(&init_user_ns, gid));
> kfree(ngroup_sid_ptr);
> return rc;
> }
> @@ -1304,7 +1361,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
> /* Convert mode bits to an ACL so we can update the ACL on the server */
> int
> id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
> - uid_t uid, gid_t gid)
> + kuid_t uid, kgid_t gid)
> {
> int rc = 0;
> int aclflag = CIFS_ACL_DACL; /* default flag to set */
> diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
> index 5c902c7..233c576 100644
> --- a/fs/cifs/cifsacl.h
> +++ b/fs/cifs/cifsacl.h
> @@ -39,8 +39,10 @@
> #define ACCESS_ALLOWED 0
> #define ACCESS_DENIED 1
>
> -#define SIDOWNER 1
> -#define SIDGROUP 2
> +enum sidtype {
> + SIDOWNER = 1,
> + SIDGROUP = 2,
> +};
> #define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */
>
> #define SID_ID_MAPPED 0
> @@ -83,9 +85,17 @@ struct cifs_wksid {
> char sidname[SIDNAMELENGTH];
> } __attribute__((packed));
>
> +struct cifs_id {
> + enum sidtype type;
> + union {
> + kuid_t uid;
> + kgid_t gid;
> + };
> +};
> +
> struct cifs_sid_id {
> unsigned int refcount; /* increment with spinlock, decrement without */
> - unsigned long id;
> + struct cifs_id id;
> unsigned long time;
> unsigned long state;
> char *sidstr;
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index e7931cc..0a4740b 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -377,13 +377,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
> (int)(srcaddr->sa_family));
> }
>
> - seq_printf(s, ",uid=%u", cifs_sb->mnt_uid);
> + seq_printf(s, ",uid=%u", from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid));
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
> seq_printf(s, ",forceuid");
> else
> seq_printf(s, ",noforceuid");
>
> - seq_printf(s, ",gid=%u", cifs_sb->mnt_gid);
> + seq_printf(s, ",gid=%u", from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid));
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
> seq_printf(s, ",forcegid");
> else
> @@ -438,9 +438,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
> seq_printf(s, ",noperm");
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
> - seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid);
> + seq_printf(s, ",backupuid=%u",
> + from_kuid_munged(&init_user_ns,
> + cifs_sb->mnt_backupuid));
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
> - seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid);
> + seq_printf(s, ",backupgid=%u",
> + from_kgid_munged(&init_user_ns,
> + cifs_sb->mnt_backupgid));
>
> seq_printf(s, ",rsize=%u", cifs_sb->rsize);
> seq_printf(s, ",wsize=%u", cifs_sb->wsize);
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index f5af252..97f1683 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -400,11 +400,11 @@ struct smb_vol {
> char *iocharset; /* local code page for mapping to and from Unicode */
> char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
> char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
> - uid_t cred_uid;
> - uid_t linux_uid;
> - gid_t linux_gid;
> - uid_t backupuid;
> - gid_t backupgid;
> + kuid_t cred_uid;
> + kuid_t linux_uid;
> + kgid_t linux_gid;
> + kuid_t backupuid;
> + kgid_t backupgid;
> umode_t file_mode;
> umode_t dir_mode;
> unsigned secFlg;
> @@ -703,8 +703,8 @@ struct cifs_ses {
> char *serverNOS; /* name of network operating system of server */
> char *serverDomain; /* security realm of server */
> __u64 Suid; /* remote smb uid */
> - uid_t linux_uid; /* overriding owner of files on the mount */
> - uid_t cred_uid; /* owner of credentials */
> + kuid_t linux_uid; /* overriding owner of files on the mount */
> + kuid_t cred_uid; /* owner of credentials */
> unsigned int capabilities;
> char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
> TCP names - will ipv6 and sctp addresses fit? */
> @@ -838,7 +838,7 @@ struct cifs_tcon {
> */
> struct tcon_link {
> struct rb_node tl_rbnode;
> - uid_t tl_uid;
> + kuid_t tl_uid;
> unsigned long tl_flags;
> #define TCON_LINK_MASTER 0
> #define TCON_LINK_PENDING 1
> @@ -931,7 +931,7 @@ struct cifsFileInfo {
> struct list_head tlist; /* pointer to next fid owned by tcon */
> struct list_head flist; /* next fid (file instance) for this inode */
> struct cifs_fid_locks *llist; /* brlocks held by this fid */
> - unsigned int uid; /* allows finding which FileInfo structure */
> + kuid_t uid; /* allows finding which FileInfo structure */
> __u32 pid; /* process id who opened file */
> struct cifs_fid fid; /* file id from remote */
> /* BB add lock scope info here if needed */ ;
> @@ -1259,8 +1259,8 @@ struct cifs_fattr {
> u64 cf_eof;
> u64 cf_bytes;
> u64 cf_createtime;
> - uid_t cf_uid;
> - gid_t cf_gid;
> + kuid_t cf_uid;
> + kgid_t cf_gid;
> umode_t cf_mode;
> dev_t cf_rdev;
> unsigned int cf_nlink;
> diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
> index b9d59a9..2ede310 100644
> --- a/fs/cifs/cifspdu.h
> +++ b/fs/cifs/cifspdu.h
> @@ -278,6 +278,8 @@
>
> #define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
> #define NO_CHANGE_32 0xFFFFFFFFUL
> +#define NO_CHANGE_UID INVALID_UID
> +#define NO_CHANGE_GID INVALID_GID
>
> /* IPC$ in ASCII */
> #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 5144e9f..27b268a 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -46,7 +46,8 @@ extern void _free_xid(unsigned int);
> ({ \
> unsigned int __xid = _get_xid(); \
> cFYI(1, "CIFS VFS: in %s as Xid: %u with uid: %d", \
> - __func__, __xid, current_fsuid()); \
> + __func__, __xid, \
> + from_kuid(&init_user_ns, current_fsuid())); \
> __xid; \
> })
>
> @@ -161,7 +162,7 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
> struct cifs_fattr *fattr, struct inode *inode,
> const char *path, const __u16 *pfid);
> extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
> - uid_t, gid_t);
> + kuid_t, kgid_t);
> extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
> const char *, u32 *);
> extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
> @@ -304,8 +305,8 @@ struct cifs_unix_set_info_args {
> __u64 atime;
> __u64 mtime;
> __u64 mode;
> - __u64 uid;
> - __u64 gid;
> + kuid_t uid;
> + kgid_t gid;
> dev_t device;
> };
>
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 76d0d29..6b88d47 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -5820,6 +5820,13 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
> const struct cifs_unix_set_info_args *args)
> {
> u64 mode = args->mode;
> + __u64 uid;
> + __u64 gid;
> +
> + uid = uid_eq(args->uid, NO_CHANGE_UID) ? NO_CHANGE_64:
> + (__u64)from_kuid(&init_user_ns, args->uid);
> + gid = gid_eq(args->gid, NO_CHANGE_GID) ? NO_CHANGE_64:
> + (__u64)from_kgid(&init_user_ns, args->gid);
>
> /*
> * Samba server ignores set of file size to zero due to bugs in some
> @@ -5833,8 +5840,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
> data_offset->LastStatusChange = cpu_to_le64(args->ctime);
> data_offset->LastAccessTime = cpu_to_le64(args->atime);
> data_offset->LastModificationTime = cpu_to_le64(args->mtime);
> - data_offset->Uid = cpu_to_le64(args->uid);
> - data_offset->Gid = cpu_to_le64(args->gid);
> + data_offset->Uid = cpu_to_le64(uid);
> + data_offset->Gid = cpu_to_le64(gid);
> /* better to leave device as zero when it is */
> data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
> data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 5c670b9..dab3cf1 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -1108,6 +1108,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> char *string = NULL;
> char *tmp_end, *value;
> char delim;
> + kuid_t uid;
> + kgid_t gid;
>
> separator[0] = ',';
> separator[1] = 0;
> @@ -1361,7 +1363,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> __func__);
> goto cifs_parse_mount_err;
> }
> - vol->backupuid = option;
> + uid = make_kuid(current_user_ns(), option);
> + if (!uid_valid(uid)) {
> + cERROR(1, "%s: Invalid backupuid value",
> + __func__);
> + goto cifs_parse_mount_err;
> + }
> + vol->backupuid = uid;
> vol->backupuid_specified = true;
> break;
> case Opt_backupgid:
> @@ -1370,7 +1378,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> __func__);
> goto cifs_parse_mount_err;
> }
> - vol->backupgid = option;
> + gid = make_kgid(current_user_ns(), option);
> + if (!gid_valid(gid)) {
> + cERROR(1, "%s: Invalid backupgid value",
> + __func__);
> + goto cifs_parse_mount_err;
> + }
> + vol->backupgid = gid;
> vol->backupgid_specified = true;
> break;
> case Opt_uid:
> @@ -1379,7 +1393,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> __func__);
> goto cifs_parse_mount_err;
> }
> - vol->linux_uid = option;
> + uid = make_kuid(current_user_ns(), option);
> + if (!uid_valid(uid)) {
> + cERROR(1, "%s: Invalid uid value",
> + __func__);
> + goto cifs_parse_mount_err;
> + }
> + vol->linux_uid = uid;
> uid_specified = true;
> break;
> case Opt_cruid:
> @@ -1388,7 +1408,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> __func__);
> goto cifs_parse_mount_err;
> }
> - vol->cred_uid = option;
> + uid = make_kuid(current_user_ns(), option);
> + if (!uid_valid(uid)) {
> + cERROR(1, "%s: Invalid cruid value",
> + __func__);
> + goto cifs_parse_mount_err;
> + }
> + vol->cred_uid = uid;
> break;
> case Opt_gid:
> if (get_option_ul(args, &option)) {
> @@ -1396,7 +1422,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
> __func__);
> goto cifs_parse_mount_err;
> }
> - vol->linux_gid = option;
> + gid = make_kgid(current_user_ns(), option);
> + if (!gid_valid(gid)) {
> + cERROR(1, "%s: Invalid gid value",
> + __func__);
> + goto cifs_parse_mount_err;
> + }
> + vol->linux_gid = gid;
> gid_specified = true;
> break;
> case Opt_file_mode:
> @@ -2203,7 +2235,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
> {
> switch (ses->server->secType) {
> case Kerberos:
> - if (vol->cred_uid != ses->cred_uid)
> + if (!uid_eq(vol->cred_uid, ses->cred_uid))
> return 0;
> break;
> default:
> @@ -2692,7 +2724,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
> if (new->rsize && new->rsize < old->rsize)
> return 0;
>
> - if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
> + if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
> return 0;
>
> if (old->mnt_file_mode != new->mnt_file_mode ||
> @@ -3910,7 +3942,7 @@ cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
> }
>
> static struct cifs_tcon *
> -cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
> +cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
> {
> int rc;
> struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
> @@ -3980,7 +4012,7 @@ cifs_sb_tcon_pending_wait(void *unused)
>
> /* find and return a tlink with given uid */
> static struct tcon_link *
> -tlink_rb_search(struct rb_root *root, uid_t uid)
> +tlink_rb_search(struct rb_root *root, kuid_t uid)
> {
> struct rb_node *node = root->rb_node;
> struct tcon_link *tlink;
> @@ -3988,9 +4020,9 @@ tlink_rb_search(struct rb_root *root, uid_t uid)
> while (node) {
> tlink = rb_entry(node, struct tcon_link, tl_rbnode);
>
> - if (tlink->tl_uid > uid)
> + if (uid_gt(tlink->tl_uid, uid))
> node = node->rb_left;
> - else if (tlink->tl_uid < uid)
> + else if (uid_lt(tlink->tl_uid, uid))
> node = node->rb_right;
> else
> return tlink;
> @@ -4009,7 +4041,7 @@ tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
> tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
> parent = *new;
>
> - if (tlink->tl_uid > new_tlink->tl_uid)
> + if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
> new = &((*new)->rb_left);
> else
> new = &((*new)->rb_right);
> @@ -4039,7 +4071,7 @@ struct tcon_link *
> cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
> {
> int ret;
> - uid_t fsuid = current_fsuid();
> + kuid_t fsuid = current_fsuid();
> struct tcon_link *tlink, *newtlink;
>
> if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index 7c0a812..d2c4062 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -310,14 +310,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
>
> *created |= FILE_CREATED;
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
> - args.uid = (__u64) current_fsuid();
> + args.uid = current_fsuid();
> if (inode->i_mode & S_ISGID)
> - args.gid = (__u64) inode->i_gid;
> + args.gid = inode->i_gid;
> else
> - args.gid = (__u64) current_fsgid();
> + args.gid = current_fsgid();
> } else {
> - args.uid = NO_CHANGE_64;
> - args.gid = NO_CHANGE_64;
> + args.uid = NO_CHANGE_UID;
> + args.gid = NO_CHANGE_GID;
> }
> CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
> current->tgid);
> @@ -547,11 +547,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
> .device = device_number,
> };
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
> - args.uid = (__u64) current_fsuid();
> - args.gid = (__u64) current_fsgid();
> + args.uid = current_fsuid();
> + args.gid = current_fsgid();
> } else {
> - args.uid = NO_CHANGE_64;
> - args.gid = NO_CHANGE_64;
> + args.uid = NO_CHANGE_UID;
> + args.gid = NO_CHANGE_GID;
> }
> rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
> cifs_sb->local_nls,
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index edb25b4..603863c 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -487,8 +487,8 @@ int cifs_open(struct inode *inode, struct file *file)
> */
> struct cifs_unix_set_info_args args = {
> .mode = inode->i_mode,
> - .uid = NO_CHANGE_64,
> - .gid = NO_CHANGE_64,
> + .uid = NO_CHANGE_UID,
> + .gid = NO_CHANGE_GID,
> .ctime = NO_CHANGE_64,
> .atime = NO_CHANGE_64,
> .mtime = NO_CHANGE_64,
> @@ -1631,7 +1631,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
> are always at the end of the list but since the first entry might
> have a close pending, we go through the whole list */
> list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> - if (fsuid_only && open_file->uid != current_fsuid())
> + if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
> continue;
> if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
> if (!open_file->invalidHandle) {
> @@ -1684,7 +1684,7 @@ refind_writable:
> list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> if (!any_available && open_file->pid != current->tgid)
> continue;
> - if (fsuid_only && open_file->uid != current_fsuid())
> + if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
> continue;
> if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
> if (!open_file->invalidHandle) {
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index afdff79..c43bfa2 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -247,12 +247,12 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
> fattr->cf_uid = cifs_sb->mnt_uid;
> else
> - fattr->cf_uid = le64_to_cpu(info->Uid);
> + fattr->cf_uid = make_kuid(&init_user_ns, le64_to_cpu(info->Uid));
>
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
> fattr->cf_gid = cifs_sb->mnt_gid;
> else
> - fattr->cf_gid = le64_to_cpu(info->Gid);
> + fattr->cf_gid = make_kgid(&init_user_ns, le64_to_cpu(info->Gid));
>
> fattr->cf_nlink = le64_to_cpu(info->Nlinks);
> }
> @@ -1245,14 +1245,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
> .device = 0,
> };
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
> - args.uid = (__u64)current_fsuid();
> - if (parent->i_mode & S_ISGID)
> - args.gid = (__u64)parent->i_gid;
> + args.uid = current_fsuid();
> + if (inode->i_mode & S_ISGID)
> + args.gid = inode->i_gid;
> else
> - args.gid = (__u64)current_fsgid();
> + args.gid = current_fsgid();
> } else {
> - args.uid = NO_CHANGE_64;
> - args.gid = NO_CHANGE_64;
> + args.uid = INVALID_UID;
> + args.gid = INVALID_GID;
> }
> CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
> cifs_sb->local_nls,
> @@ -2012,12 +2012,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
> if (attrs->ia_valid & ATTR_UID)
> args->uid = attrs->ia_uid;
> else
> - args->uid = NO_CHANGE_64;
> + args->uid = NO_CHANGE_UID;
>
> if (attrs->ia_valid & ATTR_GID)
> args->gid = attrs->ia_gid;
> else
> - args->gid = NO_CHANGE_64;
> + args->gid = NO_CHANGE_GID;
>
> if (attrs->ia_valid & ATTR_ATIME)
> args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
> @@ -2085,8 +2085,8 @@ static int
> cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
> {
> unsigned int xid;
> - uid_t uid = NO_CHANGE_32;
> - gid_t gid = NO_CHANGE_32;
> + kuid_t uid = NO_CHANGE_UID;
> + kgid_t gid = NO_CHANGE_GID;
> struct inode *inode = direntry->d_inode;
> struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> struct cifsInodeInfo *cifsInode = CIFS_I(inode);
> @@ -2145,7 +2145,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
>
> #ifdef CONFIG_CIFS_ACL
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
> - if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
> + if (!uid_eq(uid, NO_CHANGE_UID) || !gid_eq(gid, NO_CHANGE_GID)) {
> rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
> uid, gid);
> if (rc) {
> @@ -2169,7 +2169,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
> #ifdef CONFIG_CIFS_ACL
> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
> rc = id_mode_to_cifs_acl(inode, full_path, mode,
> - NO_CHANGE_32, NO_CHANGE_32);
> + NO_CHANGE_UID, NO_CHANGE_GID);
> if (rc) {
> cFYI(1, "%s: Setting ACL failed with error: %d",
> __func__, rc);
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 3a00c0d..1b15bf8 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -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) {
> diff --git a/init/Kconfig b/init/Kconfig
> index cb2c46a..58959ea 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -999,7 +999,6 @@ config UIDGID_CONVERTED
> default y
>
> # Filesystems
> - depends on CIFS = n
> depends on CODA_FS = n
> depends on GFS2_FS = n
> depends on NCP_FS = n


Looks fairly reasonable to me. Note that I have a patchset queued up
for 3.8 that rips all of the rbtree stuff out of cifsacl.c. This patch
will need to be rebased on top of that, but that should mostly consist
of dropping hunks that are no longer needed.

--
Jeff Layton <[email protected]>