Commit 42eacf9e authored by Steve French's avatar Steve French

[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: default avatarSteve French <smfrench@gmail.com>
parent 4a5c80d7
...@@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, ...@@ -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, ...@@ -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, ...@@ -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 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ...@@ -1006,19 +1007,31 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
/* 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, ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, ...@@ -378,7 +378,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
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, ...@@ -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 @@ cifs_get_file_info(struct file *filp) ...@@ -677,7 +677,7 @@ cifs_get_file_info(struct file *filp)
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 = { ...@@ -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 */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment