diff options
| author | Niels de Vos <ndevos@redhat.com> | 2015-02-10 19:13:35 +0100 | 
|---|---|---|
| committer | Raghavendra Bhat <raghavendra@redhat.com> | 2015-03-09 13:53:00 -0700 | 
| commit | 72dc1025dc17a650f3838223c78e3205132deba9 (patch) | |
| tree | 077be9e3b9113489b970a055d0b5bda0c9d643ad | |
| parent | 7d3f27d4c9421c976eec3a39004e84bad20586d7 (diff) | |
posix: add ACL translation for the GF_POSIX_ACL_*_KEY xattr
Adding support for two virtual extended attributes that are used for
converting a binary POSIX ACL to a POSIX.1e long ACL text format. This
makes it possible to transfer the ACL over the network to a different OS
which can convert the POSIX.1e text format to its native structures.
The following xattrs are sent over RPC in SETXATTR/GETXATTR procedures,
and contain the POSIX.1e long ACL text format:
- glusterfs.posix.acl: maps to ACL_TYPE_ACCESS
- glusterfs.posix.default_acl: maps to ACL_TYPE_DEFAULT
acl_from_text() (from libacl) converts the text format into an acl_t
structure. This structure is then used by acl_set_file() to set the ACL
in the filesystem.
libacl-devel is needed for linking against libacl, so it has been added
to the BuildRequires in the .spec.
NetBSD does not support POSIX ACLs. Trying to get/set POSIX ACLs on a
storage server running NetBSD, an error will be returned with errno set
to ENOTSUP. Faking support, but not enforcing ACLs seems wrong to me.
URL: http://www.gluster.org/community/documentation/index.php/Features/Improved_POSIX_ACLs
BUG: 1185654
Change-Id: Ic5eb73d69190d3492df2f711d0436775eeea7de3
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/9627
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: soumya k <skoduri@redhat.com>
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
| -rw-r--r-- | configure.ac | 37 | ||||
| -rw-r--r-- | glusterfs.spec.in | 5 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs-acl.h | 63 | ||||
| -rw-r--r-- | xlators/storage/posix/src/Makefile.am | 3 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 79 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 26 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.h | 6 | 
7 files changed, 217 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index 2c3b0e31c1c..db51080acf2 100644 --- a/configure.ac +++ b/configure.ac @@ -356,6 +356,39 @@ AC_CHECK_HEADERS([sys/ioctl.h], AC_DEFINE(HAVE_IOCTL_IN_SYS_IOCTL_H, 1, [have sy  AC_CHECK_HEADERS([sys/extattr.h]) +dnl NetBSD does not support POSIX ACLs :-( +case $host_os in +     *netbsd*) +        AC_MSG_WARN([NetBSD does not support POSIX ACLs... disabling them]) +        ACL_LIBS='' +        USE_POSIX_ACLS='0' +        ;; +     *) +        AC_CHECK_HEADERS([sys/acl.h], , +                         AC_MSG_ERROR([Support for POSIX ACLs is required])) +        USE_POSIX_ACLS='1' +        case $host_os in +             linux*) +                ACL_LIBS='-lacl' +                ;; +             solaris*) +                ACL_LIBS='-lsec' +                ;; +             *freebsd*) +                ACL_LIBS='-lc' +                ;; +             darwin*) +                ACL_LIBS='-lc' +                ;; +        esac +        if test "x${ACL_LIBS}" = "x-lacl"; then +          AC_CHECK_HEADERS([acl/libacl.h], , AC_MSG_ERROR([libacl is required for building on ${host_os}])) +        fi +        ;; +esac +AC_SUBST(ACL_LIBS) +AC_SUBST(USE_POSIX_ACLS) +  # libglusterfs/checksum  AC_CHECK_HEADERS([openssl/md5.h])  AC_CHECK_LIB([z], [adler32], [ZLIB_LIBS="-lz"], AC_MSG_ERROR([zlib is required to build glusterfs])) @@ -1167,6 +1200,9 @@ AC_SUBST(LIBGFCHANGELOG_LT_VERSION)  AC_SUBST(GFAPI_LT_VERSION)  AC_SUBST(GFAPI_EXTRA_LDFLAGS) +GFAPI_LIBS="${ACL_LIBS}" +AC_SUBST(GFAPI_LIBS) +  dnl this change necessary for run-tests.sh  AC_CONFIG_FILES([tests/env.rc],[ln -s ${ac_abs_builddir}/env.rc ${ac_abs_srcdir}/env.rc 2>/dev/null]) @@ -1192,4 +1228,5 @@ echo "XML output           : $BUILD_XML_OUTPUT"  echo "QEMU Block formats   : $BUILD_QEMU_BLOCK"  echo "Encryption xlator    : $BUILD_CRYPT_XLATOR"  echo "Unit Tests           : $BUILD_UNITTEST" +echo "POSIX ACLs           : $USE_POSIX_ACLS"  echo diff --git a/glusterfs.spec.in b/glusterfs.spec.in index dec67e2a637..69dcc5c6fb7 100644 --- a/glusterfs.spec.in +++ b/glusterfs.spec.in @@ -197,7 +197,7 @@ BuildRequires:    bison flex  BuildRequires:    gcc make automake libtool  BuildRequires:    ncurses-devel readline-devel  BuildRequires:    libxml2-devel openssl-devel -BuildRequires:    libaio-devel +BuildRequires:    libaio-devel libacl-devel  BuildRequires:    python-devel  BuildRequires:    python-ctypes  BuildRequires:    userspace-rcu-devel >= 0.7 @@ -1049,6 +1049,9 @@ fi  * Thu Feb 26 2015 Kaleb S. KEITHLEY <kkeithle@redhat.com>  - enable cmocka unittest support only when asked for (#1067059) +* Tue Feb 24 2015 Niels de Vos <ndevos@redhat.com> +- POSIX ACL conversion needs BuildRequires libacl-devel (#1185654) +  * Wed Feb 18 2015 Andreas Schneider <asn@redhat.com>  - Change cmockery2 to cmocka. diff --git a/libglusterfs/src/glusterfs-acl.h b/libglusterfs/src/glusterfs-acl.h index 174c16dd9f5..55f94ff0509 100644 --- a/libglusterfs/src/glusterfs-acl.h +++ b/libglusterfs/src/glusterfs-acl.h @@ -11,6 +11,17 @@  #ifndef _GLUSTERFS_ACL_H  #define _GLUSTERFS_ACL_H + +/* WARNING: Much if this code is restricted to Linux usage. + * + * It would be much cleaner to replace the code with something that is based on + * libacl (or its libc implementation on *BSD). + * + * Initial work for replacing this Linux specific implementation has been + * started as part of the "Improve POSIX ACLs" feature. Functionality for this + * feature has been added to the end of this file. + */ +  #include <stdint.h>  #include <sys/types.h> /* For uid_t */ @@ -99,4 +110,56 @@ struct posix_acl_conf {          struct posix_acl *minimal_acl;  }; + +/* Above this comment, the legacy POSIX ACL support is kept until it is not + * used anymore. Below you will find the more portable version to support POSIX + * ACls based on the implementation of libacl (see sys/acl.h). */ + +/* virtual xattrs passed over RPC, not stored on disk */ +#define GF_POSIX_ACL_ACCESS       "glusterfs.posix.acl" +#define GF_POSIX_ACL_DEFAULT      "glusterfs.posix.default_acl" +#define GF_POSIX_ACL_REQUEST(key) \ +        (!strncmp(key, GF_POSIX_ACL_ACCESS, strlen(GF_POSIX_ACL_ACCESS)) || \ +         !strncmp(key, GF_POSIX_ACL_DEFAULT, strlen(GF_POSIX_ACL_DEFAULT))) + +#ifdef HAVE_SYS_ACL_H /* only NetBSD does not support POSIX ACLs */ + +#include <sys/acl.h> + +static inline const char* +gf_posix_acl_get_key (const acl_type_t type) +{ +        char *acl_key = NULL; + +        switch (type) { +        case ACL_TYPE_ACCESS: +                acl_key = GF_POSIX_ACL_ACCESS; +                break; +        case ACL_TYPE_DEFAULT: +                acl_key = GF_POSIX_ACL_DEFAULT; +                break; +        default: +                errno = EINVAL; +        } + +        return acl_key; +} + +static inline const acl_type_t +gf_posix_acl_get_type (const char *key) +{ +        acl_type_t type = 0; + +        if (!strncmp (key, GF_POSIX_ACL_ACCESS, strlen (GF_POSIX_ACL_ACCESS))) +                type = ACL_TYPE_ACCESS; +        else if (!strncmp (key, GF_POSIX_ACL_DEFAULT, +                           strlen (GF_POSIX_ACL_DEFAULT))) +                type = ACL_TYPE_DEFAULT; +        else +                errno = EINVAL; + +        return type; +} + +#endif /* HAVE_SYS_ACL_H */  #endif /* _GLUSTERFS_ACL_H */ diff --git a/xlators/storage/posix/src/Makefile.am b/xlators/storage/posix/src/Makefile.am index 88efcc784db..509b0524921 100644 --- a/xlators/storage/posix/src/Makefile.am +++ b/xlators/storage/posix/src/Makefile.am @@ -5,7 +5,8 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/storage  posix_la_LDFLAGS = -module -avoid-version  posix_la_SOURCES = posix.c posix-helpers.c posix-handle.c posix-aio.c -posix_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(LIBAIO) +posix_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(LIBAIO) \ +                  $(ACL_LIBS)  noinst_HEADERS = posix.h posix-mem-types.h posix-handle.h posix-aio.h diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index ea469bf6109..edbf0241f26 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -24,6 +24,14 @@  #include <sys/stat.h>  #include <signal.h> +#ifdef HAVE_SYS_ACL_H +#ifdef HAVE_ACL_LIBACL_H /* for acl_to_any_text() */ +#include <acl/libacl.h> +#else /* FreeBSD and others */ +#include <sys/acl.h> +#endif +#endif +  #ifndef GF_BSD_HOST_OS  #include <alloca.h>  #endif /* GF_BSD_HOST_OS */ @@ -887,6 +895,75 @@ out:          return op_ret;  } +#ifdef HAVE_SYS_ACL_H +int +posix_pacl_set (const char *path, const char *key, const char *acl_s) +{ +        int ret = -1; +        acl_t acl = NULL; +        acl_type_t type = 0; + +        type = gf_posix_acl_get_type (key); + +        acl = acl_from_text (acl_s); +        ret = acl_set_file (path, type, acl); +        acl_free (acl); + +        return ret; +} + +int +posix_pacl_get (const char *path, const char *key, char **acl_s) +{ +        int ret = -1; +        acl_t acl = NULL; +        acl_type_t type = 0; +        char *acl_tmp = NULL; + +        type = gf_posix_acl_get_type (key); +        if (!type) +                return -1; + +        acl = acl_get_file (path, type); +        if (!acl) +                return -1; + +#ifdef HAVE_ACL_LIBACL_H +        acl_tmp = acl_to_any_text (acl, NULL, ',', +                                   TEXT_ABBREVIATE | TEXT_NUMERIC_IDS); +#else /* FreeBSD and the like */ +        acl_tmp = acl_to_text_np (acl, NULL, ACL_TEXT_NUMERIC_IDS); +#endif +        if (!acl_tmp) +                goto free_acl; + +        *acl_s = gf_strdup (acl_tmp); +        if (*acl_s) +                ret = 0; + +        acl_free (acl_tmp); +free_acl: +        acl_free (acl); + +        return ret; +} +#else /* !HAVE_SYS_ACL_H (NetBSD) */ +int +posix_pacl_set (const char *path, const char *key, const char *acl_s) +{ +        errno = ENOTSUP; +        return -1; +} + +int +posix_pacl_get (const char *path, const char *key, char **acl_s) +{ +        errno = ENOTSUP; +        return -1; +} +#endif + +  #ifdef GF_DARWIN_HOST_OS  static  void posix_dump_buffer (xlator_t *this, const char *real_path, const char *key, @@ -921,6 +998,8 @@ posix_handle_pair (xlator_t *this, const char *real_path,          } else if (ZR_FILE_CONTENT_REQUEST(key)) {                  ret = posix_set_file_contents (this, real_path, key, value,                                                 flags); +        } else if (GF_POSIX_ACL_REQUEST (key)) { +                ret = posix_pacl_set (real_path, key, value->data);          } else {                  sys_ret = sys_lsetxattr (real_path, key, value->data,                                           value->len, flags); diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index ccd441a2d62..47afed7fdad 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -3660,6 +3660,32 @@ posix_getxattr (call_frame_t *frame, xlator_t *this,                  goto out;          } +        if (loc->inode && name && GF_POSIX_ACL_REQUEST (name)) { +                ret = posix_pacl_get (real_path, name, &value); +                if (ret || !value) { +                        gf_log (this->name, GF_LOG_WARNING, +                                "could not get acl (%s) for %s: %s", name, +                                real_path, strerror (errno)); +                        op_ret = -1; +                        op_errno = errno; +                        goto out; +                } + +                ret = dict_set_dynstr (dict, (char *)name, value); +                if (ret < 0) { +                        GF_FREE (value); +                        gf_log (this->name, GF_LOG_WARNING, +                                "could not set acl (%s) for %s in dictionary: " +                                "(%s)", name, real_path, strerror (errno)); +                        op_ret = -1; +                        op_errno = errno; +                        goto out; +                } + +                size = ret; +                goto done; +        } +  	if (loc->inode && name &&  	    (strncmp (name, GF_XATTR_GET_REAL_FILENAME_KEY,  		      strlen (GF_XATTR_GET_REAL_FILENAME_KEY)) == 0)) { diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index 870315d0ea2..bdb56b1d59d 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -236,4 +236,10 @@ posix_get_ancestry (xlator_t *this, inode_t *leaf_inode,  void  posix_gfid_unset (xlator_t *this, dict_t *xdata); +int +posix_pacl_set (const char *path, const char *key, const char *acl_s); + +int +posix_pacl_get (const char *path, const char *key, char **acl_s); +  #endif /* _POSIX_H */  | 
