[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Tue Jan 12 17:07:20 MST 2010


The branch, master has been updated
       via  47c1d9b... 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.
       via  2f30aea... Remove the global char *LastDir.
      from  2d4dda0... s3: Lift the version of the scannedonly VFS module

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


- Log -----------------------------------------------------------------
commit 47c1d9b39f292772e8d8f7a737ddff6c8bdfdeae
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.

commit 2f30aea3324f32f9b8555e961256fc1280da2871
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jan 12 14:48:23 2010 -0800

    Remove the global char *LastDir.
    
    This is no longer used for anything.

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

Summary of changes:
 source3/include/smb.h            |    1 +
 source3/locking/locking.c        |    3 +
 source3/modules/vfs_acl_common.c |  127 ++++++++++++++++++++++++++++++++++++++
 source3/modules/vfs_acl_tdb.c    |    3 +-
 source3/modules/vfs_acl_xattr.c  |    2 +
 source3/smbd/close.c             |    3 +
 source3/smbd/globals.c           |    1 -
 source3/smbd/globals.h           |    1 -
 source3/smbd/posix_acls.c        |    7 +-
 source3/smbd/vfs.c               |   21 +------
 10 files changed, 143 insertions(+), 26 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..aeb9ce3 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;
+	}
+
+	if (is_directory) {
+		ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
+	} else {
+		ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
+	}
+	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;
+	}
+
+	become_root();
+	ret = acl_common_remove_object(handle,
+					path,
+					true);
+	unbecome_root();
+	return ret;
+}
+
 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
 				struct smb_request *req,
 				uint16_t root_dir_fid,
@@ -857,3 +959,28 @@ 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;
+	}
+
+	become_root();
+	ret = acl_common_remove_object(handle,
+					smb_fname->base_name,
+					false);
+	unbecome_root();
+	return ret;
+}
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 05c3c70..e81a2fd 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:
@@ -958,6 +960,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/globals.c b/source3/smbd/globals.c
index 68fa795..e6db5ec 100644
--- a/source3/smbd/globals.c
+++ b/source3/smbd/globals.c
@@ -122,7 +122,6 @@ int conn_ctx_stack_ndx = 0;
 
 struct vfs_init_function_entry *backends = NULL;
 char *sparse_buf = NULL;
-char *LastDir = NULL;
 
 /* Current number of oplocks we have outstanding. */
 int32_t exclusive_oplocks_open = 0;
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 0db61f8..3cc967f 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -131,7 +131,6 @@ extern int conn_ctx_stack_ndx;
 struct vfs_init_function_entry;
 extern struct vfs_init_function_entry *backends;
 extern char *sparse_buf;
-extern char *LastDir;
 
 /* Current number of oplocks we have outstanding. */
 extern int32_t exclusive_oplocks_open;
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",
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 2ce61ee..5acec70 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -706,26 +706,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
 
 int vfs_ChDir(connection_struct *conn, const char *path)
 {
-	int res;
-
-	if (!LastDir) {
-		LastDir = SMB_STRDUP("");
-	}
-
-	if (strcsequal(path,"."))
-		return(0);
-
-	if (*path == '/' && strcsequal(LastDir,path))
-		return(0);
-
-	DEBUG(4,("vfs_ChDir to %s\n",path));
-
-	res = SMB_VFS_CHDIR(conn,path);
-	if (!res) {
-		SAFE_FREE(LastDir);
-		LastDir = SMB_STRDUP(path);
-	}
-	return(res);
+	return SMB_VFS_CHDIR(conn,path);
 }
 
 /*******************************************************************


-- 
Samba Shared Repository


More information about the samba-cvs mailing list