From patchwork Thu Jan 26 02:07:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 9538311 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 0A2EE604A7 for ; Thu, 26 Jan 2017 02:07:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CDEE627C0C for ; Thu, 26 Jan 2017 02:07:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C0BF827F85; Thu, 26 Jan 2017 02:07:49 +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 E71A427D29 for ; Thu, 26 Jan 2017 02:07:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752470AbdAZCHp (ORCPT ); Wed, 25 Jan 2017 21:07:45 -0500 Received: from nm14-vm1.bullet.mail.ne1.yahoo.com ([98.138.91.38]:46203 "EHLO nm14-vm1.bullet.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752299AbdAZCHo (ORCPT ); Wed, 25 Jan 2017 21:07:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1485396462; bh=UQAoQMOFxdDEpCoOJh4tnWaX77bAbt9+1vZWlmrEzKY=; h=Subject:To:References:Cc:From:Date:In-Reply-To:From:Subject; b=b7GeIfcQxAipUMNK3AqTqSM8E/qsJeZD9vTXFagK13F2chMp4eagAuqj3OUAt+Rv68KZ4eKMsM+UAqN+aqKe69WhA+/aRgOBW6hWJT9KUMOeqgFPpJ16uqiEAlIugDLfcPZI/ccc7ktgJxDHDA92lDCe15wNsapbFKCJSElyPLh2Yz1HOH1zOFC2NQWQqoHvM+ZXzvvaPBawWo7bbfrWF0sONKcu8wsdJvD6iwDBiBOfND9vRrrEaULvvruFvzQGcHLjTW/+o0oKAbQ3lCQp81hYH7uMJQ+CgOZ4NB5ExDM8z5ql+Zb3OSaOIVxe92e6xBPAmJKB/f0n0Bvb8txClg== Received: from [98.138.101.131] by nm14.bullet.mail.ne1.yahoo.com with NNFMP; 26 Jan 2017 02:07:42 -0000 Received: from [98.138.226.56] by tm19.bullet.mail.ne1.yahoo.com with NNFMP; 26 Jan 2017 02:07:42 -0000 Received: from [127.0.0.1] by smtp207.mail.ne1.yahoo.com with NNFMP; 26 Jan 2017 02:07:42 -0000 X-Yahoo-Newman-Id: 827926.74904.bm@smtp207.mail.ne1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: Ob28UQoVM1mBZ7gxNbc5cGn1YI4SaYIA2voDyhnyNCsk9eW cygP7c0LpqDp6K8xqjsNt0tw2FxxYYJYu02xRPuUzZX.4SOrQJWmTEuCXsyu f8BCGnpDUkzQmWtBGGYkRjE9.E_NGjRBP3SvRgJiR.XcwhARPqBDu6BORYqU f8trZpQpdpSXmENOWU37aLppbXyS1PKyMWcY7bQ_H7jfL67bQ9GPEv4JKjLx mw30De26UFvF7fdx1CFZR6ETy1T9dRDAtnyj2yg3PrqmGaWHsMRYQUarEmRT 9k6NGk9aGzPWat7WKuDULwl1LZp7NOawPGvLzmsYG6i9rNNIxzV79axp1_3W PO23JGvVTSaNKQ0jAXl4._Pr78CFWZUQJs5J5eRh.f7nxvjcFzJJfKGhewP6 Qp4LBtdBLKCAJZ92UfAIrpjvxzacN.Df.KjqmV0Q.Tj50ZUXaz7TlXC7A61E 2t6qkk.Md.nI._7kiaCQEOce4JpcuoiK6fcJ9g_u8ABVa9AedcwySgY5Z8Ll V8WOIsQ2em0ruC5ZjiDFvp76iPRMFU_5SMiWuizP_La20n.pZRwBK4qC90sZ qX5jSs3ZInVlJ X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Subject: [PATCH RFC 6/9] LSM: Infrastructure management of the remaining blobs To: LSM References: Cc: James Morris , John Johansen , Tetsuo Handa , Paul Moore , Stephen Smalley , Kees Cook From: Casey Schaufler Message-ID: Date: Wed, 25 Jan 2017 18:07:40 -0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Subject: [PATCH RFC 6/9] LSM: Infrastructure management of the remaining 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 | 20 +++ security/security.c | 240 +++++++++++++++++++++++++++- security/selinux/hooks.c | 328 ++++++++++++-------------------------- 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 | 324 +++++++++++-------------------------- security/smack/smack_netfilter.c | 8 +- 10 files changed, 589 insertions(+), 479 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 86ce8da..edf6ebc 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1885,6 +1885,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; }; /* @@ -1940,6 +1946,7 @@ 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 static inline void lsm_early_cred(struct cred *cred) @@ -1954,6 +1961,19 @@ static inline void lsm_early_cred(struct cred *cred) if (rc) panic("%s: Early cred alloc failed.\n", __func__); } + +static inline 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__); +} #endif #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/security/security.c b/security/security.c index 42ab35c..67423f0 100644 --- a/security/security.c +++ b/security/security.c @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -86,7 +88,15 @@ 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); -#endif + 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); +#endif /* CONFIG_SECURITY_LSM_DEBUG */ return 0; } @@ -225,6 +235,18 @@ 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); + /* + * 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); } /** @@ -250,6 +272,147 @@ int lsm_file_alloc(struct file *file) 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) +{ +#ifdef CONFIG_SECURITY_LSM_DEBUG + if (inode->i_security) + pr_info("%s: Inbound inode blob is not NULL.\n", __func__); +#endif + if (blob_sizes.lbs_inode == 0) + return 0; + + inode->i_security = kzalloc(blob_sizes.lbs_inode, GFP_KERNEL); + if (inode->i_security == NULL) + return -ENOMEM; + return 0; +} + +/** + * 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. * @@ -422,12 +585,18 @@ int security_bprm_secureexec(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) @@ -498,14 +667,39 @@ 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 + */ + kfree(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 != NULL) { + call_rcu((struct rcu_head *)inode->i_security, + inode_free_by_rcu); + inode->i_security = NULL; + } } int security_dentry_init_security(struct dentry *dentry, int mode, @@ -1239,22 +1433,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) @@ -1281,12 +1489,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) @@ -1306,12 +1522,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) @@ -1641,12 +1865,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) @@ -1849,12 +2079,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 b7c6613..32e7abe 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -125,8 +125,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 * @@ -220,13 +218,9 @@ static inline u32 current_sid(void) 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; @@ -234,7 +228,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; } @@ -252,7 +245,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); @@ -272,7 +265,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) @@ -282,7 +275,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); } /* @@ -291,14 +284,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); } /* @@ -309,21 +302,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 @@ -340,17 +326,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) @@ -366,11 +341,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); @@ -379,18 +350,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); -} - /* The file system's label must be initialized prior to use. */ static const char *labeling_behaviors[7] = { @@ -466,7 +429,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 || @@ -481,7 +444,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; @@ -560,7 +523,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; @@ -623,7 +586,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) @@ -676,7 +640,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; @@ -920,8 +884,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; @@ -950,8 +914,9 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb, static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, struct super_block *newsb) { - 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); @@ -985,14 +950,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; } @@ -1365,7 +1333,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; @@ -1384,7 +1352,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 @@ -1709,7 +1677,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); } @@ -1806,7 +1774,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)) { @@ -1836,7 +1805,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; @@ -1984,7 +1953,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); } @@ -2583,11 +2552,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) @@ -2684,7 +2648,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; @@ -2875,7 +2839,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; @@ -2889,7 +2853,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; @@ -2987,7 +2951,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; @@ -3108,7 +3072,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; @@ -3913,7 +3877,7 @@ static int selinux_task_wait(struct task_struct *p) 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); @@ -4199,7 +4163,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, static int sock_has_perm(struct task_struct *task, 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,}; u32 tsid = task_sid(task); @@ -4254,7 +4218,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); @@ -4285,7 +4249,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; @@ -4369,7 +4333,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(current, sk, SOCKET__CONNECT); @@ -4501,9 +4465,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; @@ -4534,8 +4498,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,}; @@ -4574,7 +4538,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,}; @@ -4606,7 +4570,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; @@ -4672,13 +4636,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 || @@ -4736,34 +4702,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; @@ -4777,7 +4736,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; } @@ -4787,7 +4746,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) @@ -4798,7 +4757,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; @@ -4819,7 +4778,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; @@ -4836,7 +4795,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)) @@ -4916,7 +4875,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 @@ -4955,7 +4914,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; @@ -5094,7 +5053,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; @@ -5133,7 +5092,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; @@ -5224,7 +5183,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 @@ -5253,7 +5212,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; } @@ -5313,54 +5272,26 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) return selinux_nlmsg_perm(sk, skb); } -static int ipc_alloc_security(struct task_struct *task, - struct kern_ipc_perm *perm, +static void ipc_init_security(struct task_struct *task, + struct ipc_security_struct *isec, u16 sclass) { - struct ipc_security_struct *isec; u32 sid; - isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); - if (!isec) - return -ENOMEM; - sid = task_sid(task); isec->sclass = sclass; isec->sid = 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; + struct msg_security_struct *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) { @@ -5368,7 +5299,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; @@ -5381,11 +5312,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) { @@ -5394,36 +5320,26 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ); - if (rc) - return rc; - - isec = msq->q_perm.security; + isec = selinux_ipc(&msq->q_perm); + ipc_init_security(current, 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); + if (rc) return rc; - } return 0; } -static void selinux_msg_queue_free_security(struct msg_queue *msq) -{ - ipc_free_security(&msq->q_perm); -} - static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) { struct ipc_security_struct *isec; 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; @@ -5468,8 +5384,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 @@ -5513,8 +5429,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; @@ -5535,36 +5451,26 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM); - if (rc) - return rc; - - isec = shp->shm_perm.security; + isec = selinux_ipc(&shp->shm_perm); + ipc_init_security(current, 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); + if (rc) return rc; - } return 0; } -static void selinux_shm_free_security(struct shmid_kernel *shp) -{ - ipc_free_security(&shp->shm_perm); -} - static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) { struct ipc_security_struct *isec; 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; @@ -5627,36 +5533,26 @@ static int selinux_sem_alloc_security(struct sem_array *sma) u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM); - if (rc) - return rc; - - isec = sma->sem_perm.security; + isec = selinux_ipc(&sma->sem_perm); + ipc_init_security(current, 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); + if (rc) return rc; - } return 0; } -static void selinux_sem_free_security(struct sem_array *sma) -{ - ipc_free_security(&sma->sem_perm); -} - static int selinux_sem_associate(struct sem_array *sma, int semflg) { struct ipc_security_struct *isec; 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; @@ -5738,7 +5634,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; } @@ -5964,7 +5860,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; @@ -6003,11 +5899,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) @@ -6015,18 +5907,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) @@ -6044,14 +5927,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; @@ -6068,6 +5951,14 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) 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[] = { @@ -6094,7 +5985,6 @@ static struct security_hook_list selinux_hooks[] = { LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec), 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), @@ -6177,24 +6067,20 @@ static struct security_hook_list selinux_hooks[] = { 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), @@ -6270,7 +6156,6 @@ static struct security_hook_list selinux_hooks[] = { #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 @@ -6317,9 +6202,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 8ae0285..b89e1b0c 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -48,10 +48,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 */ @@ -153,4 +150,64 @@ static inline struct file_security_struct *selinux_file(const struct file *file) #endif } +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 aaba667..0b0091c 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 40a7fad..1006b58 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1298,7 +1298,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) goto out; @@ -1834,7 +1834,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 082b20c..fe62af7 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" @@ -2539,7 +2540,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 5af0233..e75d85e 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -372,12 +372,69 @@ static inline struct smack_known **smack_file(const struct file *file) #endif } +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; } @@ -386,7 +443,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 c4b4161..0364084 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -164,7 +164,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) @@ -196,7 +196,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) @@ -226,7 +226,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) @@ -286,24 +286,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; } /** @@ -528,12 +522,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; @@ -542,23 +531,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 @@ -750,7 +727,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; @@ -828,17 +805,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; } @@ -883,7 +856,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; @@ -916,11 +889,11 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) if (bprm->cred_prepared) 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; @@ -993,25 +966,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_security - free an inode blob - * @inode: the inode with a blob - * - * Clears the blob pointer in inode - */ -static void smack_inode_free_security(struct inode *inode) -{ - kmem_cache_free(smack_inode_cache, inode->i_security); - inode->i_security = NULL; -} - -/** * smack_inode_init_security - copy out the smack from an inode * @inode: the newly created inode * @dir: containing directory object @@ -1026,7 +985,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); @@ -1364,7 +1323,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; @@ -1445,7 +1404,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 @@ -1505,7 +1464,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; @@ -1548,7 +1507,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; } @@ -1713,7 +1672,7 @@ static int smack_mmap_file(struct file *file, if (file == NULL) 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; @@ -1869,7 +1828,7 @@ static int smack_file_receive(struct file *file) if (S_ISSOCK(inode->i_mode)) { 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 @@ -2041,7 +2000,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; @@ -2262,7 +2221,7 @@ static int smack_task_wait(struct task_struct *p) */ 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; @@ -2285,11 +2244,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. @@ -2303,23 +2258,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; } /** - * smack_sk_free_security - Free a socket blob - * @sk: the socket - * - * Clears the blob pointer - */ -static void smack_sk_free_security(struct sock *sk) -{ - kfree(sk->sk_security); -} - -/** * smack_ipv4host_label - check host based restrictions * @sip: the object end * @@ -2435,7 +2377,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; /* @@ -2480,7 +2422,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(); @@ -2556,7 +2498,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; @@ -2629,7 +2571,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; @@ -2694,7 +2636,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; @@ -2721,7 +2663,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; @@ -2769,7 +2711,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; } @@ -2821,7 +2763,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) @@ -2878,35 +2820,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 * @@ -2914,27 +2834,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 @@ -2943,7 +2849,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; @@ -3023,17 +2930,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 * @@ -3041,27 +2937,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 @@ -3070,7 +2952,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; @@ -3156,45 +3039,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 @@ -3203,7 +3061,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; @@ -3306,7 +3165,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; @@ -3327,7 +3187,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; } @@ -3355,7 +3216,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); /* @@ -3366,7 +3227,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. @@ -3671,9 +3532,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 @@ -3719,8 +3580,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; @@ -3757,7 +3618,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; @@ -3921,7 +3782,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; @@ -4030,7 +3891,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; @@ -4080,7 +3941,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: @@ -4093,7 +3954,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) { @@ -4131,7 +3992,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() */ @@ -4151,7 +4012,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; @@ -4250,7 +4111,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) { @@ -4282,24 +4143,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 @@ -4311,6 +4162,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)); @@ -4324,7 +4177,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 @@ -4340,8 +4195,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; } @@ -4356,11 +4211,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; } @@ -4569,6 +4425,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[] = { @@ -4577,7 +4441,6 @@ static struct security_hook_list smack_hooks[] = { 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 +4452,6 @@ static struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec), 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), @@ -4643,23 +4505,19 @@ static struct security_hook_list smack_hooks[] = { 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), @@ -4682,7 +4540,6 @@ static struct security_hook_list smack_hooks[] = { 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), - LSM_HOOK_INIT(sk_free_security, smack_sk_free_security), 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), @@ -4690,7 +4547,6 @@ static struct security_hook_list smack_hooks[] = { /* 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 205b785..1c6c9b0 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -30,8 +30,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; } @@ -48,8 +48,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; }