summaryrefslogtreecommitdiffstats
path: root/xlators/storage
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/storage')
-rw-r--r--xlators/storage/posix/src/posix.c118
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,