From 88b37ed00084eeb601de2a68b6c84d6d53badd25 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Aug 2013 12:03:25 -0700 Subject: [PATCH 1/3] Fix the erroneous masking of chmod requests via the UNIX extensions. Changed from switch statement to if, as "create mask", "force create mode" are only applied to new files, not existing ones. "directory mask", "force directory mode" are only applied to new directories, not existing ones. Signed-off-by: Jeremy Allison Reviewed-by: Simo Sorce (cherry picked from commit bd0156988b34feaf91c3046f7ec78f0833222395) --- source3/smbd/trans2.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5031442..fc31ad4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1451,20 +1451,22 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0); #endif - switch (ptype) { - case PERM_NEW_FILE: - case PERM_EXISTING_FILE: - /* Apply mode mask */ + if (ptype == PERM_NEW_FILE) { + /* + * "create mask"/"force create mode" are + * only applied to new files, not existing ones. + */ ret &= lp_create_mask(SNUM(conn)); /* Add in force bits */ ret |= lp_force_create_mode(SNUM(conn)); - break; - case PERM_NEW_DIR: - case PERM_EXISTING_DIR: + } else if (ptype == PERM_NEW_DIR) { + /* + * "directory mask"/"force directory mode" are + * only applied to new directories, not existing ones. + */ ret &= lp_dir_mask(SNUM(conn)); /* Add in force bits */ ret |= lp_force_dir_mode(SNUM(conn)); - break; } *ret_perms = ret; -- 1.8.3.1 From c8956df363c3c59cfc8b5c42f7d8d3c749f86cf2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Aug 2013 12:10:05 -0700 Subject: [PATCH 2/3] Allow UNIX extensions client to act on open fsp instead of pathname if available. Eliminates possible race condition on pathname op. Signed-off-by: Jeremy Allison Reviewed-by: Simo Sorce (cherry picked from commit f1ff97fc022adaacaa23b7da250be6f7d51c6ac7) --- source3/smbd/trans2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fc31ad4..0703d21 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7154,11 +7154,18 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, */ if (raw_unixmode != SMB_MODE_NO_CHANGE) { + int ret; + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " "setting mode 0%o for file %s\n", (unsigned int)unixmode, smb_fname_str_dbg(smb_fname))); - if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) { + if (fsp && fsp->fh->fd != -1) { + ret = SMB_VFS_FCHMOD(fsp, unixmode); + } else { + ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode); + } + if (ret != 0) { return map_nt_error_from_unix(errno); } } -- 1.8.3.1 From f775578a112df05b3ad64558528867a11d73bb2c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Aug 2013 12:20:48 -0700 Subject: [PATCH 3/3] Fix the UNIX extensions CHOWN calls to use FCHOWN if available, else LCHOWN. UNIX extensions calls must never deref links. Signed-off-by: Jeremy Allison Reviewed-by: Simo Sorce Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Mon Aug 26 20:19:46 CEST 2013 on sn-devel-104 (cherry picked from commit d1593a20f3a5ebf287477dfa8f5ab31dca3dd0c3) --- source3/smbd/trans2.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0703d21..74310c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7183,12 +7183,15 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, (unsigned int)set_owner, smb_fname_str_dbg(smb_fname))); - if (S_ISLNK(sbuf.st_ex_mode)) { + if (fsp && fsp->fh->fd != -1) { + ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1); + } else { + /* + * UNIX extensions calls must always operate + * on symlinks. + */ ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, set_owner, (gid_t)-1); - } else { - ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, - set_owner, (gid_t)-1); } if (ret != 0) { @@ -7206,12 +7209,23 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_ex_gid != set_grp)) { + int ret; + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " "changing group %u for file %s\n", (unsigned int)set_owner, smb_fname_str_dbg(smb_fname))); - if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1, - set_grp) != 0) { + if (fsp && fsp->fh->fd != -1) { + ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1); + } else { + /* + * UNIX extensions calls must always operate + * on symlinks. + */ + ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1, + set_grp); + } + if (ret != 0) { status = map_nt_error_from_unix(errno); if (delete_on_fail) { SMB_VFS_UNLINK(conn, smb_fname); -- 1.8.3.1