aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-09-29 19:51:11 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-06 12:12:59 -0400
commit6508d904e6fb66ce4c34617f72b38d6714c4b9f6 (patch)
treea5d24f696c9a9045c3880671eeb5fbc6ca9f61ab /fs
parent13cfb7334eb6fd0fc06da5589aea1e947791f1d6 (diff)
cifs: have find_readable/writable_file filter by fsuid
When we implement multiuser mounts, we'll need to filter filehandles by fsuid. Add a flag for multiuser mounts and code to filter by fsuid when it's set. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_fs_sb.h3
-rw-r--r--fs/cifs/cifsacl.c4
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/dir.c1
-rw-r--r--fs/cifs/file.c33
-rw-r--r--fs/cifs/inode.c6
6 files changed, 35 insertions, 16 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ba0afd3acff4..e04e6923d354 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -37,6 +37,7 @@
37#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ 37#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
38#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ 38#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
39#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ 39#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
40#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
40 41
41struct cifs_sb_info { 42struct cifs_sb_info {
42 struct cifsTconInfo *ptcon; /* primary mount */ 43 struct cifsTconInfo *ptcon; /* primary mount */
@@ -48,7 +49,7 @@ struct cifs_sb_info {
48 gid_t mnt_gid; 49 gid_t mnt_gid;
49 mode_t mnt_file_mode; 50 mode_t mnt_file_mode;
50 mode_t mnt_dir_mode; 51 mode_t mnt_dir_mode;
51 int mnt_cifs_flags; 52 unsigned int mnt_cifs_flags;
52 int prepathlen; 53 int prepathlen;
53 char *prepath; /* relative path under the share to mount to */ 54 char *prepath; /* relative path under the share to mount to */
54#ifdef CONFIG_CIFS_DFS_UPCALL 55#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 2647ea410c4c..c9b4792ae825 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -615,7 +615,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
615 struct cifsFileInfo *open_file = NULL; 615 struct cifsFileInfo *open_file = NULL;
616 616
617 if (inode) 617 if (inode)
618 open_file = find_readable_file(CIFS_I(inode)); 618 open_file = find_readable_file(CIFS_I(inode), true);
619 if (!open_file) 619 if (!open_file)
620 return get_cifs_acl_by_path(cifs_sb, path, pacllen); 620 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
621 621
@@ -685,7 +685,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
685 685
686 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode); 686 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
687 687
688 open_file = find_readable_file(CIFS_I(inode)); 688 open_file = find_readable_file(CIFS_I(inode), true);
689 if (!open_file) 689 if (!open_file)
690 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen); 690 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
691 691
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7294723d0625..29a2ee8ae51f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -78,9 +78,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
78extern bool is_valid_oplock_break(struct smb_hdr *smb, 78extern bool is_valid_oplock_break(struct smb_hdr *smb,
79 struct TCP_Server_Info *); 79 struct TCP_Server_Info *);
80extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); 80extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
81extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); 81extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
82#ifdef CONFIG_CIFS_EXPERIMENTAL 82#ifdef CONFIG_CIFS_EXPERIMENTAL
83extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); 83extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
84#endif 84#endif
85extern unsigned int smbCalcSize(struct smb_hdr *ptr); 85extern unsigned int smbCalcSize(struct smb_hdr *ptr);
86extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); 86extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 5adf47f28fed..e249b561ce8f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -144,6 +144,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
144 144
145 pCifsFile->netfid = fileHandle; 145 pCifsFile->netfid = fileHandle;
146 pCifsFile->pid = current->tgid; 146 pCifsFile->pid = current->tgid;
147 pCifsFile->uid = current_fsuid();
147 pCifsFile->pInode = igrab(newinode); 148 pCifsFile->pInode = igrab(newinode);
148 pCifsFile->mnt = mnt; 149 pCifsFile->mnt = mnt;
149 pCifsFile->pfile = file; 150 pCifsFile->pfile = file;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 24332d437150..80856f180711 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1168,9 +1168,15 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1168} 1168}
1169 1169
1170#ifdef CONFIG_CIFS_EXPERIMENTAL 1170#ifdef CONFIG_CIFS_EXPERIMENTAL
1171struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) 1171struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1172 bool fsuid_only)
1172{ 1173{
1173 struct cifsFileInfo *open_file = NULL; 1174 struct cifsFileInfo *open_file = NULL;
1175 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1176
1177 /* only filter by fsuid on multiuser mounts */
1178 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1179 fsuid_only = false;
1174 1180
1175 read_lock(&GlobalSMBSeslock); 1181 read_lock(&GlobalSMBSeslock);
1176 /* we could simply get the first_list_entry since write-only entries 1182 /* we could simply get the first_list_entry since write-only entries
@@ -1179,6 +1185,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
1179 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1185 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1180 if (open_file->closePend) 1186 if (open_file->closePend)
1181 continue; 1187 continue;
1188 if (fsuid_only && open_file->uid != current_fsuid())
1189 continue;
1182 if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) || 1190 if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
1183 (open_file->pfile->f_flags & O_RDONLY))) { 1191 (open_file->pfile->f_flags & O_RDONLY))) {
1184 if (!open_file->invalidHandle) { 1192 if (!open_file->invalidHandle) {
@@ -1198,9 +1206,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
1198} 1206}
1199#endif 1207#endif
1200 1208
1201struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) 1209struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1210 bool fsuid_only)
1202{ 1211{
1203 struct cifsFileInfo *open_file; 1212 struct cifsFileInfo *open_file;
1213 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1204 bool any_available = false; 1214 bool any_available = false;
1205 int rc; 1215 int rc;
1206 1216
@@ -1214,13 +1224,19 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1214 return NULL; 1224 return NULL;
1215 } 1225 }
1216 1226
1227 /* only filter by fsuid on multiuser mounts */
1228 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1229 fsuid_only = false;
1230
1217 read_lock(&GlobalSMBSeslock); 1231 read_lock(&GlobalSMBSeslock);
1218refind_writable: 1232refind_writable:
1219 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1233 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1220 if (open_file->closePend || 1234 if (open_file->closePend)
1221 (!any_available && open_file->pid != current->tgid)) 1235 continue;
1236 if (!any_available && open_file->pid != current->tgid)
1237 continue;
1238 if (fsuid_only && open_file->uid != current_fsuid())
1222 continue; 1239 continue;
1223
1224 if (open_file->pfile && 1240 if (open_file->pfile &&
1225 ((open_file->pfile->f_flags & O_RDWR) || 1241 ((open_file->pfile->f_flags & O_RDWR) ||
1226 (open_file->pfile->f_flags & O_WRONLY))) { 1242 (open_file->pfile->f_flags & O_WRONLY))) {
@@ -1315,7 +1331,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1315 if (mapping->host->i_size - offset < (loff_t)to) 1331 if (mapping->host->i_size - offset < (loff_t)to)
1316 to = (unsigned)(mapping->host->i_size - offset); 1332 to = (unsigned)(mapping->host->i_size - offset);
1317 1333
1318 open_file = find_writable_file(CIFS_I(mapping->host)); 1334 open_file = find_writable_file(CIFS_I(mapping->host), false);
1319 if (open_file) { 1335 if (open_file) {
1320 bytes_written = cifs_write(open_file->pfile, write_data, 1336 bytes_written = cifs_write(open_file->pfile, write_data,
1321 to-from, &offset); 1337 to-from, &offset);
@@ -1388,7 +1404,7 @@ static int cifs_writepages(struct address_space *mapping,
1388 * but it'll at least handle the return. Maybe it should be 1404 * but it'll at least handle the return. Maybe it should be
1389 * a BUG() instead? 1405 * a BUG() instead?
1390 */ 1406 */
1391 open_file = find_writable_file(CIFS_I(mapping->host)); 1407 open_file = find_writable_file(CIFS_I(mapping->host), false);
1392 if (!open_file) { 1408 if (!open_file) {
1393 kfree(iov); 1409 kfree(iov);
1394 return generic_writepages(mapping, wbc); 1410 return generic_writepages(mapping, wbc);
@@ -1505,7 +1521,8 @@ retry:
1505 break; 1521 break;
1506 } 1522 }
1507 if (n_iov) { 1523 if (n_iov) {
1508 open_file = find_writable_file(CIFS_I(mapping->host)); 1524 open_file = find_writable_file(CIFS_I(mapping->host),
1525 false);
1509 if (!open_file) { 1526 if (!open_file) {
1510 cERROR(1, "No writable handles for inode"); 1527 cERROR(1, "No writable handles for inode");
1511 rc = -EBADF; 1528 rc = -EBADF;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a39a1c451733..df29a3a3d80c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -963,7 +963,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
963 /* 963 /*
964 * If the file is already open for write, just use that fileid 964 * If the file is already open for write, just use that fileid
965 */ 965 */
966 open_file = find_writable_file(cifsInode); 966 open_file = find_writable_file(cifsInode, true);
967 if (open_file) { 967 if (open_file) {
968 netfid = open_file->netfid; 968 netfid = open_file->netfid;
969 netpid = open_file->pid; 969 netpid = open_file->pid;
@@ -1813,7 +1813,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1813 * writebehind data than the SMB timeout for the SetPathInfo 1813 * writebehind data than the SMB timeout for the SetPathInfo
1814 * request would allow 1814 * request would allow
1815 */ 1815 */
1816 open_file = find_writable_file(cifsInode); 1816 open_file = find_writable_file(cifsInode, true);
1817 if (open_file) { 1817 if (open_file) {
1818 __u16 nfid = open_file->netfid; 1818 __u16 nfid = open_file->netfid;
1819 __u32 npid = open_file->pid; 1819 __u32 npid = open_file->pid;
@@ -1978,7 +1978,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1978 args->ctime = NO_CHANGE_64; 1978 args->ctime = NO_CHANGE_64;
1979 1979
1980 args->device = 0; 1980 args->device = 0;
1981 open_file = find_writable_file(cifsInode); 1981 open_file = find_writable_file(cifsInode, true);
1982 if (open_file) { 1982 if (open_file) {
1983 u16 nfid = open_file->netfid; 1983 u16 nfid = open_file->netfid;
1984 u32 npid = open_file->pid; 1984 u32 npid = open_file->pid;