aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
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/cifs/file.c
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/cifs/file.c')
-rw-r--r--fs/cifs/file.c33
1 files changed, 25 insertions, 8 deletions
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;