diff options
author | Brian Behlendorf <[email protected]> | 2011-07-20 13:10:07 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2011-07-20 14:07:13 -0700 |
commit | 9fd91daeef4df4e2bc66f54bb97c88225c6dd2c7 (patch) | |
tree | 2df4c016c37cd9c56645fcf49100466c1e947932 | |
parent | fe0ed8f910c1e4288dc190546cfe98ecf545b547 (diff) |
Honor setgit bit on directories
Newly created files were always being created with the fsuid/fsgid
in the current users credentials. This is correct except in the
case when the parent directory sets the 'setgit' bit. In this
case according to posix the newly created file/directory should
inherit the gid of the parent directory. Additionally, in the
case of a subdirectory it should also inherit the 'setgit' bit.
Finally, this commit performs a little cleanup of the vattr_t
initialization by moving it to a common helper function.
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #262
-rw-r--r-- | module/zfs/zpl_inode.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index a6e0cbb87..dbfe61ab9 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -51,6 +51,24 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) return d_splice_alias(ip, dentry); } +static void +zpl_vap_init(vattr_t *vap, struct inode *dir, struct dentry *dentry, + mode_t mode, cred_t *cr) +{ + vap->va_mask = ATTR_MODE; + vap->va_mode = mode; + vap->va_dentry = dentry; + vap->va_uid = crgetfsuid(cr); + + if (dir && dir->i_mode & S_ISGID) { + vap->va_gid = dir->i_gid; + if (S_ISDIR(mode)) + vap->va_mode |= S_ISGID; + } else { + vap->va_gid = crgetfsgid(cr); + } +} + static int zpl_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) @@ -62,11 +80,7 @@ zpl_create(struct inode *dir, struct dentry *dentry, int mode, crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); - vap->va_mode = mode; - vap->va_mask = ATTR_MODE; - vap->va_uid = crgetfsuid(cr); - vap->va_gid = crgetfsgid(cr); - vap->va_dentry = dentry; + zpl_vap_init(vap, dir, dentry, mode, cr); error = -zfs_create(dir, (char *)dentry->d_name.name, vap, 0, mode, &ip, cr, 0, NULL); @@ -94,12 +108,8 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); - vap->va_mode = mode; - vap->va_mask = ATTR_MODE; + zpl_vap_init(vap, dir, dentry, mode, cr); vap->va_rdev = rdev; - vap->va_uid = crgetfsuid(cr); - vap->va_gid = crgetfsgid(cr); - vap->va_dentry = dentry; error = -zfs_create(dir, (char *)dentry->d_name.name, vap, 0, mode, &ip, cr, 0, NULL); @@ -134,11 +144,7 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, int mode) crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); - vap->va_mode = S_IFDIR | mode; - vap->va_mask = ATTR_MODE; - vap->va_uid = crgetfsuid(cr); - vap->va_gid = crgetfsgid(cr); - vap->va_dentry = dentry; + zpl_vap_init(vap, dir, dentry, mode | S_IFDIR, cr); error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL); kmem_free(vap, sizeof(vattr_t)); @@ -229,11 +235,7 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) crhold(cr); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); - vap->va_mode = S_IFLNK | S_IRWXUGO; - vap->va_mask = ATTR_MODE; - vap->va_uid = crgetfsuid(cr); - vap->va_gid = crgetfsgid(cr); - vap->va_dentry = dentry; + zpl_vap_init(vap, dir, dentry, S_IFLNK | S_IRWXUGO, cr); error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0); kmem_free(vap, sizeof(vattr_t)); |