From: Volker Lendecke Date: Fri, 2 Dec 2022 10:06:38 +0000 (+0100) Subject: smbd: Implement SET_REPARSE_POINT buffer size checks X-Git-Tag: talloc-2.4.0~156 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b20e95fb0a53e74891c043ebdb1375ce53831d91;p=thirdparty%2Fsamba.git smbd: Implement SET_REPARSE_POINT buffer size checks 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 Reviewed-by: Jeremy Allison --- diff --git a/source3/modules/util_reparse.c b/source3/modules/util_reparse.c index 388cfd940c2..45cacbdbe22 100644 --- a/source3/modules/util_reparse.c +++ b/source3/modules/util_reparse.c @@ -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; } diff --git a/source3/torture/test_nttrans_fsctl.c b/source3/torture/test_nttrans_fsctl.c index c2d8e684851..aea80c5431d 100644 --- a/source3/torture/test_nttrans_fsctl.c +++ b/source3/torture/test_nttrans_fsctl.c @@ -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; }