Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 00:00:49 +0000 (16:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 00:00:49 +0000 (16:00 -0800)
Pull user namespace and namespace infrastructure changes from Eric W Biederman:
 "This set of changes starts with a few small enhnacements to the user
  namespace.  reboot support, allowing more arbitrary mappings, and
  support for mounting devpts, ramfs, tmpfs, and mqueuefs as just the
  user namespace root.

  I do my best to document that if you care about limiting your
  unprivileged users that when you have the user namespace support
  enabled you will need to enable memory control groups.

  There is a minor bug fix to prevent overflowing the stack if someone
  creates way too many user namespaces.

  The bulk of the changes are a continuation of the kuid/kgid push down
  work through the filesystems.  These changes make using uids and gids
  typesafe which ensures that these filesystems are safe to use when
  multiple user namespaces are in use.  The filesystems converted for
  3.9 are ceph, 9p, afs, ocfs2, gfs2, ncpfs, nfs, nfsd, and cifs.  The
  changes for these filesystems were a little more involved so I split
  the changes into smaller hopefully obviously correct changes.

  XFS is the only filesystem that remains.  I was hoping I could get
  that in this release so that user namespace support would be enabled
  with an allyesconfig or an allmodconfig but it looks like the xfs
  changes need another couple of days before it they are ready."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (93 commits)
  cifs: Enable building with user namespaces enabled.
  cifs: Convert struct cifs_ses to use a kuid_t and a kgid_t
  cifs: Convert struct cifs_sb_info to use kuids and kgids
  cifs: Modify struct smb_vol to use kuids and kgids
  cifs: Convert struct cifsFileInfo to use a kuid
  cifs: Convert struct cifs_fattr to use kuid and kgids
  cifs: Convert struct tcon_link to use a kuid.
  cifs: Modify struct cifs_unix_set_info_args to hold a kuid_t and a kgid_t
  cifs: Convert from a kuid before printing current_fsuid
  cifs: Use kuids and kgids SID to uid/gid mapping
  cifs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring_alloc
  cifs: Use BUILD_BUG_ON to validate uids and gids are the same size
  cifs: Override unmappable incoming uids and gids
  nfsd: Enable building with user namespaces enabled.
  nfsd: Properly compare and initialize kuids and kgids
  nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids
  nfsd: Modify nfsd4_cb_sec to use kuids and kgids
  nfsd: Handle kuids and kgids in the nfs4acl to posix_acl conversion
  nfsd: Convert nfsxdr to use kuids and kgids
  nfsd: Convert nfs3xdr to use kuids and kgids
  ...

101 files changed:
Documentation/namespaces/resource-control.txt [new file with mode: 0644]
fs/9p/fid.c
fs/9p/v9fs.c
fs/9p/v9fs.h
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/afs/afs.h
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/super.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/cifs_fs_sb.h
fs/cifs/cifs_spnego.c
fs/cifs/cifsacl.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/coda/cache.c
fs/coda/coda_fs_i.h
fs/coda/coda_linux.c
fs/coda/inode.c
fs/coda/psdev.c
fs/coda/upcall.c
fs/devpts/inode.c
fs/gfs2/acl.c
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/super.c
fs/gfs2/sys.c
fs/gfs2/xattr.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/ncp_fs_sb.h
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4xdr.c
fs/nfs_common/nfsacl.c
fs/nfsd/acl.h
fs/nfsd/auth.c
fs/nfsd/auth.h
fs/nfsd/export.c
fs/nfsd/idmap.h
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsxdr.c
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/ocfs2/acl.c
fs/ocfs2/dlmglue.c
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ramfs/inode.c
include/linux/coda_psdev.h
include/linux/nfs4.h
include/linux/nfs_idmap.h
include/linux/nfs_xdr.h
include/linux/nfsd/export.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/svcauth.h
include/linux/user_namespace.h
include/net/9p/9p.h
include/net/9p/client.h
init/Kconfig
ipc/mqueue.c
kernel/sys.c
kernel/user.c
kernel/user_namespace.c
mm/shmem.c
net/9p/client.c
net/9p/protocol.c
net/ceph/ceph_common.c
net/sunrpc/auth.c
net/sunrpc/auth_generic.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_unix.c
net/sunrpc/svcauth_unix.c

diff --git a/Documentation/namespaces/resource-control.txt b/Documentation/namespaces/resource-control.txt
new file mode 100644 (file)
index 0000000..abc13c3
--- /dev/null
@@ -0,0 +1,14 @@
+There are a lot of kinds of objects in the kernel that don't have
+individual limits or that have limits that are ineffective when a set
+of processes is allowed to switch user ids.  With user namespaces
+enabled in a kernel for people who don't trust their users or their
+users programs to play nice this problems becomes more acute.
+
+Therefore it is recommended that memory control groups be enabled in
+kernels that enable user namespaces, and it is further recommended
+that userspace configure memory control groups to limit how much
+memory user's they don't trust to play nice can use.
+
+Memory control groups can be configured by installing the libcgroup
+package present on most distros editing /etc/cgrules.conf,
+/etc/cgconfig.conf and setting up libpam-cgroup.
index da8eefbe830d9a5beb7304109cf4b254a089c555..afd4724b2d923edbaf1c0caead8e8058f92cccfc 100644 (file)
@@ -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;
        /*
index d934f04e77368e00dc76d4a54720cff0758d3a58..58e6cbce4156fb37a9820297e3a35c83d3524e81 100644 (file)
@@ -161,7 +161,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                                ret = r;
                                continue;
                        }
-                       v9ses->dfltuid = option;
+                       v9ses->dfltuid = make_kuid(current_user_ns(), option);
+                       if (!uid_valid(v9ses->dfltuid)) {
+                               p9_debug(P9_DEBUG_ERROR,
+                                        "uid field, but not a uid?\n");
+                               ret = -EINVAL;
+                               continue;
+                       }
                        break;
                case Opt_dfltgid:
                        r = match_int(&args[0], &option);
@@ -171,7 +177,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                                ret = r;
                                continue;
                        }
-                       v9ses->dfltgid = option;
+                       v9ses->dfltgid = make_kgid(current_user_ns(), option);
+                       if (!gid_valid(v9ses->dfltgid)) {
+                               p9_debug(P9_DEBUG_ERROR,
+                                        "gid field, but not a gid?\n");
+                               ret = -EINVAL;
+                               continue;
+                       }
                        break;
                case Opt_afid:
                        r = match_int(&args[0], &option);
@@ -248,8 +260,9 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                        else if (strcmp(s, "client") == 0) {
                                v9ses->flags |= V9FS_ACCESS_CLIENT;
                        } else {
+                               uid_t uid;
                                v9ses->flags |= V9FS_ACCESS_SINGLE;
-                               v9ses->uid = simple_strtoul(s, &e, 10);
+                               uid = simple_strtoul(s, &e, 10);
                                if (*e != '\0') {
                                        ret = -EINVAL;
                                        pr_info("Unknown access argument %s\n",
@@ -257,6 +270,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                                        kfree(s);
                                        goto free_and_return;
                                }
+                               v9ses->uid = make_kuid(current_user_ns(), uid);
+                               if (!uid_valid(v9ses->uid)) {
+                                       ret = -EINVAL;
+                                       pr_info("Uknown uid %s\n", s);
+                                       kfree(s);
+                                       goto free_and_return;
+                               }
                        }
 
                        kfree(s);
@@ -319,7 +339,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
        list_add(&v9ses->slist, &v9fs_sessionlist);
        spin_unlock(&v9fs_sessionlist_lock);
 
-       v9ses->uid = ~0;
+       v9ses->uid = INVALID_UID;
        v9ses->dfltuid = V9FS_DEFUID;
        v9ses->dfltgid = V9FS_DEFGID;
 
@@ -364,7 +384,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 
                v9ses->flags &= ~V9FS_ACCESS_MASK;
                v9ses->flags |= V9FS_ACCESS_ANY;
-               v9ses->uid = ~0;
+               v9ses->uid = INVALID_UID;
        }
        if (!v9fs_proto_dotl(v9ses) ||
                !((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
@@ -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 */
index 34c59f14a1c9d9b4deea3f8fa3a55830813d3498..a8e127c896271143596aa5db8e001351c7134e6f 100644 (file)
@@ -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)
 {
index 57d017ac68e4f563b51141f1e223769f5497ca5d..b5340c829de1c00e7666ce98edc0df5f6c076027 100644 (file)
@@ -225,9 +225,9 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
        wstat->uid = NULL;
        wstat->gid = NULL;
        wstat->muid = NULL;
-       wstat->n_uid = ~0;
-       wstat->n_gid = ~0;
-       wstat->n_muid = ~0;
+       wstat->n_uid = INVALID_UID;
+       wstat->n_gid = INVALID_GID;
+       wstat->n_muid = INVALID_UID;
        wstat->extension = NULL;
 }
 
index 8d24ad66dfb80a4f610da10efcac7fa13db93730..07f409288d1bacbc0af6810f638990a0b4d15e94 100644 (file)
@@ -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);
 
@@ -245,7 +245,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;
@@ -396,7 +396,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;
@@ -697,7 +697,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;
@@ -837,7 +837,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;
index c548aa346f0dd6f9a7aed6664abb32bcbb6ddd79..3c462ff6db639a22ce6393ab65c2f84f1d1fe038 100644 (file)
@@ -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 */
@@ -133,13 +133,6 @@ struct afs_file_status {
 /*
  * AFS file status change request
  */
-struct afs_store_status {
-       u32                     mask;           /* which bits of the struct are set */
-       u32                     mtime_client;   /* last time client changed data */
-       u32                     owner;          /* owner ID */
-       u32                     group;          /* group ID */
-       umode_t                 mode;           /* UNIX mode */
-};
 
 #define AFS_SET_MTIME          0x01            /* set the mtime */
 #define AFS_SET_OWNER          0x02            /* set the owner ID */
index b960ff05ea0bf96dae8466de76da562b9161073a..c2e930ec288899cde31e96150dc828d8ec495b60 100644 (file)
@@ -42,6 +42,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
        umode_t mode;
        u64 data_version, size;
        u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
+       kuid_t owner;
+       kgid_t group;
 
 #define EXTRACT(DST)                           \
        do {                                    \
@@ -56,7 +58,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
        size = ntohl(*bp++);
        data_version = ntohl(*bp++);
        EXTRACT(status->author);
-       EXTRACT(status->owner);
+       owner = make_kuid(&init_user_ns, ntohl(*bp++));
+       changed |= !uid_eq(owner, status->owner);
+       status->owner = owner;
        EXTRACT(status->caller_access); /* call ticket dependent */
        EXTRACT(status->anon_access);
        EXTRACT(status->mode);
@@ -65,7 +69,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
        bp++; /* seg size */
        status->mtime_client = ntohl(*bp++);
        status->mtime_server = ntohl(*bp++);
-       EXTRACT(status->group);
+       group = make_kgid(&init_user_ns, ntohl(*bp++));
+       changed |= !gid_eq(group, status->group);
+       status->group = group;
        bp++; /* sync counter */
        data_version |= (u64) ntohl(*bp++) << 32;
        EXTRACT(status->lock_count);
@@ -181,12 +187,12 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
 
        if (attr->ia_valid & ATTR_UID) {
                mask |= AFS_SET_OWNER;
-               owner = attr->ia_uid;
+               owner = from_kuid(&init_user_ns, attr->ia_uid);
        }
 
        if (attr->ia_valid & ATTR_GID) {
                mask |= AFS_SET_GROUP;
-               group = attr->ia_gid;
+               group = from_kgid(&init_user_ns, attr->ia_gid);
        }
 
        if (attr->ia_valid & ATTR_MODE) {
index 95cffd38239fe867d5afe1e5a1740ec9564c3341..789bc253b5f63c2d3c9abfdd216e0778b140a765 100644 (file)
@@ -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;
index 43165009428da56c51b47ae9d8bb4b97310c485f..7c31ec39957587a59062b3f81dd338aa57e575aa 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/parser.h>
 #include <linux/statfs.h>
 #include <linux/sched.h>
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
 #include "internal.h"
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
@@ -363,6 +365,10 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
 
        memset(&params, 0, sizeof(params));
 
+       ret = -EINVAL;
+       if (current->nsproxy->net_ns != &init_net)
+               goto error;
+
        /* parse the options and device name */
        if (options) {
                ret = afs_parse_options(&params, options, &dev_name);
index a1d9bb30c1bf9fc5460286ff465e2bcbc338bf30..ae2be696eb5b32e5e2cbad2a591582c3d802aab5 100644 (file)
@@ -930,7 +930,7 @@ static int send_cap_msg(struct ceph_mds_session *session,
                        u64 size, u64 max_size,
                        struct timespec *mtime, struct timespec *atime,
                        u64 time_warp_seq,
-                       uid_t uid, gid_t gid, umode_t mode,
+                       kuid_t uid, kgid_t gid, umode_t mode,
                        u64 xattr_version,
                        struct ceph_buffer *xattrs_buf,
                        u64 follows)
@@ -974,8 +974,8 @@ static int send_cap_msg(struct ceph_mds_session *session,
                ceph_encode_timespec(&fc->atime, atime);
        fc->time_warp_seq = cpu_to_le32(time_warp_seq);
 
-       fc->uid = cpu_to_le32(uid);
-       fc->gid = cpu_to_le32(gid);
+       fc->uid = cpu_to_le32(from_kuid(&init_user_ns, uid));
+       fc->gid = cpu_to_le32(from_kgid(&init_user_ns, gid));
        fc->mode = cpu_to_le32(mode);
 
        fc->xattr_version = cpu_to_le64(xattr_version);
@@ -1081,8 +1081,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        struct timespec mtime, atime;
        int wake = 0;
        umode_t mode;
-       uid_t uid;
-       gid_t gid;
+       kuid_t uid;
+       kgid_t gid;
        struct ceph_mds_session *session;
        u64 xattr_version = 0;
        struct ceph_buffer *xattr_blob = NULL;
@@ -2359,10 +2359,11 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
 
        if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
                inode->i_mode = le32_to_cpu(grant->mode);
-               inode->i_uid = le32_to_cpu(grant->uid);
-               inode->i_gid = le32_to_cpu(grant->gid);
+               inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
+               inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
                dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
-                    inode->i_uid, inode->i_gid);
+                    from_kuid(&init_user_ns, inode->i_uid),
+                    from_kgid(&init_user_ns, inode->i_gid));
        }
 
        if ((issued & CEPH_CAP_LINK_EXCL) == 0)
index 2971eaa65cdce9b3b31edca64ea979eeb814ab7a..d45895f4a04dd466de53e5a6b1dfbcb01608824c 100644 (file)
@@ -612,10 +612,11 @@ static int fill_inode(struct inode *inode,
 
        if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
                inode->i_mode = le32_to_cpu(info->mode);
-               inode->i_uid = le32_to_cpu(info->uid);
-               inode->i_gid = le32_to_cpu(info->gid);
+               inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid));
+               inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid));
                dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
-                    inode->i_uid, inode->i_gid);
+                    from_kuid(&init_user_ns, inode->i_uid),
+                    from_kgid(&init_user_ns, inode->i_gid));
        }
 
        if ((issued & CEPH_CAP_LINK_EXCL) == 0)
@@ -1565,26 +1566,30 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (ia_valid & ATTR_UID) {
                dout("setattr %p uid %d -> %d\n", inode,
-                    inode->i_uid, attr->ia_uid);
+                    from_kuid(&init_user_ns, inode->i_uid),
+                    from_kuid(&init_user_ns, attr->ia_uid));
                if (issued & CEPH_CAP_AUTH_EXCL) {
                        inode->i_uid = attr->ia_uid;
                        dirtied |= CEPH_CAP_AUTH_EXCL;
                } 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);
+                    from_kgid(&init_user_ns, inode->i_gid),
+                    from_kgid(&init_user_ns, attr->ia_gid));
                if (issued & CEPH_CAP_AUTH_EXCL) {
                        inode->i_gid = attr->ia_gid;
                        dirtied |= CEPH_CAP_AUTH_EXCL;
                } 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;
                }
index 9165eb8309eba442efa237aaa313a43c92641607..7a3dfe0a9a80e551f905a4d46d1248ea9e6c26f5 100644 (file)
@@ -1658,8 +1658,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
        head->mdsmap_epoch = cpu_to_le32(mdsc->mdsmap->m_epoch);
        head->op = cpu_to_le32(req->r_op);
-       head->caller_uid = cpu_to_le32(req->r_uid);
-       head->caller_gid = cpu_to_le32(req->r_gid);
+       head->caller_uid = cpu_to_le32(from_kuid(&init_user_ns, req->r_uid));
+       head->caller_gid = cpu_to_le32(from_kgid(&init_user_ns, req->r_gid));
        head->args = req->r_args;
 
        ceph_encode_filepath(&p, end, ino1, path1);
index dd26846dd71de4267146b7deb43c7a5d7b9b976f..ff4188bf6199b5988d9ba7c111160b3f0aadbd67 100644 (file)
@@ -184,8 +184,8 @@ struct ceph_mds_request {
 
        union ceph_mds_request_args r_args;
        int r_fmode;        /* file mode, if expecting cap */
-       uid_t r_uid;
-       gid_t r_gid;
+       kuid_t r_uid;
+       kgid_t r_gid;
 
        /* for choosing which mds to send this request to */
        int r_direct_mode;
index 66ebe720e40dd40189510a1da9ce62f45385653b..f053bbd1886f215b2e2c64dab12f0a1812b5808e 100644 (file)
@@ -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;
index c865bfdfe8190e19cdc6052e398ac1b2598783e6..37e4a72a7d1c46389c35736d66f1636891874ba4 100644 (file)
@@ -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;
index 086f381d648954c4001542be40b3ba6beffbceb0..10e7747612992bcc25706851c9027762e2fc134d 100644 (file)
@@ -149,10 +149,12 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
                goto out;
 
        dp = description + strlen(description);
-       sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
+       sprintf(dp, ";uid=0x%x",
+               from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
 
        dp = description + strlen(description);
-       sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
+       sprintf(dp, ";creduid=0x%x",
+               from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
 
        if (sesInfo->user_name) {
                dp = description + strlen(description);
index 5cbd00e740671dc13a0f4a07621513eb469762ac..f1e3f25fe00412a584a70883a5cf6f661741d821 100644 (file)
@@ -266,8 +266,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
        struct key *sidkey;
        char *sidstr;
        const struct cred *saved_cred;
-       uid_t fuid = cifs_sb->mnt_uid;
-       gid_t fgid = cifs_sb->mnt_gid;
+       kuid_t fuid = cifs_sb->mnt_uid;
+       kgid_t fgid = cifs_sb->mnt_gid;
 
        /*
         * If we have too many subauthorities, then something is really wrong.
@@ -297,6 +297,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
         * probably a safe assumption but might be better to check based on
         * sidtype.
         */
+       BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
        if (sidkey->datalen != sizeof(uid_t)) {
                rc = -EIO;
                cFYI(1, "%s: Downcall contained malformed key "
@@ -305,10 +306,21 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
                goto out_key_put;
        }
 
-       if (sidtype == SIDOWNER)
-               memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
-       else
-               memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
+       if (sidtype == SIDOWNER) {
+               kuid_t uid;
+               uid_t id;
+               memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
+               uid = make_kuid(&init_user_ns, id);
+               if (uid_valid(uid))
+                       fuid = uid;
+       } else {
+               kgid_t gid;
+               gid_t id;
+               memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
+               gid = make_kgid(&init_user_ns, id);
+               if (gid_valid(gid))
+                       fgid = gid;
+       }
 
 out_key_put:
        key_put(sidkey);
@@ -346,7 +358,8 @@ init_cifs_idmap(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
+       keyring = keyring_alloc(".cifs_idmap",
+                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
                                (KEY_POS_ALL & ~KEY_POS_SETATTR) |
                                KEY_USR_VIEW | KEY_USR_READ,
                                KEY_ALLOC_NOT_IN_QUOTA, NULL);
@@ -774,7 +787,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 
 /* Convert permission bits from mode to equivalent CIFS ACL */
 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
-       __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
+       __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
 {
        int rc = 0;
        __u32 dacloffset;
@@ -806,17 +819,19 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                *aclflag = CIFS_ACL_DACL;
        } else {
                memcpy(pnntsd, pntsd, secdesclen);
-               if (uid != NO_CHANGE_32) { /* chown */
+               if (uid_valid(uid)) { /* chown */
+                       uid_t id;
                        owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
                                        le32_to_cpu(pnntsd->osidoffset));
                        nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
                                                                GFP_KERNEL);
                        if (!nowner_sid_ptr)
                                return -ENOMEM;
-                       rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
+                       id = from_kuid(&init_user_ns, uid);
+                       rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
                        if (rc) {
                                cFYI(1, "%s: Mapping error %d for owner id %d",
-                                               __func__, rc, uid);
+                                               __func__, rc, id);
                                kfree(nowner_sid_ptr);
                                return rc;
                        }
@@ -824,17 +839,19 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                        kfree(nowner_sid_ptr);
                        *aclflag = CIFS_ACL_OWNER;
                }
-               if (gid != NO_CHANGE_32) { /* chgrp */
+               if (gid_valid(gid)) { /* chgrp */
+                       gid_t id;
                        group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
                                        le32_to_cpu(pnntsd->gsidoffset));
                        ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
                                                                GFP_KERNEL);
                        if (!ngroup_sid_ptr)
                                return -ENOMEM;
-                       rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
+                       id = from_kgid(&init_user_ns, gid);
+                       rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
                        if (rc) {
                                cFYI(1, "%s: Mapping error %d for group id %d",
-                                               __func__, rc, gid);
+                                               __func__, rc, id);
                                kfree(ngroup_sid_ptr);
                                return rc;
                        }
@@ -1002,7 +1019,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
 /* Convert mode bits to an ACL so we can update the ACL on the server */
 int
 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
-                       uid_t uid, gid_t gid)
+                       kuid_t uid, kgid_t gid)
 {
        int rc = 0;
        int aclflag = CIFS_ACL_DACL; /* default flag to set */
index de7f9168a1185ace14e8212040c96285c6c0bc31..9be09b21b4e0c0f1f7a179103b667d131ba11437 100644 (file)
@@ -375,13 +375,15 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                                   (int)(srcaddr->sa_family));
        }
 
-       seq_printf(s, ",uid=%u", cifs_sb->mnt_uid);
+       seq_printf(s, ",uid=%u",
+                  from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid));
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
                seq_printf(s, ",forceuid");
        else
                seq_printf(s, ",noforceuid");
 
-       seq_printf(s, ",gid=%u", cifs_sb->mnt_gid);
+       seq_printf(s, ",gid=%u",
+                  from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid));
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
                seq_printf(s, ",forcegid");
        else
@@ -436,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);
index e6899cea1c3580e6e9217f9cb3f0ff68e8d7626c..4f07f6fbe4944c5e6f8bdf12c30b4eaed9397976 100644 (file)
@@ -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 */ ;
@@ -1245,8 +1245,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;
index b9d59a948a2c8d30c89373655238d11ef7747a76..e996ff6b26d1886f63a6c162a09a996e80edf32a 100644 (file)
 #define CIFS_NO_HANDLE        0xFFFF
 
 #define NO_CHANGE_64          0xFFFFFFFFFFFFFFFFULL
-#define NO_CHANGE_32          0xFFFFFFFFUL
 
 /* IPC$ in ASCII */
 #define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
index 1988c1baa224bf5108635929062fdddb3b7955e8..f450f0683dddcf15cb0a5febe075b5c7b5be6934 100644 (file)
@@ -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;
 };
 
index 76d0d29988507625c4d679b00e2a7cf695e86630..00e12f2d626b92c97540950f8dad5fa70bb4d485 100644 (file)
@@ -5819,8 +5819,14 @@ static void
 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
                        const struct cifs_unix_set_info_args *args)
 {
+       u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
        u64 mode = args->mode;
 
+       if (uid_valid(args->uid))
+               uid = from_kuid(&init_user_ns, args->uid);
+       if (gid_valid(args->gid))
+               gid = from_kgid(&init_user_ns, args->gid);
+
        /*
         * Samba server ignores set of file size to zero due to bugs in some
         * older clients, but we should be precise - we use SetFileSize to
@@ -5833,8 +5839,8 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
        data_offset->LastStatusChange = cpu_to_le64(args->ctime);
        data_offset->LastAccessTime = cpu_to_le64(args->atime);
        data_offset->LastModificationTime = cpu_to_le64(args->mtime);
-       data_offset->Uid = cpu_to_le64(args->uid);
-       data_offset->Gid = cpu_to_le64(args->gid);
+       data_offset->Uid = cpu_to_le64(uid);
+       data_offset->Gid = cpu_to_le64(gid);
        /* better to leave device as zero when it is  */
        data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
        data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
index 12b3da39733b2bc180cd1ac4a164d9f0d071e99a..4474a57f30ab779a0c066dbb5a2d1154fc243b1b 100644 (file)
@@ -987,6 +987,41 @@ static int get_option_ul(substring_t args[], unsigned long *option)
        return rc;
 }
 
+static int get_option_uid(substring_t args[], kuid_t *result)
+{
+       unsigned long value;
+       kuid_t uid;
+       int rc;
+
+       rc = get_option_ul(args, &value);
+       if (rc)
+               return rc;
+
+       uid = make_kuid(current_user_ns(), value);
+       if (!uid_valid(uid))
+               return -EINVAL;
+
+       *result = uid;
+       return 0;
+}
+
+static int get_option_gid(substring_t args[], kgid_t *result)
+{
+       unsigned long value;
+       kgid_t gid;
+       int rc;
+
+       rc = get_option_ul(args, &value);
+       if (rc)
+               return rc;
+
+       gid = make_kgid(current_user_ns(), value);
+       if (!gid_valid(gid))
+               return -EINVAL;
+
+       *result = gid;
+       return 0;
+}
 
 static int cifs_parse_security_flavors(char *value,
                                       struct smb_vol *vol)
@@ -1424,47 +1459,42 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
                /* Numeric Values */
                case Opt_backupuid:
-                       if (get_option_ul(args, &option)) {
+                       if (get_option_uid(args, &vol->backupuid)) {
                                cERROR(1, "%s: Invalid backupuid value",
                                        __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->backupuid = option;
                        vol->backupuid_specified = true;
                        break;
                case Opt_backupgid:
-                       if (get_option_ul(args, &option)) {
+                       if (get_option_gid(args, &vol->backupgid)) {
                                cERROR(1, "%s: Invalid backupgid value",
                                        __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->backupgid = option;
                        vol->backupgid_specified = true;
                        break;
                case Opt_uid:
-                       if (get_option_ul(args, &option)) {
+                       if (get_option_uid(args, &vol->linux_uid)) {
                                cERROR(1, "%s: Invalid uid value",
                                        __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->linux_uid = option;
                        uid_specified = true;
                        break;
                case Opt_cruid:
-                       if (get_option_ul(args, &option)) {
+                       if (get_option_uid(args, &vol->cred_uid)) {
                                cERROR(1, "%s: Invalid cruid value",
                                        __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->cred_uid = option;
                        break;
                case Opt_gid:
-                       if (get_option_ul(args, &option)) {
+                       if (get_option_gid(args, &vol->linux_gid)) {
                                cERROR(1, "%s: Invalid gid value",
                                                __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->linux_gid = option;
                        gid_specified = true;
                        break;
                case Opt_file_mode:
@@ -2241,7 +2271,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
 {
        switch (ses->server->secType) {
        case Kerberos:
-               if (vol->cred_uid != ses->cred_uid)
+               if (!uid_eq(vol->cred_uid, ses->cred_uid))
                        return 0;
                break;
        default:
@@ -2713,7 +2743,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
        if (new->rsize && new->rsize < old->rsize)
                return 0;
 
-       if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
+       if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
                return 0;
 
        if (old->mnt_file_mode != new->mnt_file_mode ||
@@ -3919,7 +3949,7 @@ cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
 }
 
 static struct cifs_tcon *
-cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
 {
        int rc;
        struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
@@ -3989,7 +4019,7 @@ cifs_sb_tcon_pending_wait(void *unused)
 
 /* find and return a tlink with given uid */
 static struct tcon_link *
-tlink_rb_search(struct rb_root *root, uid_t uid)
+tlink_rb_search(struct rb_root *root, kuid_t uid)
 {
        struct rb_node *node = root->rb_node;
        struct tcon_link *tlink;
@@ -3997,9 +4027,9 @@ tlink_rb_search(struct rb_root *root, uid_t uid)
        while (node) {
                tlink = rb_entry(node, struct tcon_link, tl_rbnode);
 
-               if (tlink->tl_uid > uid)
+               if (uid_gt(tlink->tl_uid, uid))
                        node = node->rb_left;
-               else if (tlink->tl_uid < uid)
+               else if (uid_lt(tlink->tl_uid, uid))
                        node = node->rb_right;
                else
                        return tlink;
@@ -4018,7 +4048,7 @@ tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
                tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
                parent = *new;
 
-               if (tlink->tl_uid > new_tlink->tl_uid)
+               if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
                        new = &((*new)->rb_left);
                else
                        new = &((*new)->rb_right);
@@ -4048,7 +4078,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))
index 8719bbe0dcc36e32836cef3cf0b2b9c6e8a8175a..1cd0162174486dcce77a56e9970d7b1f1154eda4 100644 (file)
@@ -342,14 +342,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
 
                *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-                       args.uid = (__u64) current_fsuid();
+                       args.uid = current_fsuid();
                        if (inode->i_mode & S_ISGID)
-                               args.gid = (__u64) inode->i_gid;
+                               args.gid = inode->i_gid;
                        else
-                               args.gid = (__u64) current_fsgid();
+                               args.gid = current_fsgid();
                } else {
-                       args.uid = NO_CHANGE_64;
-                       args.gid = NO_CHANGE_64;
+                       args.uid = INVALID_UID; /* no change */
+                       args.gid = INVALID_GID; /* no change */
                }
                CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
                                       current->tgid);
@@ -588,11 +588,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
                        .device = device_number,
                };
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-                       args.uid = (__u64) current_fsuid();
-                       args.gid = (__u64) current_fsgid();
+                       args.uid = current_fsuid();
+                       args.gid = current_fsgid();
                } else {
-                       args.uid = NO_CHANGE_64;
-                       args.gid = NO_CHANGE_64;
+                       args.uid = INVALID_UID; /* no change */
+                       args.gid = INVALID_GID; /* no change */
                }
                rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
                                            cifs_sb->local_nls,
index 8ea6ca50a665cd4dcb016042b52d16ef5492bab4..a8d8b589ee0efa6820627187098f89838a87e2cb 100644 (file)
@@ -515,8 +515,8 @@ int cifs_open(struct inode *inode, struct file *file)
                 */
                struct cifs_unix_set_info_args args = {
                        .mode   = inode->i_mode,
-                       .uid    = NO_CHANGE_64,
-                       .gid    = NO_CHANGE_64,
+                       .uid    = INVALID_UID, /* no change */
+                       .gid    = INVALID_GID, /* no change */
                        .ctime  = NO_CHANGE_64,
                        .atime  = NO_CHANGE_64,
                        .mtime  = NO_CHANGE_64,
@@ -1693,7 +1693,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) {
@@ -1746,7 +1746,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) {
index ed6208ff85a770771841a0fe54da82dff26bdfa3..9638233964fc68f3b36d3b5b7693bdf85e08014a 100644 (file)
@@ -244,15 +244,25 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
                break;
        }
 
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
-               fattr->cf_uid = cifs_sb->mnt_uid;
-       else
-               fattr->cf_uid = le64_to_cpu(info->Uid);
-
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
-               fattr->cf_gid = cifs_sb->mnt_gid;
-       else
-               fattr->cf_gid = le64_to_cpu(info->Gid);
+       fattr->cf_uid = cifs_sb->mnt_uid;
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
+               u64 id = le64_to_cpu(info->Uid);
+               if (id < ((uid_t)-1)) {
+                       kuid_t uid = make_kuid(&init_user_ns, id);
+                       if (uid_valid(uid))
+                               fattr->cf_uid = uid;
+               }
+       }
+       
+       fattr->cf_gid = cifs_sb->mnt_gid;
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
+               u64 id = le64_to_cpu(info->Gid);
+               if (id < ((gid_t)-1)) {
+                       kgid_t gid = make_kgid(&init_user_ns, id);
+                       if (gid_valid(gid))
+                               fattr->cf_gid = gid;
+               }
+       }
 
        fattr->cf_nlink = le64_to_cpu(info->Nlinks);
 }
@@ -1245,14 +1255,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
                        .device = 0,
                };
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-                       args.uid = (__u64)current_fsuid();
+                       args.uid = current_fsuid();
                        if (parent->i_mode & S_ISGID)
-                               args.gid = (__u64)parent->i_gid;
+                               args.gid = parent->i_gid;
                        else
-                               args.gid = (__u64)current_fsgid();
+                               args.gid = current_fsgid();
                } else {
-                       args.uid = NO_CHANGE_64;
-                       args.gid = NO_CHANGE_64;
+                       args.uid = INVALID_UID; /* no change */
+                       args.gid = INVALID_GID; /* no change */
                }
                CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
                                       cifs_sb->local_nls,
@@ -2013,12 +2023,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
        if (attrs->ia_valid & ATTR_UID)
                args->uid = attrs->ia_uid;
        else
-               args->uid = NO_CHANGE_64;
+               args->uid = INVALID_UID; /* no change */
 
        if (attrs->ia_valid & ATTR_GID)
                args->gid = attrs->ia_gid;
        else
-               args->gid = NO_CHANGE_64;
+               args->gid = INVALID_GID; /* no change */
 
        if (attrs->ia_valid & ATTR_ATIME)
                args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
@@ -2086,8 +2096,8 @@ static int
 cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 {
        unsigned int xid;
-       uid_t uid = NO_CHANGE_32;
-       gid_t gid = NO_CHANGE_32;
+       kuid_t uid = INVALID_UID;
+       kgid_t gid = INVALID_GID;
        struct inode *inode = direntry->d_inode;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
@@ -2146,7 +2156,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
 #ifdef CONFIG_CIFS_ACL
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-               if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
+               if (uid_valid(uid) || gid_valid(gid)) {
                        rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
                                                        uid, gid);
                        if (rc) {
@@ -2170,7 +2180,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 #ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        rc = id_mode_to_cifs_acl(inode, full_path, mode,
-                                               NO_CHANGE_32, NO_CHANGE_32);
+                                               INVALID_UID, INVALID_GID);
                        if (rc) {
                                cFYI(1, "%s: Setting ACL failed with error: %d",
                                        __func__, rc);
index 3a00c0d0cead9d6836f4e449f679a6909f14a89e..1b15bf839f376c4611c06a4166281a4299acdce4 100644 (file)
@@ -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) {
index 958ae0e0ff8c0d55d5ef18001154f56e3cb273ce..1da168c61d35c2194422fa24c5bca3235a1c19ca 100644 (file)
@@ -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);
 
index b24fdfd8a3f097a091fe5b04362cd437b96ba0f7..c64075213218065e51da038f75393c842a1d2dcf 100644 (file)
@@ -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;
index 854ace71268579b9a48e0b0001f1ebfe09c094ea..2849f41e72a209fb689c7b28915566ed8c70cde1 100644 (file)
@@ -100,9 +100,9 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
        if (attr->va_mode != (u_short) -1)
                inode->i_mode = attr->va_mode | inode_type;
         if (attr->va_uid != -1) 
-               inode->i_uid = (uid_t) attr->va_uid;
+               inode->i_uid = make_kuid(&init_user_ns, (uid_t) attr->va_uid);
         if (attr->va_gid != -1)
-               inode->i_gid = (gid_t) attr->va_gid;
+               inode->i_gid = make_kgid(&init_user_ns, (gid_t) attr->va_gid);
        if (attr->va_nlink != -1)
                set_nlink(inode, attr->va_nlink);
        if (attr->va_size != -1)
@@ -171,10 +171,10 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
                 vattr->va_mode = iattr->ia_mode;
        }
         if ( valid & ATTR_UID ) {
-                vattr->va_uid = (vuid_t) iattr->ia_uid;
+                vattr->va_uid = (vuid_t) from_kuid(&init_user_ns, iattr->ia_uid);
        }
         if ( valid & ATTR_GID ) {
-                vattr->va_gid = (vgid_t) iattr->ia_gid;
+                vattr->va_gid = (vgid_t) from_kgid(&init_user_ns, iattr->ia_gid);
        }
         if ( valid & ATTR_SIZE ) {
                 vattr->va_size = iattr->ia_size;
index be2aa49094877c22d326b0466d9cfc32bb6ed94b..cf674e9179a3c5eac4261e670b0b4b294a8dde2a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/file.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
+#include <linux/pid_namespace.h>
 
 #include <asm/uaccess.h>
 
@@ -48,7 +49,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
                return NULL;
        memset(&ei->c_fid, 0, sizeof(struct CodaFid));
        ei->c_flags = 0;
-       ei->c_uid = 0;
+       ei->c_uid = GLOBAL_ROOT_UID;
        ei->c_cached_perm = 0;
        spin_lock_init(&ei->c_lock);
        return &ei->vfs_inode;
@@ -157,6 +158,9 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        int error;
        int idx;
 
+       if (task_active_pid_ns(current) != &init_pid_ns)
+               return -EINVAL;
+
        idx = get_device_index((struct coda_mount_data *) data);
 
        /* Ignore errors in data, for backward compatibility */
index 761d5b31b18d0b27ce83d6d7ed7a815d3e63b75d..ebc2bae6c289038803f4542f88fc8291c5006c8d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
+#include <linux/pid_namespace.h>
 #include <asm/io.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
@@ -266,6 +267,12 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
        struct venus_comm *vcp;
        int idx, err;
 
+       if (task_active_pid_ns(current) != &init_pid_ns)
+               return -EINVAL;
+
+       if (current_user_ns() != &init_user_ns)
+               return -EINVAL;
+
        idx = iminor(inode);
        if (idx < 0 || idx >= MAX_CODADEVS)
                return -ENODEV;
index 0c68fd31fbf2bf3261a1ba1ce9c0e8a3148c4baa..3a731976dc5e999ffb53b10458cb6dc72540fab8 100644 (file)
@@ -50,9 +50,9 @@ static void *alloc_upcall(int opcode, int size)
                return ERR_PTR(-ENOMEM);
 
         inp->ih.opcode = opcode;
-       inp->ih.pid = current->pid;
-       inp->ih.pgid = task_pgrp_nr(current);
-       inp->ih.uid = current_fsuid();
+       inp->ih.pid = task_pid_nr_ns(current, &init_pid_ns);
+       inp->ih.pgid = task_pgrp_nr_ns(current, &init_pid_ns);
+       inp->ih.uid = 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;
 
index 472e6befc54d3640d4ca8f7b3a6458aeb7eddce6..073d30b9d1acdc735eee53cdc26330df46294165 100644 (file)
@@ -243,6 +243,13 @@ static int mknod_ptmx(struct super_block *sb)
        struct dentry *root = sb->s_root;
        struct pts_fs_info *fsi = DEVPTS_SB(sb);
        struct pts_mount_opts *opts = &fsi->mount_opts;
+       kuid_t root_uid;
+       kgid_t root_gid;
+
+       root_uid = make_kuid(current_user_ns(), 0);
+       root_gid = make_kgid(current_user_ns(), 0);
+       if (!uid_valid(root_uid) || !gid_valid(root_gid))
+               return -EINVAL;
 
        mutex_lock(&root->d_inode->i_mutex);
 
@@ -273,6 +280,8 @@ static int mknod_ptmx(struct super_block *sb)
 
        mode = S_IFCHR|opts->ptmxmode;
        init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
+       inode->i_uid = root_uid;
+       inode->i_gid = root_gid;
 
        d_add(dentry, inode);
 
@@ -438,6 +447,12 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type,
        if (error)
                return ERR_PTR(error);
 
+       /* Require newinstance for all user namespace mounts to ensure
+        * the mount options are not changed.
+        */
+       if ((current_user_ns() != &init_user_ns) && !opts.newinstance)
+               return ERR_PTR(-EINVAL);
+
        if (opts.newinstance)
                s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        else
@@ -491,6 +506,9 @@ static struct file_system_type devpts_fs_type = {
        .name           = "devpts",
        .mount          = devpts_mount,
        .kill_sb        = devpts_kill_sb,
+#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
+       .fs_flags       = FS_USERNS_MOUNT | FS_USERNS_DEV_MOUNT,
+#endif
 };
 
 /*
index f850020ad906a68cc715602e024f1a9bd18c1b88..f69ac0af5496cd456bf6df4d0c932747b6767779 100644 (file)
@@ -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;
index df686d13a7d25dcd7cd91a833af4fc77f48626ad..5e83657f046e2954226d150a80f9560c4e3087c5 100644 (file)
@@ -1099,7 +1099,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;
 
index 7179478e5a28db863d119d9c7f2f883584f3330a..c3e82bd23179533e83dc5bf57186be025cdc2e9e 100644 (file)
@@ -1849,7 +1849,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
        if (!ht)
                return -ENOMEM;
 
-       error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+       error = gfs2_quota_hold(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
        if (error)
                goto out;
 
index 78d4184ffc7d496eac9bd7adcef248d3f0a5689c..444b6503ebc404f710aafe371b8b49e100bfba1b 100644 (file)
@@ -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));
index e2601ba38ef56899869ff69e101f957f18313709..156e42ec84ea488c9c223400284c9040b5c86f69 100644 (file)
@@ -392,7 +392,6 @@ struct gfs2_revoke_replay {
 };
 
 enum {
-       QDF_USER                = 0,
        QDF_CHANGE              = 1,
        QDF_LOCKED              = 2,
        QDF_REFRESH             = 3,
@@ -404,7 +403,7 @@ struct gfs2_quota_data {
 
        atomic_t qd_count;
 
-       u32 qd_id;
+       struct kqid qd_id;
        unsigned long qd_flags;         /* QDF_... */
 
        s64 qd_change;
index db048a8ab6a859dc2466b56f61c59767f0244525..cc00bd1d1f87ed331dea2b35b76d503a4bbf1c7a 100644 (file)
@@ -368,10 +368,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip,
                               struct inode *inode)
 {
        if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
-           (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
+           (dip->i_inode.i_mode & S_ISUID) &&
+           !uid_eq(dip->i_inode.i_uid, GLOBAL_ROOT_UID)) {
                if (S_ISDIR(inode->i_mode))
                        inode->i_mode |= S_ISUID;
-               else if (dip->i_inode.i_uid != current_fsuid())
+               else if (!uid_eq(dip->i_inode.i_uid, current_fsuid()))
                        inode->i_mode &= ~07111;
                inode->i_uid = dip->i_inode.i_uid;
        } else
@@ -455,8 +456,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
        di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
        di->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
        di->di_mode = cpu_to_be32(ip->i_inode.i_mode);
-       di->di_uid = cpu_to_be32(ip->i_inode.i_uid);
-       di->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+       di->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
+       di->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
        di->di_nlink = 0;
        di->di_size = cpu_to_be64(ip->i_inode.i_size);
        di->di_blocks = cpu_to_be64(1);
@@ -548,7 +549,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;
 
@@ -978,8 +979,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
                return -EPERM;
 
        if ((dip->i_inode.i_mode & S_ISVTX) &&
-           dip->i_inode.i_uid != current_fsuid() &&
-           ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
+           !uid_eq(dip->i_inode.i_uid, current_fsuid()) &&
+           !uid_eq(ip->i_inode.i_uid, current_fsuid()) && !capable(CAP_FOWNER))
                return -EPERM;
 
        if (IS_APPEND(&dip->i_inode))
@@ -1580,7 +1581,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;
@@ -1588,16 +1590,17 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
        nuid = attr->ia_uid;
        ngid = attr->ia_gid;
 
-       if (!(attr->ia_valid & ATTR_UID) || ouid == nuid)
-               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_eq(ouid, NO_UID_QUOTA_CHANGE) ||
+           !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) {
                error = gfs2_quota_check(ip, nuid, ngid);
                if (error)
                        goto out_gunlock_q;
@@ -1611,7 +1614,8 @@ 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_eq(ouid, NO_UID_QUOTA_CHANGE) ||
+           !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) {
                u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
                gfs2_quota_change(ip, -blocks, ouid, ogid);
                gfs2_quota_change(ip, blocks, nuid, ngid);
index 06122d09c0d1d88d37143ebf0178f13b98042481..c7c840e916f82f333861ac7998ccf53710cc34d8 100644 (file)
 #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);
@@ -120,17 +117,24 @@ out:
        return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
 }
 
+static u64 qd2index(struct gfs2_quota_data *qd)
+{
+       struct kqid qid = qd->qd_id;
+       return (2 * (u64)from_kqid(&init_user_ns, qid)) +
+               (qid.type == USRQUOTA) ? 0 : 1;
+}
+
 static u64 qd2offset(struct gfs2_quota_data *qd)
 {
        u64 offset;
 
-       offset = 2 * (u64)qd->qd_id + !test_bit(QDF_USER, &qd->qd_flags);
+       offset = qd2index(qd);
        offset *= sizeof(struct gfs2_quota);
 
        return offset;
 }
 
-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 +145,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, qd2index(qd),
                              &gfs2_quota_glops, CREATE, &qd->qd_gl);
        if (error)
                goto fail;
@@ -161,7 +163,7 @@ fail:
        return error;
 }
 
-static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
+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;
@@ -173,8 +175,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 +209,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 +459,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 +492,7 @@ static void qdsb_put(struct gfs2_quota_data *qd)
        qd_put(qd);
 }
 
-int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
+int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_quota_data **qd;
@@ -512,28 +513,30 @@ 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_eq(uid, NO_UID_QUOTA_CHANGE) &&
+           !uid_eq(uid, ip->i_inode.i_uid)) {
+               error = qdsb_get(sdp, make_kqid_uid(uid), qd);
                if (error)
                        goto out;
                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_eq(gid, NO_GID_QUOTA_CHANGE) &&
+           !gid_eq(gid, ip->i_inode.i_gid)) {
+               error = qdsb_get(sdp, make_kqid_gid(gid), qd);
                if (error)
                        goto out;
                ip->i_res->rs_qa_qd_num++;
@@ -567,18 +570,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;
 }
 
@@ -595,9 +590,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;
@@ -925,7 +920,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;
@@ -1040,13 +1035,13 @@ 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;
@@ -1063,8 +1058,8 @@ 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))))
+               if (!(qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
+                     qid_eq(qd->qd_id, make_kqid_gid(gid))))
                        continue;
 
                value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
@@ -1074,10 +1069,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;
@@ -1087,10 +1079,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;
@@ -1101,7 +1090,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
 }
 
 void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
-                      u32 uid, u32 gid)
+                      kuid_t uid, kgid_t gid)
 {
        struct gfs2_quota_data *qd;
        unsigned int x;
@@ -1114,8 +1103,8 @@ 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))) {
+               if (qid_eq(qd->qd_id, make_kqid_uid(uid)) ||
+                   qid_eq(qd->qd_id, make_kqid_gid(gid))) {
                        do_qc(qd, change);
                }
        }
@@ -1170,13 +1159,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;
 
@@ -1194,7 +1183,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)
@@ -1257,8 +1248,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;
@@ -1485,21 +1475,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);
@@ -1508,8 +1494,8 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
 
        qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
        fdq->d_version = FS_DQUOT_VERSION;
-       fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
-       fdq->d_id = from_kqid(&init_user_ns, qid);
+       fdq->d_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;
@@ -1535,32 +1521,18 @@ 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;
-       default:
+       if ((qid.type != USRQUOTA) &&
+           (qid.type != GRPQUOTA))
                return -EINVAL;
-       }
 
        if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
                return -EINVAL;
-       if (fdq->d_id != from_kqid(&init_user_ns, qid))
-               return -EINVAL;
 
-       error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
+       error = qd_get(sdp, qid, &qd);
        if (error)
                return error;
 
index f25d98b87904aa7ab315c8668b90b556c67dcf90..4f5e6e44ed8320feec952a71096cc55b1b385a96 100644 (file)
@@ -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)
index a3b40eeaa6e231860fb796f0c27a7677c5adffca..cab77b8ba84f3f9d5340fed579c4df5d46af33d9 100644 (file)
@@ -673,8 +673,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));
@@ -1376,7 +1376,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;
 
index 4fb9ad80d2600ac5ac53ddd399ff29ec1cb61f89..597a612834dc136a3addb508656daafed1784a5b 100644 (file)
@@ -173,6 +173,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
 static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
                                        size_t len)
 {
+       struct kqid qid;
        int error;
        u32 id;
 
@@ -181,13 +182,18 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
 
        id = simple_strtoul(buf, NULL, 0);
 
-       error = gfs2_quota_refresh(sdp, 1, id);
+       qid = make_kqid(current_user_ns(), USRQUOTA, id);
+       if (!qid_valid(qid))
+               return -EINVAL;
+
+       error = gfs2_quota_refresh(sdp, qid);
        return error ? error : len;
 }
 
 static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
                                         size_t len)
 {
+       struct kqid qid;
        int error;
        u32 id;
 
@@ -196,7 +202,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
 
        id = simple_strtoul(buf, NULL, 0);
 
-       error = gfs2_quota_refresh(sdp, 0, id);
+       qid = make_kqid(current_user_ns(), GRPQUOTA, id);
+       if (!qid_valid(qid))
+               return -EINVAL;
+
+       error = gfs2_quota_refresh(sdp, qid);
        return error ? error : len;
 }
 
index cbb46c2baa69416f1f5771fc11f82aad5bd1fa17..ecd37f30ab91986923c5fa8c0cdf02f1bd3d330b 100644 (file)
@@ -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;
 
index 1acdad7fcec7cda8ca5aa9e88b92cce45b960c37..e2be336d1c22da50b516a1926c7cabfaf0686ff8 100644 (file)
@@ -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) &&
index 6958adfaff084e71fa66a1f7e10a00ad82fd8f60..d44318d275049c1dbe0971c23e0ca4876ad6b1ae 100644 (file)
@@ -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
index 54cc0cdb3dcbda111e24a3a67e7953e5173dd07e..c51b2c54353971f785020570ee6773e60058bef0 100644 (file)
@@ -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;
index bc3968fa81e53c1164b9ebb93c7f122303731143..b9623d19d599e5e1946b5a35192a5cb79bf1b45a 100644 (file)
@@ -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 = keyring_alloc(".id_resolver", 0, 0, cred,
+       keyring = keyring_alloc(".id_resolver",
+                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
                                (KEY_POS_ALL & ~KEY_POS_SETATTR) |
                                KEY_USR_VIEW | KEY_USR_READ,
                                KEY_ALLOC_NOT_IN_QUOTA, NULL);
@@ -836,43 +837,61 @@ idmap_release_pipe(struct inode *inode)
        nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
 }
 
-int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
 {
        struct idmap *idmap = server->nfs_client->cl_idmap;
+       __u32 id = -1;
+       int ret = 0;
 
-       if (nfs_map_string_to_numeric(name, namelen, uid))
-               return 0;
-       return nfs_idmap_lookup_id(name, namelen, "uid", uid, idmap);
+       if (!nfs_map_string_to_numeric(name, namelen, &id))
+               ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
+       if (ret == 0) {
+               *uid = make_kuid(&init_user_ns, id);
+               if (!uid_valid(*uid))
+                       ret = -ERANGE;
+       }
+       return ret;
 }
 
-int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid)
+int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
 {
        struct idmap *idmap = server->nfs_client->cl_idmap;
+       __u32 id = -1;
+       int ret = 0;
 
-       if (nfs_map_string_to_numeric(name, namelen, gid))
-               return 0;
-       return nfs_idmap_lookup_id(name, namelen, "gid", gid, idmap);
+       if (!nfs_map_string_to_numeric(name, namelen, &id))
+               ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
+       if (ret == 0) {
+               *gid = make_kgid(&init_user_ns, id);
+               if (!gid_valid(*gid))
+                       ret = -ERANGE;
+       }
+       return ret;
 }
 
-int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
+int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
 {
        struct idmap *idmap = server->nfs_client->cl_idmap;
        int ret = -EINVAL;
+       __u32 id;
 
+       id = from_kuid(&init_user_ns, uid);
        if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
-               ret = nfs_idmap_lookup_name(uid, "user", buf, buflen, idmap);
+               ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
        if (ret < 0)
-               ret = nfs_map_numeric_to_string(uid, buf, buflen);
+               ret = nfs_map_numeric_to_string(id, buf, buflen);
        return ret;
 }
-int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
+int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
 {
        struct idmap *idmap = server->nfs_client->cl_idmap;
        int ret = -EINVAL;
+       __u32 id;
 
+       id = from_kgid(&init_user_ns, gid);
        if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
-               ret = nfs_idmap_lookup_name(gid, "group", buf, buflen, idmap);
+               ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
        if (ret < 0)
-               ret = nfs_map_numeric_to_string(gid, buf, buflen);
+               ret = nfs_map_numeric_to_string(id, buf, buflen);
        return ret;
 }
index 6acc73c80d7f26421d7f2c1b7ca47236eb2a969d..468ba8bf0f56c73a971e0279722a741687baab89 100644 (file)
@@ -332,8 +332,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                inode->i_version = 0;
                inode->i_size = 0;
                clear_nlink(inode);
-               inode->i_uid = -2;
-               inode->i_gid = -2;
+               inode->i_uid = make_kuid(&init_user_ns, -2);
+               inode->i_gid = make_kgid(&init_user_ns, -2);
                inode->i_blocks = 0;
                memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
                nfsi->write_io = 0;
@@ -1006,9 +1006,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? */
@@ -1437,7 +1437,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;
                }
@@ -1448,7 +1448,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;
                }
index 06b9df49f7f7773fa62ad1b7215b2ffcdfee852a..62db136339ea9cb95b6d48ca1b4427b9723ad662 100644 (file)
@@ -290,8 +290,13 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 
        fattr->mode = be32_to_cpup(p++);
        fattr->nlink = be32_to_cpup(p++);
-       fattr->uid = be32_to_cpup(p++);
-       fattr->gid = be32_to_cpup(p++);
+       fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
+       if (!uid_valid(fattr->uid))
+               goto out_uid;
+       fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));
+       if (!gid_valid(fattr->gid))
+               goto out_gid;
+               
        fattr->size = be32_to_cpup(p++);
        fattr->du.nfs2.blocksize = be32_to_cpup(p++);
 
@@ -313,6 +318,12 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
        fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
 
        return 0;
+out_uid:
+       dprintk("NFS: returned invalid uid\n");
+       return -EINVAL;
+out_gid:
+       dprintk("NFS: returned invalid gid\n");
+       return -EINVAL;
 out_overflow:
        print_overflow_msg(__func__, xdr);
        return -EIO;
@@ -351,11 +362,11 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
        else
                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
        if (attr->ia_valid & ATTR_UID)
-               *p++ = cpu_to_be32(attr->ia_uid);
+               *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
        else
                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
        if (attr->ia_valid & ATTR_GID)
-               *p++ = cpu_to_be32(attr->ia_gid);
+               *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
        else
                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
        if (attr->ia_valid & ATTR_SIZE)
index bffc32406fbf81b764d43a298e12489b5fa37faf..fa6d72131c19e64565df105eeb9ed472bb180bf0 100644 (file)
@@ -592,13 +592,13 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 
        if (attr->ia_valid & ATTR_UID) {
                *p++ = xdr_one;
-               *p++ = cpu_to_be32(attr->ia_uid);
+               *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
        } else
                *p++ = xdr_zero;
 
        if (attr->ia_valid & ATTR_GID) {
                *p++ = xdr_one;
-               *p++ = cpu_to_be32(attr->ia_gid);
+               *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
        } else
                *p++ = xdr_zero;
 
@@ -657,8 +657,12 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 
        fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
        fattr->nlink = be32_to_cpup(p++);
-       fattr->uid = be32_to_cpup(p++);
-       fattr->gid = be32_to_cpup(p++);
+       fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
+       if (!uid_valid(fattr->uid))
+               goto out_uid;
+       fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));
+       if (!gid_valid(fattr->gid))
+               goto out_gid;
 
        p = xdr_decode_size3(p, &fattr->size);
        p = xdr_decode_size3(p, &fattr->du.nfs3.used);
@@ -675,6 +679,12 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 
        fattr->valid |= NFS_ATTR_FATTR_V3;
        return 0;
+out_uid:
+       dprintk("NFS: returned invalid uid\n");
+       return -EINVAL;
+out_gid:
+       dprintk("NFS: returned invalid gid\n");
+       return -EINVAL;
 out_overflow:
        print_overflow_msg(__func__, xdr);
        return -EIO;
index 26b143920433e628456476e0d1b708b8fc395d43..e3edda554ac7f4e17da3a6e115df1b1797d63efd 100644 (file)
@@ -1002,7 +1002,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
                owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
                if (owner_namelen < 0) {
                        dprintk("nfs: couldn't resolve uid %d to string\n",
-                                       iap->ia_uid);
+                                       from_kuid(&init_user_ns, iap->ia_uid));
                        /* XXX */
                        strcpy(owner_name, "nobody");
                        owner_namelen = sizeof("nobody") - 1;
@@ -1014,7 +1014,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
                owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
                if (owner_grouplen < 0) {
                        dprintk("nfs: couldn't resolve gid %d to string\n",
-                                       iap->ia_gid);
+                                       from_kgid(&init_user_ns, iap->ia_gid));
                        strcpy(owner_group, "nobody");
                        owner_grouplen = sizeof("nobody") - 1;
                        /* goto out; */
@@ -3778,14 +3778,14 @@ out_overflow:
 }
 
 static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
-               const struct nfs_server *server, uint32_t *uid,
+               const struct nfs_server *server, kuid_t *uid,
                struct nfs4_string *owner_name)
 {
        uint32_t len;
        __be32 *p;
        int ret = 0;
 
-       *uid = -2;
+       *uid = make_kuid(&init_user_ns, -2);
        if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
                return -EIO;
        if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
@@ -3813,7 +3813,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
                                        __func__, len);
                bitmap[1] &= ~FATTR4_WORD1_OWNER;
        }
-       dprintk("%s: uid=%d\n", __func__, (int)*uid);
+       dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid));
        return ret;
 out_overflow:
        print_overflow_msg(__func__, xdr);
@@ -3821,14 +3821,14 @@ out_overflow:
 }
 
 static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
-               const struct nfs_server *server, uint32_t *gid,
+               const struct nfs_server *server, kgid_t *gid,
                struct nfs4_string *group_name)
 {
        uint32_t len;
        __be32 *p;
        int ret = 0;
 
-       *gid = -2;
+       *gid = make_kgid(&init_user_ns, -2);
        if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
                return -EIO;
        if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
@@ -3856,7 +3856,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
                                        __func__, len);
                bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
        }
-       dprintk("%s: gid=%d\n", __func__, (int)*gid);
+       dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid));
        return ret;
 out_overflow:
        print_overflow_msg(__func__, xdr);
index 6940439bd6090a7ad09954b0cbd721ae34538e65..ed628f71274c7d22a0cbc1fde941c79f710fc7ab 100644 (file)
@@ -38,8 +38,8 @@ struct nfsacl_encode_desc {
        unsigned int count;
        struct posix_acl *acl;
        int typeflag;
-       uid_t uid;
-       gid_t gid;
+       kuid_t uid;
+       kgid_t gid;
 };
 
 struct nfsacl_simple_acl {
@@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
        *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
        switch(entry->e_tag) {
                case ACL_USER_OBJ:
-                       *p++ = htonl(nfsacl_desc->uid);
+                       *p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid));
                        break;
                case ACL_GROUP_OBJ:
-                       *p++ = htonl(nfsacl_desc->gid);
+                       *p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid));
                        break;
                case ACL_USER:
+                       *p++ = htonl(from_kuid(&init_user_ns, entry->e_uid));
+                       break;
                case ACL_GROUP:
-                       *p++ = htonl(entry->e_id);
+                       *p++ = htonl(from_kgid(&init_user_ns, entry->e_gid));
                        break;
                default:  /* Solaris depends on that! */
                        *p++ = 0;
@@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
                (struct nfsacl_decode_desc *) desc;
        __be32 *p = elem;
        struct posix_acl_entry *entry;
+       unsigned int id;
 
        if (!nfsacl_desc->acl) {
                if (desc->array_len > NFS_ACL_MAX_ENTRIES)
@@ -160,14 +163,22 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
 
        entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
        entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
-       entry->e_id = ntohl(*p++);
+       id = ntohl(*p++);
        entry->e_perm = ntohl(*p++);
 
        switch(entry->e_tag) {
-               case ACL_USER_OBJ:
                case ACL_USER:
-               case ACL_GROUP_OBJ:
+                       entry->e_uid = make_kuid(&init_user_ns, id);
+                       if (!uid_valid(entry->e_uid))
+                               return -EINVAL;
+                       break;
                case ACL_GROUP:
+                       entry->e_gid = make_kgid(&init_user_ns, id);
+                       if (!gid_valid(entry->e_gid))
+                               return -EINVAL;
+                       break;
+               case ACL_USER_OBJ:
+               case ACL_GROUP_OBJ:
                case ACL_OTHER:
                        if (entry->e_perm & ~S_IRWXO)
                                return -EINVAL;
@@ -190,9 +201,13 @@ cmp_acl_entry(const void *x, const void *y)
 
        if (a->e_tag != b->e_tag)
                return a->e_tag - b->e_tag;
-       else if (a->e_id > b->e_id)
+       else if ((a->e_tag == ACL_USER) && uid_gt(a->e_uid, b->e_uid))
+               return 1;
+       else if ((a->e_tag == ACL_USER) && uid_lt(a->e_uid, b->e_uid))
+               return -1;
+       else if ((a->e_tag == ACL_GROUP) && gid_gt(a->e_gid, b->e_gid))
                return 1;
-       else if (a->e_id < b->e_id)
+       else if ((a->e_tag == ACL_GROUP) && gid_lt(a->e_gid, b->e_gid))
                return -1;
        else
                return 0;
@@ -213,22 +228,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
        sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
             cmp_acl_entry, NULL);
 
-       /* Clear undefined identifier fields and find the ACL_GROUP_OBJ
-          and ACL_MASK entries. */
+       /* Find the ACL_GROUP_OBJ and ACL_MASK entries. */
        FOREACH_ACL_ENTRY(pa, acl, pe) {
                switch(pa->e_tag) {
                        case ACL_USER_OBJ:
-                               pa->e_id = ACL_UNDEFINED_ID;
                                break;
                        case ACL_GROUP_OBJ:
-                               pa->e_id = ACL_UNDEFINED_ID;
                                group_obj = pa;
                                break;
                        case ACL_MASK:
                                mask = pa;
                                /* fall through */
                        case ACL_OTHER:
-                               pa->e_id = ACL_UNDEFINED_ID;
                                break;
                }
        }
index 34e5c40af5ef60d44673f992bfd186acab2e1d26..8b186a4955cc8c1cd5c84e3aadc2397370ea1086 100644 (file)
@@ -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
index 34a10d78b839f4c73b3d851e19820bc712129f36..06cddd57226453ef80e8839b5243912dd82df365 100644 (file)
@@ -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,
index 78b3c0e9382279a5205cbb3e90dc86811a85a10c..53325a12ba62a05335c7989f658373ba41e18b0f 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * nfsd-specific authentication stuff.
- * uid/gid mapping not yet implemented.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
@@ -8,11 +7,6 @@
 #ifndef LINUX_NFSD_AUTH_H
 #define LINUX_NFSD_AUTH_H
 
-#define nfsd_luid(rq, uid)     ((u32)(uid))
-#define nfsd_lgid(rq, gid)     ((u32)(gid))
-#define nfsd_ruid(rq, uid)     ((u32)(uid))
-#define nfsd_rgid(rq, gid)     ((u32)(gid))
-
 /*
  * Set the current process's fsuid/fsgid etc to those of the NFS
  * client user
index a3946cf13fc8373d6234c64d4316505364914ca3..5681c5906f088a49d0925ab9c70efc85c2ddc0b0 100644 (file)
@@ -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;
index 9d513efc01baad65a0807284082315c3d5a68206..bf95f6b817a49c36ceb3b1be4af4ab7ea9eaf19b 100644 (file)
@@ -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 */
index 324c0baf7cda30c0f6123417673dc395c8e292ff..925c944bc0bc4182eb382547e13cb1a10d59123c 100644 (file)
@@ -105,12 +105,14 @@ decode_sattr3(__be32 *p, struct iattr *iap)
                iap->ia_mode = ntohl(*p++);
        }
        if (*p++) {
-               iap->ia_valid |= ATTR_UID;
-               iap->ia_uid = ntohl(*p++);
+               iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++));
+               if (uid_valid(iap->ia_uid))
+                       iap->ia_valid |= ATTR_UID;
        }
        if (*p++) {
-               iap->ia_valid |= ATTR_GID;
-               iap->ia_gid = ntohl(*p++);
+               iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++));
+               if (gid_valid(iap->ia_gid))
+                       iap->ia_valid |= ATTR_GID;
        }
        if (*p++) {
                u64     newsize;
@@ -167,8 +169,8 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
        *p++ = htonl((u32) stat->mode);
        *p++ = htonl((u32) stat->nlink);
-       *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
-       *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+       *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
+       *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
        if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
                p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
        } else {
index 9c51aff02ae28f7b77d2da214a9057da8dc06518..8a50b3c18093b0bc3a6bd04bc80d7767ef8b7ae7 100644 (file)
@@ -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 {
index a1f10c0a62553d0642b02adc7a66bd7a60c0139c..0ce12346df9c8613bd4cac8b6389a454413f893f 100644 (file)
@@ -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,40 @@ 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);
+       if (!uid_valid(*uid))
+               status = nfserr_badowner;
+       return status;
 }
 
 __be32
 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
-               __u32 *id)
+               kgid_t *gid)
 {
-       return do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
+       __be32 status;
+       u32 id = -1;
+       status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
+       *gid = make_kgid(&init_user_ns, id);
+       if (!gid_valid(*gid))
+               status = nfserr_badowner;
+       return status;
 }
 
 int
-nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
+nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name)
 {
+       u32 id = from_kuid(&init_user_ns, uid);
        return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
 }
 
 int
-nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
+nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name)
 {
+       u32 id = from_kgid(&init_user_ns, gid);
        return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
 }
index ba6fdd4a0455d6c2f970e2bb33ec3a5e369dce8d..4914af4a817e34a9aaceb1cbeb865645bf117e30 100644 (file)
@@ -73,8 +73,8 @@ nfs4_save_creds(const struct cred **original_creds)
        if (!new)
                return -ENOMEM;
 
-       new->fsuid = 0;
-       new->fsgid = 0;
+       new->fsuid = GLOBAL_ROOT_UID;
+       new->fsgid = GLOBAL_ROOT_GID;
        *original_creds = override_creds(new);
        put_cred(new);
        return 0;
index 499e957510e704730d74e743bc64d40aff141414..9e7103b6e0ad5edbb611ee8f76367bc8c2f95b62 100644 (file)
@@ -1202,7 +1202,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
        if (g1->ngroups != g2->ngroups)
                return false;
        for (i=0; i<g1->ngroups; i++)
-               if (GROUP_AT(g1, i) != GROUP_AT(g2, i))
+               if (!gid_eq(GROUP_AT(g1, i), GROUP_AT(g2, i)))
                        return false;
        return true;
 }
@@ -1227,8 +1227,8 @@ static bool
 same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 {
        if ((is_gss_cred(cr1) != is_gss_cred(cr2))
-               || (cr1->cr_uid != cr2->cr_uid)
-               || (cr1->cr_gid != cr2->cr_gid)
+               || (!uid_eq(cr1->cr_uid, cr2->cr_uid))
+               || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
                || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
                return false;
        if (cr1->cr_principal == cr2->cr_principal)
index 0dc11586682fd7d93c85790af67bd8d83f6f9002..2d1d06bae3a71f95cba2c103a34e1f6938267da6 100644 (file)
@@ -293,13 +293,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;
                }
@@ -464,9 +464,16 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
                        READ32(dummy);
                        READ_BUF(dummy * 4);
                        if (cbs->flavor == (u32)(-1)) {
-                               cbs->uid = uid;
-                               cbs->gid = gid;
-                               cbs->flavor = RPC_AUTH_UNIX;
+                               kuid_t kuid = make_kuid(&init_user_ns, uid);
+                               kgid_t kgid = make_kgid(&init_user_ns, gid);
+                               if (uid_valid(kuid) && gid_valid(kgid)) {
+                                       cbs->uid = kuid;
+                                       cbs->gid = kgid;
+                                       cbs->flavor = RPC_AUTH_UNIX;
+                               } else {
+                                       dprintk("RPC_AUTH_UNIX with invalid"
+                                               "uid or gid ignoring!\n");
+                               }
                        }
                        break;
                case RPC_AUTH_GSS:
@@ -1926,7 +1933,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;
@@ -1935,10 +1942,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);
@@ -1948,22 +1955,33 @@ 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, ace->whotype, uid, gid, p, buflen);
 }
 
 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
@@ -2224,9 +2242,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)
index 979b421069792abe517a5c210dd47d4418723b11..4201ede0ec910bcd85ecf02cfa27d9da75c94bce 100644 (file)
@@ -100,12 +100,14 @@ decode_sattr(__be32 *p, struct iattr *iap)
                iap->ia_mode = tmp;
        }
        if ((tmp = ntohl(*p++)) != (u32)-1) {
-               iap->ia_valid |= ATTR_UID;
-               iap->ia_uid = tmp;
+               iap->ia_uid = make_kuid(&init_user_ns, tmp);
+               if (uid_valid(iap->ia_uid))
+                       iap->ia_valid |= ATTR_UID;
        }
        if ((tmp = ntohl(*p++)) != (u32)-1) {
-               iap->ia_valid |= ATTR_GID;
-               iap->ia_gid = tmp;
+               iap->ia_gid = make_kgid(&init_user_ns, tmp);
+               if (gid_valid(iap->ia_gid))
+                       iap->ia_valid |= ATTR_GID;
        }
        if ((tmp = ntohl(*p++)) != (u32)-1) {
                iap->ia_valid |= ATTR_SIZE;
@@ -151,8 +153,8 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        *p++ = htonl(nfs_ftypes[type >> 12]);
        *p++ = htonl((u32) stat->mode);
        *p++ = htonl((u32) stat->nlink);
-       *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
-       *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+       *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
+       *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
 
        if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
                *p++ = htonl(NFS_MAXPATHLEN);
index d1c229feed52c129402655ad32f294054f296206..1a8c7391f7aef5a6b83f725816704c7720c21179 100644 (file)
@@ -152,8 +152,8 @@ struct nfsd4_channel_attrs {
 
 struct nfsd4_cb_sec {
        u32     flavor; /* (u32)(-1) used to mean "no valid flavor" */
-       u32     uid;
-       u32     gid;
+       kuid_t  uid;
+       kgid_t  gid;
 };
 
 struct nfsd4_create_session {
index d586117fa94a74f07105055bc053746bfa90bdfb..31ff1d642e310b243585431431c98cc2aaa16c3e 100644 (file)
@@ -401,8 +401,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 
        /* Revoke setuid/setgid on chown */
        if (!S_ISDIR(inode->i_mode) &&
-           (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) ||
-            ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid))) {
+           (((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
+            ((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
                iap->ia_valid |= ATTR_KILL_PRIV;
                if (iap->ia_valid & ATTR_MODE) {
                        /* we're setting mode too, just clear the s*id bits */
@@ -1205,7 +1205,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
         * send along the gid on create when it tries to implement
         * setgid directories via NFS:
         */
-       if (current_fsuid() != 0)
+       if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
                iap->ia_valid &= ~(ATTR_UID|ATTR_GID);
        if (iap->ia_valid)
                return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
@@ -2150,7 +2150,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
         * with NFSv3.
         */
        if ((acc & NFSD_MAY_OWNER_OVERRIDE) &&
-           inode->i_uid == current_fsuid())
+           uid_eq(inode->i_uid, current_fsuid()))
                return 0;
 
        /* This assumes  NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
index 260b16281fc349b216444c4c56b04acf8e04996c..8a404576fb26557eb8578e21f66d0277a94a9e76 100644 (file)
@@ -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;
 }
index 88577eb5d7122f688a50619895e7b43440bb956a..12ae194ac9431ba82755d0d5020a385f25d4afa9 100644 (file)
@@ -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,
index 37d313ede159bdb457667ceacc18fba18cb3999d..0a2924a2d9e6e83d62428fcc975a3ce6d1c5cde4 100644 (file)
@@ -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));
index d89e08a81eda8875fcd59d76c5e1d75827e7d7ac..f87f9bd1edffd44830f27c33301e665be5a5ae05 100644 (file)
@@ -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;
index f1fd0741162b63baeaed44d6f4118a23df7c3c32..04ee1b57c243f01a54e59f4405e282e7c633d575 100644 (file)
@@ -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));
index 30a055049e1662eb382e3ec328918e2cd143c98f..934a4ac3e7fcbaa5405f371df477f06c443a5a0d 100644 (file)
@@ -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;
index eab8c09d3801ca00db98687c49f22b58a633ccc8..c24f1e10b94695e13ba7c576e1e394f81ea43747 100644 (file)
@@ -260,6 +260,7 @@ static struct file_system_type ramfs_fs_type = {
        .name           = "ramfs",
        .mount          = ramfs_mount,
        .kill_sb        = ramfs_kill_sb,
+       .fs_flags       = FS_USERNS_MOUNT,
 };
 static struct file_system_type rootfs_fs_type = {
        .name           = "rootfs",
index 8031d6eef102b71cdf37f2a65202cb4f226f5658..5b8721efa948ec7d93fa7caeb79a535c51e8d69b 100644 (file)
@@ -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, 
index e111fa419a4e3b5670dadc09a40ffa7b6072e09b..7b8fc73810ad83baca0e61e8c843ed4cf75d9d98 100644 (file)
@@ -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 {
index 2dcef3ab58b6f87e7429200d5256eb56541b07f4..0f4b79da65845504c0ffca60a9731b041e21d917 100644 (file)
@@ -36,6 +36,7 @@
 #ifndef NFS_IDMAP_H
 #define NFS_IDMAP_H
 
+#include <linux/uidgid.h>
 #include <uapi/linux/nfs_idmap.h>
 
 
@@ -67,10 +68,10 @@ void nfs_fattr_init_names(struct nfs_fattr *fattr,
 void nfs_fattr_free_names(struct nfs_fattr *);
 void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *);
 
-int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *);
-int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t);
-int nfs_map_gid_to_group(const struct nfs_server *, __u32, char *, size_t);
+int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, kuid_t *);
+int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, kgid_t *);
+int nfs_map_uid_to_name(const struct nfs_server *, kuid_t, char *, size_t);
+int nfs_map_gid_to_group(const struct nfs_server *, kgid_t, char *, size_t);
 
 extern unsigned int nfs_idmap_cache_timeout;
 #endif /* NFS_IDMAP_H */
index 29adb12c7ecffad9b58d6144d742489cb974de80..13441ddac33d50f69d8e7fa073152cc2188df4ba 100644 (file)
@@ -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 {
index 24c139288db4a1b97022780fedcd1d8313903424..7898c997dfea400438f4f9700293f939f38b72ea 100644 (file)
@@ -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;
index f25ba922baaf022dc3814f9705a5fd51749d1422..58fda1c3c783948f4627361eba9bc93a51bde796 100644 (file)
 
 #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 */
 };
index dd74084a9799891309f54db25b8259ae3388f3c8..ff374ab3083902a7052a07b2ca8bb40cf3136338 100644 (file)
@@ -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 */
index b9bd2e6c73ccb51ec8f4fadec473d64bcb689fea..4ce009324933ebc2b048ebd5f834b0c1bf44e52d 100644 (file)
@@ -21,7 +21,7 @@ struct user_namespace {
        struct uid_gid_map      uid_map;
        struct uid_gid_map      gid_map;
        struct uid_gid_map      projid_map;
-       struct kref             kref;
+       atomic_t                count;
        struct user_namespace   *parent;
        kuid_t                  owner;
        kgid_t                  group;
@@ -35,18 +35,18 @@ extern struct user_namespace init_user_ns;
 static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
 {
        if (ns)
-               kref_get(&ns->kref);
+               atomic_inc(&ns->count);
        return ns;
 }
 
 extern int create_user_ns(struct cred *new);
 extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred);
-extern void free_user_ns(struct kref *kref);
+extern void free_user_ns(struct user_namespace *ns);
 
 static inline void put_user_ns(struct user_namespace *ns)
 {
-       if (ns)
-               kref_put(&ns->kref, free_user_ns);
+       if (ns && atomic_dec_and_test(&ns->count))
+               free_user_ns(ns);
 }
 
 struct seq_operations;
index 7184853ca36015c52d8c42573346e4edce41f1c0..27dfe85772b1b28dafddc9b8de40b94b2851532a 100644 (file)
@@ -407,17 +407,17 @@ struct p9_wstat {
        char *gid;
        char *muid;
        char *extension;        /* 9p2000.u extensions */
-       u32 n_uid;              /* 9p2000.u extensions */
-       u32 n_gid;              /* 9p2000.u extensions */
-       u32 n_muid;             /* 9p2000.u extensions */
+       kuid_t n_uid;           /* 9p2000.u extensions */
+       kgid_t n_gid;           /* 9p2000.u extensions */
+       kuid_t n_muid;          /* 9p2000.u extensions */
 };
 
 struct p9_stat_dotl {
        u64 st_result_mask;
        struct p9_qid qid;
        u32 st_mode;
-       u32 st_uid;
-       u32 st_gid;
+       kuid_t st_uid;
+       kgid_t st_gid;
        u64 st_nlink;
        u64 st_rdev;
        u64 st_size;
@@ -471,8 +471,8 @@ struct p9_stat_dotl {
 struct p9_iattr_dotl {
        u32 valid;
        u32 mode;
-       u32 uid;
-       u32 gid;
+       kuid_t uid;
+       kgid_t gid;
        u64 size;
        u64 atime_sec;
        u64 atime_nsec;
index fc9b90b0c05247fcfe2e5faff77dc23df5aea3f5..5ff70f433e873f38f4459f236e80605948251072 100644 (file)
@@ -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);
index 968c539f0ac3ba5abd0f4ab495e16a9ecb4da6bb..0a5e80fb9ba22beef93722f7bfe83ec33d81ee81 100644 (file)
@@ -1032,6 +1032,13 @@ config USER_NS
        help
          This allows containers, i.e. vservers, to use user namespaces
          to provide different user info for different servers.
+
+         When user namespaces are enabled in the kernel it is
+         recommended that the MEMCG and MEMCG_KMEM options also be
+         enabled and that user-space use the memory control groups to
+         limit the amount of memory a memory unprivileged users can
+         use.
+
          If unsure, say N.
 
 config PID_NS
@@ -1060,20 +1067,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
-       depends on CODA_FS = n
-       depends on GFS2_FS = n
-       depends on NCP_FS = n
-       depends on NFSD = n
-       depends on NFS_FS = n
-       depends on OCFS2_FS = n
        depends on XFS_FS = n
 
 config UIDGID_STRICT_TYPE_CHECKS
index 71a3ca18c873938238d03abed6c2cf8bb577d130..023c9867ff435e2020249c61e084f51534c2aee5 100644 (file)
@@ -1383,6 +1383,7 @@ static struct file_system_type mqueue_fs_type = {
        .name = "mqueue",
        .mount = mqueue_mount,
        .kill_sb = kill_litter_super,
+       .fs_flags = FS_USERNS_MOUNT,
 };
 
 int mq_init_ns(struct ipc_namespace *ns)
index 840cfdad7bfcc2a60109a195462decc0684a64bc..2e18d33ca775dc9c5219e9b3a47a6e67f3877d28 100644 (file)
@@ -434,11 +434,12 @@ static DEFINE_MUTEX(reboot_mutex);
 SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                void __user *, arg)
 {
+       struct pid_namespace *pid_ns = task_active_pid_ns(current);
        char buffer[256];
        int ret = 0;
 
        /* We only trust the superuser with rebooting the system. */
-       if (!capable(CAP_SYS_BOOT))
+       if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
                return -EPERM;
 
        /* For safety, we require "magic" arguments. */
@@ -454,7 +455,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
         * pid_namespace, the command is handled by reboot_pid_ns() which will
         * call do_exit().
         */
-       ret = reboot_pid_ns(task_active_pid_ns(current), cmd);
+       ret = reboot_pid_ns(pid_ns, cmd);
        if (ret)
                return ret;
 
index 33acb5e53a5ff0415ad14cae01ea318a92aab6d1..57ebfd42023c373e10392848a73d42af74a37b3b 100644 (file)
@@ -47,9 +47,7 @@ struct user_namespace init_user_ns = {
                        .count = 4294967295U,
                },
        },
-       .kref = {
-               .refcount       = ATOMIC_INIT(3),
-       },
+       .count = ATOMIC_INIT(3),
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
index 2b042c42fbc415b24beb45b095fc6059612de0f8..8b650837083e74f7c8bcac7b4f83081c448e36ed 100644 (file)
@@ -78,7 +78,7 @@ int create_user_ns(struct cred *new)
                return ret;
        }
 
-       kref_init(&ns->kref);
+       atomic_set(&ns->count, 1);
        /* Leave the new->user_ns reference with the new user namespace. */
        ns->parent = parent_ns;
        ns->owner = owner;
@@ -104,15 +104,16 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred)
        return create_user_ns(cred);
 }
 
-void free_user_ns(struct kref *kref)
+void free_user_ns(struct user_namespace *ns)
 {
-       struct user_namespace *parent, *ns =
-               container_of(kref, struct user_namespace, kref);
+       struct user_namespace *parent;
 
-       parent = ns->parent;
-       proc_free_inum(ns->proc_inum);
-       kmem_cache_free(user_ns_cachep, ns);
-       put_user_ns(parent);
+       do {
+               parent = ns->parent;
+               proc_free_inum(ns->proc_inum);
+               kmem_cache_free(user_ns_cachep, ns);
+               ns = parent;
+       } while (atomic_dec_and_test(&parent->count));
 }
 EXPORT_SYMBOL(free_user_ns);
 
@@ -519,6 +520,42 @@ struct seq_operations proc_projid_seq_operations = {
        .show = projid_m_show,
 };
 
+static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent *extent)
+{
+       u32 upper_first, lower_first, upper_last, lower_last;
+       unsigned idx;
+
+       upper_first = extent->first;
+       lower_first = extent->lower_first;
+       upper_last = upper_first + extent->count - 1;
+       lower_last = lower_first + extent->count - 1;
+
+       for (idx = 0; idx < new_map->nr_extents; idx++) {
+               u32 prev_upper_first, prev_lower_first;
+               u32 prev_upper_last, prev_lower_last;
+               struct uid_gid_extent *prev;
+
+               prev = &new_map->extent[idx];
+
+               prev_upper_first = prev->first;
+               prev_lower_first = prev->lower_first;
+               prev_upper_last = prev_upper_first + prev->count - 1;
+               prev_lower_last = prev_lower_first + prev->count - 1;
+
+               /* Does the upper range intersect a previous extent? */
+               if ((prev_upper_first <= upper_last) &&
+                   (prev_upper_last >= upper_first))
+                       return true;
+
+               /* Does the lower range intersect a previous extent? */
+               if ((prev_lower_first <= lower_last) &&
+                   (prev_lower_last >= lower_first))
+                       return true;
+       }
+       return false;
+}
+
+
 static DEFINE_MUTEX(id_map_mutex);
 
 static ssize_t map_write(struct file *file, const char __user *buf,
@@ -531,7 +568,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
        struct user_namespace *ns = seq->private;
        struct uid_gid_map new_map;
        unsigned idx;
-       struct uid_gid_extent *extent, *last = NULL;
+       struct uid_gid_extent *extent = NULL;
        unsigned long page = 0;
        char *kbuf, *pos, *next_line;
        ssize_t ret = -EINVAL;
@@ -634,14 +671,11 @@ static ssize_t map_write(struct file *file, const char __user *buf,
                if ((extent->lower_first + extent->count) <= extent->lower_first)
                        goto out;
 
-               /* For now only accept extents that are strictly in order */
-               if (last &&
-                   (((last->first + last->count) > extent->first) ||
-                    ((last->lower_first + last->count) > extent->lower_first)))
+               /* Do the ranges in extent overlap any previous extents? */
+               if (mappings_overlap(&new_map, extent))
                        goto out;
 
                new_map.nr_extents++;
-               last = extent;
 
                /* Fail if the file contains too many extents */
                if ((new_map.nr_extents == UID_GID_MAP_MAX_EXTENTS) &&
index 1ad79243cb7b9d191efbc9618c5d6526de62bfee..39de1d6a077a451bdba741434acd2fd11122ab9a 100644 (file)
@@ -2778,6 +2778,7 @@ static struct file_system_type shmem_fs_type = {
        .name           = "tmpfs",
        .mount          = shmem_mount,
        .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_USERNS_MOUNT,
 };
 
 int __init shmem_init(void)
@@ -2835,6 +2836,7 @@ static struct file_system_type shmem_fs_type = {
        .name           = "tmpfs",
        .mount          = ramfs_mount,
        .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_USERNS_MOUNT,
 };
 
 int __init shmem_init(void)
index 34d41767093500ba7cda60a2a1990ede456f35bd..8eb75425e6e660a6d087cb2a61890d96138b8106 100644 (file)
@@ -1100,7 +1100,7 @@ void p9_client_begin_disconnect(struct p9_client *clnt)
 EXPORT_SYMBOL(p9_client_begin_disconnect);
 
 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
-       char *uname, u32 n_uname, char *aname)
+       char *uname, kuid_t n_uname, char *aname)
 {
        int err = 0;
        struct p9_req_t *req;
@@ -1117,7 +1117,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
                goto error;
        }
 
-       req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
+       req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid,
                        afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
        if (IS_ERR(req)) {
                err = PTR_ERR(req);
@@ -1270,7 +1270,7 @@ error:
 EXPORT_SYMBOL(p9_client_open);
 
 int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
-               gid_t gid, struct p9_qid *qid)
+               kgid_t gid, struct p9_qid *qid)
 {
        int err = 0;
        struct p9_client *clnt;
@@ -1279,13 +1279,14 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
 
        p9_debug(P9_DEBUG_9P,
                        ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
-                       ofid->fid, name, flags, mode, gid);
+                       ofid->fid, name, flags, mode,
+                       from_kgid(&init_user_ns, gid));
        clnt = ofid->clnt;
 
        if (ofid->mode != -1)
                return -EINVAL;
 
-       req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags,
+       req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags,
                        mode, gid);
        if (IS_ERR(req)) {
                err = PTR_ERR(req);
@@ -1358,7 +1359,7 @@ error:
 }
 EXPORT_SYMBOL(p9_client_fcreate);
 
-int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
+int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, kgid_t gid,
                struct p9_qid *qid)
 {
        int err = 0;
@@ -1369,7 +1370,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
                        dfid->fid, name, symtgt);
        clnt = dfid->clnt;
 
-       req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt,
+       req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt,
                        gid);
        if (IS_ERR(req)) {
                err = PTR_ERR(req);
@@ -1710,7 +1711,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
                (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
                ret->atime, ret->mtime, (unsigned long long)ret->length,
                ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
-               ret->n_uid, ret->n_gid, ret->n_muid);
+               from_kuid(&init_user_ns, ret->n_uid),
+               from_kgid(&init_user_ns, ret->n_gid),
+               from_kuid(&init_user_ns, ret->n_muid));
 
        p9_free_req(clnt, req);
        return ret;
@@ -1764,8 +1767,10 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
                "<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
                "<<< st_gen=%lld st_data_version=%lld",
                ret->st_result_mask, ret->qid.type, ret->qid.path,
-               ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid,
-               ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize,
+               ret->qid.version, ret->st_mode, ret->st_nlink,
+               from_kuid(&init_user_ns, ret->st_uid),
+               from_kgid(&init_user_ns, ret->st_gid),
+               ret->st_rdev, ret->st_size, ret->st_blksize,
                ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec,
                ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec,
                ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
@@ -1828,7 +1833,9 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
                (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
                wst->atime, wst->mtime, (unsigned long long)wst->length,
                wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
-               wst->n_uid, wst->n_gid, wst->n_muid);
+               from_kuid(&init_user_ns, wst->n_uid),
+               from_kgid(&init_user_ns, wst->n_gid),
+               from_kuid(&init_user_ns, wst->n_muid));
 
        req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
        if (IS_ERR(req)) {
@@ -1857,7 +1864,9 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
                "    valid=%x mode=%x uid=%d gid=%d size=%lld\n"
                "    atime_sec=%lld atime_nsec=%lld\n"
                "    mtime_sec=%lld mtime_nsec=%lld\n",
-               p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid,
+               p9attr->valid, p9attr->mode,
+               from_kuid(&init_user_ns, p9attr->uid),
+               from_kgid(&init_user_ns, p9attr->gid),
                p9attr->size, p9attr->atime_sec, p9attr->atime_nsec,
                p9attr->mtime_sec, p9attr->mtime_nsec);
 
@@ -2106,7 +2115,7 @@ error:
 EXPORT_SYMBOL(p9_client_readdir);
 
 int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
-                       dev_t rdev, gid_t gid, struct p9_qid *qid)
+                       dev_t rdev, kgid_t gid, struct p9_qid *qid)
 {
        int err;
        struct p9_client *clnt;
@@ -2116,7 +2125,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
                "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
-       req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode,
+       req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode,
                MAJOR(rdev), MINOR(rdev), gid);
        if (IS_ERR(req))
                return PTR_ERR(req);
@@ -2137,7 +2146,7 @@ error:
 EXPORT_SYMBOL(p9_client_mknod_dotl);
 
 int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
-                               gid_t gid, struct p9_qid *qid)
+                               kgid_t gid, struct p9_qid *qid)
 {
        int err;
        struct p9_client *clnt;
@@ -2146,8 +2155,8 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
        err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
-                fid->fid, name, mode, gid);
-       req = p9_client_rpc(clnt, P9_TMKDIR, "dsdd", fid->fid, name, mode,
+                fid->fid, name, mode, from_kgid(&init_user_ns, gid));
+       req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode,
                gid);
        if (IS_ERR(req))
                return PTR_ERR(req);
index 3d33ecf133271426aec0df569c5b2a4e8eb03a8a..ab9127ec5b7a6881e7dd2116e49819186675562f 100644 (file)
@@ -85,6 +85,8 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
        d - int32_t
        q - int64_t
        s - string
+       u - numeric uid
+       g - numeric gid
        S - stat
        Q - qid
        D - data blob (int32_t size followed by void *, results are not freed)
@@ -163,6 +165,26 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                        (*sptr)[len] = 0;
                        }
                        break;
+               case 'u': {
+                               kuid_t *uid = va_arg(ap, kuid_t *);
+                               __le32 le_val;
+                               if (pdu_read(pdu, &le_val, sizeof(le_val))) {
+                                       errcode = -EFAULT;
+                                       break;
+                               }
+                               *uid = make_kuid(&init_user_ns,
+                                                le32_to_cpu(le_val));
+                       } break;
+               case 'g': {
+                               kgid_t *gid = va_arg(ap, kgid_t *);
+                               __le32 le_val;
+                               if (pdu_read(pdu, &le_val, sizeof(le_val))) {
+                                       errcode = -EFAULT;
+                                       break;
+                               }
+                               *gid = make_kgid(&init_user_ns,
+                                                le32_to_cpu(le_val));
+                       } break;
                case 'Q':{
                                struct p9_qid *qid =
                                    va_arg(ap, struct p9_qid *);
@@ -177,11 +199,12 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                    va_arg(ap, struct p9_wstat *);
 
                                memset(stbuf, 0, sizeof(struct p9_wstat));
-                               stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
-                                                                       -1;
+                               stbuf->n_uid = stbuf->n_muid = INVALID_UID;
+                               stbuf->n_gid = INVALID_GID;
+
                                errcode =
                                    p9pdu_readf(pdu, proto_version,
-                                               "wwdQdddqssss?sddd",
+                                               "wwdQdddqssss?sugu",
                                                &stbuf->size, &stbuf->type,
                                                &stbuf->dev, &stbuf->qid,
                                                &stbuf->mode, &stbuf->atime,
@@ -294,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                memset(stbuf, 0, sizeof(struct p9_stat_dotl));
                                errcode =
                                    p9pdu_readf(pdu, proto_version,
-                                       "qQdddqqqqqqqqqqqqqqq",
+                                       "qQdugqqqqqqqqqqqqqqq",
                                        &stbuf->st_result_mask,
                                        &stbuf->qid,
                                        &stbuf->st_mode,
@@ -377,6 +400,20 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                        errcode = -EFAULT;
                        }
                        break;
+               case 'u': {
+                               kuid_t uid = va_arg(ap, kuid_t);
+                               __le32 val = cpu_to_le32(
+                                               from_kuid(&init_user_ns, uid));
+                               if (pdu_write(pdu, &val, sizeof(val)))
+                                       errcode = -EFAULT;
+                       } break;
+               case 'g': {
+                               kgid_t gid = va_arg(ap, kgid_t);
+                               __le32 val = cpu_to_le32(
+                                               from_kgid(&init_user_ns, gid));
+                               if (pdu_write(pdu, &val, sizeof(val)))
+                                       errcode = -EFAULT;
+                       } break;
                case 'Q':{
                                const struct p9_qid *qid =
                                    va_arg(ap, const struct p9_qid *);
@@ -390,7 +427,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                    va_arg(ap, const struct p9_wstat *);
                                errcode =
                                    p9pdu_writef(pdu, proto_version,
-                                                "wwdQdddqssss?sddd",
+                                                "wwdQdddqssss?sugu",
                                                 stbuf->size, stbuf->type,
                                                 stbuf->dev, &stbuf->qid,
                                                 stbuf->mode, stbuf->atime,
@@ -468,7 +505,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
                                                        struct p9_iattr_dotl *);
 
                                errcode = p9pdu_writef(pdu, proto_version,
-                                                       "ddddqqqqq",
+                                                       "ddugqqqqq",
                                                        p9attr->valid,
                                                        p9attr->mode,
                                                        p9attr->uid,
index ee71ea26777ae892fafd13a8338b3f556d9f427b..1deb29af82fd2b10a2b578c4a11c362fa83d4ecf 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/slab.h>
 #include <linux/statfs.h>
 #include <linux/string.h>
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
 
 
 #include <linux/ceph/ceph_features.h>
@@ -292,6 +294,9 @@ ceph_parse_options(char *options, const char *dev_name,
        int err = -ENOMEM;
        substring_t argstr[MAX_OPT_ARGS];
 
+       if (current->nsproxy->net_ns != &init_net)
+               return ERR_PTR(-EINVAL);
+
        opt = kzalloc(sizeof(*opt), GFP_KERNEL);
        if (!opt)
                return ERR_PTR(-ENOMEM);
index b5c067bccc4595204f21bff24bbf16631e54cad4..392adc41e2e58c09fd34e7872bd39b091cbda096 100644 (file)
@@ -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",
index 6ed6f201b022aae4c2b01b97b21dd9bdeddbed2f..b6badafc6494767c68ae6bf2a5a35ae287707ccf 100644 (file)
@@ -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;
 
index 911ef008b70155b2fcb17dd3d590e770aa676f12..6ea29f4ed6c00b433eb3cf00fdb67c2559daeb37 100644 (file)
@@ -255,7 +255,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;
@@ -302,11 +302,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);
@@ -394,8 +394,11 @@ gss_upcall_callback(struct rpc_task *task)
 
 static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
 {
-       gss_msg->msg.data = &gss_msg->uid;
-       gss_msg->msg.len = sizeof(gss_msg->uid);
+       uid_t uid = from_kuid(&init_user_ns, gss_msg->uid);
+       memcpy(gss_msg->databuf, &uid, sizeof(uid));
+       gss_msg->msg.data = gss_msg->databuf;
+       gss_msg->msg.len = sizeof(uid);
+       BUG_ON(sizeof(uid) > UPCALL_BUF_LEN);
 }
 
 static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
@@ -408,7 +411,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);
@@ -444,7 +447,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;
@@ -474,7 +477,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))
@@ -516,7 +519,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
@@ -548,7 +551,8 @@ gss_refresh_upcall(struct rpc_task *task)
        gss_release_msg(gss_msg);
 out:
        dprintk("RPC: %5u %s for uid %u result %d\n",
-               task->tk_pid, __func__, cred->cr_uid, err);
+               task->tk_pid, __func__,
+               from_kuid(&init_user_ns, cred->cr_uid), err);
        return err;
 }
 
@@ -561,7 +565,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) {
@@ -603,7 +608,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;
 }
 
@@ -617,7 +622,8 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        struct gss_upcall_msg *gss_msg;
        struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe;
        struct gss_cl_ctx *ctx;
-       uid_t uid;
+       uid_t id;
+       kuid_t uid;
        ssize_t err = -EFBIG;
 
        if (mlen > MSG_BUF_MAXSIZE)
@@ -632,12 +638,18 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
                goto err;
 
        end = (const void *)((char *)buf + mlen);
-       p = simple_get_bytes(buf, end, &uid, sizeof(uid));
+       p = simple_get_bytes(buf, end, &id, sizeof(id));
        if (IS_ERR(p)) {
                err = PTR_ERR(p);
                goto err;
        }
 
+       uid = make_kuid(&init_user_ns, id);
+       if (!uid_valid(uid)) {
+               err = -EINVAL;
+               goto err;
+       }
+
        err = -ENOMEM;
        ctx = gss_alloc_context();
        if (ctx == NULL)
@@ -1058,7 +1070,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        int err = -ENOMEM;
 
        dprintk("RPC:       %s for uid %d, flavor %d\n",
-               __func__, acred->uid, auth->au_flavor);
+               __func__, from_kuid(&init_user_ns, acred->uid),
+               auth->au_flavor);
 
        if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
                goto out_err;
@@ -1114,7 +1127,7 @@ out:
        }
        if (gss_cred->gc_principal != NULL)
                return 0;
-       return rc->cr_uid == acred->uid;
+       return uid_eq(rc->cr_uid, acred->uid);
 }
 
 /*
index 73e95738660042e7a9d4e7cb252143ec74078265..ecd1d58bf611389ad283e77fd86977d97b2180fc 100644 (file)
@@ -418,6 +418,7 @@ static int rsc_parse(struct cache_detail *cd,
 {
        /* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */
        char *buf = mesg;
+       int id;
        int len, rv;
        struct rsc rsci, *rscp = NULL;
        time_t expiry;
@@ -444,7 +445,7 @@ static int rsc_parse(struct cache_detail *cd,
                goto out;
 
        /* uid, or NEGATIVE */
-       rv = get_int(&mesg, &rsci.cred.cr_uid);
+       rv = get_int(&mesg, &id);
        if (rv == -EINVAL)
                goto out;
        if (rv == -ENOENT)
@@ -452,8 +453,16 @@ static int rsc_parse(struct cache_detail *cd,
        else {
                int N, i;
 
+               /* uid */
+               rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
+               if (!uid_valid(rsci.cred.cr_uid))
+                       goto out;
+
                /* gid */
-               if (get_int(&mesg, &rsci.cred.cr_gid))
+               if (get_int(&mesg, &id))
+                       goto out;
+               rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
+               if (!gid_valid(rsci.cred.cr_gid))
                        goto out;
 
                /* number of additional gid's */
@@ -467,11 +476,10 @@ static int rsc_parse(struct cache_detail *cd,
                /* gid's */
                status = -EINVAL;
                for (i=0; i<N; i++) {
-                       gid_t gid;
                        kgid_t kgid;
-                       if (get_int(&mesg, &gid))
+                       if (get_int(&mesg, &id))
                                goto out;
-                       kgid = make_kgid(&init_user_ns, gid);
+                       kgid = make_kgid(&init_user_ns, id);
                        if (!gid_valid(kgid))
                                goto out;
                        GROUP_AT(rsci.cred.cr_group_info, i) = kgid;
index 52c5abdee211cde762075809a09ca2d849ddeca3..dc37021fc3e5c96c87a35e902a382562d47bfa02 100644 (file)
@@ -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 */
 
index 4d012920373345ccb7b76957e792900c143505e9..a1852e19ed0ced5297189dc5b5171217cc4c33e9 100644 (file)
@@ -415,10 +415,15 @@ 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;
 };
 
+static int unix_gid_hash(kuid_t uid)
+{
+       return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
+}
+
 static void unix_gid_put(struct kref *kref)
 {
        struct cache_head *item = container_of(kref, struct cache_head, ref);
@@ -433,7 +438,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 +470,7 @@ static void unix_gid_request(struct cache_detail *cd,
        char tuid[20];
        struct unix_gid *ug = container_of(h, struct unix_gid, h);
 
-       snprintf(tuid, 20, "%u", ug->uid);
+       snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
        qword_add(bpp, blen, tuid);
        (*bpp)[-1] = '\n';
 }
@@ -475,13 +480,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 +499,12 @@ static int unix_gid_parse(struct cache_detail *cd,
                return -EINVAL;
        mesg[mlen-1] = 0;
 
-       rv = get_int(&mesg, &uid);
+       rv = get_int(&mesg, &id);
        if (rv)
                return -EINVAL;
+       uid = make_kuid(&init_user_ns, id);
+       if (!uid_valid(uid))
+               return -EINVAL;
        ug.uid = uid;
 
        expiry = get_expiry(&mesg);
@@ -530,7 +539,7 @@ static int unix_gid_parse(struct cache_detail *cd,
                ug.h.expiry_time = expiry;
                ch = sunrpc_cache_update(cd,
                                         &ug.h, &ugp->h,
-                                        hash_long(uid, GID_HASHBITS));
+                                        unix_gid_hash(uid));
                if (!ch)
                        err = -ENOMEM;
                else {
@@ -549,7 +558,7 @@ static int unix_gid_show(struct seq_file *m,
                         struct cache_detail *cd,
                         struct cache_head *h)
 {
-       struct user_namespace *user_ns = current_user_ns();
+       struct user_namespace *user_ns = &init_user_ns;
        struct unix_gid *ug;
        int i;
        int glen;
@@ -565,7 +574,7 @@ static int unix_gid_show(struct seq_file *m,
        else
                glen = 0;
 
-       seq_printf(m, "%u %d:", ug->uid, glen);
+       seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
        for (i = 0; i < glen; i++)
                seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i)));
        seq_printf(m, "\n");
@@ -615,20 +624,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, unix_gid_hash(uid));
        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 +759,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 +821,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
        argv->iov_len -= slen*4;
 
-       cred->cr_uid = svc_getnl(argv);         /* uid */
-       cred->cr_gid = svc_getnl(argv);         /* gid */
+       cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
+       cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
+       if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid))
+               goto badcred;
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > 16 || (len -= (slen + 2)*4) < 0)
                goto badcred;