From d337a44e429e6de23ed3d73fcb81ec44f7b05522 Mon Sep 17 00:00:00 2001 From: Marios Makassikis Date: Tue, 27 Jul 2021 09:24:51 +0900 Subject: ksmbd: Return STATUS_OBJECT_PATH_NOT_FOUND if smb2_creat() returns ENOENT Both Windows 10's SMB server and samba return STATUS_OBJECT_PATH_NOT_FOUND when trying to access a nonexistent path. This fixes Windows 10 File History tool. The latter relies on the server returning STATUS_OBJECT_PATH_NOT_FOUND to figure out what part of the target path needs to be created. Returning STATUS_OBJECT_NAME_INVALID will make it stop and display an error to the user. Signed-off-by: Marios Makassikis Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 7e6e3d8c20e8..1b1f34d9d1a0 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); -- cgit v1.3-14-g43fede From 9fb8fac08f6670c9bba70d6c616ad84dd7a45528 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 27 Jul 2021 09:28:10 +0900 Subject: ksmbd: don't set RSS capable in FSCTL_QUERY_NETWORK_INTERFACE_INFO ksmbd does not support RSS mode stably. RSS mode enabling will be set later. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 1b1f34d9d1a0..93e98ef94c73 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -7091,8 +7091,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); -- cgit v1.3-14-g43fede From 08bdbc6ef46ad522a24dc6b8e01c039cb0c7e761 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 27 Jul 2021 09:30:29 +0900 Subject: ksmbd: use channel signingkey for binding SMB2 session setup Windows client disconnect connection by wrong signed SMB2 session setup response on SMB3 multichannel mode. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 93e98ef94c73..7f5ca471b306 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -8150,7 +8150,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); -- cgit v1.3-14-g43fede From 6c99dfc4c5f6fa1f5a90c068be6201d7a0cebff1 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 27 Jul 2021 09:40:05 +0900 Subject: ksmbd: fix missing error code in smb2_lock Dan report a warning that is missing error code in smb2_lock from static checker. This patch add error code to avoid static checker warning. Reported-by: Dan Carpenter Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 66 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 7f5ca471b306..b52375ce19e9 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -6587,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; @@ -6603,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; } @@ -6613,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; } @@ -6621,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); @@ -6662,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; } } @@ -6671,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; } @@ -6691,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; } @@ -6744,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 && @@ -6754,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 && @@ -6766,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; } } @@ -6790,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, @@ -6820,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); @@ -6872,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); @@ -6882,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; } } @@ -6908,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; @@ -6931,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; -- cgit v1.3-14-g43fede From f1abdb78a1080a49deac6e91e1675525d1d3dfbe Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 27 Jul 2021 13:25:13 +0900 Subject: ksmbd: add ipv6_addr_v4mapped check to know if connection from client is ipv4 ksmbd create socket with IPv6 to listen both IPv4 and IPv6 connection from client. Server should send IP addresses of NICs through network interface info response. If Client connection is IPv4, Server should fill IPv4 address in response buffer. But ss_family is always PF_INET6 on IPv6 socket. So This patch add ipv6_addr_v4mapped check to know client connection is IPv4. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index b52375ce19e9..209e32e61a75 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -7078,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) { @@ -7117,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); -- cgit v1.3-14-g43fede