From patchwork Fri Oct 27 21:45:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 10030683 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 731386032C for ; Fri, 27 Oct 2017 21:45:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C58828D9B for ; Fri, 27 Oct 2017 21:45:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4FDB228FE4; Fri, 27 Oct 2017 21:45:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2304A28D9B for ; Fri, 27 Oct 2017 21:45:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932453AbdJ0Vp3 (ORCPT ); Fri, 27 Oct 2017 17:45:29 -0400 Received: from sonic305-28.consmr.mail.ne1.yahoo.com ([66.163.185.154]:36633 "EHLO sonic305-28.consmr.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932360AbdJ0Vp1 (ORCPT ); Fri, 27 Oct 2017 17:45:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1509140727; bh=rG8Zx+VViIKPQX4jien10WnE+d6VuWM1SuOEzWj3eC4=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From:Subject; b=LxoLKNP+3ODx7gWQYm7XfBO2cW/QVufxVN4IGSLb/XUQEQGL9nCom+RvAQ49l9mS1DZutgG75hJfd0MueIhdJNkvl/3zRQWkpzub24Mz1g1UPNsvGu/8crHP1m17heNFltflwqpHAa/eV9dRoFcwWvOpNh0iuBEVOeNmWpL+1HPka5PVc3hnjfOAI3B+JX3VQJgkt1NE0CZoFxuIgvmtqI27sg5gMtSmNcmM4XLeewzFu1sM+kzm2a8IuhLz9qrHkLQ0QT6ggJTbPUQrCjhdj8RzmAcNxbmEx6IKMPqF+BKbgCbHFL95tGwqDykcCINZbGwLJC77pbClJXDKtzB57A== X-YMail-OSG: ibwiE5oVM1l.OHFiBQx.sPC7OkH7NTSOWlwbYaiz4bDZrGljkoOXAFVCAyZZxJG lsApU8GmpXF_KdeM1v83QR5K60z25MSIndxcPybeFJ0w.Xor0Ejq3mMZcQzwZABxlj66CrblMDlw wRsbpsmzbU4mEJAYDSJhZ6ZUD2XIo76.kfFDbSLINXNX5LkB_KWh.bNHju6Hpq.8xb3L7MZR4YAx qUpvBY_O1SnM2zzLv8i_Xc9_a60rVUNgv3cvLR7G9UIEL1ejUD4CW7LLkNfxNr5swSCotkoZ4Xd3 .Karj3kNJWHB3GsnC05LlYJBEkxizV1OomiVv84GD8x2VMw.TnQgjaLKty26AcVmvVKMw7G0g2zl 0c8RFEyqUTGBWdsSV7WCPDCfWwinwikfq5rCBkEWGXd822o74Rp3GNQMVsgT3gNhLhvHu3a1cplZ l0P45FDdcszE3MXa.I6I.9V3zHOXpDfzPACj14tGR3sm6ViCZynzH7WFSjGIPaMHD.psmsXfaANw MiJ5t1MaQP6K055EMpiZJOePY7OUJobGBjwU- Received: from sonic.gate.mail.ne1.yahoo.com by sonic305.consmr.mail.ne1.yahoo.com with HTTP; Fri, 27 Oct 2017 21:45:27 +0000 Received: from [127.0.0.1] by smtp111.mail.ne1.yahoo.com with NNFMP; 27 Oct 2017 21:45:22 -0000 X-Yahoo-Newman-Id: 596738.7300.bm@smtp111.mail.ne1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: ibwiE5oVM1l.OHFiBQx.sPC7OkH7NTSOWlwbYaiz4bDZrGl jkoOXAFVCAyZZxJGlsApU8GmpXF_KdeM1v83QR5K60z25MSIndxcPybeFJ0w .Xor0Ejq3mMZcQzwZABxlj66CrblMDlwwRsbpsmzbU4mEJAYDSJhZ6ZUD2XI o76.kfFDbSLINXNX5LkB_KWh.bNHju6Hpq.8xb3L7MZR4YAxqUpvBY_O1SnM 2zzLv8i_Xc9_a60rVUNgv3cvLR7G9UIEL1ejUD4CW7LLkNfxNr5swSCotkoZ 4Xd3.Karj3kNJWHB3GsnC05LlYJBEkxizV1OomiVv84GD8x2VMw.TnQgjaLK ty26AcVmvVKMw7G0g2zl0c8RFEyqUTGBWdsSV7WCPDCfWwinwikfq5rCBkEW GXd822o74Rp3GNQMVsgT3gNhLhvHu3a1cplZl0P45FDdcszE3MXa.I6I.9V3 zHOXpDfzPACj14tGR3sm6ViCZynzH7WFSjGIPaMHD.psmsXfaANwMiJ5t1Ma QP6K055EMpiZJOePY7OUJobGBjwU- X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Subject: [PATCH 5/9] LSM: Manage remaining security blobs To: LSM , James Morris Cc: John Johansen , Tetsuo Handa , Paul Moore , Kees Cook , Stephen Smalley References: <1473402e-a714-7ace-2698-b65d73e3f17e@schaufler-ca.com> From: Casey Schaufler Message-ID: Date: Fri, 27 Oct 2017 14:45:19 -0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <1473402e-a714-7ace-2698-b65d73e3f17e@schaufler-ca.com> Content-Language: en-US Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Subject: [PATCH 5/9] LSM: Manage remaining security blobs Move management of the inode, ipc, key, msg_msg, sock and superblock security blobs from the security modules to the infrastructure. Use of the blob pointers is abstracted in the security modules. Signed-off-by: Casey Schaufler --- include/linux/lsm_hooks.h | 8 + security/apparmor/include/net.h | 6 + security/apparmor/lsm.c | 22 +-- security/security.c | 258 +++++++++++++++++++++++++++- security/selinux/hooks.c | 333 ++++++++++++------------------------ security/selinux/include/objsec.h | 65 ++++++- security/selinux/netlabel.c | 15 +- security/selinux/selinuxfs.c | 4 +- security/selinux/ss/services.c | 3 +- security/smack/smack.h | 61 ++++++- security/smack/smack_lsm.c | 349 +++++++++++--------------------------- security/smack/smack_netfilter.c | 8 +- 12 files changed, 610 insertions(+), 522 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 44f8619d93d6..cae3f6591044 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1920,6 +1920,12 @@ struct security_hook_list { struct lsm_blob_sizes { int lbs_cred; int lbs_file; + int lbs_inode; + int lbs_ipc; + int lbs_key; + int lbs_msg_msg; + int lbs_sock; + int lbs_superblock; int lbs_task; }; @@ -1983,9 +1989,11 @@ static inline void loadpin_add_hooks(void) { }; #endif extern int lsm_cred_alloc(struct cred *cred, gfp_t gfp); +extern int lsm_inode_alloc(struct inode *inode); #ifdef CONFIG_SECURITY void lsm_early_cred(struct cred *cred); +void lsm_early_inode(struct inode *inode); #endif #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index 140c8efcf364..c0400c3a24f7 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -56,8 +56,14 @@ struct aa_sk_ctx { struct path path; }; +#ifdef CONFIG_SECURITY_STACKING +#define SK_CTX(X) ((X)->sk_security + apparmor_blob_sizes.lbs_sock) +#define SOCK_ctx(X) (SOCK_INODE(X)->i_security + apparmor_blob_sizes.lbs_inode) +#else #define SK_CTX(X) ((X)->sk_security) #define SOCK_ctx(X) SOCK_INODE(X)->i_security +#endif + #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ struct lsm_network_audit NAME ## _net = { .sk = (SK), \ .family = (F)}; \ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index f2814ba84481..8edbf79062cd 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -715,33 +715,15 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, } /** - * apparmor_sk_alloc_security - allocate and attach the sk_security field - */ -static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) -{ - struct aa_sk_ctx *ctx; - - ctx = kzalloc(sizeof(*ctx), flags); - if (!ctx) - return -ENOMEM; - - SK_CTX(sk) = ctx; - - return 0; -} - -/** * apparmor_sk_free_security - free the sk_security field */ static void apparmor_sk_free_security(struct sock *sk) { struct aa_sk_ctx *ctx = SK_CTX(sk); - SK_CTX(sk) = NULL; aa_put_label(ctx->label); aa_put_label(ctx->peer); path_put(&ctx->path); - kfree(ctx); } /** @@ -1079,6 +1061,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) struct lsm_blob_sizes apparmor_blob_sizes = { .lbs_cred = sizeof(struct aa_task_ctx), .lbs_file = sizeof(struct aa_file_ctx), + .lbs_sock = sizeof(struct aa_sk_ctx), }; static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { @@ -1115,7 +1098,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), - LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), @@ -1487,6 +1469,8 @@ static int __init apparmor_init(void) if (!finish) { if (apparmor_enabled && security_module_enable("apparmor")) security_add_blobs(&apparmor_blob_sizes); + else + apparmor_enabled = 0; finish = 1; return 0; } diff --git a/security/security.c b/security/security.c index 70740b902e16..8439acd36160 100644 --- a/security/security.c +++ b/security/security.c @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -38,6 +40,7 @@ struct security_hook_heads security_hook_heads __lsm_ro_after_init; static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); static struct kmem_cache *lsm_file_cache; +static struct kmem_cache *lsm_inode_cache; char *lsm_names; static struct lsm_blob_sizes blob_sizes; @@ -91,6 +94,10 @@ int __init security_init(void) lsm_file_cache = kmem_cache_create("lsm_file_cache", blob_sizes.lbs_file, 0, SLAB_PANIC, NULL); + if (blob_sizes.lbs_inode) + lsm_inode_cache = kmem_cache_create("lsm_inode_cache", + blob_sizes.lbs_inode, 0, + SLAB_PANIC, NULL); /* * The second call to a module specific init function * adds hooks to the hook lists and does any other early @@ -101,8 +108,16 @@ int __init security_init(void) #ifdef CONFIG_SECURITY_LSM_DEBUG pr_info("LSM: cred blob size = %d\n", blob_sizes.lbs_cred); pr_info("LSM: file blob size = %d\n", blob_sizes.lbs_file); + pr_info("LSM: inode blob size = %d\n", blob_sizes.lbs_inode); + pr_info("LSM: ipc blob size = %d\n", blob_sizes.lbs_ipc); +#ifdef CONFIG_KEYS + pr_info("LSM: key blob size = %d\n", blob_sizes.lbs_key); +#endif /* CONFIG_KEYS */ + pr_info("LSM: msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); + pr_info("LSM: sock blob size = %d\n", blob_sizes.lbs_sock); + pr_info("LSM: superblock blob size = %d\n", blob_sizes.lbs_superblock); pr_info("LSM: task blob size = %d\n", blob_sizes.lbs_task); -#endif +#endif /* CONFIG_SECURITY_LSM_DEBUG */ return 0; } @@ -279,7 +294,19 @@ void __init security_add_blobs(struct lsm_blob_sizes *needed) { lsm_set_size(&needed->lbs_cred, &blob_sizes.lbs_cred); lsm_set_size(&needed->lbs_file, &blob_sizes.lbs_file); + lsm_set_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc); + lsm_set_size(&needed->lbs_key, &blob_sizes.lbs_key); + lsm_set_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); + lsm_set_size(&needed->lbs_sock, &blob_sizes.lbs_sock); + lsm_set_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock); lsm_set_size(&needed->lbs_task, &blob_sizes.lbs_task); + /* + * The inode blob gets an rcu_head in addition to + * what the modules might need. + */ + if (needed->lbs_inode && blob_sizes.lbs_inode == 0) + blob_sizes.lbs_inode = sizeof(struct rcu_head); + lsm_set_size(&needed->lbs_inode, &blob_sizes.lbs_inode); } /** @@ -324,6 +351,162 @@ int lsm_task_alloc(struct task_struct *task) return 0; } +/** + * lsm_inode_alloc - allocate a composite inode blob + * @inode: the inode that needs a blob + * + * Allocate the inode blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_inode_alloc(struct inode *inode) +{ + if (!lsm_inode_cache) + return 0; + + inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_KERNEL); + if (inode->i_security == NULL) + return -ENOMEM; + return 0; +} + +/** + * lsm_early_inode - during initialization allocate a composite inode blob + * @inode: the inode that needs a blob + * + * Allocate the inode blob for all the modules if it's not already there + */ +void lsm_early_inode(struct inode *inode) +{ + int rc; + + if (inode == NULL) + panic("%s: NULL inode.\n", __func__); + if (inode->i_security != NULL) + return; + rc = lsm_inode_alloc(inode); + if (rc) + panic("%s: Early inode alloc failed.\n", __func__); +} + +/** + * lsm_ipc_alloc - allocate a composite ipc blob + * @kip: the ipc that needs a blob + * + * Allocate the ipc blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_ipc_alloc(struct kern_ipc_perm *kip) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (kip->security) + pr_info("%s: Inbound ipc blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_ipc == 0) + return 0; + + kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL); + if (kip->security == NULL) + return -ENOMEM; + return 0; +} + +#ifdef CONFIG_KEYS +/** + * lsm_key_alloc - allocate a composite key blob + * @key: the key that needs a blob + * + * Allocate the key blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_key_alloc(struct key *key) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (key->security) + pr_info("%s: Inbound key blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_key == 0) + return 0; + + key->security = kzalloc(blob_sizes.lbs_key, GFP_KERNEL); + if (key->security == NULL) + return -ENOMEM; + return 0; +} +#endif /* CONFIG_KEYS */ + +/** + * lsm_msg_msg_alloc - allocate a composite msg_msg blob + * @mp: the msg_msg that needs a blob + * + * Allocate the ipc blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_msg_msg_alloc(struct msg_msg *mp) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (mp->security) + pr_info("%s: Inbound msg_msg blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_msg_msg == 0) + return 0; + + mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL); + if (mp->security == NULL) + return -ENOMEM; + return 0; +} + +/** + * lsm_sock_alloc - allocate a composite sock blob + * @sock: the sock that needs a blob + * @priority: allocation mode + * + * Allocate the sock blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_sock_alloc(struct sock *sock, gfp_t priority) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (sock->sk_security) + pr_info("%s: Inbound sock blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_sock == 0) + return 0; + + sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority); + if (sock->sk_security == NULL) + return -ENOMEM; + return 0; +} + +/** + * lsm_superblock_alloc - allocate a composite superblock blob + * @sb: the superblock that needs a blob + * + * Allocate the superblock blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +int lsm_superblock_alloc(struct super_block *sb) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (sb->s_security) + pr_info("%s: Inbound superblock blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_superblock == 0) + return 0; + + sb->s_security = kzalloc(blob_sizes.lbs_superblock, GFP_KERNEL); + if (sb->s_security == NULL) + return -ENOMEM; + return 0; +} + /* * Hook list operation macros. * @@ -491,12 +674,18 @@ void security_bprm_committed_creds(struct linux_binprm *bprm) int security_sb_alloc(struct super_block *sb) { + int rc = lsm_superblock_alloc(sb); + + if (rc) + return rc; return call_int_hook(sb_alloc_security, 0, sb); } void security_sb_free(struct super_block *sb) { call_void_hook(sb_free_security, sb); + kfree(sb->s_security); + sb->s_security = NULL; } int security_sb_copy_data(char *orig, char *copy) @@ -570,14 +759,37 @@ EXPORT_SYMBOL(security_sb_parse_opts_str); int security_inode_alloc(struct inode *inode) { - inode->i_security = NULL; + int rc = lsm_inode_alloc(inode); + + if (rc) + return rc; return call_int_hook(inode_alloc_security, 0, inode); } +static void inode_free_by_rcu(struct rcu_head *head) +{ + /* + * The rcu head is at the start of the inode blob + */ + kmem_cache_free(lsm_inode_cache, head); +} + void security_inode_free(struct inode *inode) { integrity_inode_free(inode); call_void_hook(inode_free_security, inode); + /* + * The inode may still be referenced in a path walk and + * a call to security_inode_permission() can be made + * after inode_free_security() is called. Ideally, the VFS + * wouldn't do this, but fixing that is a much harder + * job. For now, simply free the i_security via RCU, and + * leave the current inode->i_security pointer intact. + * The inode will be freed after the RCU grace period too. + */ + if (inode->i_security) + call_rcu((struct rcu_head *)inode->i_security, + inode_free_by_rcu); } int security_dentry_init_security(struct dentry *dentry, int mode, @@ -1325,22 +1537,36 @@ void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) int security_msg_msg_alloc(struct msg_msg *msg) { + int rc = lsm_msg_msg_alloc(msg); + + if (rc) + return rc; return call_int_hook(msg_msg_alloc_security, 0, msg); } void security_msg_msg_free(struct msg_msg *msg) { call_void_hook(msg_msg_free_security, msg); + kfree(msg->security); + msg->security = NULL; } int security_msg_queue_alloc(struct msg_queue *msq) { + int rc = lsm_ipc_alloc(&msq->q_perm); + + if (rc) + return rc; return call_int_hook(msg_queue_alloc_security, 0, msq); } void security_msg_queue_free(struct msg_queue *msq) { + struct kern_ipc_perm *kip = &msq->q_perm; + call_void_hook(msg_queue_free_security, msq); + kfree(kip->security); + kip->security = NULL; } int security_msg_queue_associate(struct msg_queue *msq, int msqflg) @@ -1367,12 +1593,20 @@ int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, int security_shm_alloc(struct shmid_kernel *shp) { + int rc = lsm_ipc_alloc(&shp->shm_perm); + + if (rc) + return rc; return call_int_hook(shm_alloc_security, 0, shp); } void security_shm_free(struct shmid_kernel *shp) { + struct kern_ipc_perm *kip = &shp->shm_perm; + call_void_hook(shm_free_security, shp); + kfree(kip->security); + kip->security = NULL; } int security_shm_associate(struct shmid_kernel *shp, int shmflg) @@ -1392,12 +1626,20 @@ int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmfl int security_sem_alloc(struct sem_array *sma) { + int rc = lsm_ipc_alloc(&sma->sem_perm); + + if (rc) + return rc; return call_int_hook(sem_alloc_security, 0, sma); } void security_sem_free(struct sem_array *sma) { + struct kern_ipc_perm *kip = &sma->sem_perm; + call_void_hook(sem_free_security, sma); + kfree(kip->security); + kip->security = NULL; } int security_sem_associate(struct sem_array *sma, int semflg) @@ -1609,12 +1851,18 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram); int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { + int rc = lsm_sock_alloc(sk, priority); + + if (rc) + return rc; return call_int_hook(sk_alloc_security, 0, sk, family, priority); } void security_sk_free(struct sock *sk) { call_void_hook(sk_free_security, sk); + kfree(sk->sk_security); + sk->sk_security = NULL; } void security_sk_clone(const struct sock *sk, struct sock *newsk) @@ -1844,12 +2092,18 @@ EXPORT_SYMBOL(security_skb_classify_flow); int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { + int rc = lsm_key_alloc(key); + + if (rc) + return rc; return call_int_hook(key_alloc, 0, key, cred, flags); } void security_key_free(struct key *key) { call_void_hook(key_free, key); + kfree(key->security); + key->security = NULL; } int security_key_permission(key_ref_t key_ref, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 28e641f829b2..cfee70096f97 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -128,8 +128,6 @@ __setup("selinux=", selinux_enabled_setup); int selinux_enabled = 1; #endif -static struct kmem_cache *sel_inode_cache; - /** * selinux_secmark_enabled - Check to see if SECMARK is currently enabled * @@ -223,13 +221,9 @@ static inline u32 task_sid(const struct task_struct *task) static int inode_alloc_security(struct inode *inode) { - struct inode_security_struct *isec; + struct inode_security_struct *isec = selinux_inode(inode); u32 sid = current_sid(); - isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS); - if (!isec) - return -ENOMEM; - spin_lock_init(&isec->lock); INIT_LIST_HEAD(&isec->list); isec->inode = inode; @@ -237,7 +231,6 @@ static int inode_alloc_security(struct inode *inode) isec->sclass = SECCLASS_FILE; isec->task_sid = sid; isec->initialized = LABEL_INVALID; - inode->i_security = isec; return 0; } @@ -255,7 +248,7 @@ static int __inode_security_revalidate(struct inode *inode, struct dentry *opt_dentry, bool may_sleep) { - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); might_sleep_if(may_sleep); @@ -275,7 +268,7 @@ static int __inode_security_revalidate(struct inode *inode, static struct inode_security_struct *inode_security_novalidate(struct inode *inode) { - return inode->i_security; + return selinux_inode(inode); } static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu) @@ -285,7 +278,7 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo error = __inode_security_revalidate(inode, NULL, !rcu); if (error) return ERR_PTR(error); - return inode->i_security; + return selinux_inode(inode); } /* @@ -294,14 +287,14 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo static struct inode_security_struct *inode_security(struct inode *inode) { __inode_security_revalidate(inode, NULL, true); - return inode->i_security; + return selinux_inode(inode); } static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry) { struct inode *inode = d_backing_inode(dentry); - return inode->i_security; + return selinux_inode(inode); } /* @@ -312,21 +305,14 @@ static struct inode_security_struct *backing_inode_security(struct dentry *dentr struct inode *inode = d_backing_inode(dentry); __inode_security_revalidate(inode, dentry, true); - return inode->i_security; -} - -static void inode_free_rcu(struct rcu_head *head) -{ - struct inode_security_struct *isec; - - isec = container_of(head, struct inode_security_struct, rcu); - kmem_cache_free(sel_inode_cache, isec); + return selinux_inode(inode); } static void inode_free_security(struct inode *inode) { - struct inode_security_struct *isec = inode->i_security; - struct superblock_security_struct *sbsec = inode->i_sb->s_security; + struct inode_security_struct *isec = selinux_inode(inode); + struct superblock_security_struct *sbsec = + selinux_superblock(inode->i_sb); /* * As not all inode security structures are in a list, we check for @@ -343,17 +329,6 @@ static void inode_free_security(struct inode *inode) list_del_init(&isec->list); spin_unlock(&sbsec->isec_lock); } - - /* - * The inode may still be referenced in a path walk and - * a call to selinux_inode_permission() can be made - * after inode_free_security() is called. Ideally, the VFS - * wouldn't do this, but fixing that is a much harder - * job. For now, simply free the i_security via RCU, and - * leave the current inode->i_security pointer intact. - * The inode will be freed after the RCU grace period too. - */ - call_rcu(&isec->rcu, inode_free_rcu); } static int file_alloc_security(struct file *file) @@ -369,11 +344,7 @@ static int file_alloc_security(struct file *file) static int superblock_alloc_security(struct super_block *sb) { - struct superblock_security_struct *sbsec; - - sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL); - if (!sbsec) - return -ENOMEM; + struct superblock_security_struct *sbsec = selinux_superblock(sb); mutex_init(&sbsec->lock); INIT_LIST_HEAD(&sbsec->isec_head); @@ -382,18 +353,10 @@ static int superblock_alloc_security(struct super_block *sb) sbsec->sid = SECINITSID_UNLABELED; sbsec->def_sid = SECINITSID_FILE; sbsec->mntpoint_sid = SECINITSID_UNLABELED; - sb->s_security = sbsec; return 0; } -static void superblock_free_security(struct super_block *sb) -{ - struct superblock_security_struct *sbsec = sb->s_security; - sb->s_security = NULL; - kfree(sbsec); -} - static inline int inode_doinit(struct inode *inode) { return inode_doinit_with_dentry(inode, NULL); @@ -457,7 +420,7 @@ static int may_context_mount_inode_relabel(u32 sid, static int selinux_is_sblabel_mnt(struct super_block *sb) { - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); return sbsec->behavior == SECURITY_FS_USE_XATTR || sbsec->behavior == SECURITY_FS_USE_TRANS || @@ -476,7 +439,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) static int sb_finish_set_opts(struct super_block *sb) { - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); struct dentry *root = sb->s_root; struct inode *root_inode = d_backing_inode(root); int rc = 0; @@ -559,7 +522,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb, struct security_mnt_opts *opts) { int rc = 0, i; - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); char *context = NULL; u32 len; char tmp; @@ -622,7 +585,8 @@ static int selinux_get_mnt_opts(const struct super_block *sb, } if (sbsec->flags & ROOTCONTEXT_MNT) { struct dentry *root = sbsec->sb->s_root; - struct inode_security_struct *isec = backing_inode_security(root); + struct inode_security_struct *isec = + backing_inode_security(root); rc = security_sid_to_context(isec->sid, &context, &len); if (rc) @@ -675,7 +639,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, { const struct cred *cred = current_cred(); int rc = 0, i; - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); const char *name = sb->s_type->name; struct dentry *root = sbsec->sb->s_root; struct inode_security_struct *root_isec; @@ -926,8 +890,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, static int selinux_cmp_sb_context(const struct super_block *oldsb, const struct super_block *newsb) { - struct superblock_security_struct *old = oldsb->s_security; - struct superblock_security_struct *new = newsb->s_security; + struct superblock_security_struct *old = selinux_superblock(oldsb); + struct superblock_security_struct *new = selinux_superblock(newsb); char oldflags = old->flags & SE_MNTMASK; char newflags = new->flags & SE_MNTMASK; @@ -959,8 +923,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, unsigned long *set_kern_flags) { int rc = 0; - const struct superblock_security_struct *oldsbsec = oldsb->s_security; - struct superblock_security_struct *newsbsec = newsb->s_security; + const struct superblock_security_struct *oldsbsec = + selinux_superblock(oldsb); + struct superblock_security_struct *newsbsec = selinux_superblock(newsb); int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT); int set_context = (oldsbsec->flags & CONTEXT_MNT); @@ -1013,14 +978,17 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, if (!set_fscontext) newsbsec->sid = sid; if (!set_rootcontext) { - struct inode_security_struct *newisec = backing_inode_security(newsb->s_root); + struct inode_security_struct *newisec = + backing_inode_security(newsb->s_root); newisec->sid = sid; } newsbsec->mntpoint_sid = sid; } if (set_rootcontext) { - const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root); - struct inode_security_struct *newisec = backing_inode_security(newsb->s_root); + const struct inode_security_struct *oldisec = + backing_inode_security(oldsb->s_root); + struct inode_security_struct *newisec = + backing_inode_security(newsb->s_root); newisec->sid = oldisec->sid; } @@ -1464,7 +1432,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry, static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) { struct superblock_security_struct *sbsec = NULL; - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); u32 task_sid, sid = 0; u16 sclass; struct dentry *dentry; @@ -1483,7 +1451,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (isec->sclass == SECCLASS_FILE) isec->sclass = inode_mode_to_security_class(inode->i_mode); - sbsec = inode->i_sb->s_security; + sbsec = selinux_superblock(inode->i_sb); if (!(sbsec->flags & SE_SBINITIALIZED)) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security @@ -1749,7 +1717,7 @@ static int inode_has_perm(const struct cred *cred, return 0; sid = cred_sid(cred); - isec = inode->i_security; + isec = selinux_inode(inode); return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); } @@ -1846,7 +1814,8 @@ selinux_determine_inode_label(const struct task_security_struct *tsec, const struct qstr *name, u16 tclass, u32 *_new_isid) { - const struct superblock_security_struct *sbsec = dir->i_sb->s_security; + const struct superblock_security_struct *sbsec = + selinux_superblock(dir->i_sb); if ((sbsec->flags & SE_SBINITIALIZED) && (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) { @@ -1876,7 +1845,7 @@ static int may_create(struct inode *dir, int rc; dsec = inode_security(dir); - sbsec = dir->i_sb->s_security; + sbsec = selinux_superblock(dir->i_sb); sid = tsec->sid; @@ -2015,7 +1984,7 @@ static int superblock_has_perm(const struct cred *cred, struct superblock_security_struct *sbsec; u32 sid = cred_sid(cred); - sbsec = sb->s_security; + sbsec = selinux_superblock(sb); return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); } @@ -2614,11 +2583,6 @@ static int selinux_sb_alloc_security(struct super_block *sb) return superblock_alloc_security(sb); } -static void selinux_sb_free_security(struct super_block *sb) -{ - superblock_free_security(sb); -} - static inline int match_prefix(char *prefix, int plen, char *option, int olen) { if (plen > olen) @@ -2715,7 +2679,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data) int rc, i, *flags; struct security_mnt_opts opts; char *secdata, **mount_options; - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); if (!(sbsec->flags & SE_SBINITIALIZED)) return 0; @@ -2906,7 +2870,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, int rc; char *context; - sbsec = dir->i_sb->s_security; + sbsec = selinux_superblock(dir->i_sb); sid = tsec->sid; newsid = tsec->create_sid; @@ -2920,7 +2884,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, /* Possibly defer initialization to selinux_complete_init. */ if (sbsec->flags & SE_SBINITIALIZED) { - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sid = newsid; isec->initialized = LABEL_INITIALIZED; @@ -3018,7 +2982,7 @@ static noinline int audit_inode_permission(struct inode *inode, unsigned flags) { struct common_audit_data ad; - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); int rc; ad.type = LSM_AUDIT_DATA_INODE; @@ -3154,7 +3118,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, if (strcmp(name, XATTR_NAME_SELINUX)) return selinux_inode_setotherxattr(dentry, name); - sbsec = inode->i_sb->s_security; + sbsec = selinux_superblock(inode->i_sb); if (!(sbsec->flags & SBLABEL_MNT)) return -EOPNOTSUPP; @@ -3987,7 +3951,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, static void selinux_task_to_inode(struct task_struct *p, struct inode *inode) { - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); u32 sid = task_sid(p); spin_lock(&isec->lock); @@ -4273,7 +4237,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, static int sock_has_perm(struct sock *sk, u32 perms) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct common_audit_data ad; struct lsm_network_audit net = {0,}; @@ -4328,7 +4292,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, isec->initialized = LABEL_INITIALIZED; if (sock->sk) { - sksec = sock->sk->sk_security; + sksec = selinux_sock(sock->sk); sksec->sclass = sclass; sksec->sid = sid; err = selinux_netlbl_socket_post_create(sock->sk, family); @@ -4359,7 +4323,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in family = sk->sk_family; if (family == PF_INET || family == PF_INET6) { char *addrp; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct common_audit_data ad; struct lsm_network_audit net = {0,}; struct sockaddr_in *addr4 = NULL; @@ -4452,7 +4416,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { struct sock *sk = sock->sk; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); int err; err = sock_has_perm(sk, SOCKET__CONNECT); @@ -4584,9 +4548,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { - struct sk_security_struct *sksec_sock = sock->sk_security; - struct sk_security_struct *sksec_other = other->sk_security; - struct sk_security_struct *sksec_new = newsk->sk_security; + struct sk_security_struct *sksec_sock = selinux_sock(sock); + struct sk_security_struct *sksec_other = selinux_sock(other); + struct sk_security_struct *sksec_new = selinux_sock(newsk); struct common_audit_data ad; struct lsm_network_audit net = {0,}; int err; @@ -4617,8 +4581,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, static int selinux_socket_unix_may_send(struct socket *sock, struct socket *other) { - struct sk_security_struct *ssec = sock->sk->sk_security; - struct sk_security_struct *osec = other->sk->sk_security; + struct sk_security_struct *ssec = selinux_sock(sock->sk); + struct sk_security_struct *osec = selinux_sock(other->sk); struct common_audit_data ad; struct lsm_network_audit net = {0,}; @@ -4657,7 +4621,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, u16 family) { int err = 0; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); u32 sk_sid = sksec->sid; struct common_audit_data ad; struct lsm_network_audit net = {0,}; @@ -4689,7 +4653,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { int err; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); u16 family = sk->sk_family; u32 sk_sid = sksec->sid; struct common_audit_data ad; @@ -4755,13 +4719,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return err; } -static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static int selinux_socket_getpeersec_stream(struct socket *sock, + __user char *optval, + __user int *optlen, + unsigned int len) { int err = 0; char *scontext; u32 scontext_len; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sock->sk); u32 peer_sid = SECSID_NULL; if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || @@ -4819,34 +4785,27 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) { - struct sk_security_struct *sksec; - - sksec = kzalloc(sizeof(*sksec), priority); - if (!sksec) - return -ENOMEM; + struct sk_security_struct *sksec = selinux_sock(sk); sksec->peer_sid = SECINITSID_UNLABELED; sksec->sid = SECINITSID_UNLABELED; sksec->sclass = SECCLASS_SOCKET; selinux_netlbl_sk_security_reset(sksec); - sk->sk_security = sksec; return 0; } static void selinux_sk_free_security(struct sock *sk) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); - sk->sk_security = NULL; selinux_netlbl_sk_security_free(sksec); - kfree(sksec); } static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) { - struct sk_security_struct *sksec = sk->sk_security; - struct sk_security_struct *newsksec = newsk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); + struct sk_security_struct *newsksec = selinux_sock(newsk); newsksec->sid = sksec->sid; newsksec->peer_sid = sksec->peer_sid; @@ -4860,7 +4819,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid) if (!sk) *secid = SECINITSID_ANY_SOCKET; else { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); *secid = sksec->sid; } @@ -4870,7 +4829,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) { struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(parent)); - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || sk->sk_family == PF_UNIX) @@ -4881,7 +4840,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); int err; u16 family = req->rsk_ops->family; u32 connsid; @@ -4902,7 +4861,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, static void selinux_inet_csk_clone(struct sock *newsk, const struct request_sock *req) { - struct sk_security_struct *newsksec = newsk->sk_security; + struct sk_security_struct *newsksec = selinux_sock(newsk); newsksec->sid = req->secid; newsksec->peer_sid = req->peer_secid; @@ -4919,7 +4878,7 @@ static void selinux_inet_csk_clone(struct sock *newsk, static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) { u16 family = sk->sk_family; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); /* handle mapped IPv4 packets arriving via IPv6 sockets */ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) @@ -4999,7 +4958,7 @@ static int selinux_tun_dev_attach_queue(void *security) static int selinux_tun_dev_attach(struct sock *sk, void *security) { struct tun_security_struct *tunsec = security; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); /* we don't currently perform any NetLabel based labeling here and it * isn't clear that we would want to do so anyway; while we could apply @@ -5038,7 +4997,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) int err = 0; u32 perm; struct nlmsghdr *nlh; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (skb->len < NLMSG_HDRLEN) { err = -EINVAL; @@ -5177,7 +5136,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, return NF_ACCEPT; /* standard practice, label using the parent socket */ - sksec = sk->sk_security; + sksec = selinux_sock(sk); sid = sksec->sid; } else sid = SECINITSID_KERNEL; @@ -5216,7 +5175,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, if (sk == NULL) return NF_ACCEPT; - sksec = sk->sk_security; + sksec = selinux_sock(sk); ad.type = LSM_AUDIT_DATA_NET; ad.u.net = &net; @@ -5307,7 +5266,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, u32 skb_sid; struct sk_security_struct *sksec; - sksec = sk->sk_security; + sksec = selinux_sock(sk); if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) return NF_DROP; /* At this point, if the returned skb peerlbl is SECSID_NULL @@ -5336,7 +5295,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, } else { /* Locally generated packet, fetch the security label from the * associated socket. */ - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); peer_sid = sksec->sid; secmark_perm = PACKET__SEND; } @@ -5396,51 +5355,22 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) return selinux_nlmsg_perm(sk, skb); } -static int ipc_alloc_security(struct kern_ipc_perm *perm, - u16 sclass) +static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass) { - struct ipc_security_struct *isec; - - isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); - if (!isec) - return -ENOMEM; - isec->sclass = sclass; isec->sid = current_sid(); - perm->security = isec; - - return 0; -} - -static void ipc_free_security(struct kern_ipc_perm *perm) -{ - struct ipc_security_struct *isec = perm->security; - perm->security = NULL; - kfree(isec); } static int msg_msg_alloc_security(struct msg_msg *msg) { struct msg_security_struct *msec; - msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL); - if (!msec) - return -ENOMEM; - + msec = selinux_msg_msg(msg); msec->sid = SECINITSID_UNLABELED; - msg->security = msec; return 0; } -static void msg_msg_free_security(struct msg_msg *msg) -{ - struct msg_security_struct *msec = msg->security; - - msg->security = NULL; - kfree(msec); -} - static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, u32 perms) { @@ -5448,7 +5378,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, struct common_audit_data ad; u32 sid = current_sid(); - isec = ipc_perms->security; + isec = selinux_ipc(ipc_perms); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = ipc_perms->key; @@ -5461,11 +5391,6 @@ static int selinux_msg_msg_alloc_security(struct msg_msg *msg) return msg_msg_alloc_security(msg); } -static void selinux_msg_msg_free_security(struct msg_msg *msg) -{ - msg_msg_free_security(msg); -} - /* message queue security operations */ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) { @@ -5474,27 +5399,15 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ); - if (rc) - return rc; - - isec = msq->q_perm.security; + isec = selinux_ipc(&msq->q_perm); + ipc_init_security(isec, SECCLASS_MSGQ); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->q_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, MSGQ__CREATE, &ad); - if (rc) { - ipc_free_security(&msq->q_perm); - return rc; - } - return 0; -} - -static void selinux_msg_queue_free_security(struct msg_queue *msq) -{ - ipc_free_security(&msq->q_perm); + return rc; } static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) @@ -5503,7 +5416,7 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) struct common_audit_data ad; u32 sid = current_sid(); - isec = msq->q_perm.security; + isec = selinux_ipc(&msq->q_perm); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->q_perm.key; @@ -5549,8 +5462,8 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, u32 sid = current_sid(); int rc; - isec = msq->q_perm.security; - msec = msg->security; + isec = selinux_ipc(&msq->q_perm); + msec = selinux_msg_msg(msg); /* * First time through, need to assign label to the message @@ -5594,8 +5507,8 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, u32 sid = task_sid(target); int rc; - isec = msq->q_perm.security; - msec = msg->security; + isec = selinux_ipc(&msq->q_perm); + msec = selinux_msg_msg(msg); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->q_perm.key; @@ -5616,27 +5529,15 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM); - if (rc) - return rc; - - isec = shp->shm_perm.security; + isec = selinux_ipc(&shp->shm_perm); + ipc_init_security(isec, SECCLASS_SHM); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->shm_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, SHM__CREATE, &ad); - if (rc) { - ipc_free_security(&shp->shm_perm); - return rc; - } - return 0; -} - -static void selinux_shm_free_security(struct shmid_kernel *shp) -{ - ipc_free_security(&shp->shm_perm); + return rc; } static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) @@ -5645,7 +5546,7 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) struct common_audit_data ad; u32 sid = current_sid(); - isec = shp->shm_perm.security; + isec = selinux_ipc(&shp->shm_perm); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->shm_perm.key; @@ -5709,27 +5610,15 @@ static int selinux_sem_alloc_security(struct sem_array *sma) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM); - if (rc) - return rc; - - isec = sma->sem_perm.security; + isec = selinux_ipc(&sma->sem_perm); + ipc_init_security(isec, SECCLASS_SEM); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->sem_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, SEM__CREATE, &ad); - if (rc) { - ipc_free_security(&sma->sem_perm); - return rc; - } - return 0; -} - -static void selinux_sem_free_security(struct sem_array *sma) -{ - ipc_free_security(&sma->sem_perm); + return rc; } static int selinux_sem_associate(struct sem_array *sma, int semflg) @@ -5738,7 +5627,7 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) struct common_audit_data ad; u32 sid = current_sid(); - isec = sma->sem_perm.security; + isec = selinux_ipc(&sma->sem_perm); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->sem_perm.key; @@ -5821,7 +5710,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) { - struct ipc_security_struct *isec = ipcp->security; + struct ipc_security_struct *isec = selinux_ipc(ipcp); *secid = isec->sid; } @@ -6031,7 +5920,7 @@ static void selinux_release_secctx(char *secdata, u32 seclen) static void selinux_inode_invalidate_secctx(struct inode *inode) { - struct inode_security_struct *isec = inode->i_security; + struct inode_security_struct *isec = selinux_inode(inode); spin_lock(&isec->lock); isec->initialized = LABEL_INVALID; @@ -6070,11 +5959,7 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred, unsigned long flags) { const struct task_security_struct *tsec; - struct key_security_struct *ksec; - - ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); - if (!ksec) - return -ENOMEM; + struct key_security_struct *ksec = selinux_key(k); tsec = selinux_cred(cred); if (tsec->keycreate_sid) @@ -6082,18 +5967,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred, else ksec->sid = tsec->sid; - k->security = ksec; return 0; } -static void selinux_key_free(struct key *k) -{ - struct key_security_struct *ksec = k->security; - - k->security = NULL; - kfree(ksec); -} - static int selinux_key_permission(key_ref_t key_ref, const struct cred *cred, unsigned perm) @@ -6111,14 +5987,14 @@ static int selinux_key_permission(key_ref_t key_ref, sid = cred_sid(cred); key = key_ref_to_ptr(key_ref); - ksec = key->security; + ksec = selinux_key(key); return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); } static int selinux_key_getsecurity(struct key *key, char **_buffer) { - struct key_security_struct *ksec = key->security; + struct key_security_struct *ksec = selinux_key(key); char *context = NULL; unsigned len; int rc; @@ -6198,6 +6074,14 @@ static void selinux_ib_free_security(void *ib_sec) struct lsm_blob_sizes selinux_blob_sizes = { .lbs_cred = sizeof(struct task_security_struct), .lbs_file = sizeof(struct file_security_struct), + .lbs_inode = sizeof(struct inode_security_struct), + .lbs_ipc = sizeof(struct ipc_security_struct), +#ifdef CONFIG_KEYS + .lbs_key = sizeof(struct key_security_struct), +#endif /* CONFIG_KEYS */ + .lbs_msg_msg = sizeof(struct msg_security_struct), + .lbs_sock = sizeof(struct sk_security_struct), + .lbs_superblock = sizeof(struct superblock_security_struct), }; static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { @@ -6223,7 +6107,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds), LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), - LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data), LSM_HOOK_INIT(sb_remount, selinux_sb_remount), LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), @@ -6306,24 +6189,20 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security), - LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security), LSM_HOOK_INIT(msg_queue_alloc_security, selinux_msg_queue_alloc_security), - LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security), LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate), LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl), LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd), LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv), LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security), - LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security), LSM_HOOK_INIT(shm_associate, selinux_shm_associate), LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl), LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat), LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security), - LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security), LSM_HOOK_INIT(sem_associate, selinux_sem_associate), LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl), LSM_HOOK_INIT(sem_semop, selinux_sem_semop), @@ -6405,7 +6284,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { #ifdef CONFIG_KEYS LSM_HOOK_INIT(key_alloc, selinux_key_alloc), - LSM_HOOK_INIT(key_free, selinux_key_free), LSM_HOOK_INIT(key_permission, selinux_key_permission), LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity), #endif @@ -6445,9 +6323,6 @@ static __init int selinux_init(void) default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); - sel_inode_cache = kmem_cache_create("selinux_inode_security", - sizeof(struct inode_security_struct), - 0, SLAB_PANIC, NULL); avc_init(); security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 504e15ed234f..f2f1e2d15eb8 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -59,10 +59,7 @@ enum label_initialized { struct inode_security_struct { struct inode *inode; /* back pointer to inode object */ - union { - struct list_head list; /* list of inode_security_struct */ - struct rcu_head rcu; /* for freeing the inode_security_struct */ - }; + struct list_head list; /* list of inode_security_struct */ u32 task_sid; /* SID of creating task */ u32 sid; /* SID of this object */ u16 sclass; /* security class of this object */ @@ -166,4 +163,64 @@ static inline struct file_security_struct *selinux_file(const struct file *file) return file->f_security; } +static inline struct inode_security_struct *selinux_inode( + const struct inode *inode) +{ +#ifdef CONFIG_SECURITY_STACKING + return inode->i_security + selinux_blob_sizes.lbs_inode; +#else + return inode->i_security; +#endif +} + +static inline struct superblock_security_struct *selinux_superblock( + const struct super_block *superblock) +{ +#ifdef CONFIG_SECURITY_STACKING + return superblock->s_security + selinux_blob_sizes.lbs_superblock; +#else + return superblock->s_security; +#endif +} + +static inline struct msg_security_struct *selinux_msg_msg( + const struct msg_msg *msg_msg) +{ +#ifdef CONFIG_SECURITY_STACKING + return msg_msg->security + selinux_blob_sizes.lbs_msg_msg; +#else + return msg_msg->security; +#endif +} + +static inline struct ipc_security_struct *selinux_ipc( + const struct kern_ipc_perm *ipc) +{ +#ifdef CONFIG_SECURITY_STACKING + return ipc->security + selinux_blob_sizes.lbs_ipc; +#else + return ipc->security; +#endif +} + +#ifdef CONFIG_KEYS +static inline struct key_security_struct *selinux_key(const struct key *key) +{ +#ifdef CONFIG_SECURITY_STACKING + return key->security + selinux_blob_sizes.lbs_key; +#else + return key->security; +#endif +} +#endif /* CONFIG_KEYS */ + +static inline struct sk_security_struct *selinux_sock(const struct sock *sock) +{ +#ifdef CONFIG_SECURITY_STACKING + return sock->sk_security + selinux_blob_sizes.lbs_sock; +#else + return sock->sk_security; +#endif +} + #endif /* _SELINUX_OBJSEC_H_ */ diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index aaba6677ee2e..0b0091c04688 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_secattr != NULL) @@ -114,7 +115,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( const struct sock *sk, u32 sid) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; if (secattr == NULL) @@ -249,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, * being labeled by it's parent socket, if it is just exit */ sk = skb_to_full_sk(skb); if (sk != NULL) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (sksec->nlbl_state != NLBL_REQSKB) return 0; secattr = selinux_netlbl_sock_getattr(sk, sid); @@ -311,7 +312,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) */ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) { - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); if (family == PF_INET) sksec->nlbl_state = NLBL_LABELED; @@ -332,7 +333,7 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; if (family != PF_INET && family != PF_INET6) @@ -446,7 +447,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, { int rc = 0; struct sock *sk = sock->sk; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr secattr; if (selinux_netlbl_option(level, optname) && @@ -482,7 +483,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) { int rc; - struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *sksec = selinux_sock(sk); struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_state != NLBL_REQSKB && diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 855a13053a81..1b4bed79101e 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1300,7 +1300,7 @@ static int sel_make_bools(void) if (len >= PAGE_SIZE) goto out; - isec = (struct inode_security_struct *)inode->i_security; + isec = (struct inode_security_struct *)selinux_inode(inode); ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); if (ret) { pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", @@ -1841,7 +1841,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) goto err; inode->i_ino = ++sel_last_ino; - isec = (struct inode_security_struct *)inode->i_security; + isec = (struct inode_security_struct *)selinux_inode(inode); isec->sid = SECINITSID_DEVNULL; isec->sclass = SECCLASS_CHR_FILE; isec->initialized = LABEL_INITIALIZED; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index e4a1c0dc561a..bfd09d0ddfd2 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include "flask.h" @@ -2659,7 +2660,7 @@ int security_fs_use(struct super_block *sb) { int rc = 0; struct ocontext *c; - struct superblock_security_struct *sbsec = sb->s_security; + struct superblock_security_struct *sbsec = selinux_superblock(sb); const char *fstype = sb->s_type->name; read_lock(&policy_rwlock); diff --git a/security/smack/smack.h b/security/smack/smack.h index d14e8d17eea0..1b875c2f3d9d 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -366,12 +366,69 @@ static inline struct smack_known **smack_file(const struct file *file) return file->f_security; } +static inline struct inode_smack *smack_inode(const struct inode *inode) +{ +#ifdef CONFIG_SECURITY_STACKING + return inode->i_security + smack_blob_sizes.lbs_inode; +#else + return inode->i_security; +#endif +} + +static inline struct socket_smack *smack_sock(const struct sock *sock) +{ +#ifdef CONFIG_SECURITY_STACKING + return sock->sk_security + smack_blob_sizes.lbs_sock; +#else + return sock->sk_security; +#endif +} + +static inline struct superblock_smack *smack_superblock( + const struct super_block *superblock) +{ +#ifdef CONFIG_SECURITY_STACKING + return superblock->s_security + smack_blob_sizes.lbs_superblock; +#else + return superblock->s_security; +#endif +} + +static inline struct smack_known **smack_msg_msg(const struct msg_msg *msg) +{ +#ifdef CONFIG_SECURITY_STACKING + return msg->security + smack_blob_sizes.lbs_msg_msg; +#else + return msg->security; +#endif +} + +static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc) +{ +#ifdef CONFIG_SECURITY_STACKING + return ipc->security + smack_blob_sizes.lbs_ipc; +#else + return ipc->security; +#endif +} + +#ifdef CONFIG_KEYS +static inline struct smack_known **smack_key(const struct key *key) +{ +#ifdef CONFIG_SECURITY_STACKING + return key->security + smack_blob_sizes.lbs_key; +#else + return key->security; +#endif +} +#endif /* CONFIG_KEYS */ + /* * Is the directory transmuting? */ static inline int smk_inode_transmutable(const struct inode *isp) { - struct inode_smack *sip = isp->i_security; + struct inode_smack *sip = smack_inode(isp); return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; } @@ -380,7 +437,7 @@ static inline int smk_inode_transmutable(const struct inode *isp) */ static inline struct smack_known *smk_of_inode(const struct inode *isp) { - struct inode_smack *sip = isp->i_security; + struct inode_smack *sip = smack_inode(isp); return sip->smk_inode; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a807624aff9a..4588c48aab86 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -165,7 +165,7 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc) static int smk_bu_inode(struct inode *inode, int mode, int rc) { struct task_smack *tsp = smack_cred(current_cred()); - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); char acc[SMK_NUM_ACCESS_TYPE + 1]; if (isp->smk_flags & SMK_INODE_IMPURE) @@ -197,7 +197,7 @@ static int smk_bu_file(struct file *file, int mode, int rc) struct task_smack *tsp = smack_cred(current_cred()); struct smack_known *sskp = tsp->smk_task; struct inode *inode = file_inode(file); - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); char acc[SMK_NUM_ACCESS_TYPE + 1]; if (isp->smk_flags & SMK_INODE_IMPURE) @@ -227,7 +227,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file, struct task_smack *tsp = smack_cred(cred); struct smack_known *sskp = tsp->smk_task; struct inode *inode = file_inode(file); - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); char acc[SMK_NUM_ACCESS_TYPE + 1]; if (isp->smk_flags & SMK_INODE_IMPURE) @@ -287,24 +287,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, } /** - * new_inode_smack - allocate an inode security blob + * init_inode_smack - initialize an inode security blob + * @isp: the blob to initialize * @skp: a pointer to the Smack label entry to use in the blob * - * Returns the new blob or NULL if there's no memory available */ -static struct inode_smack *new_inode_smack(struct smack_known *skp) +static void init_inode_smack(struct inode *inode, struct smack_known *skp) { - struct inode_smack *isp; - - isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS); - if (isp == NULL) - return NULL; + struct inode_smack *isp = smack_inode(inode); isp->smk_inode = skp; isp->smk_flags = 0; mutex_init(&isp->smk_lock); - - return isp; } /** @@ -525,12 +519,7 @@ static int smack_syslog(int typefrom_file) */ static int smack_sb_alloc_security(struct super_block *sb) { - struct superblock_smack *sbsp; - - sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL); - - if (sbsp == NULL) - return -ENOMEM; + struct superblock_smack *sbsp = smack_superblock(sb); sbsp->smk_root = &smack_known_floor; sbsp->smk_default = &smack_known_floor; @@ -539,23 +528,11 @@ static int smack_sb_alloc_security(struct super_block *sb) /* * SMK_SB_INITIALIZED will be zero from kzalloc. */ - sb->s_security = sbsp; return 0; } /** - * smack_sb_free_security - free a superblock blob - * @sb: the superblock getting the blob - * - */ -static void smack_sb_free_security(struct super_block *sb) -{ - kfree(sb->s_security); - sb->s_security = NULL; -} - -/** * smack_sb_copy_data - copy mount options data for processing * @orig: where to start * @smackopts: mount options string @@ -745,7 +722,7 @@ static int smack_set_mnt_opts(struct super_block *sb, { struct dentry *root = sb->s_root; struct inode *inode = d_backing_inode(root); - struct superblock_smack *sp = sb->s_security; + struct superblock_smack *sp = smack_superblock(sb); struct inode_smack *isp; struct smack_known *skp; int i; @@ -823,17 +800,13 @@ static int smack_set_mnt_opts(struct super_block *sb, /* * Initialize the root inode. */ - isp = inode->i_security; - if (isp == NULL) { - isp = new_inode_smack(sp->smk_root); - if (isp == NULL) - return -ENOMEM; - inode->i_security = isp; - } else - isp->smk_inode = sp->smk_root; + lsm_early_inode(inode); + init_inode_smack(inode, sp->smk_root); - if (transmute) + if (transmute) { + isp = smack_inode(inode); isp->smk_flags |= SMK_INODE_TRANSMUTE; + } return 0; } @@ -878,7 +851,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) */ static int smack_sb_statfs(struct dentry *dentry) { - struct superblock_smack *sbp = dentry->d_sb->s_security; + struct superblock_smack *sbp = smack_superblock(dentry->d_sb); int rc; struct smk_audit_info ad; @@ -911,11 +884,11 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) if (bprm->called_set_creds) return 0; - isp = inode->i_security; + isp = smack_inode(inode); if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) return 0; - sbsp = inode->i_sb->s_security; + sbsp = smack_superblock(inode->i_sb); if ((sbsp->smk_flags & SMK_SB_UNTRUSTED) && isp->smk_task != sbsp->smk_root) return 0; @@ -962,49 +935,11 @@ static int smack_inode_alloc_security(struct inode *inode) { struct smack_known *skp = smk_of_current(); - inode->i_security = new_inode_smack(skp); - if (inode->i_security == NULL) - return -ENOMEM; + init_inode_smack(inode, skp); return 0; } /** - * smack_inode_free_rcu - Free inode_smack blob from cache - * @head: the rcu_head for getting inode_smack pointer - * - * Call back function called from call_rcu() to free - * the i_security blob pointer in inode - */ -static void smack_inode_free_rcu(struct rcu_head *head) -{ - struct inode_smack *issp; - - issp = container_of(head, struct inode_smack, smk_rcu); - kmem_cache_free(smack_inode_cache, issp); -} - -/** - * smack_inode_free_security - free an inode blob using call_rcu() - * @inode: the inode with a blob - * - * Clears the blob pointer in inode using RCU - */ -static void smack_inode_free_security(struct inode *inode) -{ - struct inode_smack *issp = inode->i_security; - - /* - * The inode may still be referenced in a path walk and - * a call to smack_inode_permission() can be made - * after smack_inode_free_security() is called. - * To avoid race condition free the i_security via RCU - * and leave the current inode->i_security pointer intact. - * The inode will be freed after the RCU grace period too. - */ - call_rcu(&issp->smk_rcu, smack_inode_free_rcu); -} - -/** * smack_inode_init_security - copy out the smack from an inode * @inode: the newly created inode * @dir: containing directory object @@ -1019,7 +954,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len) { - struct inode_smack *issp = inode->i_security; + struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_current(); struct smack_known *isp = smk_of_inode(inode); struct smack_known *dsp = smk_of_inode(dir); @@ -1204,7 +1139,7 @@ static int smack_inode_rename(struct inode *old_inode, */ static int smack_inode_permission(struct inode *inode, int mask) { - struct superblock_smack *sbsp = inode->i_sb->s_security; + struct superblock_smack *sbsp = smack_superblock(inode->i_sb); struct smk_audit_info ad; int no_block = mask & MAY_NOT_BLOCK; int rc; @@ -1357,7 +1292,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct smack_known *skp; - struct inode_smack *isp = d_backing_inode(dentry)->i_security; + struct inode_smack *isp = smack_inode(d_backing_inode(dentry)); if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { isp->smk_flags |= SMK_INODE_TRANSMUTE; @@ -1438,7 +1373,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) if (rc != 0) return rc; - isp = d_backing_inode(dentry)->i_security; + isp = smack_inode(d_backing_inode(dentry)); /* * Don't do anything special for these. * XATTR_NAME_SMACKIPIN @@ -1446,7 +1381,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) */ if (strcmp(name, XATTR_NAME_SMACK) == 0) { struct super_block *sbp = dentry->d_sb; - struct superblock_smack *sbsp = sbp->s_security; + struct superblock_smack *sbsp = smack_superblock(sbp); isp->smk_inode = sbsp->smk_default; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) @@ -1498,7 +1433,7 @@ static int smack_inode_getsecurity(struct inode *inode, if (sock == NULL || sock->sk == NULL) return -EOPNOTSUPP; - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); if (strcmp(name, XATTR_SMACK_IPIN) == 0) isp = ssp->smk_in; @@ -1541,7 +1476,7 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer, */ static void smack_inode_getsecid(struct inode *inode, u32 *secid) { - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); *secid = isp->smk_inode->smk_secid; } @@ -1718,10 +1653,10 @@ static int smack_mmap_file(struct file *file, if (unlikely(IS_PRIVATE(file_inode(file)))) return 0; - isp = file_inode(file)->i_security; + isp = smack_inode(file_inode(file)); if (isp->smk_mmap == NULL) return 0; - sbsp = file_inode(file)->i_sb->s_security; + sbsp = smack_superblock(file_inode(file)->i_sb); if (sbsp->smk_flags & SMK_SB_UNTRUSTED && isp->smk_mmap != sbsp->smk_root) return -EACCES; @@ -1874,7 +1809,7 @@ static int smack_file_receive(struct file *file) if (inode->i_sb->s_magic == SOCKFS_MAGIC) { sock = SOCKET_I(inode); - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); tsp = smack_cred(current_cred()); /* * If the receiving process can't write to the @@ -2043,7 +1978,7 @@ static int smack_kernel_act_as(struct cred *new, u32 secid) static int smack_kernel_create_files_as(struct cred *new, struct inode *inode) { - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); struct task_smack *tsp = smack_cred(new); tsp->smk_forked = isp->smk_inode; @@ -2245,7 +2180,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, */ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) { - struct inode_smack *isp = inode->i_security; + struct inode_smack *isp = smack_inode(inode); struct smack_known *skp = smk_of_task_struct(p); isp->smk_inode = skp; @@ -2268,11 +2203,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) { struct smack_known *skp = smk_of_current(); - struct socket_smack *ssp; - - ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); - if (ssp == NULL) - return -ENOMEM; + struct socket_smack *ssp = smack_sock(sk); /* * Sockets created by kernel threads receive web label. @@ -2286,11 +2217,10 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) } ssp->smk_packet = NULL; - sk->sk_security = ssp; - return 0; } +#ifdef SMACK_IPV6_PORT_LABELING /** * smack_sk_free_security - Free a socket blob * @sk: the socket @@ -2299,7 +2229,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) */ static void smack_sk_free_security(struct sock *sk) { -#ifdef SMACK_IPV6_PORT_LABELING struct smk_port_label *spp; if (sk->sk_family == PF_INET6) { @@ -2312,9 +2241,8 @@ static void smack_sk_free_security(struct sock *sk) } rcu_read_unlock(); } -#endif - kfree(sk->sk_security); } +#endif /** * smack_ipv4host_label - check host based restrictions @@ -2432,7 +2360,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip) static int smack_netlabel(struct sock *sk, int labeled) { struct smack_known *skp; - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); int rc = 0; /* @@ -2477,7 +2405,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) int rc; int sk_lbl; struct smack_known *hkp; - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); struct smk_audit_info ad; rcu_read_lock(); @@ -2553,7 +2481,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) { struct sock *sk = sock->sk; struct sockaddr_in6 *addr6; - struct socket_smack *ssp = sock->sk->sk_security; + struct socket_smack *ssp = smack_sock(sock->sk); struct smk_port_label *spp; unsigned short port = 0; @@ -2640,7 +2568,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, int act) { struct smk_port_label *spp; - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); struct smack_known *skp = NULL; unsigned short port; struct smack_known *object; @@ -2707,7 +2635,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { struct smack_known *skp; - struct inode_smack *nsp = inode->i_security; + struct inode_smack *nsp = smack_inode(inode); struct socket_smack *ssp; struct socket *sock; int rc = 0; @@ -2734,7 +2662,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, if (sock == NULL || sock->sk == NULL) return -EOPNOTSUPP; - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); if (strcmp(name, XATTR_SMACK_IPIN) == 0) ssp->smk_in = skp; @@ -2782,7 +2710,7 @@ static int smack_socket_post_create(struct socket *sock, int family, * Sockets created by kernel threads receive web label. */ if (unlikely(current->flags & PF_KTHREAD)) { - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); ssp->smk_in = &smack_known_web; ssp->smk_out = &smack_known_web; } @@ -2834,7 +2762,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, #endif #ifdef SMACK_IPV6_SECMARK_LABELING struct smack_known *rsp; - struct socket_smack *ssp = sock->sk->sk_security; + struct socket_smack *ssp = smack_sock(sock->sk); #endif if (sock->sk == NULL) @@ -2891,35 +2819,13 @@ static int smack_flags_to_may(int flags) */ static int smack_msg_msg_alloc_security(struct msg_msg *msg) { - struct smack_known *skp = smk_of_current(); + struct smack_known **blob = smack_msg_msg(msg); - msg->security = skp; + *blob = smk_of_current(); return 0; } /** - * smack_msg_msg_free_security - Clear the security blob for msg_msg - * @msg: the object - * - * Clears the blob pointer - */ -static void smack_msg_msg_free_security(struct msg_msg *msg) -{ - msg->security = NULL; -} - -/** - * smack_of_shm - the smack pointer for the shm - * @shp: the object - * - * Returns a pointer to the smack value - */ -static struct smack_known *smack_of_shm(struct shmid_kernel *shp) -{ - return (struct smack_known *)shp->shm_perm.security; -} - -/** * smack_shm_alloc_security - Set the security blob for shm * @shp: the object * @@ -2927,27 +2833,13 @@ static struct smack_known *smack_of_shm(struct shmid_kernel *shp) */ static int smack_shm_alloc_security(struct shmid_kernel *shp) { - struct kern_ipc_perm *isp = &shp->shm_perm; - struct smack_known *skp = smk_of_current(); + struct smack_known **blob = smack_ipc(&shp->shm_perm); - isp->security = skp; + *blob = smk_of_current(); return 0; } /** - * smack_shm_free_security - Clear the security blob for shm - * @shp: the object - * - * Clears the blob pointer - */ -static void smack_shm_free_security(struct shmid_kernel *shp) -{ - struct kern_ipc_perm *isp = &shp->shm_perm; - - isp->security = NULL; -} - -/** * smk_curacc_shm : check if current has access on shm * @shp : the object * @access : access requested @@ -2956,7 +2848,8 @@ static void smack_shm_free_security(struct shmid_kernel *shp) */ static int smk_curacc_shm(struct shmid_kernel *shp, int access) { - struct smack_known *ssp = smack_of_shm(shp); + struct smack_known **blob = smack_ipc(&shp->shm_perm); + struct smack_known *ssp = *blob; struct smk_audit_info ad; int rc; @@ -3036,17 +2929,6 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, } /** - * smack_of_sem - the smack pointer for the sem - * @sma: the object - * - * Returns a pointer to the smack value - */ -static struct smack_known *smack_of_sem(struct sem_array *sma) -{ - return (struct smack_known *)sma->sem_perm.security; -} - -/** * smack_sem_alloc_security - Set the security blob for sem * @sma: the object * @@ -3054,27 +2936,13 @@ static struct smack_known *smack_of_sem(struct sem_array *sma) */ static int smack_sem_alloc_security(struct sem_array *sma) { - struct kern_ipc_perm *isp = &sma->sem_perm; - struct smack_known *skp = smk_of_current(); + struct smack_known **blob = smack_ipc(&sma->sem_perm); - isp->security = skp; + *blob = smk_of_current(); return 0; } /** - * smack_sem_free_security - Clear the security blob for sem - * @sma: the object - * - * Clears the blob pointer - */ -static void smack_sem_free_security(struct sem_array *sma) -{ - struct kern_ipc_perm *isp = &sma->sem_perm; - - isp->security = NULL; -} - -/** * smk_curacc_sem : check if current has access on sem * @sma : the object * @access : access requested @@ -3083,7 +2951,8 @@ static void smack_sem_free_security(struct sem_array *sma) */ static int smk_curacc_sem(struct sem_array *sma, int access) { - struct smack_known *ssp = smack_of_sem(sma); + struct smack_known **blob = smack_ipc(&sma->sem_perm); + struct smack_known *ssp = *blob; struct smk_audit_info ad; int rc; @@ -3169,45 +3038,20 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, } /** - * smack_msg_alloc_security - Set the security blob for msg + * smack_msg_queue_alloc_security - Set the security blob for msg * @msq: the object * * Returns 0 */ static int smack_msg_queue_alloc_security(struct msg_queue *msq) { - struct kern_ipc_perm *kisp = &msq->q_perm; - struct smack_known *skp = smk_of_current(); + struct smack_known **blob = smack_ipc(&msq->q_perm); - kisp->security = skp; + *blob = smk_of_current(); return 0; } /** - * smack_msg_free_security - Clear the security blob for msg - * @msq: the object - * - * Clears the blob pointer - */ -static void smack_msg_queue_free_security(struct msg_queue *msq) -{ - struct kern_ipc_perm *kisp = &msq->q_perm; - - kisp->security = NULL; -} - -/** - * smack_of_msq - the smack pointer for the msq - * @msq: the object - * - * Returns a pointer to the smack label entry - */ -static struct smack_known *smack_of_msq(struct msg_queue *msq) -{ - return (struct smack_known *)msq->q_perm.security; -} - -/** * smk_curacc_msq : helper to check if current has access on msq * @msq : the msq * @access : access requested @@ -3216,7 +3060,8 @@ static struct smack_known *smack_of_msq(struct msg_queue *msq) */ static int smk_curacc_msq(struct msg_queue *msq, int access) { - struct smack_known *msp = smack_of_msq(msq); + struct smack_known **blob = smack_ipc(&msq->q_perm); + struct smack_known *msp = *blob; struct smk_audit_info ad; int rc; @@ -3319,7 +3164,8 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, */ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) { - struct smack_known *iskp = ipp->security; + struct smack_known **blob = smack_ipc(ipp); + struct smack_known *iskp = *blob; int may = smack_flags_to_may(flag); struct smk_audit_info ad; int rc; @@ -3340,7 +3186,8 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) */ static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) { - struct smack_known *iskp = ipp->security; + struct smack_known **blob = smack_ipc(ipp); + struct smack_known *iskp = *blob; *secid = iskp->smk_secid; } @@ -3368,7 +3215,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) if (inode == NULL) return; - isp = inode->i_security; + isp = smack_inode(inode); mutex_lock(&isp->smk_lock); /* @@ -3379,7 +3226,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) goto unlockandout; sbp = inode->i_sb; - sbsp = sbp->s_security; + sbsp = smack_superblock(sbp); /* * We're going to use the superblock default label * if there's no label on the file. @@ -3673,9 +3520,9 @@ static int smack_unix_stream_connect(struct sock *sock, { struct smack_known *skp; struct smack_known *okp; - struct socket_smack *ssp = sock->sk_security; - struct socket_smack *osp = other->sk_security; - struct socket_smack *nsp = newsk->sk_security; + struct socket_smack *ssp = smack_sock(sock); + struct socket_smack *osp = smack_sock(other); + struct socket_smack *nsp = smack_sock(newsk); struct smk_audit_info ad; int rc = 0; #ifdef CONFIG_AUDIT @@ -3721,8 +3568,8 @@ static int smack_unix_stream_connect(struct sock *sock, */ static int smack_unix_may_send(struct socket *sock, struct socket *other) { - struct socket_smack *ssp = sock->sk->sk_security; - struct socket_smack *osp = other->sk->sk_security; + struct socket_smack *ssp = smack_sock(sock->sk); + struct socket_smack *osp = smack_sock(other->sk); struct smk_audit_info ad; int rc; @@ -3759,7 +3606,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; #endif #ifdef SMACK_IPV6_SECMARK_LABELING - struct socket_smack *ssp = sock->sk->sk_security; + struct socket_smack *ssp = smack_sock(sock->sk); struct smack_known *rsp; #endif int rc = 0; @@ -3923,7 +3770,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct netlbl_lsm_secattr secattr; - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); struct smack_known *skp = NULL; int rc = 0; struct smk_audit_info ad; @@ -4032,7 +3879,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, int slen = 1; int rc = 0; - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); if (ssp->smk_packet != NULL) { rcp = ssp->smk_packet->smk_known; slen = strlen(rcp) + 1; @@ -4082,7 +3929,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, switch (family) { case PF_UNIX: - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); s = ssp->smk_out->smk_secid; break; case PF_INET: @@ -4095,7 +3942,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, * Translate what netlabel gave us. */ if (sock != NULL && sock->sk != NULL) - ssp = sock->sk->sk_security; + ssp = smack_sock(sock->sk); netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0) { @@ -4133,7 +3980,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) return; - ssp = sk->sk_security; + ssp = smack_sock(sk); ssp->smk_in = skp; ssp->smk_out = skp; /* cssp->smk_packet is already set in smack_inet_csk_clone() */ @@ -4153,7 +4000,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, { u16 family = sk->sk_family; struct smack_known *skp; - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); struct netlbl_lsm_secattr secattr; struct sockaddr_in addr; struct iphdr *hdr; @@ -4252,7 +4099,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, static void smack_inet_csk_clone(struct sock *sk, const struct request_sock *req) { - struct socket_smack *ssp = sk->sk_security; + struct socket_smack *ssp = smack_sock(sk); struct smack_known *skp; if (req->peer_secid != 0) { @@ -4284,24 +4131,14 @@ static void smack_inet_csk_clone(struct sock *sk, static int smack_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { + struct smack_known **blob = smack_key(key); struct smack_known *skp = smk_of_task(smack_cred(cred)); - key->security = skp; + *blob = skp; return 0; } /** - * smack_key_free - Clear the key security blob - * @key: the object - * - * Clear the blob pointer - */ -static void smack_key_free(struct key *key) -{ - key->security = NULL; -} - -/** * smack_key_permission - Smack access on a key * @key_ref: gets to the object * @cred: the credentials to use @@ -4313,6 +4150,8 @@ static void smack_key_free(struct key *key) static int smack_key_permission(key_ref_t key_ref, const struct cred *cred, unsigned perm) { + struct smack_known **blob; + struct smack_known *skp; struct key *keyp; struct smk_audit_info ad; struct smack_known *tkp = smk_of_task(smack_cred(cred)); @@ -4326,7 +4165,9 @@ static int smack_key_permission(key_ref_t key_ref, * If the key hasn't been initialized give it access so that * it may do so. */ - if (keyp->security == NULL) + blob = smack_key(keyp); + skp = *blob; + if (skp == NULL) return 0; /* * This should not occur @@ -4342,8 +4183,8 @@ static int smack_key_permission(key_ref_t key_ref, request = MAY_READ; if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) request = MAY_WRITE; - rc = smk_access(tkp, keyp->security, request, &ad); - rc = smk_bu_note("key access", tkp, keyp->security, request, rc); + rc = smk_access(tkp, skp, request, &ad); + rc = smk_bu_note("key access", tkp, skp, request, rc); return rc; } @@ -4358,11 +4199,12 @@ static int smack_key_permission(key_ref_t key_ref, */ static int smack_key_getsecurity(struct key *key, char **_buffer) { - struct smack_known *skp = key->security; + struct smack_known **blob = smack_key(key); + struct smack_known *skp = *blob; size_t length; char *copy; - if (key->security == NULL) { + if (skp == NULL) { *_buffer = NULL; return 0; } @@ -4571,6 +4413,14 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) struct lsm_blob_sizes smack_blob_sizes = { .lbs_cred = sizeof(struct task_smack), .lbs_file = sizeof(struct smack_known *), + .lbs_inode = sizeof(struct inode_smack), + .lbs_ipc = sizeof(struct smack_known *), +#ifdef CONFIG_KEYS + .lbs_key = sizeof(struct smack_known *), +#endif /* CONFIG_KEYS */ + .lbs_msg_msg = sizeof(struct smack_known *), + .lbs_sock = sizeof(struct socket_smack), + .lbs_superblock = sizeof(struct superblock_smack), }; static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { @@ -4579,7 +4429,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(syslog, smack_syslog), LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), - LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), @@ -4589,7 +4438,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security), - LSM_HOOK_INIT(inode_free_security, smack_inode_free_security), LSM_HOOK_INIT(inode_init_security, smack_inode_init_security), LSM_HOOK_INIT(inode_link, smack_inode_link), LSM_HOOK_INIT(inode_unlink, smack_inode_unlink), @@ -4642,23 +4490,19 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid), LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security), - LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security), LSM_HOOK_INIT(msg_queue_alloc_security, smack_msg_queue_alloc_security), - LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_free_security), LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate), LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl), LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd), LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv), LSM_HOOK_INIT(shm_alloc_security, smack_shm_alloc_security), - LSM_HOOK_INIT(shm_free_security, smack_shm_free_security), LSM_HOOK_INIT(shm_associate, smack_shm_associate), LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl), LSM_HOOK_INIT(shm_shmat, smack_shm_shmat), LSM_HOOK_INIT(sem_alloc_security, smack_sem_alloc_security), - LSM_HOOK_INIT(sem_free_security, smack_sem_free_security), LSM_HOOK_INIT(sem_associate, smack_sem_associate), LSM_HOOK_INIT(sem_semctl, smack_sem_semctl), LSM_HOOK_INIT(sem_semop, smack_sem_semop), @@ -4681,7 +4525,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream), LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram), LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security), +#ifdef SMACK_IPV6_PORT_LABELING LSM_HOOK_INIT(sk_free_security, smack_sk_free_security), +#endif LSM_HOOK_INIT(sock_graft, smack_sock_graft), LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request), LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone), @@ -4689,7 +4535,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { /* key management security hooks */ #ifdef CONFIG_KEYS LSM_HOOK_INIT(key_alloc, smack_key_alloc), - LSM_HOOK_INIT(key_free, smack_key_free), LSM_HOOK_INIT(key_permission, smack_key_permission), LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), #endif /* CONFIG_KEYS */ diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index e36d17835d4f..701a1cc1bdcc 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -31,8 +31,8 @@ static unsigned int smack_ipv6_output(void *priv, struct socket_smack *ssp; struct smack_known *skp; - if (sk && sk->sk_security) { - ssp = sk->sk_security; + if (sk && smack_sock(sk)) { + ssp = smack_sock(sk); skp = ssp->smk_out; skb->secmark = skp->smk_secid; } @@ -49,8 +49,8 @@ static unsigned int smack_ipv4_output(void *priv, struct socket_smack *ssp; struct smack_known *skp; - if (sk && sk->sk_security) { - ssp = sk->sk_security; + if (sk && smack_sock(sk)) { + ssp = smack_sock(sk); skp = ssp->smk_out; skb->secmark = skp->smk_secid; }