Samba "contaminates" Solaris ACLs

Andy Polyakov appro at fy.chalmers.se
Wed Jan 12 15:33:37 GMT 2000


Hi! Given:

- Solaris 2.6 box running Samba 2.0.6;
- a directory within a share with ACL (access control list) ensuring
  that the files are created writable for certain group (kind of per
  directory umask, very neat and useful);
- share is shared with the default "create mask" of 0744;

Problem. If created on Windows the files don't appear writable to the
intended group, group write permissions are revoked.

Cause. smbd sets umask(0) at startup and explicitly passes access
permissions to creat(2) (or open(...O_CREAT,mode)). With "create mask"
set to 0744 files files get created with at least 0644 as second argument
to creat(2) which makes group ACL to be demoted to read-only. The latter
is intended and logical behavior. Well, the former (umask(0)) is also
intended, but is it logical? I don't know...

In either case, relaxing the "create mask" to 0764 on the whole share
isn't an option. Arranging separate share for just the subcatalog in
question is too confusing for users. Being squeezed between Samba, Solaris
and users I came up with the following kludge. But before you proceed I
want to make it clear that the presented code is just a wild experiment
and my *only* point is that the problem probably needs further discussion.
And I want to point out that the attached patch addresses *two* Solaris
problems. I've already posted the SHUFFLE_OVER_256 code described in the
comment once before to this list. The "solution" to the problem with ACLs
is not commented at all, but the idea is trivial. I derive intended umask
value from the "create mask" and pass it in 16 most significant bits of
mode argument to sys_[creat|open]. In order to minimize amount of system
calls, umask value is cached in lib_system_umask global variable.

Cheers. Andy.
------------------------------------------------
*** ./smbd/dosmode.c.orig	Wed Jul 21 03:25:20 1999
--- ./smbd/dosmode.c	Tue Jan 11 23:59:52 2000
***************
*** 49,56 ****
--- 49,60 ----
      /* We never make directories read only for the owner as under DOS a user
         can always create a file in a read-only directory. */
      result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
+ #if 0
      /* Apply directory mask */
      result &= lp_dir_mask(SNUM(conn));
+ #else
+     result |= ((~lp_dir_mask(SNUM(conn))) & 0777) << 16;
+ #endif
      /* Add in force bits */
      result |= lp_force_dir_mode(SNUM(conn));
    } else { 
***************
*** 63,70 ****
--- 67,78 ----
      if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
        result |= S_IXOTH;  
   
+ #if 0
      /* Apply mode mask */
      result &= lp_create_mask(SNUM(conn));
+ #else
+     result |= ((~lp_create_mask(SNUM(conn))) & 0777) << 16;
+ #endif
      /* Add in force bits */
      result |= lp_force_create_mode(SNUM(conn));
    }
*** ./lib/doscalls.c.orig	Thu Apr  8 23:13:01 1999
--- ./lib/doscalls.c	Tue Jan 11 23:57:38 2000
***************
*** 108,114 ****
  
  int dos_mkdir(char *dname,mode_t mode)
  {
!   return(mkdir(dos_to_unix(dname,False),mode));
  }
  
  /*******************************************************************
--- 108,119 ----
  
  int dos_mkdir(char *dname,mode_t mode)
  {
!   extern mode_t lib_system_umask;
!   mode_t new_umask = (mode>>16) & 0777;
! 
!   if (new_umask != lib_system_umask) umask (lib_system_umask=new_umask);
! 
!   return(mkdir(dos_to_unix(dname,False),mode&0xFFFF));
  }
  
  /*******************************************************************
*** ./lib/system.c.orig	Wed Jul 21 03:25:09 1999
--- ./lib/system.c	Tue Jan 11 23:54:51 2000
***************
*** 280,285 ****
--- 280,310 ----
  #endif
  }
  
+ #if defined(SUNOS4) || (defined(SUNOS5) && !defined(__sparcv9))
+ /*
+  * Under SunOS/32 the member of FILE structure that keeps the UNIX file
+  * descriptor is only 8 bits wide:-( This means that stdio will fail
+  * *miserably* if first 256 file descriptors are exhausted by calls to 
+  * open(2) and creat(2). In order to avoid this let's try to shuffle file
+  * descriptors obtained from mentioned system calls over when we start
+  * approaching the limit.
+  *				Andy <appro at fy.chalmers.se>
+  */
+ #define KEEP_SOME_FD_FOR_STDIO 32
+ #define SHUFFLE_OVER_256(fd)  \
+ 	if (fd < 256 && fd > 256-KEEP_SOME_FD_FOR_STDIO) {	\
+ 	    int fdd;						\
+ 	    if ((fdd = fcntl(fd,F_DUPFD,256)) >= 256)		\
+ 		close(fd), fd = fdd;				\
+ 	}
+ #else
+ /*
+  * Other OS that would suffer from this is IRIX 5.x and earlier.
+  */
+ #endif
+ 
+ mode_t lib_system_umask=0;
+ 
  /*******************************************************************
   A creat() wrapper that will deal with 64 bit filesizes.
  ********************************************************************/
***************
*** 286,300 ****
  
  int sys_creat(const char *path, mode_t mode)
  {
  #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
!   return creat64(path, mode);
  #else
    /*
     * If creat64 isn't defined then ensure we call a potential open64.
     * JRA.
     */
!   return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
  #endif
  }
  
  /*******************************************************************
--- 311,334 ----
  
  int sys_creat(const char *path, mode_t mode)
  {
+   int fd;
+   mode_t new_umask = (mode>>16) & 0777;
+ 
+   if (new_umask != lib_system_umask) umask (lib_system_umask=new_umask);
+ 
  #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
!   fd = creat64(path, mode&0xFFFF);
  #else
    /*
     * If creat64 isn't defined then ensure we call a potential open64.
     * JRA.
     */
!   fd = sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
! #endif
! #ifdef SHUFFLE_OVER_256
!   SHUFFLE_OVER_256(fd);
  #endif
+   return fd;
  }
  
  /*******************************************************************
***************
*** 303,313 ****
  
  int sys_open(const char *path, int oflag, mode_t mode)
  {
  #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
!   return open64(path, oflag, mode);
  #else
!   return open(path, oflag, mode);
  #endif
  }
  
  /*******************************************************************
--- 337,356 ----
  
  int sys_open(const char *path, int oflag, mode_t mode)
  {
+   int fd;
+   mode_t new_umask = (mode>>16) & 0777;
+ 
+   if (new_umask != lib_system_umask) umask (lib_system_umask=new_umask);
+ 
  #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
!   fd = open64(path, oflag, mode&0xFFFF);
  #else
!   fd = open(path, oflag, mode&0xFFFF);
! #endif
! #ifdef SHUFFLE_OVER_256
!   SHUFFLE_OVER_256(fd);
  #endif
+   return fd;
  }
  
  /*******************************************************************


More information about the samba-ntdom mailing list