smbd: add vfs_valid_{pread,pwrite}_range() checks where needed
authorStefan Metzmacher <metze@samba.org>
Mon, 11 May 2020 16:18:24 +0000 (18:18 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 12 May 2020 19:53:44 +0000 (19:53 +0000)
I checked all callers of SMB_VFS_PWRITE[_SEND](),
all callers of SMB_VFS_PREAD[_SEND]() and also
places where we append to the file and allocate
more space.

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
source3/modules/vfs_default.c
source3/smbd/aio.c
source3/smbd/fileio.c
source3/smbd/vfs.c

index c6f11e03d20bb56c425aa0564d04e1e5ebcbf995..ac5fe5732390ddc473bfb5eb87f99a82a40d6cf0 100644 (file)
@@ -1,2 +1 @@
-samba3.smb2.rw.invalid
-samba4.smb2.rw.invalid
+samba4.smb2.rw.invalid.ad_dc_ntvfs
index c7f2020a9eadb68ab7cc0965ca69e74df19ee2c9..b5fbc0ed5dc430da76d947104e2f1101e8d3f4cf 100644 (file)
@@ -2579,6 +2579,13 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
        int ret;
        NTSTATUS status;
        SMB_STRUCT_STAT *pst;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(len, 0);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        status = vfs_stat_fsp(fsp);
        if (!NT_STATUS_IS_OK(status)) {
index f89ce8537a058c38f6d31c135ffd142e900bfcf2..f141d67316740b9eecbd8f26b2a61991d6fb9e7b 100644 (file)
@@ -164,6 +164,12 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        size_t bufsize;
        size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
        struct tevent_req *req;
+       bool ok;
+
+       ok = vfs_valid_pread_range(startpos, smb_maxcnt);
+       if (!ok) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        if (fsp->base_fsp != NULL) {
                /* No AIO on streams yet */
@@ -328,6 +334,7 @@ static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req, *subreq;
        struct pwrite_fsync_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct pwrite_fsync_state);
        if (req == NULL) {
@@ -337,6 +344,12 @@ static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx,
        state->fsp = fsp;
        state->write_through = write_through;
 
+       ok = vfs_valid_pwrite_range(offset, n);
+       if (!ok) {
+               tevent_req_error(req, EINVAL);
+               return tevent_req_post(req, ev);
+       }
+
        if (n == 0) {
                tevent_req_done(req);
                return tevent_req_post(req, ev);
@@ -664,6 +677,12 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
        struct aio_extra *aio_ex;
        size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
        struct tevent_req *req;
+       bool ok;
+
+       ok = vfs_valid_pread_range(startpos, smb_maxcnt);
+       if (!ok) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        if (fsp->base_fsp != NULL) {
                /* No AIO on streams yet */
index 079d414db05f19363789f1e3c618c11fbaaf675a..40c770da8bdcc5d6ba595ec401dafef91dde55a8 100644 (file)
@@ -32,6 +32,7 @@
 ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n)
 {
        ssize_t ret = 0;
+       bool ok;
 
        /* you can't read from print files */
        if (fsp->print_file) {
@@ -39,6 +40,12 @@ ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n)
                return -1;
        }
 
+       ok = vfs_valid_pread_range(pos, n);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
+
        fsp->fh->pos = pos;
 
        if (n > 0) {
@@ -69,6 +76,13 @@ static ssize_t real_write_file(struct smb_request *req,
                                size_t n)
 {
        ssize_t ret;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(pos, n);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        if (n == 0) {
                return 0;
index 5141da728a78e39e774c886b57a0948cf4dec6f7..f49b53f4b7c62cfa16a1c07d9df326ec3b6188f9 100644 (file)
@@ -455,6 +455,13 @@ ssize_t vfs_pwrite_data(struct smb_request *req,
 {
        size_t total=0;
        ssize_t ret;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(offset, N);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        if (req && req->unread_bytes) {
                int sockfd = req->xconn->transport.sock;
@@ -531,6 +538,7 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
        uint64_t space_avail;
        uint64_t bsize,dfree,dsize;
        NTSTATUS status;
+       bool ok;
 
        /*
         * Actually try and commit the space on disk....
@@ -539,8 +547,9 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
        DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
                  fsp_str_dbg(fsp), (double)len));
 
-       if (((off_t)len) < 0) {
-               DEBUG(0,("vfs_allocate_file_space: %s negative len "
+       ok = vfs_valid_pwrite_range((off_t)len, 0);
+       if (!ok) {
+               DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
                         "requested.\n", fsp_str_dbg(fsp)));
                errno = EINVAL;
                return -1;
@@ -625,6 +634,13 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
 int vfs_set_filelen(files_struct *fsp, off_t len)
 {
        int ret;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(len, 0);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
 
@@ -656,6 +672,13 @@ int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
 {
        ssize_t pwrite_ret;
        size_t total = 0;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(offset, len);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        if (!sparse_buf) {
                sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
@@ -696,6 +719,13 @@ int vfs_fill_sparse(files_struct *fsp, off_t len)
        NTSTATUS status;
        off_t offset;
        size_t num_to_write;
+       bool ok;
+
+       ok = vfs_valid_pwrite_range(len, 0);
+       if (!ok) {
+               errno = EINVAL;
+               return -1;
+       }
 
        status = vfs_stat_fsp(fsp);
        if (!NT_STATUS_IS_OK(status)) {