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