123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- From eb27f9b7bf9c1dc902d9545eecf805831bd4e46c Mon Sep 17 00:00:00 2001
- From: Jeremy Allison <jra@samba.org>
- Date: Tue, 5 Jan 2016 11:18:12 -0800
- Subject: [PATCH 1/8] CVE-2015-7560: s3: smbd: Add refuse_symlink() function
- that can be used to prevent operations on a symlink.
- BUG: https://bugzilla.samba.org/show_bug.cgi?id=11648
- Signed-off-by: Jeremy Allison <jra@samba.org>
- Reviewed-by: Michael Adam <obnox@samba.org>
- ---
- source3/smbd/trans2.c | 28 ++++++++++++++++++++++++++++
- 1 file changed, 28 insertions(+)
- --- a/source3/smbd/trans2.c
- +++ b/source3/smbd/trans2.c
- @@ -51,6 +51,34 @@ static char *store_file_unix_basic_info2
- files_struct *fsp,
- const SMB_STRUCT_STAT *psbuf);
-
- +/****************************************************************************
- + Check if an open file handle or pathname is a symlink.
- +****************************************************************************/
- +
- +static NTSTATUS refuse_symlink(connection_struct *conn,
- + const files_struct *fsp,
- + const char *name)
- +{
- + SMB_STRUCT_STAT sbuf;
- + const SMB_STRUCT_STAT *pst = NULL;
- +
- + if (fsp) {
- + pst = &fsp->fsp_name->st;
- + } else {
- + int ret = vfs_stat_smb_fname(conn,
- + name,
- + &sbuf);
- + if (ret == -1) {
- + return map_nt_error_from_unix(errno);
- + }
- + pst = &sbuf;
- + }
- + if (S_ISLNK(pst->st_ex_mode)) {
- + return NT_STATUS_ACCESS_DENIED;
- + }
- + return NT_STATUS_OK;
- +}
- +
- /********************************************************************
- Roundup a value to the nearest allocation roundup size boundary.
- Only do this for Windows clients.
- @@ -181,12 +209,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
- char **names, **tmp;
- size_t num_names;
- ssize_t sizeret = -1;
- + NTSTATUS status;
- +
- + if (pnames) {
- + *pnames = NULL;
- + }
- + *pnum_names = 0;
-
- if (!lp_ea_support(SNUM(conn))) {
- - if (pnames) {
- - *pnames = NULL;
- - }
- - *pnum_names = 0;
- + return NT_STATUS_OK;
- + }
- +
- + status = refuse_symlink(conn, fsp, fname);
- + if (!NT_STATUS_IS_OK(status)) {
- + /*
- + * Just return no EA's on a symlink.
- + */
- return NT_STATUS_OK;
- }
-
- @@ -236,10 +274,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
-
- if (sizeret == 0) {
- TALLOC_FREE(names);
- - if (pnames) {
- - *pnames = NULL;
- - }
- - *pnum_names = 0;
- return NT_STATUS_OK;
- }
-
- @@ -550,6 +584,7 @@ NTSTATUS set_ea(connection_struct *conn,
- const struct smb_filename *smb_fname, struct ea_list *ea_list)
- {
- char *fname = NULL;
- + NTSTATUS status;
-
- if (!lp_ea_support(SNUM(conn))) {
- return NT_STATUS_EAS_NOT_SUPPORTED;
- @@ -559,6 +594,12 @@ NTSTATUS set_ea(connection_struct *conn,
- return NT_STATUS_ACCESS_DENIED;
- }
-
- + status = refuse_symlink(conn, fsp, smb_fname->base_name);
- + if (!NT_STATUS_IS_OK(status)) {
- + return status;
- + }
- +
- +
- /* For now setting EAs on streams isn't supported. */
- fname = smb_fname->base_name;
-
- @@ -4931,6 +4972,13 @@ NTSTATUS smbd_do_qfilepathinfo(connectio
- uint16 num_file_acls = 0;
- uint16 num_def_acls = 0;
-
- + status = refuse_symlink(conn,
- + fsp,
- + smb_fname->base_name);
- + if (!NT_STATUS_IS_OK(status)) {
- + return status;
- + }
- +
- if (fsp && fsp->fh->fd != -1) {
- file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
- } else {
- @@ -6452,6 +6500,7 @@ static NTSTATUS smb_set_posix_acl(connec
- uint16 num_def_acls;
- bool valid_file_acls = True;
- bool valid_def_acls = True;
- + NTSTATUS status;
-
- if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
- return NT_STATUS_INVALID_PARAMETER;
- @@ -6479,6 +6528,11 @@ static NTSTATUS smb_set_posix_acl(connec
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- + status = refuse_symlink(conn, fsp, smb_fname->base_name);
- + if (!NT_STATUS_IS_OK(status)) {
- + return status;
- + }
- +
- DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
- smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
- (unsigned int)num_file_acls,
- --- a/source3/smbd/nttrans.c
- +++ b/source3/smbd/nttrans.c
- @@ -877,6 +877,12 @@ NTSTATUS set_sd(files_struct *fsp, struc
- return NT_STATUS_OK;
- }
-
- + if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
- + DEBUG(10, ("ACL set on symlink %s denied.\n",
- + fsp_str_dbg(fsp)));
- + return NT_STATUS_ACCESS_DENIED;
- + }
- +
- if (psd->owner_sid == NULL) {
- security_info_sent &= ~SECINFO_OWNER;
- }
- @@ -1925,6 +1931,12 @@ NTSTATUS smbd_do_query_security_desc(con
- return NT_STATUS_ACCESS_DENIED;
- }
-
- + if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
- + DEBUG(10, ("ACL get on symlink %s denied.\n",
- + fsp_str_dbg(fsp)));
- + return NT_STATUS_ACCESS_DENIED;
- + }
- +
- if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
- SECINFO_GROUP|SECINFO_SACL)) {
- /* Don't return SECINFO_LABEL if anything else was
|