]) # LC_HAVE_PROTECT_I_NLINK
#
+# 2.6.39 security_inode_init_security takes a 'struct qstr' parameter
+#
+# 3.2 security_inode_init_security takes a callback to set xattrs
+#
+AC_DEFUN([LC_HAVE_SECURITY_IINITSEC], [
+LB_CHECK_COMPILE([if security_inode_init_security takes a callback],
+security_inode_init_security_callback, [
+ #include <linux/security.h>
+],[
+ security_inode_init_security(NULL, NULL, NULL, (const initxattrs)NULL, NULL);
+],[
+ AC_DEFINE(HAVE_SECURITY_IINITSEC_CALLBACK, 1,
+ [security_inode_init_security takes a callback to set xattrs])
+],[
+ LB_CHECK_COMPILE([if security_inode_init_security takes a 'struct qstr' parameter],
+ security_inode_init_security_qstr, [
+ #include <linux/security.h>
+ ],[
+ security_inode_init_security(NULL, NULL, (struct qstr *)NULL, NULL, NULL, NULL);
+ ],[
+ AC_DEFINE(HAVE_SECURITY_IINITSEC_QSTR, 1,
+ [security_inode_init_security takes a 'struct qstr' parameter])
+ ])
+])
+]) # LC_HAVE_SECURITY_IINITSEC
+
+#
# LC_HAVE_MIGRATE_HEADER
#
# 3.3 introduces migrate_mode.h and migratepage has 4 args
LC_HAVE_FSTYPE_MOUNT
LC_IOP_TRUNCATE
LC_HAVE_INODE_OWNER_OR_CAPABLE
+ LC_HAVE_SECURITY_IINITSEC
# 3.0
LC_DIRTY_INODE_WITH_FLAG
#define SIZE_MAX (~(size_t)0)
#endif
+#ifdef HAVE_SECURITY_IINITSEC_CALLBACK
+# define ll_security_inode_init_security(inode, dir, name, value, len, \
+ initxattrs, dentry) \
+ security_inode_init_security(inode, dir, &((dentry)->d_name), \
+ initxattrs, dentry)
+#elif defined HAVE_SECURITY_IINITSEC_QSTR
+# define ll_security_inode_init_security(inode, dir, name, value, len, \
+ initxattrs, dentry) \
+ security_inode_init_security(inode, dir, &((dentry)->d_name), \
+ name, value, len)
+#else /* !HAVE_SECURITY_IINITSEC_CALLBACK && !HAVE_SECURITY_IINITSEC_QSTR */
+# define ll_security_inode_init_security(inode, dir, name, value, len, \
+ initxattrs, dentry) \
+ security_inode_init_security(inode, dir, name, value, len)
+#endif
+
#endif /* _LUSTRE_COMPAT_H */
lustre-objs := dcache.o dir.o file.o llite_lib.o llite_nfs.o
lustre-objs += rw.o lproc_llite.o namei.o symlink.o llite_mmap.o
lustre-objs += xattr.o xattr_cache.o remote_perm.o llite_rmtacl.o
-lustre-objs += rw26.o super25.o statahead.o
+lustre-objs += rw26.o super25.o statahead.o xattr_security.o
lustre-objs += glimpse.o
lustre-objs += lcommon_cl.o
lustre-objs += lcommon_misc.o
struct ptlrpc_request *request = NULL;
struct md_op_data *op_data;
struct ll_sb_info *sbi = ll_i2sbi(parent);
+ struct inode *inode = NULL;
+ struct dentry dentry;
int err;
ENTRY;
ll_finish_md_op_data(op_data);
if (err)
GOTO(err_exit, err);
+
+ err = ll_prep_inode(&inode, request, parent->i_sb, NULL);
+ if (err)
+ GOTO(err_exit, err);
+
+ memset(&dentry, 0, sizeof(dentry));
+ dentry.d_inode = inode;
+
+ err = ll_init_security(&dentry, inode, parent);
+ iput(inode);
+ if (err)
+ GOTO(err_exit, err);
+
err_exit:
ptlrpc_req_finished(request);
return err;
size_t size,
__u64 valid);
+int ll_init_security(struct dentry *dentry,
+ struct inode *inode,
+ struct inode *dir);
+
/*
* Locking to guarantee consistency of non-atomic updates to long long i_size,
* consistency between file size and KMS.
RETURN(PTR_ERR(inode));
d_instantiate(dentry, inode);
+
+ rc = ll_init_security(dentry, inode, dir);
+ if (rc)
+ RETURN(rc);
+
RETURN(0);
}
d_instantiate(dchild, inode);
+ err = ll_init_security(dchild, inode, dir);
+ if (err)
+ GOTO(err_exit, err);
+
EXIT;
err_exit:
if (request != NULL)
#endif
do_getxattr:
- if (sbi->ll_xattr_cache_enabled && xattr_type != XATTR_ACL_ACCESS_T) {
+ if (sbi->ll_xattr_cache_enabled &&
+ xattr_type != XATTR_ACL_ACCESS_T &&
+ (xattr_type != XATTR_SECURITY_T ||
+ strcmp(name, "security.selinux") != 0)) {
rc = ll_xattr_cache_get(inode, name, buffer, size, valid);
if (rc == -EAGAIN)
goto getxattr_nocache;
CDEBUG(D_CACHE, "not caching %s\n",
XATTR_NAME_ACL_ACCESS);
rc = 0;
+ } else if (!strcmp(xdata, "security.selinux")) {
+ /* Filter out security.selinux, it is cached in slab */
+ CDEBUG(D_CACHE, "not caching security.selinux\n");
+ rc = 0;
} else {
rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval,
*xsizes);
--- /dev/null
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright (c) 2014 Bull SAS
+ * Author: Sebastien Buisson sebastien.buisson@bull.net
+ */
+
+/*
+ * lustre/llite/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+
+#include <linux/security.h>
+#include <linux/xattr.h>
+#include "llite_internal.h"
+
+#ifdef HAVE_SECURITY_IINITSEC_CALLBACK
+/**
+ * A helper function for ll_security_inode_init_security()
+ * that takes care of setting xattrs
+ *
+ * Get security context of @inode from @xattr_array,
+ * and put it in 'security.xxx' xattr of dentry
+ * stored in @fs_info.
+ *
+ * \retval 0 success
+ * \retval -ENOMEM if no memory could be allocated for xattr name
+ * \retval < 0 failure to set xattr
+ */
+static int
+ll_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+ void *fs_info)
+{
+ const struct xattr *xattr;
+ struct dentry *dentry = fs_info;
+ size_t name_len;
+ char *full_name;
+ int err = 0;
+
+ for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+ name_len = strlen(XATTR_SECURITY_PREFIX) + strlen(xattr->name)
+ + 1;
+ OBD_ALLOC(full_name, name_len);
+ if (full_name == NULL)
+ return -ENOMEM;
+ strlcpy(full_name, XATTR_SECURITY_PREFIX, name_len);
+ strlcat(full_name, xattr->name, name_len);
+
+ err = ll_setxattr(dentry, full_name, xattr->value,
+ xattr->value_len, 0);
+
+ OBD_FREE(full_name, name_len);
+
+ if (err < 0)
+ break;
+ }
+ return err;
+}
+
+/**
+ * Initializes security context
+ *
+ * Get security context of @inode in @dir,
+ * and put it in 'security.xxx' xattr of @dentry.
+ *
+ * \retval 0 success, or SELinux is disabled
+ * \retval -ENOMEM if no memory could be allocated for xattr name
+ * \retval < 0 failure to get security context or set xattr
+ */
+int
+ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir)
+{
+ if (!selinux_is_enabled())
+ return 0;
+
+ return ll_security_inode_init_security(inode, dir, NULL, NULL, 0,
+ &ll_initxattrs, dentry);
+}
+#else /* !HAVE_SECURITY_IINITSEC_CALLBACK */
+/**
+ * Initializes security context
+ *
+ * Get security context of @inode in @dir,
+ * and put it in 'security.xxx' xattr of @dentry.
+ *
+ * \retval 0 success, or SELinux is disabled
+ * \retval -ENOMEM if no memory could be allocated for xattr name
+ * \retval < 0 failure to get security context or set xattr
+ */
+int
+ll_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir)
+{
+ int err;
+ size_t len, name_len;
+ void *value;
+ char *name, *full_name;
+
+ if (!selinux_is_enabled())
+ return 0;
+
+ err = ll_security_inode_init_security(inode, dir, &name, &value, &len,
+ NULL, dentry);
+ if (err != 0) {
+ if (err == -EOPNOTSUPP)
+ return 0;
+ return err;
+ }
+
+ name_len = strlen(XATTR_SECURITY_PREFIX) + strlen(name) + 1;
+ OBD_ALLOC(full_name, name_len);
+ if (full_name == NULL)
+ GOTO(out_free, err = -ENOMEM);
+ strlcpy(full_name, XATTR_SECURITY_PREFIX, name_len);
+ strlcat(full_name, name, name_len);
+
+ err = ll_setxattr(dentry, full_name, value, len, 0);
+ OBD_FREE(full_name, name_len);
+
+out_free:
+ kfree(name);
+ kfree(value);
+
+ return err;
+}
+#endif /* HAVE_SECURITY_IINITSEC_CALLBACK */