/* * 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 * * Copyright (c) 2015, 2016, Intel Corporation. * Author: Sebastien Buisson sebastien.buisson@bull.net */ /* * lustre/llite/xattr_security.c * Handler for storing security labels as extended attributes. */ #include #include #ifdef HAVE_LINUX_SELINUX_IS_ENABLED #include #endif #include #include "llite_internal.h" #ifndef XATTR_SELINUX_SUFFIX # define XATTR_SELINUX_SUFFIX "selinux" #endif #ifndef XATTR_NAME_SELINUX # define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX #endif #ifdef HAVE_SECURITY_DENTRY_INIT_SECURTY_WITH_CTX #define HAVE_SECURITY_DENTRY_INIT_WITH_XATTR_NAME_ARG 1 #endif /* * Check for LL_SBI_FILE_SECCTX before calling. */ int ll_dentry_init_security(struct dentry *dentry, int mode, struct qstr *name, const char **secctx_name, __u32 *secctx_name_size, void **secctx, __u32 *secctx_size, int *secctx_slot) { struct ll_sb_info *sbi = ll_s2sbi(dentry->d_sb); #ifdef HAVE_SECURITY_DENTRY_INIT_WITH_XATTR_NAME_ARG const char *secctx_name_lsm = NULL; #endif #ifdef HAVE_SECURITY_DENTRY_INIT_SECURTY_WITH_CTX struct lsmcontext ctx = {}; #endif int rc; /* * Before kernel 5.15-rc1-20-g15bf32398ad4, * security_inode_init_security() does not return to us the name of the * extended attribute to store the context under (for example * "security.selinux"). So we only call it when we think we know what * the name of the extended attribute will be. This is OK-ish since * SELinux is the only module that implements * security_dentry_init_security(). Note that the NFS client code just * calls it and assumes that if anything is returned then it must come * from SELinux. */ *secctx_name_size = ll_secctx_name_get(sbi, secctx_name); /* xattr name length == 0 means no LSM module manage file contexts */ if (*secctx_name_size == 0) return 0; rc = security_dentry_init_security(dentry, mode, name, #ifdef HAVE_SECURITY_DENTRY_INIT_WITH_XATTR_NAME_ARG &secctx_name_lsm, #endif #ifdef HAVE_SECURITY_DENTRY_INIT_SECURTY_WITH_CTX &ctx); #else secctx, secctx_size); #endif /* ignore error if the hook is not supported by the LSM module */ if (rc == -EOPNOTSUPP) return 0; if (rc < 0) return rc; #ifdef HAVE_SECURITY_DENTRY_INIT_SECURTY_WITH_CTX *secctx = ctx.context; *secctx_size = ctx.len; *secctx_slot = ctx.slot; #endif #ifdef HAVE_SECURITY_DENTRY_INIT_WITH_XATTR_NAME_ARG if (strncmp(*secctx_name, secctx_name_lsm, *secctx_name_size) != 0) { CERROR("%s: LSM secctx_name '%s' does not match the one stored by Lustre '%s'\n", sbi->ll_fsname, secctx_name_lsm, *secctx_name); return -EOPNOTSUPP; } #endif return 0; } /** * A helper function for 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) { struct dentry *dentry = fs_info; const struct xattr *xattr; int err = 0; for (xattr = xattr_array; xattr->name; xattr++) { char *full_name; full_name = kasprintf(GFP_KERNEL, "%s%s", XATTR_SECURITY_PREFIX, xattr->name); if (!full_name) { err = -ENOMEM; break; } err = ll_vfs_setxattr(dentry, inode, full_name, xattr->value, xattr->value_len, XATTR_CREATE); kfree(full_name); 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_inode_init_security(struct dentry *dentry, struct inode *inode, struct inode *dir) { int rc; if (!ll_security_xattr_wanted(dir)) return 0; rc = security_inode_init_security(inode, dir, NULL, &ll_initxattrs, dentry); if (rc == -EOPNOTSUPP) return 0; return rc; } /** * Notify security context to the security layer * * Notify security context @secctx of inode @inode to the security layer. * * \retval 0 success, or SELinux is disabled or not supported by the fs * \retval < 0 failure to set the security context */ int ll_inode_notifysecctx(struct inode *inode, void *secctx, __u32 secctxlen) { struct ll_sb_info *sbi = ll_i2sbi(inode); int rc; if (!test_bit(LL_SBI_FILE_SECCTX, sbi->ll_flags) || !ll_security_xattr_wanted(inode) || !secctx || !secctxlen) return 0; /* no need to protect selinux_inode_setsecurity() by * inode_lock. Taking it would lead to a client deadlock * LU-13617 */ rc = security_inode_notifysecctx(inode, secctx, secctxlen); if (rc) CWARN("%s: cannot set security context for "DFID": rc = %d\n", sbi->ll_fsname, PFID(ll_inode2fid(inode)), rc); return rc; } /** * Free the security context xattr name used by policy */ void ll_secctx_name_free(struct ll_sb_info *sbi) { OBD_FREE(sbi->ll_secctx_name, sbi->ll_secctx_name_size + 1); sbi->ll_secctx_name = NULL; sbi->ll_secctx_name_size = 0; } /** * Get security context xattr name used by policy and save it. * * \retval > 0 length of xattr name * \retval == 0 no LSM module registered supporting security contexts * \retval <= 0 failure to get xattr name or xattr is not supported */ int ll_secctx_name_store(struct inode *in) { struct ll_sb_info *sbi = ll_i2sbi(in); int rc = 0; if (!ll_security_xattr_wanted(in)) return 0; /* get size of xattr name */ rc = security_inode_listsecurity(in, NULL, 0); if (rc <= 0) return rc; if (sbi->ll_secctx_name) ll_secctx_name_free(sbi); OBD_ALLOC(sbi->ll_secctx_name, rc + 1); if (!sbi->ll_secctx_name) return -ENOMEM; /* save the xattr name */ sbi->ll_secctx_name_size = rc; rc = security_inode_listsecurity(in, sbi->ll_secctx_name, sbi->ll_secctx_name_size); if (rc <= 0) goto err_free; if (rc > sbi->ll_secctx_name_size) { rc = -ERANGE; goto err_free; } /* sanity check */ sbi->ll_secctx_name[rc] = '\0'; if (rc < sizeof(XATTR_SECURITY_PREFIX)) { rc = -EINVAL; goto err_free; } if (strncmp(sbi->ll_secctx_name, XATTR_SECURITY_PREFIX, sizeof(XATTR_SECURITY_PREFIX) - 1) != 0) { rc = -EOPNOTSUPP; goto err_free; } return rc; err_free: ll_secctx_name_free(sbi); return rc; } /** * Retrieved file security context xattr name stored. * * \retval security context xattr name size stored. * \retval 0 no xattr name stored. */ __u32 ll_secctx_name_get(struct ll_sb_info *sbi, const char **secctx_name) { if (!sbi->ll_secctx_name || !sbi->ll_secctx_name_size) return 0; *secctx_name = sbi->ll_secctx_name; return sbi->ll_secctx_name_size; } /** * Filter out xattr file security context if not managed by LSM * * This is done to improve performance for application that blindly try to get * file context (like "ls -l" for security.linux). * See LU-549 for more information. * * \retval 0 xattr not filtered * \retval -EOPNOTSUPP no enabled LSM security module supports the xattr */ int ll_security_secctx_name_filter(struct ll_sb_info *sbi, int xattr_type, const char *suffix) { const char *cached_suffix = NULL; if (xattr_type != XATTR_SECURITY_T || !ll_xattr_suffix_is_seclabel(suffix)) return 0; /* is the xattr label used by lsm ? */ if (!ll_secctx_name_get(sbi, &cached_suffix)) return -EOPNOTSUPP; cached_suffix += sizeof(XATTR_SECURITY_PREFIX) - 1; if (strcmp(suffix, cached_suffix) != 0) return -EOPNOTSUPP; return 0; }