[SCM] Samba Shared Repository - branch v3-5-test updated

Karolin Seeger kseeger at samba.org
Mon Jan 18 02:23:37 MST 2010


The branch, v3-5-test has been updated
       via  8c8412f... Modification of fix for bug 6876 - Delete of an object whose parent folder does not have delete rights fails even if the delete right is set on the object
       via  eec11c0... Fix bug #6876 - Delete of an object whose parent folder does not have delete rights fails even if the delete right is set on the object.
      from  54b98a3... WHATSNEW: Start 3.5.0rc2 release notes.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 8c8412fa88f752797abebd940d488b1c09009d96
Author: Jeremy Allison <jra at samba.org>
Date:   Sat Jan 16 17:03:06 2010 -0800

    Modification of fix for bug 6876 - Delete of an object whose parent folder does not have delete rights fails even if the delete right is set on the object
    
    Suggested by Volker. Reduce the surface area of the
    become_root() unbecome_root() code to reduce the chance
    of errors.
    
    Jeremy.
    (cherry picked from commit 98a495f1e674b7562a3d8b5dfc958ee95d256896)

commit eec11c0d2ba61aa2f86a100064b3a9de3f56bb7d
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jan 12 16:04:44 2010 -0800

    Fix bug #6876 - Delete of an object whose parent folder does not have delete rights fails even if the delete right is set on the object.
    
    Final fix for the vfs_acl_xattr and vfs_acl_tdb code.
    Ensure we can delete a file even if the underlying POSIX
    permissions don't allow it, if the Windows permissions do.
    
    Jeremy.
    (cherry picked from commit 47c1d9b39f292772e8d8f7a737ddff6c8bdfdeae)

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

Summary of changes:
 source3/include/smb.h            |    1 +
 source3/locking/locking.c        |    3 +
 source3/modules/vfs_acl_common.c |  124 ++++++++++++++++++++++++++++++++++++++
 source3/modules/vfs_acl_tdb.c    |    3 +-
 source3/modules/vfs_acl_xattr.c  |    2 +
 source3/smbd/close.c             |    3 +
 source3/smbd/posix_acls.c        |    7 +-
 7 files changed, 139 insertions(+), 4 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/smb.h b/source3/include/smb.h
index b23ea64..bc7a90d 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -451,6 +451,7 @@ typedef struct files_struct {
 	bool aio_write_behind;
 	bool lockdb_clean;
 	bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */
+	bool delete_on_close;
 	bool posix_open;
 	struct smb_filename *fsp_name;
 
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 26018f9..095d0b1 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -1459,6 +1459,9 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USE
 	}
 
 	TALLOC_FREE(lck);
+
+	fsp->delete_on_close = delete_on_close;
+
 	return True;
 }
 
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index 1eec448..8c15cc7 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -760,6 +760,108 @@ static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
 	return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 }
 
+static int acl_common_remove_object(vfs_handle_struct *handle,
+					const char *path,
+					bool is_directory)
+{
+	connection_struct *conn = handle->conn;
+	struct file_id id;
+	files_struct *fsp = NULL;
+	int ret = 0;
+	char *parent_dir = NULL;
+	const char *final_component = NULL;
+	struct smb_filename local_fname;
+	int saved_errno = 0;
+
+	if (!parent_dirname(talloc_tos(), path,
+			&parent_dir, &final_component)) {
+		saved_errno = ENOMEM;
+		goto out;
+	}
+
+	DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
+		is_directory ? "directory" : "file",
+		parent_dir, final_component ));
+
+	/* cd into the parent dir to pin it. */
+	ret = SMB_VFS_CHDIR(conn, parent_dir);
+	if (ret == -1) {
+		saved_errno = errno;
+		goto out;
+	}
+
+	ZERO_STRUCT(local_fname);
+	local_fname.base_name = CONST_DISCARD(char *,final_component);
+
+	/* Must use lstat here. */
+	ret = SMB_VFS_LSTAT(conn, &local_fname);
+	if (ret == -1) {
+		saved_errno = errno;
+		goto out;
+	}
+
+	/* Ensure we have this file open with DELETE access. */
+	id = vfs_file_id_from_sbuf(conn, &local_fname.st);
+	for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) {
+		if (fsp->access_mask & DELETE_ACCESS &&
+				fsp->delete_on_close) {
+			/* We did open this for delete,
+			 * allow the delete as root.
+			 */
+			break;
+		}
+	}
+
+	if (!fsp) {
+		DEBUG(10,("acl_common_remove_object: %s %s/%s "
+			"not an open file\n",
+			is_directory ? "directory" : "file",
+			parent_dir, final_component ));
+		saved_errno = EACCES;
+		goto out;
+	}
+
+	become_root();
+	if (is_directory) {
+		ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
+	} else {
+		ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
+	}
+	unbecome_root();
+
+	if (ret == -1) {
+		saved_errno = errno;
+	}
+
+  out:
+
+	TALLOC_FREE(parent_dir);
+
+	vfs_ChDir(conn, conn->connectpath);
+	if (saved_errno) {
+		errno = saved_errno;
+	}
+	return ret;
+}
+
+static int rmdir_acl_common(struct vfs_handle_struct *handle,
+				const char *path)
+{
+	int ret;
+
+	ret = SMB_VFS_NEXT_RMDIR(handle, path);
+	if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+		DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
+			path,
+			strerror(errno) ));
+		return ret;
+	}
+
+	return acl_common_remove_object(handle,
+					path,
+					true);
+}
+
 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
 				struct smb_request *req,
 				uint16_t root_dir_fid,
@@ -857,3 +959,25 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
 	/* NOTREACHED */
 	return status;
 }
+
+static int unlink_acl_common(struct vfs_handle_struct *handle,
+			const struct smb_filename *smb_fname)
+{
+	int ret;
+
+	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+	if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+		DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
+			smb_fname->base_name,
+			strerror(errno) ));
+		return ret;
+	}
+	/* Don't do anything fancy for streams. */
+	if (smb_fname->stream_name) {
+		return ret;
+	}
+
+	return acl_common_remove_object(handle,
+					smb_fname->base_name,
+					false);
+}
diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c
index a1088ab..2afe69d 100644
--- a/source3/modules/vfs_acl_tdb.c
+++ b/source3/modules/vfs_acl_tdb.c
@@ -265,7 +265,7 @@ static int unlink_acl_tdb(vfs_handle_struct *handle,
 		goto out;
 	}
 
-	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
+	ret = unlink_acl_common(handle, smb_fname_tmp);
 
 	if (ret == -1) {
 		goto out;
@@ -413,6 +413,7 @@ static struct vfs_fn_pointers vfs_acl_tdb_fns = {
 	.connect_fn = connect_acl_tdb,
 	.opendir = opendir_acl_common,
 	.mkdir = mkdir_acl_common,
+	.rmdir = rmdir_acl_common,
 	.open = open_acl_common,
 	.create_file = create_file_acl_common,
 	.unlink = unlink_acl_tdb,
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index 625ef91..18f2d42 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -199,8 +199,10 @@ static struct vfs_fn_pointers vfs_acl_xattr_fns = {
 	.connect_fn = connect_acl_xattr,
 	.opendir = opendir_acl_common,
 	.mkdir = mkdir_acl_common,
+	.rmdir = rmdir_acl_common,
 	.open = open_acl_common,
 	.create_file = create_file_acl_common,
+	.unlink = unlink_acl_common,
 	.fget_nt_acl = fget_nt_acl_common,
 	.get_nt_acl = get_nt_acl_common,
 	.fset_nt_acl = fset_nt_acl_common,
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index fa83e16..ca1ac47 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -336,6 +336,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 			become_user(conn, fsp->vuid);
 			became_user = True;
 		}
+		fsp->delete_on_close = true;
 		set_delete_on_close_lck(lck, True, &current_user.ut);
 		if (became_user) {
 			unbecome_user();
@@ -481,6 +482,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
  	 * the delete on close flag. JRA.
  	 */
 
+	fsp->delete_on_close = false;
 	set_delete_on_close_lck(lck, False, NULL);
 
  done:
@@ -959,6 +961,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
 		}
 		send_stat_cache_delete_message(fsp->fsp_name->base_name);
 		set_delete_on_close_lck(lck, True, &current_user.ut);
+		fsp->delete_on_close = true;
 		if (became_user) {
 			unbecome_user();
 		}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 8d66bf1..7342420 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -1107,9 +1107,10 @@ uint32_t map_canon_ace_perms(int snum,
 			nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
 			nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
 		}
-		if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
-			nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER);
-		}
+	}
+
+	if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
+		nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|DELETE_ACCESS);
 	}
 
 	DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",


-- 
Samba Shared Repository


More information about the samba-cvs mailing list