vfs_gpfs: Check group quota for directory when SGID is set
authorChristof Schmitt <cs@samba.org>
Wed, 7 Aug 2019 17:42:26 +0000 (10:42 -0700)
committerChristof Schmitt <cs@samba.org>
Wed, 14 Aug 2019 16:27:43 +0000 (16:27 +0000)
On directories with the "set group id" (SGID) bit is set, new files and
subfolders will be created with the group of the directory, and not with
the primary group of the user. Checking for free space in this case
should query the group quota for the gid of the directory.

This is the same change as the common smbd code, but since vfs_gpfs
still has its own check for available space and quotas, add it here as
well. A future goal would be to use the common free space check instead
of duplicating code in vfs_gpfs.

Signed-off-by: Christof Schmitt <cs@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/modules/vfs_gpfs.c

index 6994aa0..d8e9a32 100644 (file)
@@ -2306,8 +2306,24 @@ static uint64_t vfs_gpfs_disk_free(vfs_handle_struct *handle,
                                              bsize, dfree, dsize);
        }
 
-       err = get_gpfs_quota(smb_fname->base_name,
-                       GPFS_GRPQUOTA, utok->gid, &qi_group);
+       /*
+        * If new files created under this folder get this folder's
+        * GID, then available space is governed by the quota of the
+        * folder's GID, not the primary group of the creating user.
+        */
+       if (VALID_STAT(smb_fname->st) &&
+           S_ISDIR(smb_fname->st.st_ex_mode) &&
+           smb_fname->st.st_ex_mode & S_ISGID) {
+               become_root();
+               err = get_gpfs_quota(smb_fname->base_name, GPFS_GRPQUOTA,
+                                    smb_fname->st.st_ex_gid, &qi_group);
+               unbecome_root();
+
+       } else {
+               err = get_gpfs_quota(smb_fname->base_name, GPFS_GRPQUOTA,
+                                    utok->gid, &qi_group);
+       }
+
        if (err) {
                return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
                                              bsize, dfree, dsize);