]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Implement SET_REPARSE_POINT buffer size checks
authorVolker Lendecke <vl@samba.org>
Fri, 2 Dec 2022 10:06:38 +0000 (11:06 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 22 Dec 2022 19:50:34 +0000 (19:50 +0000)
Partially survives

samba.tests.reparsepoints.ReparsePoints.test_create_reparse

NTTRANS-FSCTL needs changing: Windows 2016 returns INVALID_BUFFER_SIZE
instead of our NOT_A_REPARSE_POINT. This is not the whole story, but
this smbtorture3 change makes autobuild survive.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/util_reparse.c
source3/torture/test_nttrans_fsctl.c

index 388cfd940c25f087d78af812f67682765158b68b..45cacbdbe222ae12b6f3936da05a5ca63a0e75c6 100644 (file)
@@ -31,12 +31,46 @@ NTSTATUS fsctl_get_reparse_point(struct files_struct *fsp,
        return NT_STATUS_NOT_A_REPARSE_POINT;
 }
 
+static NTSTATUS check_reparse_data_buffer(
+       const uint8_t *in_data, size_t in_len)
+{
+       uint16_t reparse_data_length;
+
+       if (in_len == 0) {
+               DBG_DEBUG("in_len=0\n");
+               return NT_STATUS_INVALID_BUFFER_SIZE;
+       }
+       if (in_len < 8) {
+               DBG_DEBUG("in_len=%zu\n", in_len);
+               return NT_STATUS_IO_REPARSE_DATA_INVALID;
+       }
+
+       reparse_data_length = PULL_LE_U16(in_data, 4);
+
+       if (reparse_data_length != (in_len - 8)) {
+               DBG_DEBUG("in_len=%zu, reparse_data_length=%"PRIu16"\n",
+                         in_len,
+                         reparse_data_length);
+               return NT_STATUS_IO_REPARSE_DATA_INVALID;
+       }
+
+       return NT_STATUS_OK;
+}
+
 NTSTATUS fsctl_set_reparse_point(struct files_struct *fsp,
                                 TALLOC_CTX *mem_ctx,
                                 const uint8_t *in_data,
                                 uint32_t in_len)
 {
+       NTSTATUS status;
+
        DBG_DEBUG("Called on %s\n", fsp_str_dbg(fsp));
+
+       status = check_reparse_data_buffer(in_data, in_len);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        return NT_STATUS_NOT_A_REPARSE_POINT;
 }
 
index c2d8e6848518ce58230b867ce092b24c84e18af5..aea80c5431d5fa0c83bde897b3521fe6d3c2d9f2 100644 (file)
@@ -141,7 +141,7 @@ bool run_nttrans_fsctl(int dummy)
        printf("FSCTL_GET_REPARSE_POINT returned correct status \n");
 
        /* Fill in for FSCTL_SET_REPARSE_POINT and call cli_trans ... */
-       SIVAL(setup, 0, FSCTL_SET_REPARSE_POINT); /* returns NOT A REPARSE POINT */
+       SIVAL(setup, 0, FSCTL_SET_REPARSE_POINT); /* returns INVALID_BUFFER_SIZE */
        SSVAL(setup, 4, fnum);
        SCVAL(setup, 6, 0x1);   /* It is an fsctl */
        SCVAL(setup, 7, 0x0);
@@ -156,8 +156,10 @@ bool run_nttrans_fsctl(int dummy)
                           NULL, 0, NULL, /* rsetup, min_rsetup, num_rsetup */
                           NULL, 0, NULL, /* rparam, min_rparam, num_rparam */
                           NULL, 0, NULL); /* rdata, ... */
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_REPARSE_POINT)) {
-               d_fprintf(stderr, "cli_trans of FSCTL_SET_REPARSE_POINT returned %s instead of NT_STATUS_NOT_A_REPARSE_POINT\n",
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_BUFFER_SIZE)) {
+               d_fprintf(stderr,
+                         "cli_trans of FSCTL_SET_REPARSE_POINT returned %s "
+                         "instead of NT_STATUS_INVALID_BUFFER_SIZE\n",
                        nt_errstr(status));
                goto fail;
        }