From: Jeremy Allison Date: Tue, 18 Jun 2019 18:24:12 +0000 (-0700) Subject: s3: smbd: Fix smb_query_posix_acl() to use modern coding standards. X-Git-Tag: ldb-2.0.5~242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9f55b782dbde399fe6283e9d434c1dca770a5f5;p=thirdparty%2Fsamba.git s3: smbd: Fix smb_query_posix_acl() to use modern coding standards. Add wrap protection. Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke --- diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ccc242a1927..4e3d279a70e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4860,13 +4860,15 @@ static NTSTATUS smb_query_posix_acl(connection_struct *conn, uint16_t num_file_acls = 0; uint16_t num_def_acls = 0; SMB_STRUCT_STAT *psbuf = &smb_fname->st; + unsigned int size_needed = 0; NTSTATUS status; + bool ok; status = refuse_symlink(conn, fsp, smb_fname); if (!NT_STATUS_IS_OK(status)) { - return status; + goto out; } if (fsp && fsp->fh->fd != -1) { @@ -4880,11 +4882,11 @@ static NTSTATUS smb_query_posix_acl(connection_struct *conn, } if (file_acl == NULL && no_acl_syscall_error(errno)) { - DEBUG(5,("smb_query_posix_acl: ACLs " - "not implemented on " + DBG_INFO("ACLs not implemented on " "filesystem containing %s\n", - smb_fname->base_name)); - return NT_STATUS_NOT_IMPLEMENTED; + smb_fname->base_name); + status = NT_STATUS_NOT_IMPLEMENTED; + goto out; } if (S_ISDIR(psbuf->st_ex_mode)) { @@ -4905,50 +4907,70 @@ static NTSTATUS smb_query_posix_acl(connection_struct *conn, num_file_acls = count_acl_entries(conn, file_acl); num_def_acls = count_acl_entries(conn, def_acl); - if ( data_size_in < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { - DEBUG(5,("smb_query_posix_acl: data_size too small (%u) need %u\n", + /* Wrap checks. */ + if (num_file_acls + num_def_acls < num_file_acls) { + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + size_needed = num_file_acls + num_def_acls; + + /* + * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less + * than UINT_MAX, so check by division. + */ + if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) { + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE; + if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) { + status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + size_needed += SMB_POSIX_ACL_HEADER_SIZE; + + if ( data_size_in < size_needed) { + DBG_INFO("data_size too small (%u) need %u\n", data_size_in, - (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + - SMB_POSIX_ACL_HEADER_SIZE) )); - if (file_acl) { - TALLOC_FREE(file_acl); - } - if (def_acl) { - TALLOC_FREE(def_acl); - } - return NT_STATUS_BUFFER_TOO_SMALL; + size_needed); + status = NT_STATUS_BUFFER_TOO_SMALL; + goto out; } SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); SSVAL(pdata,2,num_file_acls); SSVAL(pdata,4,num_def_acls); - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) { - if (file_acl) { - TALLOC_FREE(file_acl); - } - if (def_acl) { - TALLOC_FREE(def_acl); - } - return NT_STATUS_INTERNAL_ERROR; - } - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) { - if (file_acl) { - TALLOC_FREE(file_acl); - } - if (def_acl) { - TALLOC_FREE(def_acl); - } - return NT_STATUS_INTERNAL_ERROR; - } + pdata += SMB_POSIX_ACL_HEADER_SIZE; - if (file_acl) { - TALLOC_FREE(file_acl); + ok = marshall_posix_acl(conn, + pdata, + psbuf, + file_acl); + if (!ok) { + status = NT_STATUS_INTERNAL_ERROR; + goto out; } - if (def_acl) { - TALLOC_FREE(def_acl); + pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE); + + ok = marshall_posix_acl(conn, + pdata, + psbuf, + def_acl); + if (!ok) { + status = NT_STATUS_INTERNAL_ERROR; + goto out; } - *pdata_size_out = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; - return NT_STATUS_OK; + + *pdata_size_out = size_needed; + status = NT_STATUS_OK; + + out: + + TALLOC_FREE(file_acl); + TALLOC_FREE(def_acl); + return status; } #endif