[PATCH] Fix setting the initial permission bits

Volker Lendecke vl at samba.org
Thu Dec 27 20:31:08 GMT 2007


This fixes a make test failure on Solaris. When creating a new file,
file_set_dosmode() called from open_file_ntcreate calculates a new permission
mask, very likely different from what had been calculated in
open_file_ntcreate. Further down we overwrote the newly calculated value with
SMB_FCHMOD_ACL, ignoring what file_set_dosmode had calculated.

Why did Linux not see this? fchmod_acl on a newly created file without acls
would not retrieve an acl at all, whereas under Solaris acl(2) returns
something even for files with just posix permissions returns something.

Jeremy, given that we have very similar code in 3.0.28 this might also explain
some of the bug reports that people have concerning ACLs on new files.

Volker

P.S: This one took a while to find...
---
 source/smbd/dosmode.c |   18 ++++++++++++++++--
 source/smbd/open.c    |   13 +++++++++----
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 8e3c9b4..a96f80e 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -438,12 +438,19 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 	dosmode &= SAMBA_ATTRIBUTES_MASK;
 
 	DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
-	if (!st || (st && !VALID_STAT(*st))) {
+
+	if (st == NULL) {
+		SET_STAT_INVALID(st1);
 		st = &st1;
+	}
+
+	if (!VALID_STAT(*st)) {
 		if (SMB_VFS_STAT(conn,fname,st))
 			return(-1);
 	}
 
+	unixmode = st->st_mode;
+
 	get_acl_group_bits(conn, fname, &st->st_mode);
 
 	if (S_ISDIR(st->st_mode))
@@ -451,8 +458,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 	else
 		dosmode &= ~aDIR;
 
-	if (dos_mode(conn,fname,st) == dosmode)
+	if (dos_mode(conn,fname,st) == dosmode) {
+		st->st_mode = unixmode;
 		return(0);
+	}
 
 	/* Store the DOS attributes in an EA by preference. */
 	if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
@@ -460,6 +469,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 			notify_fname(conn, NOTIFY_ACTION_MODIFIED,
 				FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
 		}
+		st->st_mode = unixmode;
 		return 0;
 	}
 
@@ -500,6 +510,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 			notify_fname(conn, NOTIFY_ACTION_MODIFIED,
 				FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
 		}
+		st->st_mode = unixmode;
 		return 0;
 	}
 
@@ -534,6 +545,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 			notify_fname(conn, NOTIFY_ACTION_MODIFIED,
 				FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
 		}
+		if (ret == 0) {
+			st->st_mode = unixmode;
+		}
 	}
 
 	return( ret );
diff --git a/source/smbd/open.c b/source/smbd/open.c
index f30808b..d3ba9e0 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -1864,10 +1864,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
 		if (lp_map_archive(SNUM(conn)) ||
 		    lp_store_dos_attributes(SNUM(conn))) {
 			if (!posix_open) {
-				file_set_dosmode(conn, fname,
-					 new_dos_attributes | aARCH, NULL,
-					 parent_dir,
-					 true);
+				SMB_STRUCT_STAT tmp_sbuf;
+				SET_STAT_INVALID(tmp_sbuf);
+				if (file_set_dosmode(
+					    conn, fname,
+					    new_dos_attributes | aARCH,
+					    &tmp_sbuf, parent_dir,
+					    true) == 0) {
+					unx_mode = tmp_sbuf.st_mode;
+				}
 			}
 		}
 	}
-- 
1.5.3.7



More information about the samba-technical mailing list