]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:torture: add tests to test the SMB2 read/write offset/length boundaries
authorStefan Metzmacher <metze@samba.org>
Mon, 11 May 2020 10:37:41 +0000 (12:37 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 12 May 2020 19:53:43 +0000 (19:53 +0000)
[MS-FSA] 2.1.5.2 Server Requests a Read and
2.1.5.3 Server Requests a Write define some contraints.

These tests demonstrate that ((int64_t)offset) < 0) is
not allowed for both reads and writes for SMB.
Also the special case for writes at offset -2 is not possible
nor the append mode with offset < 0.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/rw-invalid [new file with mode: 0644]
source4/torture/smb2/read_write.c

diff --git a/selftest/knownfail.d/rw-invalid b/selftest/knownfail.d/rw-invalid
new file mode 100644 (file)
index 0000000..c6f11e0
--- /dev/null
@@ -0,0 +1,2 @@
+samba3.smb2.rw.invalid
+samba4.smb2.rw.invalid
index bc8898cec31ae1315e9795c7c31bd63222ee6872..b0eea55d7f1f87e46cb6c934207dd378a7c5d016 100644 (file)
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "torture/torture.h"
+#include "torture/util.h"
 #include "torture/smb2/proto.h"
 
+#define CHECK_STATUS(_status, _expected) \
+       torture_assert_ntstatus_equal_goto(torture, _status, _expected, \
+                ret, done, "Incorrect status")
+
+#define CHECK_VALUE(v, correct) \
+       torture_assert_int_equal_goto(torture, v, correct, \
+                ret, done, "Incorrect value")
+
+#define FNAME "smb2_writetest.dat"
+
 static bool run_smb2_readwritetest(struct torture_context *tctx,
                                   struct smb2_tree *t1, struct smb2_tree *t2)
 {
@@ -150,12 +161,190 @@ static bool run_smb2_wrap_readwritetest(struct torture_context *tctx,
        return run_smb2_readwritetest(tctx, tree1, tree1);
 }
 
+static bool test_rw_invalid(struct torture_context *torture, struct smb2_tree *tree)
+{
+       bool ret = true;
+       NTSTATUS status;
+       struct smb2_handle h;
+       uint8_t buf[64*1024];
+       struct smb2_read rd;
+       struct smb2_write w = {0};
+       TALLOC_CTX *tmp_ctx = talloc_new(tree);
+
+       ZERO_STRUCT(buf);
+
+       smb2_util_unlink(tree, FNAME);
+
+       status = torture_smb2_testfile(tree, FNAME, &h);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       ZERO_STRUCT(rd);
+       rd.in.file.handle = h;
+       rd.in.length = 10;
+       rd.in.offset = 0;
+       rd.in.min_count = 1;
+
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(rd.out.data.length, 10);
+
+       rd.in.min_count = 0;
+       rd.in.length = 10;
+       rd.in.offset = sizeof(buf);
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = sizeof(buf);
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(rd.out.data.length, 0);
+
+       rd.in.min_count = 0;
+       rd.in.length = 1;
+       rd.in.offset = INT64_MAX - 1;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = INT64_MAX;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(rd.out.data.length, 0);
+
+       rd.in.min_count = 0;
+       rd.in.length = 1;
+       rd.in.offset = INT64_MAX;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = (uint64_t)INT64_MAX + 1;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = (uint64_t)INT64_MIN;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = (uint64_t)(int64_t)-1;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = (uint64_t)(int64_t)-2;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       rd.in.min_count = 0;
+       rd.in.length = 0;
+       rd.in.offset = (uint64_t)(int64_t)-3;
+       status = smb2_read(tree, tmp_ctx, &rd);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = (int64_t)-1;
+       w.in.data.data = buf;
+       w.in.data.length = ARRAY_SIZE(buf);
+
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = (int64_t)-2;
+       w.in.data.data = buf;
+       w.in.data.length = ARRAY_SIZE(buf);
+
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = INT64_MIN;
+       w.in.data.data = buf;
+       w.in.data.length = 1;
+
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = INT64_MIN;
+       w.in.data.data = buf;
+       w.in.data.length = 0;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = INT64_MAX;
+       w.in.data.data = buf;
+       w.in.data.length = 0;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(w.out.nwritten, 0);
+
+       w.in.file.handle = h;
+       w.in.offset = INT64_MAX;
+       w.in.data.data = buf;
+       w.in.data.length = 1;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = (uint64_t)INT64_MAX + 1;
+       w.in.data.data = buf;
+       w.in.data.length = 0;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = 0xfffffff0000; /* MAXFILESIZE */
+       w.in.data.data = buf;
+       w.in.data.length = 1;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+       w.in.file.handle = h;
+       w.in.offset = 0xfffffff0000 - 1; /* MAXFILESIZE - 1 */
+       w.in.data.data = buf;
+       w.in.data.length = 1;
+       status = smb2_write(tree, &w);
+       if (TARGET_IS_SAMBA3(torture) || TARGET_IS_SAMBA4(torture)) {
+               CHECK_STATUS(status, NT_STATUS_OK);
+               CHECK_VALUE(w.out.nwritten, 1);
+       } else {
+               CHECK_STATUS(status, NT_STATUS_DISK_FULL);
+       }
+
+       w.in.file.handle = h;
+       w.in.offset = 0xfffffff0000; /* MAXFILESIZE */
+       w.in.data.data = buf;
+       w.in.data.length = 0;
+       status = smb2_write(tree, &w);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(w.out.nwritten, 0);
+
+done:
+       talloc_free(tmp_ctx);
+       return ret;
+}
+
 struct torture_suite *torture_smb2_readwrite_init(TALLOC_CTX *ctx)
 {
        struct torture_suite *suite = torture_suite_create(ctx, "rw");
 
        torture_suite_add_2smb2_test(suite, "rw1", run_smb2_readwritetest);
        torture_suite_add_2smb2_test(suite, "rw2", run_smb2_wrap_readwritetest);
+       torture_suite_add_1smb2_test(suite, "invalid", test_rw_invalid);
 
        suite->description = talloc_strdup(suite, "SMB2 Samba4 Read/Write");