diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-09-29 19:51:11 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-06 12:12:59 -0400 |
commit | 6508d904e6fb66ce4c34617f72b38d6714c4b9f6 (patch) | |
tree | a5d24f696c9a9045c3880671eeb5fbc6ca9f61ab /fs | |
parent | 13cfb7334eb6fd0fc06da5589aea1e947791f1d6 (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.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
-rw-r--r-- | fs/cifs/dir.c | 1 | ||||
-rw-r--r-- | fs/cifs/file.c | 33 | ||||
-rw-r--r-- | fs/cifs/inode.c | 6 |
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 | ||
41 | struct cifs_sb_info { | 42 | struct 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); | |||
78 | extern bool is_valid_oplock_break(struct smb_hdr *smb, | 78 | extern bool is_valid_oplock_break(struct smb_hdr *smb, |
79 | struct TCP_Server_Info *); | 79 | struct TCP_Server_Info *); |
80 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 80 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
81 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); | 81 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
82 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 82 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
83 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); | 83 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
84 | #endif | 84 | #endif |
85 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 85 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
86 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 86 | extern 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 |
1171 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) | 1171 | struct 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 | ||
1201 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | 1209 | struct 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); |
1218 | refind_writable: | 1232 | refind_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; |