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

Jeff Layton
2012-11-25T12:47:38Z

On Tue, 20 Nov 2012 04:43:32 -0800
"Eric W. Biederman" <ebiederm@xmission.com> wrote:

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

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

--
Jeff Layton <jlayton@redhat.com>