mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
[CIFS] Fix cifsacl mounts over smb2 to not call cifs
When mounting with smb2/smb3 (e.g. vers=2.1) and cifsacl mount option, it was trying to get the mode by querying the acl over the cifs rather than smb2 protocol. This patch makes that protocol independent and makes cifsacl smb2 mounts return a more intuitive operation not supported error (until we add a worker function for smb2_get_acl). Note that a previous patch fixed getxattr/setxattr for the CIFSACL xattr which would unconditionally call cifs_get_acl and cifs_set_acl (even when mounted smb2). I made those protocol independent last week (new protocol version operations "get_acl" and "set_acl" but did not add an smb2_get_acl and smb2_set_acl yet so those now simply return EOPNOTSUPP which at least is better than sending cifs requests on smb2 mount) The previous patches did not fix the one remaining case though ie mounting with "cifsacl" when getting mode from acl would unconditionally end up calling "cifs_get_acl_from_fid" even for smb2 - so made that protocol independent but to make that protocol independent had to make sure that the callers were passing the protocol independent handle structure (cifs_fid) instead of cifs specific _u16 network file handle (ie cifs_fid instead of cifs_fid->fid) Now mount with smb2 and cifsacl mount options will return EOPNOTSUP (instead of timing out) and a future patch will add smb2 operations (e.g. get_smb2_acl) to enable this. Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
4a5c80d7b5
commit
42eacf9e57
@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||||
__u16 fid, u32 *pacllen)
|
const struct cifs_fid *cifsfid, u32 *pacllen)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct cifs_ntsd *pntsd = NULL;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|||||||
return ERR_CAST(tlink);
|
return ERR_CAST(tlink);
|
||||||
|
|
||||||
xid = get_xid();
|
xid = get_xid();
|
||||||
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
|
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
|
||||||
|
pacllen);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
|
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|||||||
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);
|
||||||
|
|
||||||
pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
|
pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
|
||||||
cifsFileInfo_put(open_file);
|
cifsFileInfo_put(open_file);
|
||||||
return pntsd;
|
return pntsd;
|
||||||
}
|
}
|
||||||
@ -1006,19 +1007,31 @@ out:
|
|||||||
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
||||||
int
|
int
|
||||||
cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
||||||
struct inode *inode, const char *path, const __u16 *pfid)
|
struct inode *inode, const char *path,
|
||||||
|
const struct cifs_fid *pfid)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct cifs_ntsd *pntsd = NULL;
|
||||||
u32 acllen = 0;
|
u32 acllen = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
struct cifs_tcon *tcon;
|
||||||
|
|
||||||
cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
|
cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
|
||||||
|
|
||||||
if (pfid)
|
if (IS_ERR(tlink))
|
||||||
pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
|
return PTR_ERR(tlink);
|
||||||
else
|
tcon = tlink_tcon(tlink);
|
||||||
pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
|
|
||||||
|
|
||||||
|
if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
|
||||||
|
pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
|
||||||
|
&acllen);
|
||||||
|
else if (tcon->ses->server->ops->get_acl)
|
||||||
|
pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
|
||||||
|
&acllen);
|
||||||
|
else {
|
||||||
|
cifs_put_tlink(tlink);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
|
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
|
||||||
if (IS_ERR(pntsd)) {
|
if (IS_ERR(pntsd)) {
|
||||||
rc = PTR_ERR(pntsd);
|
rc = PTR_ERR(pntsd);
|
||||||
@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
|||||||
cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
|
cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cifs_put_tlink(tlink);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +398,8 @@ struct smb_version_operations {
|
|||||||
const struct nls_table *, int);
|
const struct nls_table *, int);
|
||||||
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
||||||
const char *, u32 *);
|
const char *, u32 *);
|
||||||
|
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
|
||||||
|
const struct cifs_fid *, u32 *);
|
||||||
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
|
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
|
||||||
int);
|
int);
|
||||||
};
|
};
|
||||||
|
@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb,
|
|||||||
|
|
||||||
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
|
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||||
FILE_ALL_INFO *data, struct super_block *sb,
|
FILE_ALL_INFO *data, struct super_block *sb,
|
||||||
int xid, const __u16 *fid);
|
int xid, const struct cifs_fid *fid);
|
||||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
struct super_block *sb, unsigned int xid);
|
struct super_block *sb, unsigned int xid);
|
||||||
@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path,
|
|||||||
const unsigned int xid);
|
const unsigned int xid);
|
||||||
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_fattr *fattr, struct inode *inode,
|
struct cifs_fattr *fattr, struct inode *inode,
|
||||||
const char *path, const __u16 *pfid);
|
const char *path, const struct cifs_fid *pfid);
|
||||||
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
|
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
|
||||||
kuid_t, kgid_t);
|
kuid_t, kgid_t);
|
||||||
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
|
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
|
||||||
const char *, u32 *);
|
const char *, u32 *);
|
||||||
|
extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
|
||||||
|
const struct cifs_fid *, u32 *);
|
||||||
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
|
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
|
||||||
const char *, int);
|
const char *, int);
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ cifs_create_get_file_info:
|
|||||||
xid);
|
xid);
|
||||||
else {
|
else {
|
||||||
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
|
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
|
||||||
xid, &fid->netfid);
|
xid, fid);
|
||||||
if (newinode) {
|
if (newinode) {
|
||||||
if (server->ops->set_lease_key)
|
if (server->ops->set_lease_key)
|
||||||
server->ops->set_lease_key(newinode, fid);
|
server->ops->set_lease_key(newinode, fid);
|
||||||
|
@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
|||||||
xid);
|
xid);
|
||||||
else
|
else
|
||||||
rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
|
rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
|
||||||
xid, &fid->netfid);
|
xid, fid);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
@ -677,7 +677,7 @@ cgfi_exit:
|
|||||||
int
|
int
|
||||||
cifs_get_inode_info(struct inode **inode, const char *full_path,
|
cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||||
FILE_ALL_INFO *data, struct super_block *sb, int xid,
|
FILE_ALL_INFO *data, struct super_block *sb, int xid,
|
||||||
const __u16 *fid)
|
const struct cifs_fid *fid)
|
||||||
{
|
{
|
||||||
bool validinum = false;
|
bool validinum = false;
|
||||||
__u16 srchflgs;
|
__u16 srchflgs;
|
||||||
|
@ -1073,6 +1073,7 @@ struct smb_version_operations smb1_operations = {
|
|||||||
#endif /* CIFS_XATTR */
|
#endif /* CIFS_XATTR */
|
||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
.get_acl = get_cifs_acl,
|
.get_acl = get_cifs_acl,
|
||||||
|
.get_acl_by_fid = get_cifs_acl_by_fid,
|
||||||
.set_acl = set_cifs_acl,
|
.set_acl = set_cifs_acl,
|
||||||
#endif /* CIFS_ACL */
|
#endif /* CIFS_ACL */
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user