diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 301631c..62dcf63 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -2,7 +2,11 @@ Version 1.49 ------------ IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6 address after the "ip=" mount option, at least until mount.cifs is fixed to -handle DNS host to ipv6 name translation). +handle DNS host to ipv6 name translation). Accept override of uid or gid +on mount even when Unix Extensions are negotiated (it used to be ignored +when Unix Extensions were ignored). This allows users to override the +default uid and gid for files when they are certain that the uids or +gids on the server do not match those of the client. Version 1.48 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index 080c5eb..93fe359 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -257,13 +257,19 @@ A partial list of the supported mount op mount. domain Set the SMB/CIFS workgroup name prepended to the username during CIFS session establishment - uid If CIFS Unix extensions are not supported by the server - this overrides the default uid for inodes. For mounts to - servers which do support the CIFS Unix extensions, such - as a properly configured Samba server, the server provides - the uid, gid and mode. For servers which do not support - the Unix extensions, the default uid (and gid) returned on - lookup of existing files is the uid (gid) of the person + uid Set the default uid for inodes. For mounts to servers + which do support the CIFS Unix extensions, such as a + properly configured Samba server, the server provides + the uid, gid and mode so this parameter should not be + specified unless the server and clients uid and gid + numbering differ. If the server and client are in the + same domain (e.g. running winbind or nss_ldap) and + the server supports the Unix Extensions then the uid + and gid can be retrieved from the server (and uid + and gid would not have to be specifed on the mount. + For servers which do not support the CIFS Unix + extensions, the default uid (and gid) returned on lookup + of existing files will be the uid (gid) of the person who executed the mount (root, except when mount.cifs is configured setuid for user mounts) unless the "uid=" (gid) mount option is specified. For the uid (gid) of newly @@ -281,8 +287,7 @@ A partial list of the supported mount op the client. Note that the mount.cifs helper must be at version 1.10 or higher to support specifying the uid (or gid) in non-numberic form. - gid If CIFS Unix extensions are not supported by the server - this overrides the default gid for inodes. + gid Set the default gid for inodes (similar to above). file_mode If CIFS Unix extensions are not supported by the server this overrides the default mode for file inodes. dir_mode If CIFS Unix extensions are not supported by the server diff --git a/fs/cifs/TODO b/fs/cifs/TODO index b70a69b..78b620e 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -80,7 +80,7 @@ need to add ability to set time to serve u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too) -v) mount check for unmatched uids - and uid override +v) mount check for unmatched uids w) Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index fd1e52e..4cc2012 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -22,12 +22,14 @@ #define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */ #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ -#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ -#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ -#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ -#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ -#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ -#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ +#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ +#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ +#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible*/ +#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ +#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ +#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ +#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ +#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index dd03e68..24eb0c5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -306,6 +306,14 @@ cifs_show_options(struct seq_file *s, st cifs_sb->tcon->ses->domainName); } } + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) + seq_printf(s, ",posixpaths"); + if((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || + !(cifs_sb->tcon->ses->capabilities & CAP_UNIX)) + seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); + if((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || + !(cifs_sb->tcon->ses->capabilities & CAP_UNIX)) + seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); seq_printf(s, ",rsize=%d",cifs_sb->rsize); seq_printf(s, ",wsize=%d",cifs_sb->wsize); } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c1af159..a7c6c35 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -75,6 +75,8 @@ struct smb_vol { unsigned retry:1; unsigned intr:1; unsigned setuids:1; + unsigned override_uid:1; + unsigned override_gid:1; unsigned noperm:1; unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ unsigned cifs_acl:1; @@ -1042,11 +1044,13 @@ cifs_parse_mount_options(char *options, if (value && *value) { vol->linux_uid = simple_strtoul(value, &value, 0); + vol->override_uid = 1; } } else if (strnicmp(data, "gid", 3) == 0) { if (value && *value) { vol->linux_gid = simple_strtoul(value, &value, 0); + vol->override_gid = 1; } } else if (strnicmp(data, "file_mode", 4) == 0) { if (value && *value) { @@ -1989,7 +1993,10 @@ cifs_mount(struct super_block *sb, struc cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; if(volume_info.cifs_acl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; - + if(volume_info.override_uid) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; + if(volume_info.override_gid) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; if(volume_info.direct_io) { cFYI(1,("mounting share using direct i/o")); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f74f37c..fe5d326 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -139,8 +139,17 @@ int cifs_get_inode_info_unix(struct inod inode->i_mode |= S_IFREG; cFYI(1,("unknown type %d",type)); } - inode->i_uid = le64_to_cpu(findData.Uid); - inode->i_gid = le64_to_cpu(findData.Gid); + + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) + inode->i_uid = cifs_sb->mnt_uid; + else + inode->i_uid = le64_to_cpu(findData.Uid); + + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) + inode->i_gid = cifs_sb->mnt_gid; + else + inode->i_gid = le64_to_cpu(findData.Gid); + inode->i_nlink = le64_to_cpu(findData.Nlinks); spin_lock(&inode->i_lock); @@ -523,6 +532,8 @@ int cifs_get_inode_info(struct inode **p or retrieve from NTFS stream extended attribute */ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { /* fill in uid, gid, mode from server ACL */ + /* BB FIXME this should also take into account the + * default uid specified on mount if present */ get_sfu_uid_mode(inode, search_path, cifs_sb, xid); } else if (atomic_read(&cifsInfo->inUse) == 0) { inode->i_uid = cifs_sb->mnt_uid; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b80b0fc..24d3133 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -357,8 +357,14 @@ static void unix_fill_in_inode(struct in cFYI(1,("unknown inode type %d",type)); } - tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); - tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) + tmp_inode->i_uid = cifs_sb->mnt_uid; + else + tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) + tmp_inode->i_gid = cifs_sb->mnt_gid; + else + tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); spin_lock(&tmp_inode->i_lock); @@ -382,7 +388,6 @@ static void unix_fill_in_inode(struct in tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; else tmp_inode->i_fop = &cifs_file_direct_ops; - } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) tmp_inode->i_fop = &cifs_file_nobrl_ops; else