[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Apr 15 14:12:02 MDT 2011


The branch, master has been updated
       via  e49893c Use handle based xattr set if available.
       via  525ccd5 Ensure vfs_chown_fsp() is safe against races.
      from  e4c4dcf s3-waf: only LIBNMB needs to linked against -lresolv.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e49893c68ef29f71ac6301f3955a7404e9c6daba
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Apr 15 10:49:34 2011 -0700

    Use handle based xattr set if available.
    
    Autobuild-User: Jeremy Allison <jra at samba.org>
    Autobuild-Date: Fri Apr 15 22:11:12 CEST 2011 on sn-devel-104

commit 525ccd589ede79e97e83699629a1d98538855803
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Apr 15 12:21:39 2011 -0700

    Ensure vfs_chown_fsp() is safe against races.

-----------------------------------------------------------------------

Summary of changes:
 source3/smbd/dosmode.c |    9 +++--
 source3/smbd/open.c    |    2 +-
 source3/smbd/proto.h   |    2 +
 source3/smbd/vfs.c     |   76 ++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 79 insertions(+), 10 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 1ea4c68..a9b6dfe 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -348,8 +348,6 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 	struct xattr_DOSATTRIB dosattrib;
 	enum ndr_err_code ndr_err;
 	DATA_BLOB blob;
-	files_struct *fsp = NULL;
-	bool ret = false;
 
 	if (!lp_store_dos_attributes(SNUM(conn))) {
 		return False;
@@ -387,6 +385,9 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 	if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
 			     SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
 			     0) == -1) {
+		bool ret = false;
+		files_struct *fsp = NULL;
+
 		if((errno != EPERM) && (errno != EACCES)) {
 			if (errno == ENOSYS
 #if defined(ENOTSUP)
@@ -419,9 +420,9 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 
 		if (!NT_STATUS_IS_OK(open_file_fchmod(conn, smb_fname,
 						      &fsp)))
-			return ret;
+			return false;
 		become_root();
-		if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
+		if (SMB_VFS_FSETXATTR(fsp,
 				     SAMBA_XATTR_DOS_ATTRIB, blob.data,
 				     blob.length, 0) == 0) {
 			ret = true;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index b7c8540..14e6bf9 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2563,7 +2563,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
  Ensure we didn't get symlink raced on opening a directory.
 ****************************************************************************/
 
-static bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
+bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
 			const SMB_STRUCT_STAT *sbuf2)
 {
 	if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index c097202..36eea5e 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -567,6 +567,8 @@ void remove_deferred_open_entry(struct file_id id, uint64_t mid,
 NTSTATUS open_file_fchmod(connection_struct *conn,
 			  struct smb_filename *smb_fname,
 			  files_struct **result);
+bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
+			const SMB_STRUCT_STAT *sbuf2);
 NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
 			  struct smb_filename *smb_dname);
 void msg_file_was_renamed(struct messaging_context *msg,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index d8c57a6..0438f79 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1455,6 +1455,11 @@ int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path,
 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
 {
 	int ret;
+	bool as_root = false;
+	const char *path;
+	char *saved_dir = NULL;
+	char *parent_dir = NULL;
+	NTSTATUS status;
 
 	if (fsp->fh->fd != -1) {
 		/* Try fchown. */
@@ -1467,19 +1472,80 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
 		}
 	}
 
-	if (fsp->posix_open) {
+	as_root = (geteuid() == 0);
+
+	if (as_root) {
+		/*
+		 * We are being asked to chown as root. Make
+		 * sure we chdir() into the path to pin it,
+		 * and always act using lchown to ensure we
+		 * don't deref any symbolic links.
+		 */
+		const char *final_component = NULL;
+		struct smb_filename local_fname;
+
+		saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
+		if (!saved_dir) {
+			status = map_nt_error_from_unix(errno);
+			DEBUG(0,("vfs_chown_fsp: failed to get "
+				"current working directory. Error was %s\n",
+				strerror(errno)));
+			return status;
+		}
+
+		if (!parent_dirname(talloc_tos(),
+				fsp->fsp_name->base_name,
+				&parent_dir,
+				&final_component)) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		/* cd into the parent dir to pin it. */
+		ret = SMB_VFS_CHDIR(fsp->conn, parent_dir);
+		if (ret == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+
+		ZERO_STRUCT(local_fname);
+		local_fname.base_name = CONST_DISCARD(char *,final_component);
+
+		/* Must use lstat here. */
+		ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
+		if (ret == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+
+		/* Ensure it matches the fsp stat. */
+		if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) {
+                        return NT_STATUS_ACCESS_DENIED;
+                }
+                path = final_component;
+        } else {
+                path = fsp->fsp_name->base_name;
+        }
+
+	if (fsp->posix_open || as_root) {
 		ret = SMB_VFS_LCHOWN(fsp->conn,
-			fsp->fsp_name->base_name,
+			path,
 			uid, gid);
 	} else {
 		ret = SMB_VFS_CHOWN(fsp->conn,
-			fsp->fsp_name->base_name,
+			path,
 			uid, gid);
 	}
+
 	if (ret == 0) {
-		return NT_STATUS_OK;
+		status = NT_STATUS_OK;
+	} else {
+		status = map_nt_error_from_unix(errno);
+	}
+
+	if (as_root) {
+		vfs_ChDir(fsp->conn,saved_dir);
+		TALLOC_FREE(saved_dir);
+		TALLOC_FREE(parent_dir);
 	}
-	return map_nt_error_from_unix(errno);
+	return status;
 }
 
 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list