/* * 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, void **secctx, __u32 *secctx_size) { #ifdef HAVE_SECURITY_DENTRY_INIT_SECURITY int rc; /* security_dentry_init_security() is strange. Like * security_inode_init_security() it may return a context (provided a * Linux security module is enabled) but unlike * security_inode_init_security() it 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. */ if (!selinux_is_enabled()) return 0; rc = security_dentry_init_security(dentry, mode, name, secctx, secctx_size); if (rc < 0) return rc; *secctx_name = XATTR_NAME_SELINUX; #endif /* HAVE_SECURITY_DENTRY_INIT_SECURITY */ return 0; }
/** * Get security context xattr name used by policy. * * \retval >= 0 length of xattr name * \retval < 0 failure to get security context xattr name */ int ll_listsecurity(struct inode *inode, char *secctx_name, size_t secctx_name_size) { int rc; if (!selinux_is_enabled()) return 0; #ifdef HAVE_SECURITY_INODE_LISTSECURITY rc = security_inode_listsecurity(inode, secctx_name, secctx_name_size); if (rc >= secctx_name_size) rc = -ERANGE; else if (rc >= 0) secctx_name[rc] = '\0'; return rc; #else /* !HAVE_SECURITY_INODE_LISTSECURITY */ rc = sizeof(XATTR_NAME_SELINUX); if (secctx_name && rc < secctx_name_size) { memcpy(secctx_name, XATTR_NAME_SELINUX, rc); secctx_name[rc] = '\0'; } else { rc = -ERANGE; } return rc; #endif /* HAVE_SECURITY_INODE_LISTSECURITY */ }
/** * 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) { char *full_name; void *value; char *name; size_t len; int err; 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; } full_name = kasprintf(GFP_KERNEL, "%s%s", XATTR_SECURITY_PREFIX, name); if (!full_name) GOTO(out_free, err = -ENOMEM); err = __vfs_setxattr(dentry, inode, full_name, value, len, XATTR_CREATE); kfree(full_name); out_free: kfree(name); kfree(value); 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) { if (!selinux_is_enabled()) return 0; return ll_security_inode_init_security(inode, dir, NULL, NULL, 0, &ll_initxattrs, dentry); }
static int __init selinux_mod_init(void) { selinux_is_enabled_t selinux_is_enabled = (selinux_is_enabled_t)kallsyms_lookup_name("selinux_is_enabled"); printk(KERN_INFO "[%s] module loaded\n", __this_module.name); if(!selinux_is_enabled) { printk(KERN_INFO "[%s] Failed to find selinux_is_enabled\n", __this_module.name); return 1; } status_enabled = selinux_is_enabled(); printk(KERN_INFO "[%s] old selinux_enabled: %lu\n", __this_module.name, status_enabled); selinux_enabled = (unsigned long*)kallsyms_lookup_name("selinux_enabled"); if(!selinux_enabled) { printk(KERN_INFO "[%s] Failed to find selinux_enabled address\n", __this_module.name); return 1; } *selinux_enabled = 0U; printk(KERN_INFO "[%s] current selinux_enabled: %u\n", __this_module.name, selinux_is_enabled()); selinux_enforcing = (unsigned long*)kallsyms_lookup_name("selinux_enforcing"); if(!selinux_enforcing ) { printk(KERN_INFO "[%s] Failed to find selinux_enforcing address\n", __this_module.name); return 1; } status_enforcing = *selinux_enforcing; printk(KERN_INFO "[%s] old selinux_enforcing: %lu\n", __this_module.name, status_enforcing); *selinux_enforcing = 0U; printk(KERN_INFO "[%s] current selinux_enforcing: %lu\n", __this_module.name, *selinux_enforcing); return 0; }
static int ll_getxattr_common(struct inode *inode, const char *name, void *buffer, size_t size, __u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; struct mdt_body *body; int xattr_type, rc; void *xdata; struct obd_capa *oc; struct rmtacl_ctl_entry *rce = NULL; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); /* listxattr have slightly different behavior from of ext3: * without 'user_xattr' ext3 will list all xattr names but * filtered out "^user..*"; we list them all for simplicity. */ if (!name) { xattr_type = XATTR_OTHER_T; goto do_getxattr; } xattr_type = get_xattr_type(name); rc = xattr_type_filter(sbi, xattr_type); if (rc) return rc; /* b15587: ignore security.capability xattr for now */ if ((xattr_type == XATTR_SECURITY_T && strcmp(name, "security.capability") == 0)) return -ENODATA; /* LU-549: Disable security.selinux when selinux is disabled */ if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && strcmp(name, "security.selinux") == 0) return -EOPNOTSUPP; #ifdef CONFIG_FS_POSIX_ACL if (sbi->ll_flags & LL_SBI_RMT_CLIENT && (xattr_type == XATTR_ACL_ACCESS_T || xattr_type == XATTR_ACL_DEFAULT_T)) { rce = rct_search(&sbi->ll_rct, current_pid()); if (rce == NULL || (rce->rce_ops != RMT_LSETFACL && rce->rce_ops != RMT_LGETFACL && rce->rce_ops != RMT_RSETFACL && rce->rce_ops != RMT_RGETFACL)) return -EOPNOTSUPP; } /* posix acl is under protection of LOOKUP lock. when calling to this, * we just have path resolution to the target inode, so we have great * chance that cached ACL is uptodate. */ if (xattr_type == XATTR_ACL_ACCESS_T && !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) { struct ll_inode_info *lli = ll_i2info(inode); struct posix_acl *acl; spin_lock(&lli->lli_lock); acl = posix_acl_dup(lli->lli_posix_acl); spin_unlock(&lli->lli_lock); if (!acl) return -ENODATA; rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); posix_acl_release(acl); return rc; } if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) return -ENODATA; #endif do_getxattr: if (sbi->ll_xattr_cache_enabled && (rce == NULL || rce->rce_ops == RMT_LGETFACL || rce->rce_ops == RMT_LSETFACL)) { rc = ll_xattr_cache_get(inode, name, buffer, size, valid); if (rc < 0) GOTO(out_xattr, rc); } else { oc = ll_mdscapa_get(inode); rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid | (rce ? rce_ops2valid(rce->rce_ops) : 0), name, NULL, 0, size, 0, &req); capa_put(oc); if (rc < 0) GOTO(out_xattr, rc); body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); LASSERT(body); /* only detect the xattr size */ if (size == 0) GOTO(out, rc = body->eadatasize); if (size < body->eadatasize) { CERROR("server bug: replied size %u > %u\n", body->eadatasize, (int)size); GOTO(out, rc = -ERANGE); } if (body->eadatasize == 0) GOTO(out, rc = -ENODATA); /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, body->eadatasize); if (!xdata) GOTO(out, rc = -EFAULT); memcpy(buffer, xdata, body->eadatasize); rc = body->eadatasize; } #ifdef CONFIG_FS_POSIX_ACL if (rce && rce->rce_ops == RMT_LSETFACL) { ext_acl_xattr_header *acl; acl = lustre_posix_acl_xattr_2ext( (posix_acl_xattr_header *)buffer, rc); if (IS_ERR(acl)) GOTO(out, rc = PTR_ERR(acl)); rc = ee_add(&sbi->ll_et, current_pid(), ll_inode2fid(inode), xattr_type, acl); if (unlikely(rc < 0)) { lustre_ext_acl_xattr_free(acl); GOTO(out, rc); } } #endif out_xattr: if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { LCONSOLE_INFO( "%s: disabling user_xattr feature because it is not supported on the server: rc = %d\n", ll_get_fsname(inode->i_sb, NULL, 0), rc); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } out: ptlrpc_req_finished(req); return rc; }
static int ll_setxattr_common(struct inode *inode, const char *name, const void *value, size_t size, int flags, __u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; int xattr_type, rc; struct obd_capa *oc; struct rmtacl_ctl_entry *rce = NULL; #ifdef CONFIG_FS_POSIX_ACL posix_acl_xattr_header *new_value = NULL; ext_acl_xattr_header *acl = NULL; #endif const char *pv = value; xattr_type = get_xattr_type(name); rc = xattr_type_filter(sbi, xattr_type); if (rc) return rc; /* b10667: ignore lustre special xattr for now */ if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) || (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0)) return 0; /* b15587: ignore security.capability xattr for now */ if ((xattr_type == XATTR_SECURITY_T && strcmp(name, "security.capability") == 0)) return 0; /* LU-549: Disable security.selinux when selinux is disabled */ if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && strcmp(name, "security.selinux") == 0) return -EOPNOTSUPP; #ifdef CONFIG_FS_POSIX_ACL if (sbi->ll_flags & LL_SBI_RMT_CLIENT && (xattr_type == XATTR_ACL_ACCESS_T || xattr_type == XATTR_ACL_DEFAULT_T)) { rce = rct_search(&sbi->ll_rct, current_pid()); if (rce == NULL || (rce->rce_ops != RMT_LSETFACL && rce->rce_ops != RMT_RSETFACL)) return -EOPNOTSUPP; if (rce->rce_ops == RMT_LSETFACL) { struct eacl_entry *ee; ee = et_search_del(&sbi->ll_et, current_pid(), ll_inode2fid(inode), xattr_type); LASSERT(ee != NULL); if (valid & OBD_MD_FLXATTR) { acl = lustre_acl_xattr_merge2ext( (posix_acl_xattr_header *)value, size, ee->ee_acl); if (IS_ERR(acl)) { ee_free(ee); return PTR_ERR(acl); } size = CFS_ACL_XATTR_SIZE(\ le32_to_cpu(acl->a_count), \ ext_acl_xattr); pv = (const char *)acl; } ee_free(ee); } else if (rce->rce_ops == RMT_RSETFACL) { size = lustre_posix_acl_xattr_filter( (posix_acl_xattr_header *)value, size, &new_value); if (unlikely(size < 0)) return size; pv = (const char *)new_value; } else return -EOPNOTSUPP; valid |= rce_ops2valid(rce->rce_ops); } #endif if (sbi->ll_xattr_cache_enabled && (rce == NULL || rce->rce_ops == RMT_LSETFACL)) { rc = ll_xattr_cache_update(inode, name, pv, size, valid, flags); } else { oc = ll_mdscapa_get(inode); rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name, pv, size, 0, flags, ll_i2suppgid(inode), &req); capa_put(oc); } #ifdef CONFIG_FS_POSIX_ACL if (new_value != NULL) lustre_posix_acl_xattr_free(new_value, size); if (acl != NULL) lustre_ext_acl_xattr_free(acl); #endif if (rc) { if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { LCONSOLE_INFO("Disabling user_xattr feature because " "it is not supported on the server\n"); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } return rc; } ptlrpc_req_finished(req); return 0; }