ksmbd: check invalid FileOffset and BeyondFinalZero in FSCTL_ZERO_DATA
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 19 Jun 2022 13:37:17 +0000 (22:37 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 7 Jul 2022 15:53:23 +0000 (17:53 +0200)
commit b5e5f9dfc915ff05b41dff56181e1dae101712bd upstream.

FileOffset should not be greater than BeyondFinalZero in FSCTL_ZERO_DATA.
And don't call ksmbd_vfs_zero_data() if length is zero.

Cc: stable@vger.kernel.org
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ksmbd/smb2pdu.c

index 1ed3046..5fc161b 100644 (file)
@@ -7684,7 +7684,7 @@ int smb2_ioctl(struct ksmbd_work *work)
        {
                struct file_zero_data_information *zero_data;
                struct ksmbd_file *fp;
-               loff_t off, len;
+               loff_t off, len, bfz;
 
                if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
                        ksmbd_debug(SMB,
@@ -7701,19 +7701,26 @@ int smb2_ioctl(struct ksmbd_work *work)
                zero_data =
                        (struct file_zero_data_information *)&req->Buffer[0];
 
-               fp = ksmbd_lookup_fd_fast(work, id);
-               if (!fp) {
-                       ret = -ENOENT;
+               off = le64_to_cpu(zero_data->FileOffset);
+               bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+               if (off > bfz) {
+                       ret = -EINVAL;
                        goto out;
                }
 
-               off = le64_to_cpu(zero_data->FileOffset);
-               len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
+               len = bfz - off;
+               if (len) {
+                       fp = ksmbd_lookup_fd_fast(work, id);
+                       if (!fp) {
+                               ret = -ENOENT;
+                               goto out;
+                       }
 
-               ret = ksmbd_vfs_zero_data(work, fp, off, len);
-               ksmbd_fd_put(work, fp);
-               if (ret < 0)
-                       goto out;
+                       ret = ksmbd_vfs_zero_data(work, fp, off, len);
+                       ksmbd_fd_put(work, fp);
+                       if (ret < 0)
+                               goto out;
+               }
                break;
        }
        case FSCTL_QUERY_ALLOCATED_RANGES: