summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/ksmbd/smb2pdu.c82
1 files changed, 45 insertions, 37 deletions
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 7e6e3d8c20e8..209e32e61a75 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2768,8 +2768,13 @@ int smb2_open(struct ksmbd_work *work)
if (!file_present) {
rc = smb2_creat(work, &path, name, open_flags, posix_mode,
req->CreateOptions & FILE_DIRECTORY_FILE_LE);
- if (rc)
+ if (rc) {
+ if (rc == -ENOENT) {
+ rc = -EIO;
+ rsp->hdr.Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
goto err_out;
+ }
created = true;
user_ns = mnt_user_ns(path.mnt);
@@ -6582,7 +6587,7 @@ int smb2_lock(struct ksmbd_work *work)
int lock_count;
int flags = 0;
int cmd = 0;
- int err = 0, i;
+ int err = -EIO, i, rc = 0;
u64 lock_start, lock_length;
struct ksmbd_lock *smb_lock = NULL, *cmp_lock, *tmp, *tmp2;
struct ksmbd_conn *conn;
@@ -6598,7 +6603,7 @@ int smb2_lock(struct ksmbd_work *work)
if (!fp) {
ksmbd_debug(SMB, "Invalid file id for lock : %llu\n",
le64_to_cpu(req->VolatileFileId));
- rsp->hdr.Status = STATUS_FILE_CLOSED;
+ err = -ENOENT;
goto out2;
}
@@ -6608,7 +6613,7 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB, "lock count is %d\n", lock_count);
if (!lock_count) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out2;
}
@@ -6616,10 +6621,8 @@ int smb2_lock(struct ksmbd_work *work)
flags = le32_to_cpu(lock_ele[i].Flags);
flock = smb_flock_init(filp);
- if (!flock) {
- rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
+ if (!flock)
goto out;
- }
cmd = smb2_set_flock_flags(flock, flags);
@@ -6657,8 +6660,7 @@ int smb2_lock(struct ksmbd_work *work)
if (cmp_lock->fl->fl_type != F_UNLCK &&
flock->fl_type != F_UNLCK) {
pr_err("conflict two locks in one request\n");
- rsp->hdr.Status =
- STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out;
}
}
@@ -6666,19 +6668,19 @@ int smb2_lock(struct ksmbd_work *work)
smb_lock = smb2_lock_init(flock, cmd, flags, &lock_list);
if (!smb_lock) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out;
}
}
list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
if (smb_lock->cmd < 0) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out;
}
if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out;
}
@@ -6686,7 +6688,7 @@ int smb2_lock(struct ksmbd_work *work)
smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) ||
(prior_lock == SMB2_LOCKFLAG_UNLOCK &&
!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EINVAL;
goto out;
}
@@ -6739,8 +6741,7 @@ int smb2_lock(struct ksmbd_work *work)
spin_unlock(&conn->llist_lock);
read_unlock(&conn_list_lock);
pr_err("previous lock conflict with zero byte lock range\n");
- rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
- goto out;
+ goto out;
}
if (smb_lock->zero_len && !cmp_lock->zero_len &&
@@ -6749,8 +6750,7 @@ int smb2_lock(struct ksmbd_work *work)
spin_unlock(&conn->llist_lock);
read_unlock(&conn_list_lock);
pr_err("current lock conflict with zero byte lock range\n");
- rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
- goto out;
+ goto out;
}
if (((cmp_lock->start <= smb_lock->start &&
@@ -6761,8 +6761,6 @@ int smb2_lock(struct ksmbd_work *work)
spin_unlock(&conn->llist_lock);
read_unlock(&conn_list_lock);
pr_err("Not allow lock operation on exclusive lock range\n");
- rsp->hdr.Status =
- STATUS_LOCK_NOT_GRANTED;
goto out;
}
}
@@ -6785,19 +6783,19 @@ no_check_cl:
flock = smb_lock->fl;
list_del(&smb_lock->llist);
retry:
- err = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
+ rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
skip:
if (flags & SMB2_LOCKFLAG_UNLOCK) {
- if (!err) {
+ if (!rc) {
ksmbd_debug(SMB, "File unlocked\n");
- } else if (err == -ENOENT) {
+ } else if (rc == -ENOENT) {
rsp->hdr.Status = STATUS_NOT_LOCKED;
goto out;
}
locks_free_lock(flock);
kfree(smb_lock);
} else {
- if (err == FILE_LOCK_DEFERRED) {
+ if (rc == FILE_LOCK_DEFERRED) {
void **argv;
ksmbd_debug(SMB,
@@ -6815,12 +6813,11 @@ skip:
}
argv[0] = flock;
- err = setup_async_work(work,
- smb2_remove_blocked_lock,
- argv);
- if (err) {
- rsp->hdr.Status =
- STATUS_INSUFFICIENT_RESOURCES;
+ rc = setup_async_work(work,
+ smb2_remove_blocked_lock,
+ argv);
+ if (rc) {
+ err = -ENOMEM;
goto out;
}
spin_lock(&fp->f_lock);
@@ -6867,7 +6864,7 @@ skip:
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
goto retry;
- } else if (!err) {
+ } else if (!rc) {
spin_lock(&work->conn->llist_lock);
list_add_tail(&smb_lock->clist,
&work->conn->lock_list);
@@ -6877,7 +6874,6 @@ skip:
list_add(&smb_lock->llist, &rollback_list);
ksmbd_debug(SMB, "successful in taking lock\n");
} else {
- rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
goto out;
}
}
@@ -6903,7 +6899,6 @@ out:
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;
@@ -6926,7 +6921,19 @@ out:
kfree(smb_lock);
}
out2:
- ksmbd_debug(SMB, "failed in taking lock(flags : %x)\n", flags);
+ ksmbd_debug(SMB, "failed in taking lock(flags : %x), err : %d\n", flags, err);
+
+ if (!rsp->hdr.Status) {
+ if (err == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (err == -ENOMEM)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ else if (err == -ENOENT)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else
+ rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
+ }
+
smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp);
return err;
@@ -7071,6 +7078,7 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
struct sockaddr_storage_rsp *sockaddr_storage;
unsigned int flags;
unsigned long long speed;
+ struct sockaddr_in6 *csin6 = (struct sockaddr_in6 *)&conn->peer_addr;
rtnl_lock();
for_each_netdev(&init_net, netdev) {
@@ -7086,8 +7094,6 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex);
nii_rsp->Capability = 0;
- if (netdev->num_tx_queues > 1)
- nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE);
if (ksmbd_rdma_capable_netdev(netdev))
nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE);
@@ -7112,7 +7118,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
nii_rsp->SockAddr_Storage;
memset(sockaddr_storage, 0, 128);
- if (conn->peer_addr.ss_family == PF_INET) {
+ if (conn->peer_addr.ss_family == PF_INET ||
+ ipv6_addr_v4mapped(&csin6->sin6_addr)) {
struct in_device *idev;
sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
@@ -8147,7 +8154,8 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
len = ALIGN(len, 8);
}
- if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
+ if (conn->binding == false &&
+ le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey;
} else {
chann = lookup_chann_list(work->sess, work->conn);