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 | |
| 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
| -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,  | 
