Skip to content

Commit

Permalink
Merge pull request multipath-tcp#60 from namjaejeon/cifsd-for-next
Browse files Browse the repository at this point in the history
ksmbd-fixes
  • Loading branch information
smfrench committed Jul 13, 2021
2 parents 7c4ed5d + 0a427cc commit 904729b
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 109 deletions.
2 changes: 1 addition & 1 deletion fs/ksmbd/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ int ksmbd_conn_transport_init(void)

ret = ksmbd_rdma_init();
if (ret) {
pr_err("Failed to init KSMBD subsystem: %d\n", ret);
pr_err("Failed to init RDMA subsystem: %d\n", ret);
goto out;
}
out:
Expand Down
3 changes: 2 additions & 1 deletion fs/ksmbd/oplock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,8 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
* @open_req: buffer containing smb2 file open(create) request
* @tag: context name to search for
*
* Return: pointer to requested context, NULL if @str context not found
* Return: pointer to requested context, NULL if @str context not found
* or error pointer if name length is invalid.
*/
struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
{
Expand Down
93 changes: 35 additions & 58 deletions fs/ksmbd/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "asn1.h"
#include "connection.h"
#include "transport_ipc.h"
#include "transport_rdma.h"
#include "vfs.h"
#include "vfs_cache.h"
#include "misc.h"
Expand Down Expand Up @@ -2126,21 +2127,6 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path)
return rc;
}

static inline int check_context_err(void *ctx, char *str)
{
int err;

err = PTR_ERR(ctx);
ksmbd_debug(SMB, "find context %s err %d\n", str, err ? err : -ENOENT);

if (err == -EINVAL) {
pr_err("bad name length\n");
return err;
}

return 0;
}

static noinline int smb2_set_stream_name_xattr(struct path *path,
struct ksmbd_file *fp,
char *stream_name, int s_type)
Expand Down Expand Up @@ -2523,11 +2509,10 @@ int smb2_open(struct ksmbd_work *work)
if (req->CreateContextsOffset) {
/* Parse non-durable handle create contexts */
context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER);
if (IS_ERR_OR_NULL(context)) {
rc = check_context_err(context, SMB2_CREATE_EA_BUFFER);
if (rc < 0)
goto err_out1;
} else {
if (IS_ERR(context)) {
rc = PTR_ERR(context);
goto err_out1;
} else if (context) {
ea_buf = (struct create_ea_buf_req *)context;
if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
rsp->hdr.Status = STATUS_ACCESS_DENIED;
Expand All @@ -2538,25 +2523,21 @@ int smb2_open(struct ksmbd_work *work)

context = smb2_find_context_vals(req,
SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
if (IS_ERR_OR_NULL(context)) {
rc = check_context_err(context,
SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
if (rc < 0)
goto err_out1;
} else {
if (IS_ERR(context)) {
rc = PTR_ERR(context);
goto err_out1;
} else if (context) {
ksmbd_debug(SMB,
"get query maximal access context\n");
maximal_access_ctxt = 1;
}

context = smb2_find_context_vals(req,
SMB2_CREATE_TIMEWARP_REQUEST);
if (IS_ERR_OR_NULL(context)) {
rc = check_context_err(context,
SMB2_CREATE_TIMEWARP_REQUEST);
if (rc < 0)
goto err_out1;
} else {
if (IS_ERR(context)) {
rc = PTR_ERR(context);
goto err_out1;
} else if (context) {
ksmbd_debug(SMB, "get timewarp context\n");
rc = -EBADF;
goto err_out1;
Expand All @@ -2565,12 +2546,10 @@ int smb2_open(struct ksmbd_work *work)
if (tcon->posix_extensions) {
context = smb2_find_context_vals(req,
SMB2_CREATE_TAG_POSIX);
if (IS_ERR_OR_NULL(context)) {
rc = check_context_err(context,
SMB2_CREATE_TAG_POSIX);
if (rc < 0)
goto err_out1;
} else {
if (IS_ERR(context)) {
rc = PTR_ERR(context);
goto err_out1;
} else if (context) {
struct create_posix *posix =
(struct create_posix *)context;
ksmbd_debug(SMB, "get posix context\n");
Expand Down Expand Up @@ -2968,12 +2947,10 @@ int smb2_open(struct ksmbd_work *work)

az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
SMB2_CREATE_ALLOCATION_SIZE);
if (IS_ERR_OR_NULL(az_req)) {
rc = check_context_err(az_req,
SMB2_CREATE_ALLOCATION_SIZE);
if (rc < 0)
goto err_out;
} else {
if (IS_ERR(az_req)) {
rc = PTR_ERR(az_req);
goto err_out;
} else if (az_req) {
loff_t alloc_size = le64_to_cpu(az_req->AllocationSize);
int err;

Expand All @@ -2990,11 +2967,10 @@ int smb2_open(struct ksmbd_work *work)
}

context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID);
if (IS_ERR_OR_NULL(context)) {
rc = check_context_err(context, SMB2_CREATE_QUERY_ON_DISK_ID);
if (rc < 0)
goto err_out;
} else {
if (IS_ERR(context)) {
rc = PTR_ERR(context);
goto err_out;
} else if (context) {
ksmbd_debug(SMB, "get query on disk id context\n");
query_disk_id = 1;
}
Expand Down Expand Up @@ -6860,7 +6836,7 @@ int smb2_lock(struct ksmbd_work *work)
rsp->Reserved = 0;
inc_rfc1001_len(rsp, 4);
ksmbd_fd_put(work, fp);
return err;
return 0;

out:
list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
Expand All @@ -6871,15 +6847,16 @@ int smb2_lock(struct ksmbd_work *work)

list_for_each_entry_safe(smb_lock, tmp, &rollback_list, llist) {
struct file_lock *rlock = NULL;
int rc;

rlock = smb_flock_init(filp);
rlock->fl_type = F_UNLCK;
rlock->fl_start = smb_lock->start;
rlock->fl_end = smb_lock->end;

err = vfs_lock_file(filp, 0, rlock, NULL);
if (err)
pr_err("rollback unlock fail : %d\n", err);
rc = vfs_lock_file(filp, 0, rlock, NULL);
if (rc)
pr_err("rollback unlock fail : %d\n", rc);

list_del(&smb_lock->llist);
spin_lock(&work->conn->llist_lock);
Expand All @@ -6896,7 +6873,7 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB, "failed in taking lock(flags : %x)\n", flags);
smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp);
return 0;
return err;
}

static int fsctl_copychunk(struct ksmbd_work *work, struct smb2_ioctl_req *req,
Expand Down Expand Up @@ -7052,11 +7029,11 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
&rsp->Buffer[nbytes];
nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex);

/* TODO: specify the RDMA capabilities */
nii_rsp->Capability = 0;
if (netdev->num_tx_queues > 1)
nii_rsp->Capability = cpu_to_le32(RSS_CAPABLE);
else
nii_rsp->Capability = 0;
nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE);
if (ksmbd_rdma_capable_netdev(netdev))
nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE);

nii_rsp->Next = cpu_to_le32(152);
nii_rsp->Reserved = 0;
Expand Down
14 changes: 14 additions & 0 deletions fs/ksmbd/transport_rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,20 @@ int ksmbd_rdma_destroy(void)
return 0;
}

bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
{
struct ib_device *ibdev;
bool rdma_capable = false;

ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
if (ibdev) {
if (rdma_frwr_is_supported(&ibdev->attrs))
rdma_capable = true;
ib_device_put(ibdev);
}
return rdma_capable;
}

static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
.prepare = smb_direct_prepare,
.disconnect = smb_direct_disconnect,
Expand Down
2 changes: 2 additions & 0 deletions fs/ksmbd/transport_rdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ struct smb_direct_data_transfer {
#ifdef CONFIG_SMB_SERVER_SMBDIRECT
int ksmbd_rdma_init(void);
int ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
#else
static inline int ksmbd_rdma_init(void) { return 0; }
static inline int ksmbd_rdma_destroy(void) { return 0; }
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
#endif

#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
101 changes: 52 additions & 49 deletions fs/ksmbd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1498,63 +1498,66 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
{
int rc;
struct ndr n;
struct inode *inode = d_inode(dentry);
struct ndr acl_ndr = {0};
struct xattr_ntacl acl;
struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
__u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};

rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data);
if (rc > 0) {
struct inode *inode = d_inode(dentry);
struct ndr acl_ndr = {0};
struct xattr_ntacl acl;
struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
__u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};

n.length = rc;
rc = ndr_decode_v4_ntacl(&n, &acl);
if (rc)
return rc;

smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
ACL_TYPE_ACCESS);
if (S_ISDIR(inode->i_mode))
def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns,
inode,
ACL_TYPE_DEFAULT);

rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
smb_acl, def_smb_acl);
if (rc) {
pr_err("failed to encode ndr to posix acl\n");
goto out;
}
if (rc <= 0)
return rc;

rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
cmp_hash);
if (rc) {
pr_err("failed to generate hash for ndr acl\n");
goto out;
}
n.length = rc;
rc = ndr_decode_v4_ntacl(&n, &acl);
if (rc)
goto free_n_data;

if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
pr_err("hash value diff\n");
rc = -EINVAL;
goto out;
}
smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
ACL_TYPE_ACCESS);
if (S_ISDIR(inode->i_mode))
def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
ACL_TYPE_DEFAULT);

rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, smb_acl,
def_smb_acl);
if (rc) {
pr_err("failed to encode ndr to posix acl\n");
goto out_free;
}

*pntsd = acl.sd_buf;
(*pntsd)->osidoffset =
cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) - NDR_NTSD_OFFSETOF);
(*pntsd)->gsidoffset =
cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) - NDR_NTSD_OFFSETOF);
(*pntsd)->dacloffset =
cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) - NDR_NTSD_OFFSETOF);
rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, cmp_hash);
if (rc) {
pr_err("failed to generate hash for ndr acl\n");
goto out_free;
}

rc = acl.sd_size;
out:
kfree(n.data);
kfree(acl_ndr.data);
kfree(smb_acl);
kfree(def_smb_acl);
if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
pr_err("hash value diff\n");
rc = -EINVAL;
goto out_free;
}

*pntsd = acl.sd_buf;
(*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) -
NDR_NTSD_OFFSETOF);
(*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -
NDR_NTSD_OFFSETOF);
(*pntsd)->dacloffset = cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) -
NDR_NTSD_OFFSETOF);

rc = acl.sd_size;
out_free:
kfree(acl_ndr.data);
kfree(smb_acl);
kfree(def_smb_acl);
if (rc < 0) {
kfree(acl.sd_buf);
*pntsd = NULL;
}

free_n_data:
kfree(n.data);
return rc;
}

Expand Down

0 comments on commit 904729b

Please sign in to comment.