summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeghana Madhusudhan <mmadhusu@redhat.com>2014-11-10 15:20:51 +0530
committerNiels de Vos <ndevos@redhat.com>2014-11-13 11:58:00 -0800
commit878b30420891c8b00043391cdce90930eaf18795 (patch)
tree5a6e783a4dda30d3020b0a00b482ca7e6f70169a
parentb4597a92ccfebf362c63977bc4bada7b65e28753 (diff)
gNFS: Allow reading ACLs even without read permissions on the file.
When root-squash is enabled or when no permissions are given to a file, NFS threw permission errors. According to the kernel-nfs behaviour, no permissions are required to read ACLs. When no ACLs are set, the system call sys_lgetxattr fails and returns a ENODATA error. This translates to ESERVERFAULT error in NFS. Fuse makes an exception to this error and returns a success case. Similar changes are made here to achieve the expected behaviour. Change-Id: I46b8f5911114eb087a3f8ca4e921b6b41e83f3b3 BUG: 1161092 Signed-off-by: Meghana Madhusudhan <mmadhusu@redhat.com> Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/9085 Tested-by: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r--tests/bugs/bug-1161092-nfs-acls.t36
-rw-r--r--xlators/nfs/server/src/acl3.c86
-rw-r--r--xlators/system/posix-acl/src/posix-acl.c2
3 files changed, 115 insertions, 9 deletions
diff --git a/tests/bugs/bug-1161092-nfs-acls.t b/tests/bugs/bug-1161092-nfs-acls.t
new file mode 100644
index 00000000000..f64ae5b3c18
--- /dev/null
+++ b/tests/bugs/bug-1161092-nfs-acls.t
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../nfs.rc
+
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info
+
+TEST $CLI volume create $V0 $H0:$B0/brick1;
+EXPECT 'Created' volinfo_field $V0 'Status';
+
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+EXPECT_WITHIN $NFS_EXPORT_TIMEOUT 1 is_nfs_export_available
+TEST mount_nfs $H0:/$V0 $N0
+
+TEST touch $N0/file1
+TEST chmod 700 $N0/file1
+TEST getfacl $N0/file1
+
+TEST $CLI volume set $V0 root-squash on
+TEST getfacl $N0/file1
+
+TEST umount_nfs $H0:/$V0 $N0
+TEST mount_nfs $H0:/$V0 $N0
+TEST getfacl $N0/file1
+
+## Before killing daemon to avoid deadlocks
+umount_nfs $N0
+
+cleanup;
+
diff --git a/xlators/nfs/server/src/acl3.c b/xlators/nfs/server/src/acl3.c
index 5cd8b8e7061..b00e8170ebd 100644
--- a/xlators/nfs/server/src/acl3.c
+++ b/xlators/nfs/server/src/acl3.c
@@ -29,6 +29,7 @@
#include "nfs-generics.h"
#include "acl3.h"
#include "byte-order.h"
+#include "compat-errno.h"
static int
acl3_nfs_acl_to_xattr (aclentry *ace, void *xattrbuf,
@@ -244,7 +245,10 @@ acl3_setacl_reply (rpcsvc_request_t *req, setaclreply *reply)
return 0;
}
-
+/* acl3_getacl_cbk: fetch and decode the ACL in the POSIX_ACL_ACCESS_XATTR
+ *
+ * The POSIX_ACL_ACCESS_XATTR can be set on files and directories.
+ */
int
acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *dict,
@@ -260,17 +264,16 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (!frame->local) {
gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument,"
" frame->local NULL");
- return EINVAL;
+ return -EINVAL;
}
cs = frame->local;
getaclreply = &cs->args.getaclreply;
- if (op_ret < 0) {
+ if ((op_ret < 0) && (op_errno != ENODATA && op_errno != ENOATTR)) {
stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto err;
}
getaclreply->aclentry.aclentry_val = cs->aclentry;
- getaclreply->daclentry.daclentry_val = cs->daclentry;
/* getfacl: NFS USER ACL */
data = dict_get (dict, POSIX_ACL_ACCESS_XATTR);
@@ -285,11 +288,59 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
stat = nfs3_errno_to_nfsstat3 (-aclcount);
goto err;
}
-
getaclreply->aclcount = aclcount;
getaclreply->aclentry.aclentry_len = aclcount;
}
+ acl3_getacl_reply (cs->req, getaclreply);
+ nfs3_call_state_wipe (cs);
+ return 0;
+
+err:
+ if (getaclreply)
+ getaclreply->status = stat;
+ acl3_getacl_reply (cs->req, getaclreply);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+/* acl3_default_getacl_cbk: fetch and decode the ACL set in the
+ * POSIX_ACL_DEFAULT_XATTR xattr.
+ *
+ * The POSIX_ACL_DEFAULT_XATTR xattr is only set on directories, not on files.
+ *
+ * When done with POSIX_ACL_DEFAULT_XATTR, we also need to get and decode the
+ * ACL that can be set in POSIX_ACL_DEFAULT_XATTR.
+ */
+int
+acl3_default_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs3_call_state_t *cs = NULL;
+ data_t *data = NULL;
+ getaclreply *getaclreply = NULL;
+ int aclcount = 0;
+ int defacl = 1; /* DEFAULT ACL */
+ nfs_user_t nfu = {0, };
+ int ret = -1;
+
+ if (!frame->local) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument,"
+ " frame->local NULL");
+ return -EINVAL;
+ }
+ cs = frame->local;
+ getaclreply = &cs->args.getaclreply;
+ if ((op_ret < 0) && (op_errno != ENODATA && op_errno != ENOATTR)) {
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ goto err;
+ }
+
+
+ getaclreply->daclentry.daclentry_val = cs->daclentry;
+
/* getfacl: NFS DEFAULT ACL */
data = dict_get (dict, POSIX_ACL_DEFAULT_XATTR);
if (data && data->data) {
@@ -308,8 +359,15 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
getaclreply->daclentry.daclentry_len = aclcount;
}
- acl3_getacl_reply (cs->req, getaclreply);
- nfs3_call_state_wipe (cs);
+ getaclreply->attr_follows = TRUE;
+ nfs_request_user_init (&nfu, cs->req);
+ ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ POSIX_ACL_ACCESS_XATTR, NULL, acl3_getacl_cbk, cs);
+ if (ret < 0) {
+ stat = nfs3_errno_to_nfsstat3 (-ret);
+ goto err;
+ }
+
return 0;
err:
@@ -320,6 +378,7 @@ err:
return 0;
}
+
int
acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf,
@@ -353,12 +412,21 @@ acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
getaclreply->attr = nfs3_stat_to_fattr3 (buf);
nfs_request_user_init (&nfu, cs->req);
- ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- NULL, NULL, acl3_getacl_cbk, cs);
+ if (buf->ia_type == IA_IFDIR) {
+ ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ POSIX_ACL_DEFAULT_XATTR, NULL,
+ acl3_default_getacl_cbk, cs);
+ } else {
+ ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ POSIX_ACL_ACCESS_XATTR, NULL,
+ acl3_getacl_cbk, cs);
+ }
+
if (ret < 0) {
stat = nfs3_errno_to_nfsstat3 (-ret);
goto err;
}
+
return 0;
err:
getaclreply->status = stat;
diff --git a/xlators/system/posix-acl/src/posix-acl.c b/xlators/system/posix-acl/src/posix-acl.c
index 500bd6c3c79..05608696ea6 100644
--- a/xlators/system/posix-acl/src/posix-acl.c
+++ b/xlators/system/posix-acl/src/posix-acl.c
@@ -1973,11 +1973,13 @@ posix_acl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
goto green;
else
goto red;
+
green:
STACK_WIND (frame, posix_acl_getxattr_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr,
loc, name, xdata);
return 0;
+
red:
STACK_UNWIND_STRICT (getxattr, frame, -1, EACCES, NULL, xdata);