[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:
Steve French 2014-02-10 14:08:16 -06:00
parent 4a5c80d7b5
commit 42eacf9e57
7 changed files with 34 additions and 14 deletions

View File

@ -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;
} }

View File

@ -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);
}; };

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 */
}; };