diff options
author | Vikas Gorur <vikas@gluster.com> | 2009-09-07 03:13:50 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-09-08 03:22:28 -0700 |
commit | fdef6f360f0755847d2520d79a4c7f0af35c7b0a (patch) | |
tree | d8cbb5716899f3134d7de1299e0734aeacadbe4e /xlators/storage | |
parent | eecce95c2fc4713146e4ba99817abaac94102763 (diff) |
storage/posix: Handle setgid bit on directories correctly
If a directory has the setgid bit set, then any entry
created under it must have group ownership same as
the directory.
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 241 (Gluster not honouring SETGID flag)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=241
Diffstat (limited to 'xlators/storage')
-rw-r--r-- | xlators/storage/posix/src/posix.c | 118 |
1 files changed, 108 insertions, 10 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 4eb484bc0..0c2259132 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -28,6 +28,7 @@ #include <sys/time.h> #include <sys/resource.h> #include <errno.h> +#include <libgen.h> #include <ftw.h> #ifndef GF_BSD_HOST_OS @@ -240,6 +241,58 @@ posix_scale_st_ino (struct posix_private *priv, struct stat *buf) } +/* + * If the parent directory of {real_path} has the setgid bit set, + * then set {gid} to the gid of the parent. Otherwise, + * leave {gid} unchanged. + */ + +int +setgid_override (char *real_path, gid_t *gid) +{ + char * tmp_path = NULL; + char * parent_path = NULL; + struct stat parent_stbuf; + + int op_ret = 0; + + tmp_path = strdup (real_path); + if (!tmp_path) { + op_ret = -ENOMEM; + gf_log ("[storage/posix]", GF_LOG_ERROR, + "Out of memory"); + goto out; + } + + parent_path = dirname (tmp_path); + + op_ret = lstat (parent_path, &parent_stbuf); + + if (op_ret == -1) { + op_ret = -errno; + gf_log ("[storage/posix]", GF_LOG_ERROR, + "lstat on parent directory (%s) failed: %s", + parent_path, strerror (errno)); + goto out; + } + + if (parent_stbuf.st_mode & S_ISGID) { + /* + Entries created inside a setgid directory + should inherit the gid from the parent + */ + + *gid = parent_stbuf.st_gid; + } +out: + + if (tmp_path) + FREE (tmp_path); + + return op_ret; +} + + int32_t posix_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) @@ -728,15 +781,24 @@ posix_mknod (call_frame_t *frame, xlator_t *this, char * real_path = 0; struct stat stbuf = { 0, }; + gid_t gid = 0; + DECLARE_OLD_FS_ID_VAR; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (loc, out); - SET_FS_ID (frame->root->uid, frame->root->gid); MAKE_REAL_PATH (real_path, this, loc->path); + gid = frame->root->gid; + + op_ret = setgid_override (real_path, &gid); + if (op_ret < 0) + goto out; + + SET_FS_ID (frame->root->uid, gid); + op_ret = mknod (real_path, mode, dev); if (op_ret == -1) { @@ -758,7 +820,7 @@ posix_mknod (call_frame_t *frame, xlator_t *this, } #ifndef HAVE_SET_FSID - op_ret = lchown (real_path, frame->root->uid, frame->root->gid); + op_ret = lchown (real_path, frame->root->uid, gid); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, @@ -797,15 +859,24 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, char * real_path = NULL; struct stat stbuf = {0, }; + gid_t gid = 0; + DECLARE_OLD_FS_ID_VAR; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (loc, out); - SET_FS_ID (frame->root->uid, frame->root->gid); MAKE_REAL_PATH (real_path, this, loc->path); + gid = frame->root->gid; + + op_ret = setgid_override (real_path, &gid); + if (op_ret < 0) + goto out; + + SET_FS_ID (frame->root->uid, gid); + op_ret = mkdir (real_path, mode); if (op_ret == -1) { op_errno = errno; @@ -816,7 +887,7 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, } #ifndef HAVE_SET_FSID - op_ret = chown (real_path, frame->root->uid, frame->root->gid); + op_ret = chown (real_path, frame->root->uid, gid); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, @@ -951,6 +1022,8 @@ posix_symlink (call_frame_t *frame, xlator_t *this, char * real_path = 0; struct stat stbuf = { 0, }; + gid_t gid = 0; + DECLARE_OLD_FS_ID_VAR; VALIDATE_OR_GOTO (frame, out); @@ -958,9 +1031,16 @@ posix_symlink (call_frame_t *frame, xlator_t *this, VALIDATE_OR_GOTO (linkname, out); VALIDATE_OR_GOTO (loc, out); - SET_FS_ID (frame->root->uid, frame->root->gid); MAKE_REAL_PATH (real_path, this, loc->path); + gid = frame->root->gid; + + op_ret = setgid_override (real_path, &gid); + if (op_ret < 0) + goto out; + + SET_FS_ID (frame->root->uid, gid); + op_ret = symlink (linkname, real_path); if (op_ret == -1) { @@ -972,7 +1052,7 @@ posix_symlink (call_frame_t *frame, xlator_t *this, } #ifndef HAVE_SET_FSID - op_ret = lchown (real_path, frame->root->uid, frame->root->gid); + op_ret = lchown (real_path, frame->root->uid, gid); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, @@ -1333,6 +1413,8 @@ posix_create (call_frame_t *frame, xlator_t *this, struct posix_fd * pfd = NULL; struct posix_private * priv = NULL; + gid_t gid = 0; + DECLARE_OLD_FS_ID_VAR; VALIDATE_OR_GOTO (frame, out); @@ -1343,9 +1425,18 @@ posix_create (call_frame_t *frame, xlator_t *this, priv = this->private; - SET_FS_ID (frame->root->uid, frame->root->gid); MAKE_REAL_PATH (real_path, this, loc->path); + gid = frame->root->gid; + + op_ret = setgid_override (real_path, &gid); + + if (op_ret < 0) { + goto out; + } + + SET_FS_ID (frame->root->uid, gid); + if (!flags) { _flags = O_CREAT | O_RDWR | O_EXCL; } @@ -1367,7 +1458,7 @@ posix_create (call_frame_t *frame, xlator_t *this, } #ifndef HAVE_SET_FSID - op_ret = chown (real_path, frame->root->uid, frame->root->gid); + op_ret = chown (real_path, frame->root->uid, gid); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, @@ -1425,6 +1516,8 @@ posix_open (call_frame_t *frame, xlator_t *this, struct posix_fd * pfd = NULL; struct posix_private * priv = NULL; + gid_t gid = 0; + DECLARE_OLD_FS_ID_VAR; VALIDATE_OR_GOTO (frame, out); @@ -1435,9 +1528,14 @@ posix_open (call_frame_t *frame, xlator_t *this, priv = this->private; - SET_FS_ID (frame->root->uid, frame->root->gid); MAKE_REAL_PATH (real_path, this, loc->path); + op_ret = setgid_override (real_path, &gid); + if (op_ret < 0) + goto out; + + SET_FS_ID (frame->root->uid, gid); + if (priv->o_direct) flags |= O_DIRECT; @@ -1467,7 +1565,7 @@ posix_open (call_frame_t *frame, xlator_t *this, #ifndef HAVE_SET_FSID if (flags & O_CREAT) { - op_ret = chown (real_path, frame->root->uid, frame->root->gid); + op_ret = chown (real_path, frame->root->uid, gid); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, |