From 6fa753a1a67d563cd22d0cad73ae15ee267512fc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 11 May 2020 18:18:24 +0200 Subject: [PATCH] smbd: add vfs_valid_{pread,pwrite}_range() checks where needed 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 Reviewed-by: Jeremy Allison --- selftest/knownfail.d/rw-invalid | 3 +-- source3/modules/vfs_default.c | 7 +++++++ source3/smbd/aio.c | 19 +++++++++++++++++++ source3/smbd/fileio.c | 14 ++++++++++++++ source3/smbd/vfs.c | 34 ++++++++++++++++++++++++++++++++-- 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/selftest/knownfail.d/rw-invalid b/selftest/knownfail.d/rw-invalid index c6f11e03d20..ac5fe573239 100644 --- a/selftest/knownfail.d/rw-invalid +++ b/selftest/knownfail.d/rw-invalid @@ -1,2 +1 @@ -samba3.smb2.rw.invalid -samba4.smb2.rw.invalid +samba4.smb2.rw.invalid.ad_dc_ntvfs diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index c7f2020a9ea..b5fbc0ed5dc 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -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)) { diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f89ce8537a0..f141d673167 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -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 */ diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 079d414db05..40c770da8bd 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -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; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5141da728a7..f49b53f4b7c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -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)) { -- 2.11.4.GIT