mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-23 05:47:53 +07:00
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>
This commit is contained in:
parent
13cfb7334e
commit
6508d904e6
@ -37,6 +37,7 @@
|
|||||||
#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
|
#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
|
||||||
#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
|
#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
|
||||||
#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
|
#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
|
||||||
|
#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
|
||||||
|
|
||||||
struct cifs_sb_info {
|
struct cifs_sb_info {
|
||||||
struct cifsTconInfo *ptcon; /* primary mount */
|
struct cifsTconInfo *ptcon; /* primary mount */
|
||||||
@ -48,7 +49,7 @@ struct cifs_sb_info {
|
|||||||
gid_t mnt_gid;
|
gid_t mnt_gid;
|
||||||
mode_t mnt_file_mode;
|
mode_t mnt_file_mode;
|
||||||
mode_t mnt_dir_mode;
|
mode_t mnt_dir_mode;
|
||||||
int mnt_cifs_flags;
|
unsigned int mnt_cifs_flags;
|
||||||
int prepathlen;
|
int prepathlen;
|
||||||
char *prepath; /* relative path under the share to mount to */
|
char *prepath; /* relative path under the share to mount to */
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
|
@ -615,7 +615,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|||||||
struct cifsFileInfo *open_file = NULL;
|
struct cifsFileInfo *open_file = NULL;
|
||||||
|
|
||||||
if (inode)
|
if (inode)
|
||||||
open_file = find_readable_file(CIFS_I(inode));
|
open_file = find_readable_file(CIFS_I(inode), true);
|
||||||
if (!open_file)
|
if (!open_file)
|
||||||
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
|
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
|
||||||
|
|
||||||
@ -685,7 +685,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|||||||
|
|
||||||
cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
|
cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
|
||||||
|
|
||||||
open_file = find_readable_file(CIFS_I(inode));
|
open_file = find_readable_file(CIFS_I(inode), true);
|
||||||
if (!open_file)
|
if (!open_file)
|
||||||
return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
|
return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
|
|||||||
extern bool is_valid_oplock_break(struct smb_hdr *smb,
|
extern bool is_valid_oplock_break(struct smb_hdr *smb,
|
||||||
struct TCP_Server_Info *);
|
struct TCP_Server_Info *);
|
||||||
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
|
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
|
||||||
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
|
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
|
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
|
||||||
#endif
|
#endif
|
||||||
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
||||||
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||||
|
@ -144,6 +144,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
|
|||||||
|
|
||||||
pCifsFile->netfid = fileHandle;
|
pCifsFile->netfid = fileHandle;
|
||||||
pCifsFile->pid = current->tgid;
|
pCifsFile->pid = current->tgid;
|
||||||
|
pCifsFile->uid = current_fsuid();
|
||||||
pCifsFile->pInode = igrab(newinode);
|
pCifsFile->pInode = igrab(newinode);
|
||||||
pCifsFile->mnt = mnt;
|
pCifsFile->mnt = mnt;
|
||||||
pCifsFile->pfile = file;
|
pCifsFile->pfile = file;
|
||||||
|
@ -1168,9 +1168,15 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
|
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||||
|
bool fsuid_only)
|
||||||
{
|
{
|
||||||
struct cifsFileInfo *open_file = NULL;
|
struct cifsFileInfo *open_file = NULL;
|
||||||
|
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
|
||||||
|
|
||||||
|
/* only filter by fsuid on multiuser mounts */
|
||||||
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
|
||||||
|
fsuid_only = false;
|
||||||
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
/* we could simply get the first_list_entry since write-only entries
|
/* 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)
|
|||||||
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
||||||
if (open_file->closePend)
|
if (open_file->closePend)
|
||||||
continue;
|
continue;
|
||||||
|
if (fsuid_only && open_file->uid != current_fsuid())
|
||||||
|
continue;
|
||||||
if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
|
if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
|
||||||
(open_file->pfile->f_flags & O_RDONLY))) {
|
(open_file->pfile->f_flags & O_RDONLY))) {
|
||||||
if (!open_file->invalidHandle) {
|
if (!open_file->invalidHandle) {
|
||||||
@ -1198,9 +1206,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
|
||||||
|
bool fsuid_only)
|
||||||
{
|
{
|
||||||
struct cifsFileInfo *open_file;
|
struct cifsFileInfo *open_file;
|
||||||
|
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
|
||||||
bool any_available = false;
|
bool any_available = false;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -1214,13 +1224,19 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only filter by fsuid on multiuser mounts */
|
||||||
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
|
||||||
|
fsuid_only = false;
|
||||||
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
refind_writable:
|
refind_writable:
|
||||||
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
||||||
if (open_file->closePend ||
|
if (open_file->closePend)
|
||||||
(!any_available && open_file->pid != current->tgid))
|
continue;
|
||||||
|
if (!any_available && open_file->pid != current->tgid)
|
||||||
|
continue;
|
||||||
|
if (fsuid_only && open_file->uid != current_fsuid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (open_file->pfile &&
|
if (open_file->pfile &&
|
||||||
((open_file->pfile->f_flags & O_RDWR) ||
|
((open_file->pfile->f_flags & O_RDWR) ||
|
||||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||||
@ -1315,7 +1331,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
|||||||
if (mapping->host->i_size - offset < (loff_t)to)
|
if (mapping->host->i_size - offset < (loff_t)to)
|
||||||
to = (unsigned)(mapping->host->i_size - offset);
|
to = (unsigned)(mapping->host->i_size - offset);
|
||||||
|
|
||||||
open_file = find_writable_file(CIFS_I(mapping->host));
|
open_file = find_writable_file(CIFS_I(mapping->host), false);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
bytes_written = cifs_write(open_file->pfile, write_data,
|
bytes_written = cifs_write(open_file->pfile, write_data,
|
||||||
to-from, &offset);
|
to-from, &offset);
|
||||||
@ -1388,7 +1404,7 @@ static int cifs_writepages(struct address_space *mapping,
|
|||||||
* but it'll at least handle the return. Maybe it should be
|
* but it'll at least handle the return. Maybe it should be
|
||||||
* a BUG() instead?
|
* a BUG() instead?
|
||||||
*/
|
*/
|
||||||
open_file = find_writable_file(CIFS_I(mapping->host));
|
open_file = find_writable_file(CIFS_I(mapping->host), false);
|
||||||
if (!open_file) {
|
if (!open_file) {
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
return generic_writepages(mapping, wbc);
|
return generic_writepages(mapping, wbc);
|
||||||
@ -1505,7 +1521,8 @@ static int cifs_writepages(struct address_space *mapping,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (n_iov) {
|
if (n_iov) {
|
||||||
open_file = find_writable_file(CIFS_I(mapping->host));
|
open_file = find_writable_file(CIFS_I(mapping->host),
|
||||||
|
false);
|
||||||
if (!open_file) {
|
if (!open_file) {
|
||||||
cERROR(1, "No writable handles for inode");
|
cERROR(1, "No writable handles for inode");
|
||||||
rc = -EBADF;
|
rc = -EBADF;
|
||||||
|
@ -963,7 +963,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
|
|||||||
/*
|
/*
|
||||||
* If the file is already open for write, just use that fileid
|
* If the file is already open for write, just use that fileid
|
||||||
*/
|
*/
|
||||||
open_file = find_writable_file(cifsInode);
|
open_file = find_writable_file(cifsInode, true);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
netfid = open_file->netfid;
|
netfid = open_file->netfid;
|
||||||
netpid = open_file->pid;
|
netpid = open_file->pid;
|
||||||
@ -1813,7 +1813,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
|||||||
* writebehind data than the SMB timeout for the SetPathInfo
|
* writebehind data than the SMB timeout for the SetPathInfo
|
||||||
* request would allow
|
* request would allow
|
||||||
*/
|
*/
|
||||||
open_file = find_writable_file(cifsInode);
|
open_file = find_writable_file(cifsInode, true);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
__u16 nfid = open_file->netfid;
|
__u16 nfid = open_file->netfid;
|
||||||
__u32 npid = open_file->pid;
|
__u32 npid = open_file->pid;
|
||||||
@ -1978,7 +1978,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
|||||||
args->ctime = NO_CHANGE_64;
|
args->ctime = NO_CHANGE_64;
|
||||||
|
|
||||||
args->device = 0;
|
args->device = 0;
|
||||||
open_file = find_writable_file(cifsInode);
|
open_file = find_writable_file(cifsInode, true);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
u16 nfid = open_file->netfid;
|
u16 nfid = open_file->netfid;
|
||||||
u32 npid = open_file->pid;
|
u32 npid = open_file->pid;
|
||||||
|
Loading…
Reference in New Issue
Block a user