From c1e992b99603a84d7debb188542b64f2d9232c07 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Fri, 26 Feb 2010 22:49:55 +0800 Subject: Security: Add __init to register_security to disable load a security module on runtime LSM framework doesn't allow to load a security module on runtime, it must be loaded on boot time. but in security/security.c: int register_security(struct security_operations *ops) { ... if (security_ops != &default_security_ops) return -EAGAIN; ... } if security_ops == &default_security_ops, it can access to register a security module. If selinux is enabled, other security modules can't register, but if selinux is disabled on boot time, the security_ops was set to default_security_ops, LSM allows other kernel modules to use register_security() to register a not trust security module. For example: disable selinux on boot time(selinux=0). #include #include #include #include #include #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("wzt"); extern int register_security(struct security_operations *ops); int (*new_register_security)(struct security_operations *ops); int rootkit_bprm_check_security(struct linux_binprm *bprm) { return 0; } struct security_operations rootkit_ops = { .bprm_check_security = rootkit_bprm_check_security, }; static int rootkit_init(void) { printk("Load LSM rootkit module.\n"); /* cat /proc/kallsyms | grep register_security */ new_register_security = 0xc0756689; if (new_register_security(&rootkit_ops)) { printk("Can't register rootkit module.\n"); return 0; } printk("Register rootkit module ok.\n"); return 0; } static void rootkit_exit(void) { printk("Unload LSM rootkit module.\n"); } module_init(rootkit_init); module_exit(rootkit_exit); Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/security.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index 122b748..7da630a 100644 --- a/security/security.c +++ b/security/security.c @@ -110,7 +110,7 @@ int __init security_module_enable(struct security_operations *ops) * If there is already a security module registered with the kernel, * an error will be returned. Otherwise %0 is returned on success. */ -int register_security(struct security_operations *ops) +int __init register_security(struct security_operations *ops) { if (verify(ops)) { printk(KERN_DEBUG "%s could not verify " -- cgit v1.1 From b380de9e54ec354ccac55fd9a611ffe28b4daa76 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 1 Mar 2010 19:47:04 +0900 Subject: TOMOYO: Remove unused variables. Variable "atmark" is currently unused. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index e0d0354..be1099b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1424,7 +1424,6 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, { int pos; u8 bit; - const char *atmark = ""; const char *filename; const u16 perm = ptr->perm; @@ -1441,8 +1440,7 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, continue; msg = tomoyo_sp2keyword(bit); pos = head->read_avail; - if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, - atmark, filename)) + if (!tomoyo_io_printf(head, "allow_%s %s\n", msg, filename)) goto out; } head->read_bit = 0; @@ -1466,8 +1464,6 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, ptr) { int pos; - const char *atmark1 = ""; - const char *atmark2 = ""; const char *filename1; const char *filename2; const u8 perm = ptr->perm; @@ -1482,8 +1478,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, continue; msg = tomoyo_dp2keyword(bit); pos = head->read_avail; - if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, - atmark1, filename1, atmark2, filename2)) + if (!tomoyo_io_printf(head, "allow_%s %s %s\n", msg, + filename1, filename2)) goto out; } head->read_bit = 0; -- cgit v1.1 From 31637b55b09753de9d5e24afc3a1d7fbdb2108d8 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Tue, 2 Mar 2010 15:08:58 +0800 Subject: Selinux: Remove unused headers list.h in selinux/netlink.c list.h is unused in netlink.c, so remove it. Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/selinux/netlink.c | 1 - 1 file changed, 1 deletion(-) (limited to 'security') diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1ae5564..7d7be29 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From dbba541f9d9bd2c200041bc1b37c59dbaf9beb75 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Tue, 2 Mar 2010 17:03:43 +0800 Subject: Selinux: Remove unused headers slab.h in selinux/ss/symtab.c slab.h is unused in symtab.c, so remove it. Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/selinux/ss/symtab.c | 1 - 1 file changed, 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a..bcf9f62 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -4,7 +4,6 @@ * Author : Stephen Smalley, */ #include -#include #include #include #include "symtab.h" -- cgit v1.1 From 06b9b72df43800b9ae4e77202c8bf5848c9d6998 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Wed, 3 Mar 2010 21:29:37 +0800 Subject: Selinux: Remove unused headers skbuff.h in selinux/nlmsgtab.c skbuff.h is already included by netlink.h, so remove it. Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/selinux/nlmsgtab.c | 1 - 1 file changed, 1 deletion(-) (limited to 'security') diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index dd7cc6d..75ec0c6 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -11,7 +11,6 @@ */ #include #include -#include #include #include #include -- cgit v1.1 From c8563473c1259f5686ceb918c548c80132089f79 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Thu, 4 Mar 2010 21:26:23 +0800 Subject: Security: Fix some coding styles in security/keys/keyring.c Fix some coding styles in security/keys/keyring.c Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/keys/keyring.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e814d21..a98fb37 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -170,12 +170,10 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) { struct keyring_list *klist; - if (keyring->description) { + if (keyring->description) seq_puts(m, keyring->description); - } - else { + else seq_puts(m, "[anon]"); - } rcu_read_lock(); klist = rcu_dereference(keyring->payload.subscriptions); -- cgit v1.1 From 634a539e16bd7a1ba31c3f832baa725565cc9f96 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 4 Mar 2010 21:59:03 -0800 Subject: selinux: const strings in tables Several places strings tables are used that should be declared const. Signed-off-by: Stephen Hemminger Signed-off-by: James Morris --- security/selinux/hooks.c | 2 +- security/selinux/include/initial_sid_to_string.h | 2 +- security/selinux/ss/policydb.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9a2ee84..e1202cb 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -329,7 +329,7 @@ extern int ss_initialized; /* The file system's label must be initialized prior to use. */ -static char *labeling_behaviors[6] = { +static const char *labeling_behaviors[6] = { "uses xattr", "uses transition SIDs", "uses task SIDs", diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index d4fac82..a59b64e 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h @@ -1,5 +1,5 @@ /* This file is automatically generated. Do not edit. */ -static char *initial_sid_to_string[] = +static const char *initial_sid_to_string[] = { "null", "kernel", diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f036672..6236198 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -40,7 +40,7 @@ #define _DEBUG_HASHES #ifdef DEBUG_HASHES -static char *symtab_name[SYM_NUM] = { +static const char *symtab_name[SYM_NUM] = { "common prefixes", "classes", "roles", -- cgit v1.1 From 512ea3bc30c0e052a961e1abce8e783f3e28c92a Mon Sep 17 00:00:00 2001 From: Chihau Chau Date: Mon, 8 Mar 2010 20:11:34 -0300 Subject: Security: key: keyring: fix some code style issues This fixes to include instead and some code style issues like to put a else sentence below close brace '}' and to replace a tab instead of some space characters. Signed-off-by: Chihau Chau Acked-by: David Howells Signed-off-by: James Morris --- security/keys/keyring.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/keys/keyring.c b/security/keys/keyring.c index a98fb37..fe0763a 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "internal.h" /* @@ -304,7 +304,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, key_check(keyring); /* top keyring must have search permission to begin the search */ - err = key_task_permission(keyring_ref, cred, KEY_SEARCH); + err = key_task_permission(keyring_ref, cred, KEY_SEARCH); if (err < 0) { key_ref = ERR_PTR(err); goto error; @@ -773,8 +773,7 @@ int __key_link(struct key *keyring, struct key *key) smp_wmb(); klist->nkeys++; smp_wmb(); - } - else { + } else { /* grow the key list */ max = 4; if (klist) -- cgit v1.1 From a19c5bbefb37ebe22fb42bd3861a8d3b2a2652a1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 9 Mar 2010 17:59:59 -0600 Subject: security/ima: replace gcc specific __FUNCTION__ with __func__ As noted by checkpatch.pl, __func__ should be used instead of gcc specific __FUNCTION__. Signed-off-by: H Hartley Sweeten Signed-off-by: James Morris --- security/integrity/ima/ima_iint.c | 6 +++--- security/integrity/ima/ima_main.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 2d4d05d..6cc2243 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c @@ -79,17 +79,17 @@ void iint_free(struct kref *kref) iint->version = 0; iint->flags = 0UL; if (iint->readcount != 0) { - printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__, + printk(KERN_INFO "%s: readcount: %ld\n", __func__, iint->readcount); iint->readcount = 0; } if (iint->writecount != 0) { - printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__, + printk(KERN_INFO "%s: writecount: %ld\n", __func__, iint->writecount); iint->writecount = 0; } if (iint->opencount != 0) { - printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__, + printk(KERN_INFO "%s: opencount: %ld\n", __func__, iint->opencount); iint->opencount = 0; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 294b005..983037f 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -194,7 +194,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, (iint->writecount < 0)) && !ima_limit_imbalance(file)) { printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", - __FUNCTION__, iint->readcount, iint->writecount, + __func__, iint->readcount, iint->writecount, iint->opencount); dump_stack(); } -- cgit v1.1 From 77c160e7798b4141a0705c734397a9236bb0e726 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Mon, 15 Mar 2010 10:42:11 -0400 Subject: SELinux: Reduce max avtab size to avoid page allocation failures Reduce MAX_AVTAB_HASH_BITS so that the avtab allocation is an order 2 allocation rather than an order 4 allocation on x86_64. This addresses reports of page allocation failures: http://marc.info/?l=selinux&m=126757230625867&w=2 https://bugzilla.redhat.com/show_bug.cgi?id=570433 Reported-by: Russell Coker Signed-off-by: Stephen D. Smalley Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/ss/avtab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a84..cd4f734 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified void avtab_cache_init(void); void avtab_cache_destroy(void); -#define MAX_AVTAB_HASH_BITS 13 +#define MAX_AVTAB_HASH_BITS 11 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS -- cgit v1.1 From dd3e7836bfe093fc611f715c323cf53be9252b27 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:08:46 -0400 Subject: selinux: always call sk_security_struct sksec trying to grep everything that messes with a sk_security_struct isn't easy since we don't always call it sksec. Just rename everything sksec. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 50 ++++++++++++++++++------------------- security/selinux/include/netlabel.h | 8 +++--- security/selinux/netlabel.c | 14 +++++------ 3 files changed, 36 insertions(+), 36 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 63c2d36d..ebee467 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -293,28 +293,28 @@ static void superblock_free_security(struct super_block *sb) static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) { - struct sk_security_struct *ssec; + struct sk_security_struct *sksec; - ssec = kzalloc(sizeof(*ssec), priority); - if (!ssec) + sksec = kzalloc(sizeof(*sksec), priority); + if (!sksec) return -ENOMEM; - ssec->peer_sid = SECINITSID_UNLABELED; - ssec->sid = SECINITSID_UNLABELED; - sk->sk_security = ssec; + sksec->peer_sid = SECINITSID_UNLABELED; + sksec->sid = SECINITSID_UNLABELED; + sk->sk_security = sksec; - selinux_netlbl_sk_security_reset(ssec); + selinux_netlbl_sk_security_reset(sksec); return 0; } static void sk_free_security(struct sock *sk) { - struct sk_security_struct *ssec = sk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; sk->sk_security = NULL; - selinux_netlbl_sk_security_free(ssec); - kfree(ssec); + selinux_netlbl_sk_security_free(sksec); + kfree(sksec); } /* The security server must be initialized before @@ -4002,7 +4002,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, struct socket *other, struct sock *newsk) { - struct sk_security_struct *ssec; + struct sk_security_struct *sksec; struct inode_security_struct *isec; struct inode_security_struct *other_isec; struct common_audit_data ad; @@ -4021,13 +4021,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, return err; /* connecting socket */ - ssec = sock->sk->sk_security; - ssec->peer_sid = other_isec->sid; + sksec = sock->sk->sk_security; + sksec->peer_sid = other_isec->sid; /* server child socket */ - ssec = newsk->sk_security; - ssec->peer_sid = isec->sid; - err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); + sksec = newsk->sk_security; + sksec->peer_sid = isec->sid; + err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); return err; } @@ -4190,7 +4190,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op int err = 0; char *scontext; u32 scontext_len; - struct sk_security_struct *ssec; + struct sk_security_struct *sksec; struct inode_security_struct *isec; u32 peer_sid = SECSID_NULL; @@ -4198,8 +4198,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || isec->sclass == SECCLASS_TCP_SOCKET) { - ssec = sock->sk->sk_security; - peer_sid = ssec->peer_sid; + sksec = sock->sk->sk_security; + peer_sid = sksec->peer_sid; } if (peer_sid == SECSID_NULL) { err = -ENOPROTOOPT; @@ -4266,14 +4266,14 @@ static void selinux_sk_free_security(struct sock *sk) static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) { - struct sk_security_struct *ssec = sk->sk_security; - struct sk_security_struct *newssec = newsk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *newsksec = newsk->sk_security; - newssec->sid = ssec->sid; - newssec->peer_sid = ssec->peer_sid; - newssec->sclass = ssec->sclass; + newsksec->sid = sksec->sid; + newsksec->peer_sid = sksec->peer_sid; + newsksec->sclass = sksec->sclass; - selinux_netlbl_sk_security_reset(newssec); + selinux_netlbl_sk_security_reset(newsksec); } static void selinux_sk_getsecid(struct sock *sk, u32 *secid) diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 8d73842..cf2f628 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -42,8 +42,8 @@ void selinux_netlbl_cache_invalidate(void); void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); -void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); -void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec); +void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); +void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, @@ -79,13 +79,13 @@ static inline void selinux_netlbl_err(struct sk_buff *skb, } static inline void selinux_netlbl_sk_security_free( - struct sk_security_struct *ssec) + struct sk_security_struct *sksec) { return; } static inline void selinux_netlbl_sk_security_reset( - struct sk_security_struct *ssec) + struct sk_security_struct *sksec) { return; } diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2534400..3d09a2a 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -131,21 +131,21 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) /** * selinux_netlbl_sk_security_free - Free the NetLabel fields - * @sssec: the sk_security_struct + * @sksec: the sk_security_struct * * Description: * Free all of the memory in the NetLabel fields of a sk_security_struct. * */ -void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) +void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) { - if (ssec->nlbl_secattr != NULL) - netlbl_secattr_free(ssec->nlbl_secattr); + if (sksec->nlbl_secattr != NULL) + netlbl_secattr_free(sksec->nlbl_secattr); } /** * selinux_netlbl_sk_security_reset - Reset the NetLabel fields - * @ssec: the sk_security_struct + * @sksec: the sk_security_struct * @family: the socket family * * Description: @@ -153,9 +153,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) * The caller is responsibile for all the NetLabel sk_security_struct locking. * */ -void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) +void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) { - ssec->nlbl_state = NLBL_UNSET; + sksec->nlbl_state = NLBL_UNSET; } /** -- cgit v1.1 From e2902eb79fdea3c3bf679a8f15f3432b393cb2c0 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:10:35 -0400 Subject: SMACK: remove dead cred_commit hook This is an unused hook in SMACK so remove it. Signed-off-by: Eric Paris Acked-by: Casey Schaufler Signed-off-by: James Morris --- security/smack/smack_lsm.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5225e66..98eeddc 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1118,15 +1118,6 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, } /** - * smack_cred_commit - commit new credentials - * @new: the new credentials - * @old: the original credentials - */ -static void smack_cred_commit(struct cred *new, const struct cred *old) -{ -} - -/** * smack_cred_transfer - Transfer the old credentials to the new credentials * @new: the new credentials * @old: the original credentials @@ -3120,7 +3111,6 @@ struct security_operations smack_ops = { .cred_alloc_blank = smack_cred_alloc_blank, .cred_free = smack_cred_free, .cred_prepare = smack_cred_prepare, - .cred_commit = smack_cred_commit, .cred_transfer = smack_cred_transfer, .kernel_act_as = smack_kernel_act_as, .kernel_create_files_as = smack_kernel_create_files_as, -- cgit v1.1 From c1a7368a6f0b18b10fdec87972da680ebdf03794 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Fri, 9 Apr 2010 19:30:29 +0800 Subject: Security: Fix coding style in security/ Fix coding style in security/ Signed-off-by: Zhitong Wang Signed-off-by: James Morris --- security/selinux/selinuxfs.c | 44 +++++++++++++++++++++--------------------- security/selinux/ss/mls.c | 2 +- security/selinux/ss/policydb.c | 4 ++-- security/selinux/ss/services.c | 12 ++++++------ 4 files changed, 31 insertions(+), 31 deletions(-) (limited to 'security') diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cd191bb..0293843 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -503,11 +503,11 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kzalloc(size+1, GFP_KERNEL); + scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) return length; - tcon = kzalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; @@ -515,10 +515,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out2; - length = security_context_to_sid(scon, strlen(scon)+1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length < 0) goto out2; - length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length < 0) goto out2; @@ -550,11 +550,11 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kzalloc(size+1, GFP_KERNEL); + scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) return length; - tcon = kzalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; @@ -562,10 +562,10 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out2; - length = security_context_to_sid(scon, strlen(scon)+1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length < 0) goto out2; - length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length < 0) goto out2; @@ -609,11 +609,11 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kzalloc(size+1, GFP_KERNEL); + scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) return length; - tcon = kzalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; @@ -621,10 +621,10 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out2; - length = security_context_to_sid(scon, strlen(scon)+1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length < 0) goto out2; - length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length < 0) goto out2; @@ -666,11 +666,11 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) return length; length = -ENOMEM; - con = kzalloc(size+1, GFP_KERNEL); + con = kzalloc(size + 1, GFP_KERNEL); if (!con) return length; - user = kzalloc(size+1, GFP_KERNEL); + user = kzalloc(size + 1, GFP_KERNEL); if (!user) goto out; @@ -678,7 +678,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s", con, user) != 2) goto out2; - length = security_context_to_sid(con, strlen(con)+1, &sid); + length = security_context_to_sid(con, strlen(con) + 1, &sid); if (length < 0) goto out2; @@ -727,11 +727,11 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) return length; length = -ENOMEM; - scon = kzalloc(size+1, GFP_KERNEL); + scon = kzalloc(size + 1, GFP_KERNEL); if (!scon) return length; - tcon = kzalloc(size+1, GFP_KERNEL); + tcon = kzalloc(size + 1, GFP_KERNEL); if (!tcon) goto out; @@ -739,10 +739,10 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out2; - length = security_context_to_sid(scon, strlen(scon)+1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length < 0) goto out2; - length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); if (length < 0) goto out2; @@ -1401,7 +1401,7 @@ static int sel_make_perm_files(char *objclass, int classvalue, } inode->i_fop = &sel_perm_ops; /* i+1 since perm values are 1-indexed */ - inode->i_ino = sel_perm_to_ino(classvalue, i+1); + inode->i_ino = sel_perm_to_ino(classvalue, i + 1); d_add(dentry, inode); } @@ -1489,7 +1489,7 @@ static int sel_make_classes(void) goto out; /* +2 since classes are 1-indexed */ - last_class_ino = sel_class_to_ino(nclasses+2); + last_class_ino = sel_class_to_ino(nclasses + 2); for (i = 0; i < nclasses; i++) { struct dentry *class_name_dir; @@ -1506,7 +1506,7 @@ static int sel_make_classes(void) goto out1; /* i+1 since class values are 1-indexed */ - rc = sel_make_class_dir_entries(classes[i], i+1, + rc = sel_make_class_dir_entries(classes[i], i + 1, class_name_dir); if (rc) goto out1; diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 372b773..b4eff7a 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -255,7 +255,7 @@ int mls_context_to_sid(struct policydb *pol, if (!pol->mls_enabled) { if (def_sid != SECSID_NULL && oldc) - *scontext += strlen(*scontext)+1; + *scontext += strlen(*scontext) + 1; return 0; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 24ced65..4f584fb 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -156,7 +156,7 @@ static int roles_init(struct policydb *p) rc = -EINVAL; goto out_free_role; } - key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL); + key = kmalloc(strlen(OBJECT_R) + 1, GFP_KERNEL); if (!key) { rc = -ENOMEM; goto out_free_role; @@ -2195,7 +2195,7 @@ int policydb_read(struct policydb *p, void *fp) rangetr_hash_eval(p->range_tr); } - p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); + p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); if (!p->type_attr_map) goto bad; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index cf27b3e..0b44f5a 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -274,15 +274,15 @@ static int constraint_expr_eval(struct context *scontext, case CEXPR_AND: BUG_ON(sp < 1); sp--; - s[sp] &= s[sp+1]; + s[sp] &= s[sp + 1]; break; case CEXPR_OR: BUG_ON(sp < 1); sp--; - s[sp] |= s[sp+1]; + s[sp] |= s[sp + 1]; break; case CEXPR_ATTR: - if (sp == (CEXPR_MAXDEPTH-1)) + if (sp == (CEXPR_MAXDEPTH - 1)) return 0; switch (e->attr) { case CEXPR_USER: @@ -1216,7 +1216,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, *sid = SECSID_NULL; /* Copy the string so that we can modify the copy as we parse it. */ - scontext2 = kmalloc(scontext_len+1, gfp_flags); + scontext2 = kmalloc(scontext_len + 1, gfp_flags); if (!scontext2) return -ENOMEM; memcpy(scontext2, scontext, scontext_len); @@ -2101,9 +2101,9 @@ int security_get_user_sids(u32 fromsid, ebitmap_for_each_positive_bit(&user->roles, rnode, i) { role = policydb.role_val_to_struct[i]; - usercon.role = i+1; + usercon.role = i + 1; ebitmap_for_each_positive_bit(&role->types, tnode, j) { - usercon.type = j+1; + usercon.type = j + 1; if (mls_setup_user_range(fromcon, user, &usercon)) continue; -- cgit v1.1 From 353633100d8d684ac0acae4ce93fb833f92881f4 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:15 -0400 Subject: security: remove sb_check_sb hooks Unused hook. Remove it. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 4875142..a7e905d 100644 --- a/security/capability.c +++ b/security/capability.c @@ -80,11 +80,6 @@ static int cap_sb_mount(char *dev_name, struct path *path, char *type, return 0; } -static int cap_sb_check_sb(struct vfsmount *mnt, struct path *path) -{ - return 0; -} - static int cap_sb_umount(struct vfsmount *mnt, int flags) { return 0; @@ -941,7 +936,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_show_options); set_to_cap_if_null(ops, sb_statfs); set_to_cap_if_null(ops, sb_mount); - set_to_cap_if_null(ops, sb_check_sb); set_to_cap_if_null(ops, sb_umount); set_to_cap_if_null(ops, sb_umount_close); set_to_cap_if_null(ops, sb_umount_busy); diff --git a/security/security.c b/security/security.c index b98334b..a0bee70 100644 --- a/security/security.c +++ b/security/security.c @@ -306,11 +306,6 @@ int security_sb_mount(char *dev_name, struct path *path, return security_ops->sb_mount(dev_name, path, type, flags, data); } -int security_sb_check_sb(struct vfsmount *mnt, struct path *path) -{ - return security_ops->sb_check_sb(mnt, path); -} - int security_sb_umount(struct vfsmount *mnt, int flags) { return security_ops->sb_umount(mnt, flags); -- cgit v1.1 From 231923bd0e06cba69f7c2028f4a68602b8d22160 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:21 -0400 Subject: security: remove dead hook sb_umount_close Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index a7e905d..db72f4f 100644 --- a/security/capability.c +++ b/security/capability.c @@ -85,10 +85,6 @@ static int cap_sb_umount(struct vfsmount *mnt, int flags) return 0; } -static void cap_sb_umount_close(struct vfsmount *mnt) -{ -} - static void cap_sb_umount_busy(struct vfsmount *mnt) { } @@ -937,7 +933,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_statfs); set_to_cap_if_null(ops, sb_mount); set_to_cap_if_null(ops, sb_umount); - set_to_cap_if_null(ops, sb_umount_close); set_to_cap_if_null(ops, sb_umount_busy); set_to_cap_if_null(ops, sb_post_remount); set_to_cap_if_null(ops, sb_post_addmount); diff --git a/security/security.c b/security/security.c index a0bee70..591c25f 100644 --- a/security/security.c +++ b/security/security.c @@ -311,11 +311,6 @@ int security_sb_umount(struct vfsmount *mnt, int flags) return security_ops->sb_umount(mnt, flags); } -void security_sb_umount_close(struct vfsmount *mnt) -{ - security_ops->sb_umount_close(mnt); -} - void security_sb_umount_busy(struct vfsmount *mnt) { security_ops->sb_umount_busy(mnt); -- cgit v1.1 From 4b61d12c84293ac061909f27f567c1905e4d90e3 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:27 -0400 Subject: security: remove dead hook sb_umount_busy Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index db72f4f..476d4303 100644 --- a/security/capability.c +++ b/security/capability.c @@ -85,10 +85,6 @@ static int cap_sb_umount(struct vfsmount *mnt, int flags) return 0; } -static void cap_sb_umount_busy(struct vfsmount *mnt) -{ -} - static void cap_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data) { @@ -933,7 +929,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_statfs); set_to_cap_if_null(ops, sb_mount); set_to_cap_if_null(ops, sb_umount); - set_to_cap_if_null(ops, sb_umount_busy); set_to_cap_if_null(ops, sb_post_remount); set_to_cap_if_null(ops, sb_post_addmount); set_to_cap_if_null(ops, sb_pivotroot); diff --git a/security/security.c b/security/security.c index 591c25f..c1341fb 100644 --- a/security/security.c +++ b/security/security.c @@ -311,11 +311,6 @@ int security_sb_umount(struct vfsmount *mnt, int flags) return security_ops->sb_umount(mnt, flags); } -void security_sb_umount_busy(struct vfsmount *mnt) -{ - security_ops->sb_umount_busy(mnt); -} - void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data) { security_ops->sb_post_remount(mnt, flags, data); -- cgit v1.1 From 82dab10453d65ad9ca551de5b8925673ca05c7e9 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:33 -0400 Subject: security: remove dead hook sb_post_remount Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 476d4303..26fc92c 100644 --- a/security/capability.c +++ b/security/capability.c @@ -85,11 +85,6 @@ static int cap_sb_umount(struct vfsmount *mnt, int flags) return 0; } -static void cap_sb_post_remount(struct vfsmount *mnt, unsigned long flags, - void *data) -{ -} - static void cap_sb_post_addmount(struct vfsmount *mnt, struct path *path) { } @@ -929,7 +924,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_statfs); set_to_cap_if_null(ops, sb_mount); set_to_cap_if_null(ops, sb_umount); - set_to_cap_if_null(ops, sb_post_remount); set_to_cap_if_null(ops, sb_post_addmount); set_to_cap_if_null(ops, sb_pivotroot); set_to_cap_if_null(ops, sb_post_pivotroot); diff --git a/security/security.c b/security/security.c index c1341fb..d9538d9 100644 --- a/security/security.c +++ b/security/security.c @@ -311,11 +311,6 @@ int security_sb_umount(struct vfsmount *mnt, int flags) return security_ops->sb_umount(mnt, flags); } -void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data) -{ - security_ops->sb_post_remount(mnt, flags, data); -} - void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint) { security_ops->sb_post_addmount(mnt, mountpoint); -- cgit v1.1 From 3db291017753e539af64c8bab373785f34e43ed2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:39 -0400 Subject: security: remove dead hook sb_post_addmount Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 26fc92c..38752dd 100644 --- a/security/capability.c +++ b/security/capability.c @@ -85,10 +85,6 @@ static int cap_sb_umount(struct vfsmount *mnt, int flags) return 0; } -static void cap_sb_post_addmount(struct vfsmount *mnt, struct path *path) -{ -} - static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) { return 0; @@ -924,7 +920,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_statfs); set_to_cap_if_null(ops, sb_mount); set_to_cap_if_null(ops, sb_umount); - set_to_cap_if_null(ops, sb_post_addmount); set_to_cap_if_null(ops, sb_pivotroot); set_to_cap_if_null(ops, sb_post_pivotroot); set_to_cap_if_null(ops, sb_set_mnt_opts); diff --git a/security/security.c b/security/security.c index d9538d9..6a8e541 100644 --- a/security/security.c +++ b/security/security.c @@ -311,11 +311,6 @@ int security_sb_umount(struct vfsmount *mnt, int flags) return security_ops->sb_umount(mnt, flags); } -void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint) -{ - security_ops->sb_post_addmount(mnt, mountpoint); -} - int security_sb_pivotroot(struct path *old_path, struct path *new_path) { return security_ops->sb_pivotroot(old_path, new_path); -- cgit v1.1 From 91a9420f5826db482030c21eca8c507271bbc441 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:45 -0400 Subject: security: remove dead hook sb_post_pivotroot Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 38752dd..b64b501 100644 --- a/security/capability.c +++ b/security/capability.c @@ -90,10 +90,6 @@ static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) return 0; } -static void cap_sb_post_pivotroot(struct path *old_path, struct path *new_path) -{ -} - static int cap_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts) { @@ -921,7 +917,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sb_mount); set_to_cap_if_null(ops, sb_umount); set_to_cap_if_null(ops, sb_pivotroot); - set_to_cap_if_null(ops, sb_post_pivotroot); set_to_cap_if_null(ops, sb_set_mnt_opts); set_to_cap_if_null(ops, sb_clone_mnt_opts); set_to_cap_if_null(ops, sb_parse_opts_str); diff --git a/security/security.c b/security/security.c index 6a8e541..5223fa4 100644 --- a/security/security.c +++ b/security/security.c @@ -316,11 +316,6 @@ int security_sb_pivotroot(struct path *old_path, struct path *new_path) return security_ops->sb_pivotroot(old_path, new_path); } -void security_sb_post_pivotroot(struct path *old_path, struct path *new_path) -{ - security_ops->sb_post_pivotroot(old_path, new_path); -} - int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts) { -- cgit v1.1 From 9d5ed77dadc66a72b40419c91df942adfa55a102 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:50 -0400 Subject: security: remove dead hook inode_delete Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 7 ------- 2 files changed, 12 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index b64b501..b855e9f 100644 --- a/security/capability.c +++ b/security/capability.c @@ -195,10 +195,6 @@ static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) return 0; } -static void cap_inode_delete(struct inode *ino) -{ -} - static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { @@ -936,7 +932,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, inode_permission); set_to_cap_if_null(ops, inode_setattr); set_to_cap_if_null(ops, inode_getattr); - set_to_cap_if_null(ops, inode_delete); set_to_cap_if_null(ops, inode_setxattr); set_to_cap_if_null(ops, inode_post_setxattr); set_to_cap_if_null(ops, inode_getxattr); diff --git a/security/security.c b/security/security.c index 5223fa4..c65b0bc 100644 --- a/security/security.c +++ b/security/security.c @@ -550,13 +550,6 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) return security_ops->inode_getattr(mnt, dentry); } -void security_inode_delete(struct inode *inode) -{ - if (unlikely(IS_PRIVATE(inode))) - return; - security_ops->inode_delete(inode); -} - int security_inode_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { -- cgit v1.1 From 0968d0060a3c885e53d453380266c7792a55d302 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:14:56 -0400 Subject: security: remove dead hook cred_commit Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 5 ----- security/security.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index b855e9f..a927bde 100644 --- a/security/capability.c +++ b/security/capability.c @@ -373,10 +373,6 @@ static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) return 0; } -static void cap_cred_commit(struct cred *new, const struct cred *old) -{ -} - static void cap_cred_transfer(struct cred *new, const struct cred *old) { } @@ -972,7 +968,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, cred_alloc_blank); set_to_cap_if_null(ops, cred_free); set_to_cap_if_null(ops, cred_prepare); - set_to_cap_if_null(ops, cred_commit); set_to_cap_if_null(ops, cred_transfer); set_to_cap_if_null(ops, kernel_act_as); set_to_cap_if_null(ops, kernel_create_files_as); diff --git a/security/security.c b/security/security.c index c65b0bc..6e59426 100644 --- a/security/security.c +++ b/security/security.c @@ -712,11 +712,6 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) return security_ops->cred_prepare(new, old, gfp); } -void security_commit_creds(struct cred *new, const struct cred *old) -{ - security_ops->cred_commit(new, old); -} - void security_transfer_creds(struct cred *new, const struct cred *old) { security_ops->cred_transfer(new, old); -- cgit v1.1 From 43ed8c3b4573d5f5cd314937fee63b4ab046ac5f Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:15:02 -0400 Subject: security: remove dead hook task_setuid Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index a927bde..41ff54f 100644 --- a/security/capability.c +++ b/security/capability.c @@ -392,11 +392,6 @@ static int cap_kernel_module_request(char *kmod_name) return 0; } -static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) -{ - return 0; -} - static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) { return 0; @@ -972,7 +967,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, kernel_act_as); set_to_cap_if_null(ops, kernel_create_files_as); set_to_cap_if_null(ops, kernel_module_request); - set_to_cap_if_null(ops, task_setuid); set_to_cap_if_null(ops, task_fix_setuid); set_to_cap_if_null(ops, task_setgid); set_to_cap_if_null(ops, task_setpgid); diff --git a/security/security.c b/security/security.c index 6e59426..3900da3 100644 --- a/security/security.c +++ b/security/security.c @@ -732,11 +732,6 @@ int security_kernel_module_request(char *kmod_name) return security_ops->kernel_module_request(kmod_name); } -int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) -{ - return security_ops->task_setuid(id0, id1, id2, flags); -} - int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { -- cgit v1.1 From 06ad187e280e725e356c62c3a30ddcd01564f8be Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:15:08 -0400 Subject: security: remove dead hook task_setgid Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 41ff54f..66cd745 100644 --- a/security/capability.c +++ b/security/capability.c @@ -392,11 +392,6 @@ static int cap_kernel_module_request(char *kmod_name) return 0; } -static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) -{ - return 0; -} - static int cap_task_setpgid(struct task_struct *p, pid_t pgid) { return 0; @@ -968,7 +963,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, kernel_create_files_as); set_to_cap_if_null(ops, kernel_module_request); set_to_cap_if_null(ops, task_fix_setuid); - set_to_cap_if_null(ops, task_setgid); set_to_cap_if_null(ops, task_setpgid); set_to_cap_if_null(ops, task_getpgid); set_to_cap_if_null(ops, task_getsid); diff --git a/security/security.c b/security/security.c index 3900da3..1e35dd6 100644 --- a/security/security.c +++ b/security/security.c @@ -738,11 +738,6 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old, return security_ops->task_fix_setuid(new, old, flags); } -int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) -{ - return security_ops->task_setgid(id0, id1, id2, flags); -} - int security_task_setpgid(struct task_struct *p, pid_t pgid) { return security_ops->task_setpgid(p, pgid); -- cgit v1.1 From 6307f8fee295b364716d28686df6e69c2fee751a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:15:13 -0400 Subject: security: remove dead hook task_setgroups Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 66cd745..247c04e 100644 --- a/security/capability.c +++ b/security/capability.c @@ -412,11 +412,6 @@ static void cap_task_getsecid(struct task_struct *p, u32 *secid) *secid = 0; } -static int cap_task_setgroups(struct group_info *group_info) -{ - return 0; -} - static int cap_task_getioprio(struct task_struct *p) { return 0; @@ -967,7 +962,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, task_getpgid); set_to_cap_if_null(ops, task_getsid); set_to_cap_if_null(ops, task_getsecid); - set_to_cap_if_null(ops, task_setgroups); set_to_cap_if_null(ops, task_setnice); set_to_cap_if_null(ops, task_setioprio); set_to_cap_if_null(ops, task_getioprio); diff --git a/security/security.c b/security/security.c index 1e35dd6..5cf9ca6 100644 --- a/security/security.c +++ b/security/security.c @@ -759,11 +759,6 @@ void security_task_getsecid(struct task_struct *p, u32 *secid) } EXPORT_SYMBOL(security_task_getsecid); -int security_task_setgroups(struct group_info *group_info) -{ - return security_ops->task_setgroups(group_info); -} - int security_task_setnice(struct task_struct *p, int nice) { return security_ops->task_setnice(p, nice); -- cgit v1.1 From 3011a344cdcda34cdbcb40c3fb3d1a6e89954abb Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:15:19 -0400 Subject: security: remove dead hook key_session_to_parent Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 8 -------- security/keys/keyctl.c | 7 ------- security/security.c | 7 ------- 3 files changed, 22 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 247c04e..8cc2b8f 100644 --- a/security/capability.c +++ b/security/capability.c @@ -826,13 +826,6 @@ static int cap_key_getsecurity(struct key *key, char **_buffer) return 0; } -static int cap_key_session_to_parent(const struct cred *cred, - const struct cred *parent_cred, - struct key *key) -{ - return 0; -} - #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT @@ -1053,7 +1046,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, key_free); set_to_cap_if_null(ops, key_permission); set_to_cap_if_null(ops, key_getsecurity); - set_to_cap_if_null(ops, key_session_to_parent); #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT set_to_cap_if_null(ops, audit_rule_init); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index e9c2e7c5..34b302b 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1295,13 +1295,6 @@ long keyctl_session_to_parent(void) mycred->tgcred->session_keyring->uid != mycred->euid) goto not_permitted; - /* the LSM must permit the replacement of the parent's keyring with the - * keyring from this process */ - ret = security_key_session_to_parent(mycred, pcred, - key_ref_to_ptr(keyring_r)); - if (ret < 0) - goto not_permitted; - /* if there's an already pending keyring replacement, then we replace * that */ oldcred = parent->replacement_session_keyring; diff --git a/security/security.c b/security/security.c index 5cf9ca6..490f777 100644 --- a/security/security.c +++ b/security/security.c @@ -1262,13 +1262,6 @@ int security_key_getsecurity(struct key *key, char **_buffer) return security_ops->key_getsecurity(key, _buffer); } -int security_key_session_to_parent(const struct cred *cred, - const struct cred *parent_cred, - struct key *key) -{ - return security_ops->key_session_to_parent(cred, parent_cred, key); -} - #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT -- cgit v1.1 From 05b90496f2f366b9d3eea468351888ddf010782a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 7 Apr 2010 15:15:25 -0400 Subject: security: remove dead hook acct Unused hook. Remove. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/capability.c | 6 ------ security/security.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 8cc2b8f..7f093d5 100644 --- a/security/capability.c +++ b/security/capability.c @@ -12,11 +12,6 @@ #include -static int cap_acct(struct file *file) -{ - return 0; -} - static int cap_sysctl(ctl_table *table, int op) { return 0; @@ -865,7 +860,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, ptrace_traceme); set_to_cap_if_null(ops, capget); set_to_cap_if_null(ops, capset); - set_to_cap_if_null(ops, acct); set_to_cap_if_null(ops, capable); set_to_cap_if_null(ops, quotactl); set_to_cap_if_null(ops, quota_on); diff --git a/security/security.c b/security/security.c index 490f777..8585019 100644 --- a/security/security.c +++ b/security/security.c @@ -190,11 +190,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) return ret; } -int security_acct(struct file *file) -{ - return security_ops->acct(file); -} - int security_sysctl(struct ctl_table *table, int op) { return security_ops->sysctl(table, op); -- cgit v1.1 From 6f262d8e1acb7b1605b811700326163fa707d355 Mon Sep 17 00:00:00 2001 From: "wzt.wzt@gmail.com" Date: Mon, 19 Apr 2010 09:16:17 +0800 Subject: Security: Fix the comment of cap_file_mmap() In the comment of cap_file_mmap(), replace mmap_min_addr to be dac_mmap_min_addr. Signed-off-by: Zhitong Wang Acked-by: Eric Paris Signed-off-by: James Morris --- security/commoncap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/commoncap.c b/security/commoncap.c index 6166973..c45c4d2 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -931,7 +931,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) * @addr: address attempting to be mapped * @addr_only: unused * - * If the process is attempting to map memory below mmap_min_addr they need + * If the process is attempting to map memory below dac_mmap_min_addr they need * CAP_SYS_RAWIO. The other parameters to this function are unused by the * capability security module. Returns 0 if this mapping should be allowed * -EPERM if not. -- cgit v1.1 From a200005038955057063fc8ea82129ebc785df41c Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:29:42 -0400 Subject: SELinux: return error codes on policy load failure policy load failure always return EINVAL even if the failure was for some other reason (usually ENOMEM). This patch passes error codes back up the stack where they will make their way to userspace. This might help in debugging future problems with policy load. Signed-off-by: Eric Paris Acked-by: Stephen Smalley Signed-off-by: James Morris --- security/selinux/ss/services.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 0b44f5a..1de60ce9 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1760,22 +1760,28 @@ int security_load_policy(void *data, size_t len) if (!ss_initialized) { avtab_cache_init(); - if (policydb_read(&policydb, fp)) { + rc = policydb_read(&policydb, fp); + if (rc) { avtab_cache_destroy(); - return -EINVAL; + return rc; } - if (selinux_set_mapping(&policydb, secclass_map, - ¤t_mapping, - ¤t_mapping_size)) { + + rc = selinux_set_mapping(&policydb, secclass_map, + ¤t_mapping, + ¤t_mapping_size); + if (rc) { policydb_destroy(&policydb); avtab_cache_destroy(); - return -EINVAL; + return rc; } - if (policydb_load_isids(&policydb, &sidtab)) { + + rc = policydb_load_isids(&policydb, &sidtab); + if (rc) { policydb_destroy(&policydb); avtab_cache_destroy(); - return -EINVAL; + return rc; } + security_load_policycaps(); ss_initialized = 1; seqno = ++latest_granting; @@ -1791,8 +1797,9 @@ int security_load_policy(void *data, size_t len) sidtab_hash_eval(&sidtab, "sids"); #endif - if (policydb_read(&newpolicydb, fp)) - return -EINVAL; + rc = policydb_read(&newpolicydb, fp); + if (rc) + return rc; /* If switching between different policy types, log MLS status */ if (policydb.mls_enabled && !newpolicydb.mls_enabled) @@ -1807,8 +1814,8 @@ int security_load_policy(void *data, size_t len) return rc; } - if (selinux_set_mapping(&newpolicydb, secclass_map, - &map, &map_size)) + rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); + if (rc) goto err; rc = security_preserve_bools(&newpolicydb); @@ -1819,10 +1826,10 @@ int security_load_policy(void *data, size_t len) /* Clone the SID table. */ sidtab_shutdown(&sidtab); - if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { - rc = -ENOMEM; + + rc = sidtab_map(&sidtab, clone_sid, &newsidtab); + if (rc) goto err; - } /* * Convert the internal representations of contexts -- cgit v1.1 From 6ccd045630054c99ba1bb35673db12cfcf1eea58 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:20:54 -0400 Subject: ima: handle multiple rules per write Currently IMA will only accept one rule per write(). This patch allows IMA to accept writes which contain multiple rules but only processes one rule per write. \n is used as the delimiter between rules. IMA will return a short write indicating that it only accepted up to the first \n. This allows simple userspace utilities like cat to be used to load an IMA policy instead of needing a special userspace utility that understood 'one write per rule' Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_fs.c | 38 +++++++++++++++++++------------------ security/integrity/ima/ima_policy.c | 18 +++++++++++------- 3 files changed, 32 insertions(+), 26 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 47fb65d..16d100d3 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -135,7 +135,7 @@ enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); void ima_init_policy(void); void ima_update_policy(void); -int ima_parse_add_rule(char *); +ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); /* LSM based policy rules require audit */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 0c72c9c..3674a52 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -243,32 +243,34 @@ static const struct file_operations ima_ascii_measurements_ops = { static ssize_t ima_write_policy(struct file *file, const char __user *buf, size_t datalen, loff_t *ppos) { - char *data; - int rc; + char *data = NULL; + ssize_t result; if (datalen >= PAGE_SIZE) - return -ENOMEM; - if (*ppos != 0) { - /* No partial writes. */ - return -EINVAL; - } + datalen = PAGE_SIZE - 1; + + /* No partial writes. */ + result = -EINVAL; + if (*ppos != 0) + goto out; + + result = -ENOMEM; data = kmalloc(datalen + 1, GFP_KERNEL); if (!data) - return -ENOMEM; + goto out; - if (copy_from_user(data, buf, datalen)) { - kfree(data); - return -EFAULT; - } *(data + datalen) = '\0'; - rc = ima_parse_add_rule(data); - if (rc < 0) { - datalen = -EINVAL; - valid_policy = 0; - } + result = -EFAULT; + if (copy_from_user(data, buf, datalen)) + goto out; + + result = ima_parse_add_rule(data); +out: + if (result < 0) + valid_policy = 0; kfree(data); - return datalen; + return result; } static struct dentry *ima_dir; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4759d0f..49998f9 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -261,7 +261,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); entry->action = -1; - while ((p = strsep(&rule, " \n")) != NULL) { + while ((p = strsep(&rule, " ")) != NULL) { substring_t args[MAX_OPT_ARGS]; int token; unsigned long lnum; @@ -269,7 +269,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) if (result < 0) break; if (!*p) - continue; + break; token = match_token(p, policy_tokens, args); switch (token) { case Opt_measure: @@ -373,7 +373,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) if (entry->action == UNKNOWN) result = -EINVAL; - audit_log_format(ab, "res=%d", !result ? 0 : 1); + audit_log_format(ab, "res=%d", !!result); audit_log_end(ab); return result; } @@ -383,13 +383,14 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) * @rule - ima measurement policy rule * * Uses a mutex to protect the policy list from multiple concurrent writers. - * Returns 0 on success, an error code on failure. + * Returns the length of the rule parsed, an error code on failure */ -int ima_parse_add_rule(char *rule) +ssize_t ima_parse_add_rule(char *rule) { const char *op = "update_policy"; + char *p; struct ima_measure_rule_entry *entry; - int result = 0; + ssize_t result, len; int audit_info = 0; /* Prevent installed policy from changing */ @@ -409,8 +410,11 @@ int ima_parse_add_rule(char *rule) INIT_LIST_HEAD(&entry->list); - result = ima_parse_rule(rule, entry); + p = strsep(&rule, "\n"); + len = strlen(p) + 1; + result = ima_parse_rule(p, entry); if (!result) { + result = len; mutex_lock(&ima_measure_mutex); list_add_tail(&entry->list, &measure_policy_rules); mutex_unlock(&ima_measure_mutex); -- cgit v1.1 From 7b62e162129c3b28d51016774e0c7c57c710c452 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:01 -0400 Subject: IMA: do not allow the same rule to specify the same thing twice IMA will accept rules which specify things twice and will only pay attention to the last one. We should reject such rules. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 49998f9..c771a20 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -245,6 +245,9 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, { int result; + if (entry->lsm[lsm_rule].rule) + return -EINVAL; + entry->lsm[lsm_rule].type = audit_type; result = security_filter_rule_init(entry->lsm[lsm_rule].type, Audit_equal, args, @@ -260,6 +263,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); + entry->uid = -1; entry->action = -1; while ((p = strsep(&rule, " ")) != NULL) { substring_t args[MAX_OPT_ARGS]; @@ -274,14 +278,26 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) switch (token) { case Opt_measure: audit_log_format(ab, "%s ", "measure"); + + if (entry->action != UNKNOWN) + result = -EINVAL; + entry->action = MEASURE; break; case Opt_dont_measure: audit_log_format(ab, "%s ", "dont_measure"); + + if (entry->action != UNKNOWN) + result = -EINVAL; + entry->action = DONT_MEASURE; break; case Opt_func: audit_log_format(ab, "func=%s ", args[0].from); + + if (entry->func) + result = -EINVAL; + if (strcmp(args[0].from, "FILE_CHECK") == 0) entry->func = FILE_CHECK; /* PATH_CHECK is for backwards compat */ @@ -298,6 +314,10 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) break; case Opt_mask: audit_log_format(ab, "mask=%s ", args[0].from); + + if (entry->mask) + result = -EINVAL; + if ((strcmp(args[0].from, "MAY_EXEC")) == 0) entry->mask = MAY_EXEC; else if (strcmp(args[0].from, "MAY_WRITE") == 0) @@ -313,6 +333,12 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) break; case Opt_fsmagic: audit_log_format(ab, "fsmagic=%s ", args[0].from); + + if (entry->fsmagic) { + result = -EINVAL; + break; + } + result = strict_strtoul(args[0].from, 16, &entry->fsmagic); if (!result) @@ -320,6 +346,12 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) break; case Opt_uid: audit_log_format(ab, "uid=%s ", args[0].from); + + if (entry->uid != -1) { + result = -EINVAL; + break; + } + result = strict_strtoul(args[0].from, 10, &lnum); if (!result) { entry->uid = (uid_t) lnum; @@ -370,7 +402,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) break; } } - if (entry->action == UNKNOWN) + if (!result && (entry->action == UNKNOWN)) result = -EINVAL; audit_log_format(ab, "res=%d", !!result); -- cgit v1.1 From b9035b1fd7933c11e68dbbf49b530cc43bf1da65 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:07 -0400 Subject: IMA: set entry->action to UNKNOWN rather than hard coding ima_parse_rule currently sets entry->action = -1 and then later tests if (entry->action == UNKNOWN). It is true that UNKNOWN == -1 but actually setting it to UNKNOWN makes a lot more sense in case things change in the future. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c771a20..0127011 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -264,7 +264,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); entry->uid = -1; - entry->action = -1; + entry->action = UNKNOWN; while ((p = strsep(&rule, " ")) != NULL) { substring_t args[MAX_OPT_ARGS]; int token; -- cgit v1.1 From e9d393bf8660fbbbe00617015224342bac3ea6fc Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:13 -0400 Subject: IMA: reject policies with unknown entries Currently the ima policy load code will print what it doesn't understand but really I think it should reject any policy it doesn't understand. This patch makes it so! Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 0127011..dee2dc0 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -398,6 +398,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) AUDIT_SUBJ_TYPE); break; case Opt_err: + result = -EINVAL; audit_log_format(ab, "UNKNOWN=%s ", p); break; } -- cgit v1.1 From 28ef4002ec7b4be27f1110b83e255df8159c786a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:18 -0400 Subject: IMA: handle whitespace better IMA parser will fail if whitespace is used in any way other than a single space. Using a tab or even using 2 spaces in a row will result in a policy being rejected. This patch makes the kernel ignore whitespace a bit better. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index dee2dc0..1bc9e31 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -265,15 +265,15 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->uid = -1; entry->action = UNKNOWN; - while ((p = strsep(&rule, " ")) != NULL) { + while ((p = strsep(&rule, " \t")) != NULL) { substring_t args[MAX_OPT_ARGS]; int token; unsigned long lnum; if (result < 0) break; - if (!*p) - break; + if ((*p == '\0') || (*p == ' ') || (*p == '\t')) + continue; token = match_token(p, policy_tokens, args); switch (token) { case Opt_measure: -- cgit v1.1 From 7233e3ee22b1506723411fe437bcf69f678e8cdd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:24 -0400 Subject: IMA: handle comments in policy IMA policy load parser will reject any policies with a comment. This patch will allow the parser to just ignore lines which start with a #. This is not very robust. # can ONLY be used at the very beginning of a line. Inline comments are not allowed. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 1bc9e31..babc500 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -445,19 +445,26 @@ ssize_t ima_parse_add_rule(char *rule) p = strsep(&rule, "\n"); len = strlen(p) + 1; + + if (*p == '#') { + kfree(entry); + return len; + } + result = ima_parse_rule(p, entry); - if (!result) { - result = len; - mutex_lock(&ima_measure_mutex); - list_add_tail(&entry->list, &measure_policy_rules); - mutex_unlock(&ima_measure_mutex); - } else { + if (result) { kfree(entry); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, op, "invalid policy", result, audit_info); + return result; } - return result; + + mutex_lock(&ima_measure_mutex); + list_add_tail(&entry->list, &measure_policy_rules); + mutex_unlock(&ima_measure_mutex); + + return len; } /* ima_delete_rules called to cleanup invalid policy */ -- cgit v1.1 From 2f1506cd82e0725ba00c7146a9a9b47824a5edcf Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:30 -0400 Subject: IMA: use audit_log_untrusted_string rather than %s Convert all of the places IMA calls audit_log_format with %s into audit_log_untrusted_string(). This is going to cause them all to get quoted, but it should make audit log injection harder. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index babc500..778a735 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -255,6 +255,13 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, return result; } +static void ima_log_string(struct audit_buffer *ab, char *key, char *value) +{ + audit_log_format(ab, "%s=", key); + audit_log_untrustedstring(ab, value); + audit_log_format(ab, " "); +} + static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) { struct audit_buffer *ab; @@ -277,7 +284,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) token = match_token(p, policy_tokens, args); switch (token) { case Opt_measure: - audit_log_format(ab, "%s ", "measure"); + ima_log_string(ab, "action", "measure"); if (entry->action != UNKNOWN) result = -EINVAL; @@ -285,7 +292,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->action = MEASURE; break; case Opt_dont_measure: - audit_log_format(ab, "%s ", "dont_measure"); + ima_log_string(ab, "action", "dont_measure"); if (entry->action != UNKNOWN) result = -EINVAL; @@ -293,7 +300,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->action = DONT_MEASURE; break; case Opt_func: - audit_log_format(ab, "func=%s ", args[0].from); + ima_log_string(ab, "func", args[0].from); if (entry->func) result = -EINVAL; @@ -313,7 +320,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->flags |= IMA_FUNC; break; case Opt_mask: - audit_log_format(ab, "mask=%s ", args[0].from); + ima_log_string(ab, "mask", args[0].from); if (entry->mask) result = -EINVAL; @@ -332,7 +339,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->flags |= IMA_MASK; break; case Opt_fsmagic: - audit_log_format(ab, "fsmagic=%s ", args[0].from); + ima_log_string(ab, "fsmagic", args[0].from); if (entry->fsmagic) { result = -EINVAL; @@ -345,7 +352,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) entry->flags |= IMA_FSMAGIC; break; case Opt_uid: - audit_log_format(ab, "uid=%s ", args[0].from); + ima_log_string(ab, "uid", args[0].from); if (entry->uid != -1) { result = -EINVAL; @@ -362,44 +369,44 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) } break; case Opt_obj_user: - audit_log_format(ab, "obj_user=%s ", args[0].from); + ima_log_string(ab, "obj_user", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_OBJ_USER, AUDIT_OBJ_USER); break; case Opt_obj_role: - audit_log_format(ab, "obj_role=%s ", args[0].from); + ima_log_string(ab, "obj_role", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_OBJ_ROLE, AUDIT_OBJ_ROLE); break; case Opt_obj_type: - audit_log_format(ab, "obj_type=%s ", args[0].from); + ima_log_string(ab, "obj_type", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_OBJ_TYPE, AUDIT_OBJ_TYPE); break; case Opt_subj_user: - audit_log_format(ab, "subj_user=%s ", args[0].from); + ima_log_string(ab, "subj_user", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_SUBJ_USER, AUDIT_SUBJ_USER); break; case Opt_subj_role: - audit_log_format(ab, "subj_role=%s ", args[0].from); + ima_log_string(ab, "subj_role", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_SUBJ_ROLE, AUDIT_SUBJ_ROLE); break; case Opt_subj_type: - audit_log_format(ab, "subj_type=%s ", args[0].from); + ima_log_string(ab, "subj_type", args[0].from); result = ima_lsm_rule_init(entry, args[0].from, LSM_SUBJ_TYPE, AUDIT_SUBJ_TYPE); break; case Opt_err: + ima_log_string(ab, "UNKNOWN", p); result = -EINVAL; - audit_log_format(ab, "UNKNOWN=%s ", p); break; } } -- cgit v1.1 From 34c111f626e91adb23f90a91d2c7cd4dac9fa4b1 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 20 Apr 2010 10:21:36 -0400 Subject: IMA: drop the word integrity in the audit message integrity_audit_msg() uses "integrity:" in the audit message. This violates the (loosely defined) audit system requirements that everything be a key=value pair and it doesn't provide additional information. This can be obviously gleaned from the message type. Just drop it. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index ff513ff..fcb1f71 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c @@ -40,7 +40,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, return; ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); - audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u", + audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", current->pid, current_cred()->uid, audit_get_loginuid(current), audit_get_sessionid(current)); -- cgit v1.1 From eb8dae9607901fd3fc181325ff3f30dce8f574c5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 22 Apr 2010 10:49:36 -0400 Subject: IMA: include the word IMA in printk messages As an example IMA emits a warning when it can't find a TPM chip: "No TPM chip found, activating TPM-bypass!" This patch prefaces that message with IMA so we know what subsystem is bypassing the TPM. Do this for all pr_info and pr_err messages. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/ima/ima_crypto.c | 4 ++-- security/integrity/ima/ima_init.c | 2 +- security/integrity/ima/ima_queue.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 46642a1..acd4226 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -26,7 +26,7 @@ static int init_desc(struct hash_desc *desc) desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(desc->tfm)) { - pr_info("failed to load %s transform: %ld\n", + pr_info("IMA: failed to load %s transform: %ld\n", ima_hash, PTR_ERR(desc->tfm)); rc = PTR_ERR(desc->tfm); return rc; @@ -111,7 +111,7 @@ static void __init ima_pcrread(int idx, u8 *pcr) return; if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) - pr_err("Error Communicating to TPM chip\n"); + pr_err("IMA: Error Communicating to TPM chip\n"); } /* diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index a40da7a..b93eddc 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -82,7 +82,7 @@ int __init ima_init(void) ima_used_chip = 1; if (!ima_used_chip) - pr_info("No TPM chip found, activating TPM-bypass!\n"); + pr_info("IMA: No TPM chip found, activating TPM-bypass!\n"); ima_add_boot_aggregate(); /* boot aggregate must be first entry */ ima_init_policy(); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index a0880e9..148a3d8 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -70,7 +70,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry) qe = kmalloc(sizeof(*qe), GFP_KERNEL); if (qe == NULL) { - pr_err("OUT OF MEMORY ERROR creating queue entry.\n"); + pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n"); return -ENOMEM; } qe->entry = entry; @@ -93,7 +93,7 @@ static int ima_pcr_extend(const u8 *hash) result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); if (result != 0) - pr_err("Error Communicating to TPM chip\n"); + pr_err("IMA: Error Communicating to TPM chip\n"); return result; } -- cgit v1.1 From 822cceec7248013821d655545ea45d1c6a9d15b3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 22 Apr 2010 12:19:17 -0700 Subject: mmap_min_addr check CAP_SYS_RAWIO only for write Redirecting directly to lsm, here's the patch discussed on lkml: http://lkml.org/lkml/2010/4/22/219 The mmap_min_addr value is useful information for an admin to see without being root ("is my system vulnerable to kernel NULL pointer attacks?") and its setting is trivially easy for an attacker to determine by calling mmap() in PAGE_SIZE increments starting at 0, so trying to keep it private has no value. Only require CAP_SYS_RAWIO if changing the value, not reading it. Comment from Serge : Me, I like to write my passwords with light blue pen on dark blue paper, pasted on my window - if you're going to get my password, you're gonna get a headache. Signed-off-by: Kees Cook Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/min_addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/min_addr.c b/security/min_addr.c index e86f297..f728728 100644 --- a/security/min_addr.c +++ b/security/min_addr.c @@ -33,7 +33,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, { int ret; - if (!capable(CAP_SYS_RAWIO)) + if (write && !capable(CAP_SYS_RAWIO)) return -EPERM; ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); -- cgit v1.1 From c5b60b5e67af8be4c58d3ffcc36894f69c4fbdc1 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Wed, 21 Apr 2010 00:02:11 -0700 Subject: security: whitespace coding style fixes Whitespace coding style fixes. Signed-off-by: Justin P. Mattock Signed-off-by: James Morris --- security/commoncap.c | 4 ++-- security/device_cgroup.c | 2 +- security/keys/key.c | 2 +- security/keys/keyctl.c | 58 +++++++++++++++++++++++----------------------- security/keys/keyring.c | 20 ++++++++-------- security/keys/permission.c | 2 +- security/keys/proc.c | 2 +- 7 files changed, 45 insertions(+), 45 deletions(-) (limited to 'security') diff --git a/security/commoncap.c b/security/commoncap.c index c45c4d2..4e01599 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -570,7 +570,7 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name, } if (!strncmp(name, XATTR_SECURITY_PREFIX, - sizeof(XATTR_SECURITY_PREFIX) - 1) && + sizeof(XATTR_SECURITY_PREFIX) - 1) && !capable(CAP_SYS_ADMIN)) return -EPERM; return 0; @@ -596,7 +596,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) } if (!strncmp(name, XATTR_SECURITY_PREFIX, - sizeof(XATTR_SECURITY_PREFIX) - 1) && + sizeof(XATTR_SECURITY_PREFIX) - 1) && !capable(CAP_SYS_ADMIN)) return -EPERM; return 0; diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 6cf8fd2..37c5af6 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -469,7 +469,7 @@ struct cgroup_subsys devices_subsys = { .name = "devices", .can_attach = devcgroup_can_attach, .create = devcgroup_create, - .destroy = devcgroup_destroy, + .destroy = devcgroup_destroy, .populate = devcgroup_populate, .subsys_id = devices_subsys_id, }; diff --git a/security/keys/key.c b/security/keys/key.c index e50d264..c70da6f 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -355,7 +355,7 @@ EXPORT_SYMBOL(key_alloc); */ int key_payload_reserve(struct key *key, size_t datalen) { - int delta = (int) datalen - key->datalen; + int delta = (int)datalen - key->datalen; int ret = 0; key_check(key); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 34b302b..8f4dce1 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -212,15 +212,15 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, ret = key->serial; key_put(key); - error5: +error5: key_type_put(ktype); - error4: +error4: key_ref_put(dest_ref); - error3: +error3: kfree(callout_info); - error2: +error2: kfree(description); - error: +error: return ret; } /* end sys_request_key() */ @@ -246,7 +246,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) ret = key_ref_to_ptr(key_ref)->serial; key_ref_put(key_ref); - error: +error: return ret; } /* end keyctl_get_keyring_ID() */ @@ -275,7 +275,7 @@ long keyctl_join_session_keyring(const char __user *_name) ret = join_session_keyring(name); kfree(name); - error: +error: return ret; } /* end keyctl_join_session_keyring() */ @@ -322,9 +322,9 @@ long keyctl_update_key(key_serial_t id, ret = key_update(key_ref, payload, plen); key_ref_put(key_ref); - error2: +error2: kfree(payload); - error: +error: return ret; } /* end keyctl_update_key() */ @@ -356,7 +356,7 @@ long keyctl_revoke_key(key_serial_t id) ret = 0; key_ref_put(key_ref); - error: +error: return ret; } /* end keyctl_revoke_key() */ @@ -381,7 +381,7 @@ long keyctl_keyring_clear(key_serial_t ringid) ret = keyring_clear(key_ref_to_ptr(keyring_ref)); key_ref_put(keyring_ref); - error: +error: return ret; } /* end keyctl_keyring_clear() */ @@ -413,9 +413,9 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); key_ref_put(key_ref); - error2: +error2: key_ref_put(keyring_ref); - error: +error: return ret; } /* end keyctl_keyring_link() */ @@ -447,9 +447,9 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); key_ref_put(key_ref); - error2: +error2: key_ref_put(keyring_ref); - error: +error: return ret; } /* end keyctl_keyring_unlink() */ @@ -529,9 +529,9 @@ okay: } kfree(tmpbuf); - error2: +error2: key_ref_put(key_ref); - error: +error: return ret; } /* end keyctl_describe_key() */ @@ -616,17 +616,17 @@ long keyctl_keyring_search(key_serial_t ringid, ret = key_ref_to_ptr(key_ref)->serial; - error6: +error6: key_ref_put(key_ref); - error5: +error5: key_type_put(ktype); - error4: +error4: key_ref_put(dest_ref); - error3: +error3: key_ref_put(keyring_ref); - error2: +error2: kfree(description); - error: +error: return ret; } /* end keyctl_keyring_search() */ @@ -673,7 +673,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) } /* the key is probably readable - now try to read it */ - can_read_key: +can_read_key: ret = key_validate(key); if (ret == 0) { ret = -EOPNOTSUPP; @@ -686,9 +686,9 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) } } - error2: +error2: key_put(key); - error: +error: return ret; } /* end keyctl_read_key() */ @@ -1282,16 +1282,16 @@ long keyctl_session_to_parent(void) /* the parent must have the same effective ownership and mustn't be * SUID/SGID */ - if (pcred-> uid != mycred->euid || + if (pcred->uid != mycred->euid || pcred->euid != mycred->euid || pcred->suid != mycred->euid || - pcred-> gid != mycred->egid || + pcred->gid != mycred->egid || pcred->egid != mycred->egid || pcred->sgid != mycred->egid) goto not_permitted; /* the keyrings must have the same UID */ - if (pcred ->tgcred->session_keyring->uid != mycred->euid || + if (pcred->tgcred->session_keyring->uid != mycred->euid || mycred->tgcred->session_keyring->uid != mycred->euid) goto not_permitted; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index fe0763a..ce7c44b 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -39,7 +39,7 @@ static inline unsigned keyring_hash(const char *desc) unsigned bucket = 0; for (; *desc; desc++) - bucket += (unsigned char) *desc; + bucket += (unsigned char)*desc; return bucket & (KEYRING_NAME_HASH_SIZE - 1); } @@ -235,7 +235,7 @@ static long keyring_read(const struct key *keyring, ret = qty; } - error: +error: return ret; } /* end keyring_read() */ @@ -506,7 +506,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, rcu_read_unlock(); return ERR_PTR(-ENOKEY); - found: +found: atomic_inc(&key->usage); rcu_read_unlock(); return make_key_ref(key, possessed); @@ -563,7 +563,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) read_unlock(&keyring_name_lock); keyring = ERR_PTR(-ENOKEY); - error: +error: return keyring; } /* end find_keyring_by_name() */ @@ -596,7 +596,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) sp = 0; /* start processing a new keyring */ - descend: +descend: if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) goto not_this_keyring; @@ -605,7 +605,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) goto not_this_keyring; kix = 0; - ascend: +ascend: /* iterate through the remaining keys in this keyring */ for (; kix < keylist->nkeys; kix++) { key = keylist->keys[kix]; @@ -631,7 +631,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) /* the keyring we're looking at was disqualified or didn't contain a * matching key */ - not_this_keyring: +not_this_keyring: if (sp > 0) { /* resume the checking of a keyring higher up in the tree */ sp--; @@ -642,15 +642,15 @@ static int keyring_detect_cycle(struct key *A, struct key *B) ret = 0; /* no cycles detected */ - error: +error: rcu_read_unlock(); return ret; - too_deep: +too_deep: ret = -ELOOP; goto error; - cycle_detected: +cycle_detected: ret = -EDEADLK; goto error; diff --git a/security/keys/permission.c b/security/keys/permission.c index 0ed802c..2864550 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -109,7 +109,7 @@ int key_validate(struct key *key) } } - error: +error: return ret; } /* end key_validate() */ diff --git a/security/keys/proc.c b/security/keys/proc.c index 9d01021..81bf98d 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -307,7 +307,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) { (*_pos)++; - return key_user_next((struct rb_node *) v); + return key_user_next((struct rb_node *)v); } static void proc_key_users_stop(struct seq_file *p, void *v) -- cgit v1.1 From 98ec4373bab1d839f794e9a4edc29f77eb9d897e Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 23 Apr 2010 12:48:12 +0100 Subject: SMACK: Don't #include Ext2 headers Don't #include Ext2 headers into Smack unnecessarily. Signed-off-by: David Howells Acked-by: Casey Schaufler Signed-off-by: James Morris --- security/smack/smack_lsm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 98eeddc..2a20738 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From cb84aa9b42b506299e5aea1ba4da26c03ab12877 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 27 Apr 2010 17:20:38 -0400 Subject: LSM Audit: rename LSM_AUDIT_NO_AUDIT to LSM_AUDIT_DATA_NONE Most of the LSM common audit work uses LSM_AUDIT_DATA_* for the naming. This was not so for LSM_AUDIT_NO_AUDIT which means the generic initializer cannot be used. This patch just renames the flag so the generic initializer can be used. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/lsm_audit.c | 2 +- security/selinux/avc.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/lsm_audit.c b/security/lsm_audit.c index acba3df..8c36506 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, } switch (a->type) { - case LSM_AUDIT_NO_AUDIT: + case LSM_AUDIT_DATA_NONE: return; case LSM_AUDIT_DATA_IPC: audit_log_format(ab, " key=%d ", a->u.ipc_id); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 989fef8..7f1a304 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -499,8 +499,7 @@ void avc_audit(u32 ssid, u32 tsid, return; if (!a) { a = &stack_data; - memset(a, 0, sizeof(*a)); - a->type = LSM_AUDIT_NO_AUDIT; + COMMON_AUDIT_DATA_INIT(a, NONE); } a->selinux_audit_data.tclass = tclass; a->selinux_audit_data.requested = requested; -- cgit v1.1 From fcaaade1db63bb2d6f7611d7824eb50d2f07a546 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Wed, 28 Apr 2010 15:57:57 -0400 Subject: selinux: generalize disabling of execmem for plt-in-heap archs On Tue, 2010-04-27 at 11:47 -0700, David Miller wrote: > From: "Tom \"spot\" Callaway" > Date: Tue, 27 Apr 2010 14:20:21 -0400 > > > [root@apollo ~]$ cat /proc/2174/maps > > 00010000-00014000 r-xp 00000000 fd:00 15466577 > > /sbin/mingetty > > 00022000-00024000 rwxp 00002000 fd:00 15466577 > > /sbin/mingetty > > 00024000-00046000 rwxp 00000000 00:00 0 > > [heap] > > SELINUX probably barfs on the executable heap, the PLT is in the HEAP > just like powerpc32 and that's why VM_DATA_DEFAULT_FLAGS has to set > both executable and writable. > > You also can't remove the CONFIG_PPC32 ifdefs in selinux, since > because of the VM_DATA_DEFAULT_FLAGS setting used still in that arch, > the heap will always have executable permission, just like sparc does. > You have to support those binaries forever, whether you like it or not. > > Let's just replace the CONFIG_PPC32 ifdef in SELINUX with CONFIG_PPC32 > || CONFIG_SPARC as in Tom's original patch and let's be done with > this. > > In fact I would go through all the arch/ header files and check the > VM_DATA_DEFAULT_FLAGS settings and add the necessary new ifdefs to the > SELINUX code so that other platforms don't have the pain of having to > go through this process too. To avoid maintaining per-arch ifdefs, it seems that we could just directly use (VM_DATA_DEFAULT_FLAGS & VM_EXEC) as the basis for deciding whether to enable or disable these checks. VM_DATA_DEFAULT_FLAGS isn't constant on some architectures but instead depends on current->personality, but we want this applied uniformly. So we'll just use the initial task state to determine whether or not to enable these checks. Signed-off-by: Stephen Smalley Acked-by: David S. Miller Signed-off-by: James Morris --- security/selinux/hooks.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ebee467..a03fd74 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2999,13 +2999,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, return file_has_perm(cred, file, av); } +static int default_noexec; + static int file_map_prot_check(struct file *file, unsigned long prot, int shared) { const struct cred *cred = current_cred(); int rc = 0; -#ifndef CONFIG_PPC32 - if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { + if (default_noexec && + (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { /* * We are making executable an anonymous mapping or a * private file mapping that will also be writable. @@ -3015,7 +3017,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared if (rc) goto error; } -#endif if (file) { /* read access is always possible with a mapping */ @@ -3076,8 +3077,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, if (selinux_checkreqprot) prot = reqprot; -#ifndef CONFIG_PPC32 - if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { + if (default_noexec && + (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { int rc = 0; if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { @@ -3099,7 +3100,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, if (rc) return rc; } -#endif return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); } @@ -5662,6 +5662,8 @@ static __init int selinux_init(void) /* Set the security state for the initial task. */ cred_init_security(); + 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); -- cgit v1.1 From a674fa46c79ffa37995bd1c8e4daa2b3be5a95ae Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 4 May 2010 18:16:30 -0400 Subject: ima: remove ACPI dependency The ACPI dependency moved to the TPM, where it belongs. Although IMA per-se does not require access to the bios measurement log, verifying the IMA boot aggregate does, which requires ACPI. This patch prereq's 'TPM: ACPI/PNP dependency removal' http://lkml.org/lkml/2010/5/4/378. Signed-off-by: Mimi Zohar Reported-by: Jean-Christophe Dubois Acked-by: Serge Hallyn Tested-by: Serge Hallyn Signed-off-by: James Morris --- security/integrity/ima/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 3d7846d..b6ecfd4d 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -2,15 +2,14 @@ # config IMA bool "Integrity Measurement Architecture(IMA)" - depends on ACPI depends on SECURITY select SECURITYFS select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_SHA1 - select TCG_TPM - select TCG_TIS + select TCG_TPM if !S390 + select TCG_TIS if TCG_TPM help The Trusted Computing Group(TCG) runtime Integrity Measurement Architecture(IMA) maintains a list of hash -- cgit v1.1 From 4e5d6f7ec3833c0da9cf34fa5c53c6058c5908b6 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 28 Apr 2010 14:17:42 +0900 Subject: TOMOYO: Use GFP_NOFS rather than GFP_KERNEL. In Ubuntu, security_path_*() hooks are exported to Unionfs. Thus, prepare for being called from inside VFS functions because I'm not sure whether it is safe to use GFP_KERNEL or not. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 10 +++++----- security/tomoyo/domain.c | 10 +++++----- security/tomoyo/file.c | 12 ++++++------ security/tomoyo/realpath.c | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'security') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 588f36a..b9f64ca 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -883,7 +883,7 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned ptr = tomoyo_profile_ptr[profile]; if (ptr) goto ok; - ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); + ptr = kmalloc(sizeof(*ptr), GFP_NOFS); if (!tomoyo_memory_ok(ptr)) { kfree(ptr); ptr = NULL; @@ -1088,7 +1088,7 @@ static int tomoyo_update_manager_entry(const char *manager, if (!saved_manager) return -ENOMEM; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) @@ -1881,7 +1881,7 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) */ static int tomoyo_open_control(const u8 type, struct file *file) { - struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL); + struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); if (!head) return -ENOMEM; @@ -1942,7 +1942,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) } else { if (!head->readbuf_size) head->readbuf_size = 4096 * 2; - head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL); + head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); if (!head->read_buf) { kfree(head); return -ENOMEM; @@ -1956,7 +1956,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) head->write = NULL; } else if (head->write) { head->writebuf_size = 4096 * 2; - head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL); + head->write_buf = kzalloc(head->writebuf_size, GFP_NOFS); if (!head->write_buf) { kfree(head->read_buf); kfree(head); diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 66caaa1..ed51418 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -152,7 +152,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, if (!saved_program) goto out; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || @@ -372,7 +372,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, if (!saved_domainname) goto out; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || @@ -564,7 +564,7 @@ static int tomoyo_update_alias_entry(const char *original_name, if (!saved_original_name || !saved_aliased_name) goto out; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || @@ -664,7 +664,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) return NULL; - entry = kzalloc(sizeof(*entry), GFP_KERNEL); + entry = kzalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { if (domain->is_deleted || @@ -704,7 +704,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) * This function assumes that the size of buffer returned by * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. */ - struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS); struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *old_domain_name = old_domain->domainname->name; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 1b24304..cf67e55 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -99,7 +99,7 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) { int error; struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), - GFP_KERNEL); + GFP_NOFS); if (!buf) return NULL; @@ -174,7 +174,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, if (!saved_filename) return -ENOMEM; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) @@ -321,7 +321,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, if (!saved_pattern->is_patterned) goto out; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) @@ -474,7 +474,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, if (!saved_pattern) return error; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) @@ -820,7 +820,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, if (!saved_filename) return -ENOMEM; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path_acl *acl = @@ -906,7 +906,7 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, if (!saved_filename1 || !saved_filename2) goto out; if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_NOFS); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path2_acl *acl = diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index cf7d61f..8fe3ee2 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -138,7 +138,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, */ char *tomoyo_realpath_from_path(struct path *path) { - char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL); + char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS); BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) <= TOMOYO_MAX_PATHNAME_LEN - 1); @@ -269,7 +269,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) atomic_inc(&ptr->users); goto out; } - ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); + ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); allocated_len = ptr ? ksize(ptr) : 0; if (!ptr || (tomoyo_quota_for_policy && atomic_read(&tomoyo_policy_memory_size) + allocated_len -- cgit v1.1 From 553d603c8fce8cf727eb26e4bf6b9549cd4623f1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Apr 2010 14:32:28 +0100 Subject: KEYS: keyring_serialise_link_sem is only needed for keyring->keyring links keyring_serialise_link_sem is only needed for keyring->keyring links as it's used to prevent cycle detection from being avoided by parallel keyring additions. Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/keyring.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 2fb2bc9..29de5ee 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -705,13 +705,14 @@ int __key_link(struct key *keyring, struct key *key) if (keyring->type != &key_type_keyring) goto error; - /* serialise link/link calls to prevent parallel calls causing a - * cycle when applied to two keyring in opposite orders */ - down_write(&keyring_serialise_link_sem); - - /* check that we aren't going to create a cycle adding one keyring to - * another */ + /* do some special keyring->keyring link checks */ if (key->type == &key_type_keyring) { + /* serialise link/link calls to prevent parallel calls causing + * a cycle when applied to two keyring in opposite orders */ + down_write(&keyring_serialise_link_sem); + + /* check that we aren't going to create a cycle adding one + * keyring to another */ ret = keyring_detect_cycle(keyring, key); if (ret < 0) goto error2; @@ -814,7 +815,8 @@ int __key_link(struct key *keyring, struct key *key) done: ret = 0; error2: - up_write(&keyring_serialise_link_sem); + if (key->type == &key_type_keyring) + up_write(&keyring_serialise_link_sem); error: return ret; -- cgit v1.1 From 2b9e4688fad8867b6e918610f396af3ab9246898 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Apr 2010 14:32:34 +0100 Subject: KEYS: Better handling of errors from construct_alloc_key() Errors from construct_alloc_key() shouldn't just be ignored in the way they are by construct_key_and_link(). The only error that can be ignored so is EINPROGRESS as that is used to indicate that we've found a key and don't need to construct one. We don't, however, handle ENOMEM, EDQUOT or EACCES to indicate allocation failures of one sort or another. Reported-by: Vegard Nossum Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/request_key.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/keys/request_key.c b/security/keys/request_key.c index d737cea..1bc3858 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -302,6 +302,7 @@ static int construct_alloc_key(struct key_type *type, const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; + int ret; kenter("%s,%s,,,", type->name, description); @@ -337,14 +338,23 @@ static int construct_alloc_key(struct key_type *type, kleave(" = 0 [%d]", key_serial(key)); return 0; + /* the key is now present - we tell the caller that we found it by + * returning -EINPROGRESS */ key_already_present: mutex_unlock(&key_construction_mutex); + ret = 0; if (dest_keyring) { - __key_link(dest_keyring, key_ref_to_ptr(key_ref)); + ret = __key_link(dest_keyring, key_ref_to_ptr(key_ref)); up_write(&dest_keyring->sem); } mutex_unlock(&user->cons_lock); key_put(key); + if (ret < 0) { + key_ref_put(key_ref); + *_key = NULL; + kleave(" = %d [link]", ret); + return ret; + } *_key = key = key_ref_to_ptr(key_ref); kleave(" = -EINPROGRESS [%d]", key_serial(key)); return -EINPROGRESS; @@ -390,6 +400,10 @@ static struct key *construct_key_and_link(struct key_type *type, kdebug("cons failed"); goto construction_failed; } + } else if (ret == -EINPROGRESS) { + ret = 0; + } else { + key = ERR_PTR(ret); } key_put(dest_keyring); @@ -422,6 +436,7 @@ struct key *request_key_and_link(struct key_type *type, const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; + int ret; kenter("%s,%s,%p,%zu,%p,%p,%lx", type->name, description, callout_info, callout_len, aux, @@ -435,8 +450,13 @@ struct key *request_key_and_link(struct key_type *type, key = key_ref_to_ptr(key_ref); if (dest_keyring) { construct_get_dest_keyring(&dest_keyring); - key_link(dest_keyring, key); + ret = key_link(dest_keyring, key); key_put(dest_keyring); + if (ret < 0) { + key_put(key); + key = ERR_PTR(ret); + goto error; + } } } else if (PTR_ERR(key_ref) != -EAGAIN) { key = ERR_CAST(key_ref); -- cgit v1.1 From 292823814261e085cdcef06b6b691e6c2563fbd4 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 6 May 2010 00:18:15 +0900 Subject: TOMOYO: Use mutex_lock_interruptible. Some of TOMOYO's functions may sleep after mutex_lock(). If OOM-killer selected a process which is waiting at mutex_lock(), the to-be-killed process can't be killed. Thus, replace mutex_lock() with mutex_lock_interruptible() so that the to-be-killed process can immediately return from TOMOYO's functions. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 13 ++++++++----- security/tomoyo/common.h | 1 - security/tomoyo/domain.c | 15 ++++++++++----- security/tomoyo/file.c | 18 +++++++++++++----- security/tomoyo/gc.c | 7 +++---- security/tomoyo/realpath.c | 7 +++---- 6 files changed, 37 insertions(+), 24 deletions(-) (limited to 'security') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 3c86bbc..8f34036 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -874,13 +874,13 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned int profile) { - static DEFINE_MUTEX(lock); struct tomoyo_profile *ptr = NULL; int i; if (profile >= TOMOYO_MAX_PROFILES) return NULL; - mutex_lock(&lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + return NULL; ptr = tomoyo_profile_ptr[profile]; if (ptr) goto ok; @@ -895,7 +895,7 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned mb(); /* Avoid out-of-order execution. */ tomoyo_profile_ptr[profile] = ptr; ok: - mutex_unlock(&lock); + mutex_unlock(&tomoyo_policy_lock); return ptr; } @@ -1090,7 +1090,8 @@ static int tomoyo_update_manager_entry(const char *manager, return -ENOMEM; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; @@ -1107,6 +1108,7 @@ static int tomoyo_update_manager_entry(const char *manager, error = 0; } mutex_unlock(&tomoyo_policy_lock); + out: tomoyo_put_name(saved_manager); kfree(entry); return error; @@ -1287,7 +1289,8 @@ static int tomoyo_delete_domain(char *domainname) name.name = domainname; tomoyo_fill_path_info(&name); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + return 0; /* Is there an active domain? */ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { /* Never delete tomoyo_kernel_domain */ diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 67bd22d..52c9502 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -662,7 +662,6 @@ extern struct list_head tomoyo_pattern_list; extern struct list_head tomoyo_no_rewrite_list; extern struct list_head tomoyo_policy_manager_list; extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; -extern struct mutex tomoyo_name_list_lock; /* Lock for protecting policy. */ extern struct mutex tomoyo_policy_lock; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index e1edec4..a1723bb 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -154,7 +154,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, goto out; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -374,7 +375,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, goto out; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -566,7 +568,8 @@ static int tomoyo_update_alias_entry(const char *original_name, goto out; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || ptr->aliased_name != saved_aliased_name) @@ -656,7 +659,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * const u8 profile) { struct tomoyo_domain_info *entry; - struct tomoyo_domain_info *domain; + struct tomoyo_domain_info *domain = NULL; const struct tomoyo_path_info *saved_domainname; bool found = false; @@ -666,7 +669,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!saved_domainname) return NULL; entry = kzalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { if (domain->is_deleted || tomoyo_pathcmp(saved_domainname, domain->domainname)) @@ -685,6 +689,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * found = true; } mutex_unlock(&tomoyo_policy_lock); + out: tomoyo_put_name(saved_domainname); kfree(entry); return found ? domain : NULL; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 0687ada..060bbf3 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -176,7 +176,8 @@ static int tomoyo_update_globally_readable_entry(const char *filename, return -ENOMEM; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; @@ -192,6 +193,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, error = 0; } mutex_unlock(&tomoyo_policy_lock); + out: tomoyo_put_name(saved_filename); kfree(entry); return error; @@ -323,7 +325,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, goto out; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; @@ -476,7 +479,8 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, return error; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; @@ -492,6 +496,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, error = 0; } mutex_unlock(&tomoyo_policy_lock); + out: tomoyo_put_name(saved_pattern); kfree(entry); return error; @@ -822,7 +827,8 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, return -ENOMEM; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path_acl *acl = container_of(ptr, struct tomoyo_path_acl, head); @@ -867,6 +873,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, error = 0; } mutex_unlock(&tomoyo_policy_lock); + out: kfree(entry); tomoyo_put_name(saved_filename); return error; @@ -908,7 +915,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, goto out; if (!is_delete) entry = kmalloc(sizeof(*entry), GFP_NOFS); - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path2_acl *acl = container_of(ptr, struct tomoyo_path2_acl, head); diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index d9ad35b..245bf42 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -151,7 +151,8 @@ static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) static void tomoyo_collect_entry(void) { - mutex_lock(&tomoyo_policy_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + return; { struct tomoyo_globally_readable_file_entry *ptr; list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, @@ -275,8 +276,6 @@ static void tomoyo_collect_entry(void) break; } } - mutex_unlock(&tomoyo_policy_lock); - mutex_lock(&tomoyo_name_list_lock); { int i; for (i = 0; i < TOMOYO_MAX_HASH; i++) { @@ -294,7 +293,7 @@ static void tomoyo_collect_entry(void) } } } - mutex_unlock(&tomoyo_name_list_lock); + mutex_unlock(&tomoyo_policy_lock); } static void tomoyo_kfree_entry(void) diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 6a51e0a..62062a6 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -240,8 +240,6 @@ void tomoyo_memory_free(void *ptr) * "const struct tomoyo_path_info *". */ struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; -/* Lock for protecting tomoyo_name_list . */ -DEFINE_MUTEX(tomoyo_name_list_lock); /** * tomoyo_get_name - Allocate permanent memory for string data. @@ -263,7 +261,8 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) len = strlen(name) + 1; hash = full_name_hash((const unsigned char *) name, len - 1); head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; - mutex_lock(&tomoyo_name_list_lock); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + return NULL; list_for_each_entry(ptr, head, list) { if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) continue; @@ -290,7 +289,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) tomoyo_fill_path_info(&ptr->entry); list_add_tail(&ptr->list, head); out: - mutex_unlock(&tomoyo_name_list_lock); + mutex_unlock(&tomoyo_policy_lock); return ptr ? &ptr->entry : NULL; } -- cgit v1.1 From f70e2e06196ad4c1c762037da2f75354f6c16b81 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 30 Apr 2010 14:32:39 +0100 Subject: KEYS: Do preallocation for __key_link() Do preallocation for __key_link() so that the various callers in request_key.c can deal with any errors from this source before attempting to construct a key. This allows them to assume that the actual linkage step is guaranteed to be successful. Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/internal.h | 11 +- security/keys/key.c | 45 +++++--- security/keys/keyring.c | 242 ++++++++++++++++++++++++++------------------ security/keys/request_key.c | 47 ++++++--- 4 files changed, 215 insertions(+), 130 deletions(-) (limited to 'security') diff --git a/security/keys/internal.h b/security/keys/internal.h index 24ba030..5d4402a 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -87,7 +87,16 @@ extern wait_queue_head_t request_key_conswq; extern struct key_type *key_type_lookup(const char *type); extern void key_type_put(struct key_type *ktype); -extern int __key_link(struct key *keyring, struct key *key); +extern int __key_link_begin(struct key *keyring, + const struct key_type *type, + const char *description, + struct keyring_list **_prealloc); +extern int __key_link_check_live_key(struct key *keyring, struct key *key); +extern void __key_link(struct key *keyring, struct key *key, + struct keyring_list **_prealloc); +extern void __key_link_end(struct key *keyring, + struct key_type *type, + struct keyring_list *prealloc); extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, const struct key_type *type, diff --git a/security/keys/key.c b/security/keys/key.c index c70da6f..c1eac80 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -398,7 +398,8 @@ static int __key_instantiate_and_link(struct key *key, const void *data, size_t datalen, struct key *keyring, - struct key *authkey) + struct key *authkey, + struct keyring_list **_prealloc) { int ret, awaken; @@ -425,7 +426,7 @@ static int __key_instantiate_and_link(struct key *key, /* and link it into the destination keyring */ if (keyring) - ret = __key_link(keyring, key); + __key_link(keyring, key, _prealloc); /* disable the authorisation key */ if (authkey) @@ -453,15 +454,21 @@ int key_instantiate_and_link(struct key *key, struct key *keyring, struct key *authkey) { + struct keyring_list *prealloc; int ret; - if (keyring) - down_write(&keyring->sem); + if (keyring) { + ret = __key_link_begin(keyring, key->type, key->description, + &prealloc); + if (ret < 0) + return ret; + } - ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); + ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, + &prealloc); if (keyring) - up_write(&keyring->sem); + __key_link_end(keyring, key->type, prealloc); return ret; @@ -478,8 +485,9 @@ int key_negate_and_link(struct key *key, struct key *keyring, struct key *authkey) { + struct keyring_list *prealloc; struct timespec now; - int ret, awaken; + int ret, awaken, link_ret = 0; key_check(key); key_check(keyring); @@ -488,7 +496,8 @@ int key_negate_and_link(struct key *key, ret = -EBUSY; if (keyring) - down_write(&keyring->sem); + link_ret = __key_link_begin(keyring, key->type, + key->description, &prealloc); mutex_lock(&key_construction_mutex); @@ -508,8 +517,8 @@ int key_negate_and_link(struct key *key, ret = 0; /* and link it into the destination keyring */ - if (keyring) - ret = __key_link(keyring, key); + if (keyring && link_ret == 0) + __key_link(keyring, key, &prealloc); /* disable the authorisation key */ if (authkey) @@ -519,13 +528,13 @@ int key_negate_and_link(struct key *key, mutex_unlock(&key_construction_mutex); if (keyring) - up_write(&keyring->sem); + __key_link_end(keyring, key->type, prealloc); /* wake up anyone waiting for a key to be constructed */ if (awaken) wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); - return ret; + return ret == 0 ? link_ret : ret; } /* end key_negate_and_link() */ @@ -749,6 +758,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_perm_t perm, unsigned long flags) { + struct keyring_list *prealloc; const struct cred *cred = current_cred(); struct key_type *ktype; struct key *keyring, *key = NULL; @@ -775,7 +785,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, if (keyring->type != &key_type_keyring) goto error_2; - down_write(&keyring->sem); + ret = __key_link_begin(keyring, ktype, description, &prealloc); + if (ret < 0) + goto error_2; /* if we're going to allocate a new key, we're going to have * to modify the keyring */ @@ -817,7 +829,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } /* instantiate it and link it into the target keyring */ - ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); + ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, + &prealloc); if (ret < 0) { key_put(key); key_ref = ERR_PTR(ret); @@ -827,7 +840,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_3: - up_write(&keyring->sem); + __key_link_end(keyring, ktype, prealloc); error_2: key_type_put(ktype); error: @@ -837,7 +850,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* we found a matching key, so we're going to try to update it * - we can drop the locks first as we have the key pinned */ - up_write(&keyring->sem); + __key_link_end(keyring, ktype, prealloc); key_type_put(ktype); key_ref = __key_update(key_ref, payload, plen); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 3f425a6..ef03a82a0 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -660,20 +660,6 @@ cycle_detected: } /* end keyring_detect_cycle() */ -/*****************************************************************************/ -/* - * dispose of a keyring list after the RCU grace period - */ -static void keyring_link_rcu_disposal(struct rcu_head *rcu) -{ - struct keyring_list *klist = - container_of(rcu, struct keyring_list, rcu); - - kfree(klist); - -} /* end keyring_link_rcu_disposal() */ - -/*****************************************************************************/ /* * dispose of a keyring list after the RCU grace period, freeing the unlinked * key @@ -683,56 +669,51 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) struct keyring_list *klist = container_of(rcu, struct keyring_list, rcu); - key_put(klist->keys[klist->delkey]); + if (klist->delkey != USHORT_MAX) + key_put(klist->keys[klist->delkey]); kfree(klist); +} -} /* end keyring_unlink_rcu_disposal() */ - -/*****************************************************************************/ /* - * link a key into to a keyring - * - must be called with the keyring's semaphore write-locked - * - discard already extant link to matching key if there is one + * preallocate memory so that a key can be linked into to a keyring */ -int __key_link(struct key *keyring, struct key *key) +int __key_link_begin(struct key *keyring, const struct key_type *type, + const char *description, + struct keyring_list **_prealloc) + __acquires(&keyring->sem) { struct keyring_list *klist, *nklist; unsigned max; size_t size; int loop, ret; - ret = -EKEYREVOKED; - if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) - goto error; + kenter("%d,%s,%s,", key_serial(keyring), type->name, description); - ret = -ENOTDIR; if (keyring->type != &key_type_keyring) - goto error; + return -ENOTDIR; + + down_write(&keyring->sem); + + ret = -EKEYREVOKED; + if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) + goto error_krsem; - /* do some special keyring->keyring link checks */ - if (key->type == &key_type_keyring) { - /* serialise link/link calls to prevent parallel calls causing - * a cycle when applied to two keyring in opposite orders */ + /* serialise link/link calls to prevent parallel calls causing a cycle + * when linking two keyring in opposite orders */ + if (type == &key_type_keyring) down_write(&keyring_serialise_link_sem); - /* check that we aren't going to create a cycle adding one - * keyring to another */ - ret = keyring_detect_cycle(keyring, key); - if (ret < 0) - goto error2; - } + klist = rcu_dereference_locked_keyring(keyring); /* see if there's a matching key we can displace */ - klist = rcu_dereference_locked_keyring(keyring); if (klist && klist->nkeys > 0) { - struct key_type *type = key->type; - for (loop = klist->nkeys - 1; loop >= 0; loop--) { if (klist->keys[loop]->type == type && strcmp(klist->keys[loop]->description, - key->description) == 0 + description) == 0 ) { - /* found a match - replace with new key */ + /* found a match - we'll replace this one with + * the new key */ size = sizeof(struct key *) * klist->maxkeys; size += sizeof(*klist); BUG_ON(size > PAGE_SIZE); @@ -740,22 +721,10 @@ int __key_link(struct key *keyring, struct key *key) ret = -ENOMEM; nklist = kmemdup(klist, size, GFP_KERNEL); if (!nklist) - goto error2; - - /* replace matched key */ - atomic_inc(&key->usage); - nklist->keys[loop] = key; - - rcu_assign_pointer( - keyring->payload.subscriptions, - nklist); - - /* dispose of the old keyring list and the - * displaced key */ - klist->delkey = loop; - call_rcu(&klist->rcu, - keyring_unlink_rcu_disposal); + goto error_sem; + /* note replacement slot */ + klist->delkey = nklist->delkey = loop; goto done; } } @@ -765,16 +734,11 @@ int __key_link(struct key *keyring, struct key *key) ret = key_payload_reserve(keyring, keyring->datalen + KEYQUOTA_LINK_BYTES); if (ret < 0) - goto error2; + goto error_sem; if (klist && klist->nkeys < klist->maxkeys) { - /* there's sufficient slack space to add directly */ - atomic_inc(&key->usage); - - klist->keys[klist->nkeys] = key; - smp_wmb(); - klist->nkeys++; - smp_wmb(); + /* there's sufficient slack space to append directly */ + nklist = NULL; } else { /* grow the key list */ max = 4; @@ -782,71 +746,155 @@ int __key_link(struct key *keyring, struct key *key) max += klist->maxkeys; ret = -ENFILE; - if (max > 65535) - goto error3; + if (max > USHORT_MAX - 1) + goto error_quota; size = sizeof(*klist) + sizeof(struct key *) * max; if (size > PAGE_SIZE) - goto error3; + goto error_quota; ret = -ENOMEM; nklist = kmalloc(size, GFP_KERNEL); if (!nklist) - goto error3; - nklist->maxkeys = max; - nklist->nkeys = 0; + goto error_quota; + nklist->maxkeys = max; if (klist) { - nklist->nkeys = klist->nkeys; - memcpy(nklist->keys, - klist->keys, + memcpy(nklist->keys, klist->keys, sizeof(struct key *) * klist->nkeys); + nklist->delkey = klist->nkeys; + nklist->nkeys = klist->nkeys + 1; + klist->delkey = USHORT_MAX; + } else { + nklist->nkeys = 1; + nklist->delkey = 0; } /* add the key into the new space */ - atomic_inc(&key->usage); - nklist->keys[nklist->nkeys++] = key; - - rcu_assign_pointer(keyring->payload.subscriptions, nklist); - - /* dispose of the old keyring list */ - if (klist) - call_rcu(&klist->rcu, keyring_link_rcu_disposal); + nklist->keys[nklist->delkey] = NULL; } done: - ret = 0; -error2: - if (key->type == &key_type_keyring) - up_write(&keyring_serialise_link_sem); -error: - return ret; + *_prealloc = nklist; + kleave(" = 0"); + return 0; -error3: +error_quota: /* undo the quota changes */ key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); - goto error2; +error_sem: + if (type == &key_type_keyring) + up_write(&keyring_serialise_link_sem); +error_krsem: + up_write(&keyring->sem); + kleave(" = %d", ret); + return ret; +} -} /* end __key_link() */ +/* + * check already instantiated keys aren't going to be a problem + * - the caller must have called __key_link_begin() + * - don't need to call this for keys that were created since __key_link_begin() + * was called + */ +int __key_link_check_live_key(struct key *keyring, struct key *key) +{ + if (key->type == &key_type_keyring) + /* check that we aren't going to create a cycle by linking one + * keyring to another */ + return keyring_detect_cycle(keyring, key); + return 0; +} + +/* + * link a key into to a keyring + * - must be called with __key_link_begin() having being called + * - discard already extant link to matching key if there is one + */ +void __key_link(struct key *keyring, struct key *key, + struct keyring_list **_prealloc) +{ + struct keyring_list *klist, *nklist; + + nklist = *_prealloc; + *_prealloc = NULL; + + kenter("%d,%d,%p", keyring->serial, key->serial, nklist); + + klist = rcu_dereference_protected(keyring->payload.subscriptions, + rwsem_is_locked(&keyring->sem)); + + atomic_inc(&key->usage); + + /* there's a matching key we can displace or an empty slot in a newly + * allocated list we can fill */ + if (nklist) { + kdebug("replace %hu/%hu/%hu", + nklist->delkey, nklist->nkeys, nklist->maxkeys); + + nklist->keys[nklist->delkey] = key; + + rcu_assign_pointer(keyring->payload.subscriptions, nklist); + + /* dispose of the old keyring list and, if there was one, the + * displaced key */ + if (klist) { + kdebug("dispose %hu/%hu/%hu", + klist->delkey, klist->nkeys, klist->maxkeys); + call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); + } + } else { + /* there's sufficient slack space to append directly */ + klist->keys[klist->nkeys] = key; + smp_wmb(); + klist->nkeys++; + } +} + +/* + * finish linking a key into to a keyring + * - must be called with __key_link_begin() having being called + */ +void __key_link_end(struct key *keyring, struct key_type *type, + struct keyring_list *prealloc) + __releases(&keyring->sem) +{ + BUG_ON(type == NULL); + BUG_ON(type->name == NULL); + kenter("%d,%s,%p", keyring->serial, type->name, prealloc); + + if (type == &key_type_keyring) + up_write(&keyring_serialise_link_sem); + + if (prealloc) { + kfree(prealloc); + key_payload_reserve(keyring, + keyring->datalen - KEYQUOTA_LINK_BYTES); + } + up_write(&keyring->sem); +} -/*****************************************************************************/ /* * link a key to a keyring */ int key_link(struct key *keyring, struct key *key) { + struct keyring_list *prealloc; int ret; key_check(keyring); key_check(key); - down_write(&keyring->sem); - ret = __key_link(keyring, key); - up_write(&keyring->sem); + ret = __key_link_begin(keyring, key->type, key->description, &prealloc); + if (ret == 0) { + ret = __key_link_check_live_key(keyring, key); + if (ret == 0) + __key_link(keyring, key, &prealloc); + __key_link_end(keyring, key->type, prealloc); + } return ret; - -} /* end key_link() */ +} EXPORT_SYMBOL(key_link); diff --git a/security/keys/request_key.c b/security/keys/request_key.c index ac49c8a..f656e9c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -299,6 +299,7 @@ static int construct_alloc_key(struct key_type *type, struct key_user *user, struct key **_key) { + struct keyring_list *prealloc; const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; @@ -306,6 +307,7 @@ static int construct_alloc_key(struct key_type *type, kenter("%s,%s,,,", type->name, description); + *_key = NULL; mutex_lock(&user->cons_lock); key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, @@ -315,8 +317,12 @@ static int construct_alloc_key(struct key_type *type, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); - if (dest_keyring) - down_write(&dest_keyring->sem); + if (dest_keyring) { + ret = __key_link_begin(dest_keyring, type, description, + &prealloc); + if (ret < 0) + goto link_prealloc_failed; + } /* attach the key to the destination keyring under lock, but we do need * to do another check just in case someone beat us to it whilst we @@ -328,11 +334,11 @@ static int construct_alloc_key(struct key_type *type, goto key_already_present; if (dest_keyring) - __key_link(dest_keyring, key); + __key_link(dest_keyring, key, &prealloc); mutex_unlock(&key_construction_mutex); if (dest_keyring) - up_write(&dest_keyring->sem); + __key_link_end(dest_keyring, type, prealloc); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); @@ -341,27 +347,36 @@ static int construct_alloc_key(struct key_type *type, /* the key is now present - we tell the caller that we found it by * returning -EINPROGRESS */ key_already_present: + key_put(key); mutex_unlock(&key_construction_mutex); - ret = 0; + key = key_ref_to_ptr(key_ref); if (dest_keyring) { - ret = __key_link(dest_keyring, key_ref_to_ptr(key_ref)); - up_write(&dest_keyring->sem); + ret = __key_link_check_live_key(dest_keyring, key); + if (ret == 0) + __key_link(dest_keyring, key, &prealloc); + __key_link_end(dest_keyring, type, prealloc); + if (ret < 0) + goto link_check_failed; } mutex_unlock(&user->cons_lock); - key_put(key); - if (ret < 0) { - key_ref_put(key_ref); - *_key = NULL; - kleave(" = %d [link]", ret); - return ret; - } - *_key = key = key_ref_to_ptr(key_ref); + *_key = key; kleave(" = -EINPROGRESS [%d]", key_serial(key)); return -EINPROGRESS; +link_check_failed: + mutex_unlock(&user->cons_lock); + key_put(key); + kleave(" = %d [linkcheck]", ret); + return ret; + +link_prealloc_failed: + up_write(&dest_keyring->sem); + mutex_unlock(&user->cons_lock); + kleave(" = %d [prelink]", ret); + return ret; + alloc_failed: mutex_unlock(&user->cons_lock); - *_key = NULL; kleave(" = %ld", PTR_ERR(key)); return PTR_ERR(key); } -- cgit v1.1 From 83c36ccfe4d849f482ea0a62402c7624f4e59f0e Mon Sep 17 00:00:00 2001 From: James Morris Date: Fri, 7 May 2010 09:20:03 +1000 Subject: Revert "ima: remove ACPI dependency" This reverts commit a674fa46c79ffa37995bd1c8e4daa2b3be5a95ae. Previous revert was a prereq. Signed-off-by: James Morris --- security/integrity/ima/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index b6ecfd4d..3d7846d 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -2,14 +2,15 @@ # config IMA bool "Integrity Measurement Architecture(IMA)" + depends on ACPI depends on SECURITY select SECURITYFS select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_SHA1 - select TCG_TPM if !S390 - select TCG_TIS if TCG_TPM + select TCG_TPM + select TCG_TIS help The Trusted Computing Group(TCG) runtime Integrity Measurement Architecture(IMA) maintains a list of hash -- cgit v1.1 From 9e4b50e93786d00c703f16ed46e6a4029c0dfdd1 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 6 May 2010 12:40:02 +0900 Subject: TOMOYO: Use stack memory for pending entry. Use stack memory for pending entry to reduce kmalloc() which will be kfree()d. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 32 ++++---- security/tomoyo/common.h | 26 +++++++ security/tomoyo/domain.c | 124 ++++++++++++------------------- security/tomoyo/file.c | 181 +++++++++++++++++++++------------------------ security/tomoyo/realpath.c | 19 +++++ 5 files changed, 190 insertions(+), 192 deletions(-) (limited to 'security') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 8f34036..62e089c 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1071,46 +1071,42 @@ LIST_HEAD(tomoyo_policy_manager_list); static int tomoyo_update_manager_entry(const char *manager, const bool is_delete) { - struct tomoyo_policy_manager_entry *entry = NULL; struct tomoyo_policy_manager_entry *ptr; - const struct tomoyo_path_info *saved_manager; + struct tomoyo_policy_manager_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; - bool is_domain = false; if (tomoyo_is_domain_def(manager)) { if (!tomoyo_is_correct_domain(manager)) return -EINVAL; - is_domain = true; + e.is_domain = true; } else { if (!tomoyo_is_correct_path(manager, 1, -1, -1)) return -EINVAL; } - saved_manager = tomoyo_get_name(manager); - if (!saved_manager) + e.manager = tomoyo_get_name(manager); + if (!e.manager) return -ENOMEM; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { - if (ptr->manager != saved_manager) + if (ptr->manager != e.manager) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->manager = saved_manager; - saved_manager = NULL; - entry->is_domain = is_domain; - list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_policy_manager_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, + &tomoyo_policy_manager_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_manager); - kfree(entry); + tomoyo_put_name(e.manager); return error; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 52c9502..c95f486 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -616,6 +616,7 @@ char *tomoyo_realpath_from_path(struct path *path); /* Check memory quota. */ bool tomoyo_memory_ok(void *ptr); +void *tomoyo_commit_ok(void *data, const unsigned int size); /* * Keep the given name on the RAM. @@ -735,6 +736,31 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct return task_cred_xxx(task, security); } +static inline bool tomoyo_is_same_domain_initializer_entry +(const struct tomoyo_domain_initializer_entry *p1, + const struct tomoyo_domain_initializer_entry *p2) +{ + return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name + && p1->domainname == p2->domainname + && p1->program == p2->program; +} + +static inline bool tomoyo_is_same_domain_keeper_entry +(const struct tomoyo_domain_keeper_entry *p1, + const struct tomoyo_domain_keeper_entry *p2) +{ + return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name + && p1->domainname == p2->domainname + && p1->program == p2->program; +} + +static inline bool tomoyo_is_same_alias_entry +(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2) +{ + return p1->original_name == p2->original_name && + p1->aliased_name == p2->aliased_name; +} + /** * list_for_each_cookie - iterate over a list with cookie. * @pos: the &struct list_head to use as a loop cursor. diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index a1723bb..cd8ba44 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -130,58 +130,47 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_initializer_entry *entry = NULL; struct tomoyo_domain_initializer_entry *ptr; - const struct tomoyo_path_info *saved_program = NULL; - const struct tomoyo_path_info *saved_domainname = NULL; + struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; int error = is_delete ? -ENOENT : -ENOMEM; - bool is_last_name = false; if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ if (domainname) { if (!tomoyo_is_domain_def(domainname) && tomoyo_is_correct_path(domainname, 1, -1, -1)) - is_last_name = true; + e.is_last_name = true; else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; - saved_domainname = tomoyo_get_name(domainname); - if (!saved_domainname) + e.domainname = tomoyo_get_name(domainname); + if (!e.domainname) goto out; } - saved_program = tomoyo_get_name(program); - if (!saved_program) + e.program = tomoyo_get_name(program); + if (!e.program) goto out; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { - if (ptr->is_not != is_not || - ptr->domainname != saved_domainname || - ptr->program != saved_program) + if (!tomoyo_is_same_domain_initializer_entry(ptr, &e)) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->domainname = saved_domainname; - saved_domainname = NULL; - entry->program = saved_program; - saved_program = NULL; - entry->is_not = is_not; - entry->is_last_name = is_last_name; - list_add_tail_rcu(&entry->list, - &tomoyo_domain_initializer_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_domain_initializer_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, + &tomoyo_domain_initializer_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_domainname); - tomoyo_put_name(saved_program); - kfree(entry); + tomoyo_put_name(e.domainname); + tomoyo_put_name(e.program); return error; } @@ -351,57 +340,47 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_keeper_entry *entry = NULL; struct tomoyo_domain_keeper_entry *ptr; - const struct tomoyo_path_info *saved_domainname = NULL; - const struct tomoyo_path_info *saved_program = NULL; + struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; int error = is_delete ? -ENOENT : -ENOMEM; - bool is_last_name = false; if (!tomoyo_is_domain_def(domainname) && tomoyo_is_correct_path(domainname, 1, -1, -1)) - is_last_name = true; + e.is_last_name = true; else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; if (program) { if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; - saved_program = tomoyo_get_name(program); - if (!saved_program) + e.program = tomoyo_get_name(program); + if (!e.program) goto out; } - saved_domainname = tomoyo_get_name(domainname); - if (!saved_domainname) + e.domainname = tomoyo_get_name(domainname); + if (!e.domainname) goto out; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { - if (ptr->is_not != is_not || - ptr->domainname != saved_domainname || - ptr->program != saved_program) + if (!tomoyo_is_same_domain_keeper_entry(ptr, &e)) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->domainname = saved_domainname; - saved_domainname = NULL; - entry->program = saved_program; - saved_program = NULL; - entry->is_not = is_not; - entry->is_last_name = is_last_name; - list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_domain_keeper_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, + &tomoyo_domain_keeper_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_domainname); - tomoyo_put_name(saved_program); - kfree(entry); + tomoyo_put_name(e.domainname); + tomoyo_put_name(e.program); return error; } @@ -553,45 +532,38 @@ static int tomoyo_update_alias_entry(const char *original_name, const char *aliased_name, const bool is_delete) { - struct tomoyo_alias_entry *entry = NULL; struct tomoyo_alias_entry *ptr; - const struct tomoyo_path_info *saved_original_name; - const struct tomoyo_path_info *saved_aliased_name; + struct tomoyo_alias_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ - saved_original_name = tomoyo_get_name(original_name); - saved_aliased_name = tomoyo_get_name(aliased_name); - if (!saved_original_name || !saved_aliased_name) + e.original_name = tomoyo_get_name(original_name); + e.aliased_name = tomoyo_get_name(aliased_name); + if (!e.original_name || !e.aliased_name) goto out; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { - if (ptr->original_name != saved_original_name || - ptr->aliased_name != saved_aliased_name) + if (!tomoyo_is_same_alias_entry(ptr, &e)) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->original_name = saved_original_name; - saved_original_name = NULL; - entry->aliased_name = saved_aliased_name; - saved_aliased_name = NULL; - list_add_tail_rcu(&entry->list, &tomoyo_alias_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_alias_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, &tomoyo_alias_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_original_name); - tomoyo_put_name(saved_aliased_name); - kfree(entry); + tomoyo_put_name(e.original_name); + tomoyo_put_name(e.aliased_name); return error; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 060bbf3..6651cac8 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -164,38 +164,36 @@ LIST_HEAD(tomoyo_globally_readable_list); static int tomoyo_update_globally_readable_entry(const char *filename, const bool is_delete) { - struct tomoyo_globally_readable_file_entry *entry = NULL; struct tomoyo_globally_readable_file_entry *ptr; - const struct tomoyo_path_info *saved_filename; + struct tomoyo_globally_readable_file_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(filename, 1, 0, -1)) return -EINVAL; - saved_filename = tomoyo_get_name(filename); - if (!saved_filename) + e.filename = tomoyo_get_name(filename); + if (!e.filename) return -ENOMEM; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { - if (ptr->filename != saved_filename) + if (ptr->filename != e.filename) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->filename = saved_filename; - saved_filename = NULL; - list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_globally_readable_file_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, + &tomoyo_globally_readable_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_filename); - kfree(entry); + tomoyo_put_name(e.filename); return error; } @@ -313,38 +311,34 @@ LIST_HEAD(tomoyo_pattern_list); static int tomoyo_update_file_pattern_entry(const char *pattern, const bool is_delete) { - struct tomoyo_pattern_entry *entry = NULL; struct tomoyo_pattern_entry *ptr; - const struct tomoyo_path_info *saved_pattern; + struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) }; int error = is_delete ? -ENOENT : -ENOMEM; - saved_pattern = tomoyo_get_name(pattern); - if (!saved_pattern) + if (!e.pattern) return error; - if (!saved_pattern->is_patterned) + if (!e.pattern->is_patterned) goto out; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { - if (saved_pattern != ptr->pattern) + if (e.pattern != ptr->pattern) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->pattern = saved_pattern; - saved_pattern = NULL; - list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_pattern_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - kfree(entry); - tomoyo_put_name(saved_pattern); + tomoyo_put_name(e.pattern); return error; } @@ -467,38 +461,36 @@ LIST_HEAD(tomoyo_no_rewrite_list); static int tomoyo_update_no_rewrite_entry(const char *pattern, const bool is_delete) { - struct tomoyo_no_rewrite_entry *entry = NULL; struct tomoyo_no_rewrite_entry *ptr; - const struct tomoyo_path_info *saved_pattern; + struct tomoyo_no_rewrite_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) return -EINVAL; - saved_pattern = tomoyo_get_name(pattern); - if (!saved_pattern) + e.pattern = tomoyo_get_name(pattern); + if (!e.pattern) return error; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { - if (ptr->pattern != saved_pattern) + if (ptr->pattern != e.pattern) continue; ptr->is_deleted = is_delete; error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->pattern = saved_pattern; - saved_pattern = NULL; - list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_no_rewrite_entry *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, + &tomoyo_no_rewrite_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_pattern); - kfree(entry); + tomoyo_put_name(e.pattern); return error; } @@ -810,23 +802,26 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, struct tomoyo_domain_info *const domain, const bool is_delete) { - static const u32 rw_mask = + static const u32 tomoyo_rw_mask = (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); - const struct tomoyo_path_info *saved_filename; + const u32 perm = 1 << type; struct tomoyo_acl_info *ptr; - struct tomoyo_path_acl *entry = NULL; + struct tomoyo_path_acl e = { + .head.type = TOMOYO_TYPE_PATH_ACL, + .perm_high = perm >> 16, + .perm = perm + }; int error = is_delete ? -ENOENT : -ENOMEM; - const u32 perm = 1 << type; + if (type == TOMOYO_TYPE_READ_WRITE) + e.perm |= tomoyo_rw_mask; if (!domain) return -EINVAL; if (!tomoyo_is_correct_path(filename, 0, 0, 0)) return -EINVAL; - saved_filename = tomoyo_get_name(filename); - if (!saved_filename) + e.filename = tomoyo_get_name(filename); + if (!e.filename) return -ENOMEM; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -834,48 +829,42 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, container_of(ptr, struct tomoyo_path_acl, head); if (ptr->type != TOMOYO_TYPE_PATH_ACL) continue; - if (acl->filename != saved_filename) + if (acl->filename != e.filename) continue; if (is_delete) { if (perm <= 0xFFFF) acl->perm &= ~perm; else acl->perm_high &= ~(perm >> 16); - if ((acl->perm & rw_mask) != rw_mask) + if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) - acl->perm &= ~rw_mask; + acl->perm &= ~tomoyo_rw_mask; } else { if (perm <= 0xFFFF) acl->perm |= perm; else acl->perm_high |= (perm >> 16); - if ((acl->perm & rw_mask) == rw_mask) + if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) - acl->perm |= rw_mask; + acl->perm |= tomoyo_rw_mask; } error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->head.type = TOMOYO_TYPE_PATH_ACL; - if (perm <= 0xFFFF) - entry->perm = perm; - else - entry->perm_high = (perm >> 16); - if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) - entry->perm |= rw_mask; - entry->filename = saved_filename; - saved_filename = NULL; - list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_path_acl *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->head.list, + &domain->acl_info_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - kfree(entry); - tomoyo_put_name(saved_filename); + tomoyo_put_name(e.filename); return error; } @@ -897,24 +886,23 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, struct tomoyo_domain_info *const domain, const bool is_delete) { - const struct tomoyo_path_info *saved_filename1; - const struct tomoyo_path_info *saved_filename2; + const u8 perm = 1 << type; + struct tomoyo_path2_acl e = { + .head.type = TOMOYO_TYPE_PATH2_ACL, + .perm = perm + }; struct tomoyo_acl_info *ptr; - struct tomoyo_path2_acl *entry = NULL; int error = is_delete ? -ENOENT : -ENOMEM; - const u8 perm = 1 << type; if (!domain) return -EINVAL; if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || !tomoyo_is_correct_path(filename2, 0, 0, 0)) return -EINVAL; - saved_filename1 = tomoyo_get_name(filename1); - saved_filename2 = tomoyo_get_name(filename2); - if (!saved_filename1 || !saved_filename2) + e.filename1 = tomoyo_get_name(filename1); + e.filename2 = tomoyo_get_name(filename2); + if (!e.filename1 || !e.filename2) goto out; - if (!is_delete) - entry = kmalloc(sizeof(*entry), GFP_NOFS); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -922,8 +910,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, container_of(ptr, struct tomoyo_path2_acl, head); if (ptr->type != TOMOYO_TYPE_PATH2_ACL) continue; - if (acl->filename1 != saved_filename1 || - acl->filename2 != saved_filename2) + if (acl->filename1 != e.filename1 || + acl->filename2 != e.filename2) continue; if (is_delete) acl->perm &= ~perm; @@ -932,22 +920,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, error = 0; break; } - if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->head.type = TOMOYO_TYPE_PATH2_ACL; - entry->perm = perm; - entry->filename1 = saved_filename1; - saved_filename1 = NULL; - entry->filename2 = saved_filename2; - saved_filename2 = NULL; - list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); - entry = NULL; - error = 0; + if (!is_delete && error) { + struct tomoyo_path2_acl *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->head.list, + &domain->acl_info_list); + error = 0; + } } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(saved_filename1); - tomoyo_put_name(saved_filename2); - kfree(entry); + tomoyo_put_name(e.filename1); + tomoyo_put_name(e.filename2); return error; } diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 62062a6..d1b96f0 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -223,6 +223,25 @@ bool tomoyo_memory_ok(void *ptr) } /** + * tomoyo_commit_ok - Check memory quota. + * + * @data: Data to copy from. + * @size: Size in byte. + * + * Returns pointer to allocated memory on success, NULL otherwise. + */ +void *tomoyo_commit_ok(void *data, const unsigned int size) +{ + void *ptr = kzalloc(size, GFP_NOFS); + if (tomoyo_memory_ok(ptr)) { + memmove(ptr, data, size); + memset(data, 0, size); + return ptr; + } + return NULL; +} + +/** * tomoyo_memory_free - Free memory for elements. * * @ptr: Pointer to allocated memory. -- cgit v1.1 From b3139bbc52762268769e7af842aade0e64372433 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 14 May 2010 21:30:30 +0200 Subject: security/selinux/ss: Use kstrdup Use kstrdup when the goal of an allocation is copy a string into the allocated region. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to; expression flag,E1,E2; statement S; @@ - to = kmalloc(strlen(from) + 1,flag); + to = kstrdup(from, flag); ... when != \(from = E1 \| to = E1 \) if (to==NULL || ...) S ... when != \(from = E2 \| to = E2 \) - strcpy(to, from); // Signed-off-by: Julia Lawall Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/ss/policydb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 4f584fb..c57802a 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -156,12 +156,11 @@ static int roles_init(struct policydb *p) rc = -EINVAL; goto out_free_role; } - key = kmalloc(strlen(OBJECT_R) + 1, GFP_KERNEL); + key = kstrdup(OBJECT_R, GFP_KERNEL); if (!key) { rc = -ENOMEM; goto out_free_role; } - strcpy(key, OBJECT_R); rc = hashtab_insert(p->p_roles.table, key, role); if (rc) goto out_free_key; -- cgit v1.1 From ba0c1709f4946a5ca1a678f4318ed72c0d409b3c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 4 May 2010 18:16:30 -0400 Subject: ima: remove ACPI dependency The ACPI dependency moved to the TPM, where it belongs. Although IMA per-se does not require access to the bios measurement log, verifying the IMA boot aggregate does, which requires ACPI. This patch prereq's 'TPM: ACPI/PNP dependency removal' http://lkml.org/lkml/2010/5/4/378. Signed-off-by: Mimi Zohar Reported-by: Jean-Christophe Dubois Acked-by: Serge Hallyn Tested-by: Serge Hallyn Signed-off-by: James Morris --- security/integrity/ima/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 3d7846d..b6ecfd4d 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -2,15 +2,14 @@ # config IMA bool "Integrity Measurement Architecture(IMA)" - depends on ACPI depends on SECURITY select SECURITYFS select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_SHA1 - select TCG_TPM - select TCG_TIS + select TCG_TPM if !S390 + select TCG_TIS if TCG_TPM help The Trusted Computing Group(TCG) runtime Integrity Measurement Architecture(IMA) maintains a list of hash -- cgit v1.1 From 7762fbfffdbce8191f5236d5053b290035d3d749 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 10 May 2010 17:30:26 +0900 Subject: TOMOYO: Add pathname grouping support. This patch adds pathname grouping support, which is useful for grouping pathnames that cannot be represented using /\{dir\}/ pattern. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/Makefile | 2 +- security/tomoyo/common.c | 100 +++++++++++++++++++++---- security/tomoyo/common.h | 94 ++++++++++++++++++++--- security/tomoyo/file.c | 71 +++++++++++------- security/tomoyo/gc.c | 48 +++++++++++- security/tomoyo/path_group.c | 172 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 433 insertions(+), 54 deletions(-) create mode 100644 security/tomoyo/path_group.c (limited to 'security') diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 60a9e20..4fb3903 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1 +1 @@ -obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o +obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 62e089c..b5dbdc9 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -76,6 +76,49 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, const int buffer_len); /** + * tomoyo_parse_name_union - Parse a tomoyo_name_union. + * + * @filename: Name or name group. + * @ptr: Pointer to "struct tomoyo_name_union". + * + * Returns true on success, false otherwise. + */ +bool tomoyo_parse_name_union(const char *filename, + struct tomoyo_name_union *ptr) +{ + if (!tomoyo_is_correct_path(filename, 0, 0, 0)) + return false; + if (filename[0] == '@') { + ptr->group = tomoyo_get_path_group(filename + 1); + ptr->is_group = true; + return ptr->group != NULL; + } + ptr->filename = tomoyo_get_name(filename); + ptr->is_group = false; + return ptr->filename != NULL; +} + +/** + * tomoyo_print_name_union - Print a tomoyo_name_union. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * @ptr: Pointer to "struct tomoyo_name_union". + * + * Returns true on success, false otherwise. + */ +static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, + const struct tomoyo_name_union *ptr) +{ + int pos = head->read_avail; + if (pos && head->read_buf[pos - 1] == ' ') + head->read_avail--; + if (ptr->is_group) + return tomoyo_io_printf(head, " @%s", + ptr->group->group_name->name); + return tomoyo_io_printf(head, " %s", ptr->filename->name); +} + +/** * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. * * @str: Pointer to the string. @@ -172,6 +215,33 @@ static void tomoyo_normalize_line(unsigned char *buffer) } /** + * tomoyo_tokenize - Tokenize string. + * + * @buffer: The line to tokenize. + * @w: Pointer to "char *". + * @size: Sizeof @w . + * + * Returns true on success, false otherwise. + */ +bool tomoyo_tokenize(char *buffer, char *w[], size_t size) +{ + int count = size / sizeof(char *); + int i; + for (i = 0; i < count; i++) + w[i] = ""; + for (i = 0; i < count; i++) { + char *cp = strchr(buffer, ' '); + if (cp) + *cp = '\0'; + w[i] = buffer; + if (!cp) + break; + buffer = cp + 1; + } + return i < count || !*buffer; +} + +/** * tomoyo_is_correct_path - Validate a pathname. * @filename: The pathname to check. * @start_type: Should the pathname start with '/'? @@ -1368,21 +1438,20 @@ static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, { int pos; u8 bit; - const char *filename; const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); - filename = ptr->filename->name; for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { - const char *msg; if (!(perm & (1 << bit))) continue; /* Print "read/write" instead of "read" and "write". */ if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) continue; - msg = tomoyo_path2keyword(bit); pos = head->read_avail; - if (!tomoyo_io_printf(head, "allow_%s %s\n", msg, filename)) + if (!tomoyo_io_printf(head, "allow_%s ", + tomoyo_path2keyword(bit)) || + !tomoyo_print_name_union(head, &ptr->name) || + !tomoyo_io_printf(head, "\n")) goto out; } head->read_bit = 0; @@ -1405,21 +1474,18 @@ static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, struct tomoyo_path2_acl *ptr) { int pos; - const char *filename1; - const char *filename2; const u8 perm = ptr->perm; u8 bit; - filename1 = ptr->filename1->name; - filename2 = ptr->filename2->name; for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { - const char *msg; if (!(perm & (1 << bit))) continue; - msg = tomoyo_path22keyword(bit); pos = head->read_avail; - if (!tomoyo_io_printf(head, "allow_%s %s %s\n", msg, - filename1, filename2)) + if (!tomoyo_io_printf(head, "allow_%s ", + tomoyo_path22keyword(bit)) || + !tomoyo_print_name_union(head, &ptr->name1) || + !tomoyo_print_name_union(head, &ptr->name2) || + !tomoyo_io_printf(head, "\n")) goto out; } head->read_bit = 0; @@ -1682,6 +1748,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) return tomoyo_write_pattern_policy(data, is_delete); if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) return tomoyo_write_no_rewrite_policy(data, is_delete); + if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) + return tomoyo_write_path_group_policy(data, is_delete); return -EINVAL; } @@ -1738,6 +1806,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) head->read_var2 = NULL; head->read_step = 9; case 9: + if (!tomoyo_read_path_group_policy(head)) + break; + head->read_var1 = NULL; + head->read_var2 = NULL; + head->read_step = 10; + case 10: head->read_eof = true; break; default: diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index c95f486..9f1ae5e 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -54,6 +54,7 @@ struct linux_binprm; #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " +#define TOMOYO_KEYWORD_PATH_GROUP "path_group " #define TOMOYO_KEYWORD_SELECT "select " #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" @@ -204,6 +205,27 @@ struct tomoyo_path_info_with_data { char barrier2[16]; /* Safeguard for overrun. */ }; +struct tomoyo_name_union { + const struct tomoyo_path_info *filename; + struct tomoyo_path_group *group; + u8 is_group; +}; + +/* Structure for "path_group" directive. */ +struct tomoyo_path_group { + struct list_head list; + const struct tomoyo_path_info *group_name; + struct list_head member_list; + atomic_t users; +}; + +/* Structure for "path_group" directive. */ +struct tomoyo_path_group_member { + struct list_head list; + bool is_deleted; + const struct tomoyo_path_info *member_name; +}; + /* * tomoyo_acl_info is a structure which is used for holding * @@ -274,7 +296,7 @@ struct tomoyo_domain_info { * * (1) "head" which is a "struct tomoyo_acl_info". * (2) "perm" which is a bitmask of permitted operations. - * (3) "filename" is the pathname. + * (3) "name" is the pathname. * * Directives held by this structure are "allow_read/write", "allow_execute", * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", @@ -287,8 +309,7 @@ struct tomoyo_path_acl { struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ u8 perm_high; u16 perm; - /* Pointer to single pathname. */ - const struct tomoyo_path_info *filename; + struct tomoyo_name_union name; }; /* @@ -298,8 +319,8 @@ struct tomoyo_path_acl { * * (1) "head" which is a "struct tomoyo_acl_info". * (2) "perm" which is a bitmask of permitted operations. - * (3) "filename1" is the source/old pathname. - * (4) "filename2" is the destination/new pathname. + * (3) "name1" is the source/old pathname. + * (4) "name2" is the destination/new pathname. * * Directives held by this structure are "allow_rename", "allow_link" and * "allow_pivot_root". @@ -307,10 +328,8 @@ struct tomoyo_path_acl { struct tomoyo_path2_acl { struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ u8 perm; - /* Pointer to single pathname. */ - const struct tomoyo_path_info *filename1; - /* Pointer to single pathname. */ - const struct tomoyo_path_info *filename2; + struct tomoyo_name_union name1; + struct tomoyo_name_union name2; }; /* @@ -514,6 +533,9 @@ struct tomoyo_policy_manager_entry { /********** Function prototypes. **********/ +/* Check whether the given name matches the given name_union. */ +bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, + const struct tomoyo_name_union *ptr); /* Check whether the domain has too many ACL entries to hold. */ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); /* Transactional sprintf() for policy dump. */ @@ -526,6 +548,12 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, const s8 pattern_type, const s8 end_type); /* Check whether the token can be a domainname. */ bool tomoyo_is_domain_def(const unsigned char *buffer); +bool tomoyo_parse_name_union(const char *filename, + struct tomoyo_name_union *ptr); +/* Check whether the given filename matches the given path_group. */ +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_path_group *group, + const bool may_use_pattern); /* Check whether the given filename matches the given pattern. */ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, const struct tomoyo_path_info *pattern); @@ -540,10 +568,14 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head); bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); /* Read "file_pattern" entry in exception policy. */ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); +/* Read "path_group" entry in exception policy. */ +bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); /* Read "allow_read" entry in exception policy. */ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); /* Read "deny_rewrite" entry in exception policy. */ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); +/* Tokenize a line. */ +bool tomoyo_tokenize(char *buffer, char *w[], size_t size); /* Write domain policy violation warning message to console? */ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); /* Convert double path operation to operation name. */ @@ -580,12 +612,18 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); /* Create "file_pattern" entry in exception policy. */ int tomoyo_write_pattern_policy(char *data, const bool is_delete); +/* Create "path_group" entry in exception policy. */ +int tomoyo_write_path_group_policy(char *data, const bool is_delete); /* Find a domain by the given name. */ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); /* Find or create a domain by the given name. */ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile); + +/* Allocate memory for "struct tomoyo_path_group". */ +struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); + /* Check mode for specified functionality. */ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, const u8 index); @@ -642,6 +680,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, int tomoyo_check_rewrite_permission(struct file *filp); int tomoyo_find_next_domain(struct linux_binprm *bprm); +/* Drop refcount on tomoyo_name_union. */ +void tomoyo_put_name_union(struct tomoyo_name_union *ptr); + /* Run garbage collector. */ void tomoyo_run_gc(void); @@ -655,6 +696,7 @@ extern struct srcu_struct tomoyo_ss; /* The list for "struct tomoyo_domain_info". */ extern struct list_head tomoyo_domain_list; +extern struct list_head tomoyo_path_group_list; extern struct list_head tomoyo_domain_initializer_list; extern struct list_head tomoyo_domain_keeper_list; extern struct list_head tomoyo_alias_list; @@ -725,6 +767,12 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) } } +static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) +{ + if (group) + atomic_dec(&group->users); +} + static inline struct tomoyo_domain_info *tomoyo_domain(void) { return current_cred()->security; @@ -736,6 +784,34 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct return task_cred_xxx(task, security); } +static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, + const struct tomoyo_acl_info *p2) +{ + return p1->type == p2->type; +} + +static inline bool tomoyo_is_same_name_union +(const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) +{ + return p1->filename == p2->filename && p1->group == p2->group && + p1->is_group == p2->is_group; +} + +static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, + const struct tomoyo_path_acl *p2) +{ + return tomoyo_is_same_acl_head(&p1->head, &p2->head) && + tomoyo_is_same_name_union(&p1->name, &p2->name); +} + +static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, + const struct tomoyo_path2_acl *p2) +{ + return tomoyo_is_same_acl_head(&p1->head, &p2->head) && + tomoyo_is_same_name_union(&p1->name1, &p2->name1) && + tomoyo_is_same_name_union(&p1->name2, &p2->name2); +} + static inline bool tomoyo_is_same_domain_initializer_entry (const struct tomoyo_domain_initializer_entry *p1, const struct tomoyo_domain_initializer_entry *p2) diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 6651cac8..1c6f823 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -45,6 +45,37 @@ static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", }; +void tomoyo_put_name_union(struct tomoyo_name_union *ptr) +{ + if (!ptr) + return; + if (ptr->is_group) + tomoyo_put_path_group(ptr->group); + else + tomoyo_put_name(ptr->filename); +} + +bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, + const struct tomoyo_name_union *ptr) +{ + if (ptr->is_group) + return tomoyo_path_matches_group(name, ptr->group, 1); + return tomoyo_path_matches_pattern(name, ptr->filename); +} + +static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info + *name, + const struct tomoyo_name_union + *ptr, const bool may_use_pattern) +{ + if (ptr->is_group) + return tomoyo_path_matches_group(name, ptr->group, + may_use_pattern); + if (may_use_pattern || !ptr->filename->is_patterned) + return tomoyo_path_matches_pattern(name, ptr->filename); + return false; +} + /** * tomoyo_path2keyword - Get the name of single path operation. * @@ -637,13 +668,9 @@ static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, if (!(acl->perm_high & (perm >> 16))) continue; } - if (may_use_pattern || !acl->filename->is_patterned) { - if (!tomoyo_path_matches_pattern(filename, - acl->filename)) - continue; - } else { + if (!tomoyo_compare_name_union_pattern(filename, &acl->name, + may_use_pattern)) continue; - } error = 0; break; } @@ -817,19 +844,14 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, e.perm |= tomoyo_rw_mask; if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename, 0, 0, 0)) + if (!tomoyo_parse_name_union(filename, &e.name)) return -EINVAL; - e.filename = tomoyo_get_name(filename); - if (!e.filename) - return -ENOMEM; if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path_acl *acl = container_of(ptr, struct tomoyo_path_acl, head); - if (ptr->type != TOMOYO_TYPE_PATH_ACL) - continue; - if (acl->filename != e.filename) + if (!tomoyo_is_same_path_acl(acl, &e)) continue; if (is_delete) { if (perm <= 0xFFFF) @@ -864,7 +886,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(e.filename); + tomoyo_put_name_union(&e.name); return error; } @@ -896,22 +918,15 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || - !tomoyo_is_correct_path(filename2, 0, 0, 0)) - return -EINVAL; - e.filename1 = tomoyo_get_name(filename1); - e.filename2 = tomoyo_get_name(filename2); - if (!e.filename1 || !e.filename2) + if (!tomoyo_parse_name_union(filename1, &e.name1) || + !tomoyo_parse_name_union(filename2, &e.name2)) goto out; if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_path2_acl *acl = container_of(ptr, struct tomoyo_path2_acl, head); - if (ptr->type != TOMOYO_TYPE_PATH2_ACL) - continue; - if (acl->filename1 != e.filename1 || - acl->filename2 != e.filename2) + if (!tomoyo_is_same_path2_acl(acl, &e)) continue; if (is_delete) acl->perm &= ~perm; @@ -931,8 +946,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, } mutex_unlock(&tomoyo_policy_lock); out: - tomoyo_put_name(e.filename1); - tomoyo_put_name(e.filename2); + tomoyo_put_name_union(&e.name1); + tomoyo_put_name_union(&e.name2); return error; } @@ -985,9 +1000,9 @@ static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, acl = container_of(ptr, struct tomoyo_path2_acl, head); if (!(acl->perm & perm)) continue; - if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) + if (!tomoyo_compare_name_union(filename1, &acl->name1)) continue; - if (!tomoyo_path_matches_pattern(filename2, acl->filename2)) + if (!tomoyo_compare_name_union(filename2, &acl->name2)) continue; error = 0; break; diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 245bf42..b9cc71b 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -12,6 +12,8 @@ #include enum tomoyo_gc_id { + TOMOYO_ID_PATH_GROUP, + TOMOYO_ID_PATH_GROUP_MEMBER, TOMOYO_ID_DOMAIN_INITIALIZER, TOMOYO_ID_DOMAIN_KEEPER, TOMOYO_ID_ALIAS, @@ -91,15 +93,15 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) { struct tomoyo_path_acl *entry = container_of(acl, typeof(*entry), head); - tomoyo_put_name(entry->filename); + tomoyo_put_name_union(&entry->name); } break; case TOMOYO_TYPE_PATH2_ACL: { struct tomoyo_path2_acl *entry = container_of(acl, typeof(*entry), head); - tomoyo_put_name(entry->filename1); - tomoyo_put_name(entry->filename2); + tomoyo_put_name_union(&entry->name1); + tomoyo_put_name_union(&entry->name2); } break; default: @@ -149,6 +151,17 @@ static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) { } +static void tomoyo_del_path_group_member(struct tomoyo_path_group_member + *member) +{ + tomoyo_put_name(member->member_name); +} + +static void tomoyo_del_path_group(struct tomoyo_path_group *group) +{ + tomoyo_put_name(group->group_name); +} + static void tomoyo_collect_entry(void) { if (mutex_lock_interruptible(&tomoyo_policy_lock)) @@ -293,6 +306,29 @@ static void tomoyo_collect_entry(void) } } } + { + struct tomoyo_path_group *group; + list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { + struct tomoyo_path_group_member *member; + list_for_each_entry_rcu(member, &group->member_list, + list) { + if (!member->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, + member)) + list_del_rcu(&member->list); + else + break; + } + if (!list_empty(&group->member_list) || + atomic_read(&group->users)) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) + list_del_rcu(&group->list); + else + break; + } + } mutex_unlock(&tomoyo_policy_lock); } @@ -334,6 +370,12 @@ static void tomoyo_kfree_entry(void) if (!tomoyo_del_domain(p->element)) continue; break; + case TOMOYO_ID_PATH_GROUP_MEMBER: + tomoyo_del_path_group_member(p->element); + break; + case TOMOYO_ID_PATH_GROUP: + tomoyo_del_path_group(p->element); + break; default: printk(KERN_WARNING "Unknown type\n"); break; diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c new file mode 100644 index 0000000..c988041 --- /dev/null +++ b/security/tomoyo/path_group.c @@ -0,0 +1,172 @@ +/* + * security/tomoyo/path_group.c + * + * Copyright (C) 2005-2009 NTT DATA CORPORATION + */ + +#include +#include "common.h" +/* The list for "struct ccs_path_group". */ +LIST_HEAD(tomoyo_path_group_list); + +/** + * tomoyo_get_path_group - Allocate memory for "struct tomoyo_path_group". + * + * @group_name: The name of pathname group. + * + * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise. + */ +struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name) +{ + struct tomoyo_path_group *entry = NULL; + struct tomoyo_path_group *group = NULL; + const struct tomoyo_path_info *saved_group_name; + int error = -ENOMEM; + if (!tomoyo_is_correct_path(group_name, 0, 0, 0) || + !group_name[0]) + return NULL; + saved_group_name = tomoyo_get_name(group_name); + if (!saved_group_name) + return NULL; + entry = kzalloc(sizeof(*entry), GFP_NOFS); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { + if (saved_group_name != group->group_name) + continue; + atomic_inc(&group->users); + error = 0; + break; + } + if (error && tomoyo_memory_ok(entry)) { + INIT_LIST_HEAD(&entry->member_list); + entry->group_name = saved_group_name; + saved_group_name = NULL; + atomic_set(&entry->users, 1); + list_add_tail_rcu(&entry->list, &tomoyo_path_group_list); + group = entry; + entry = NULL; + error = 0; + } + mutex_unlock(&tomoyo_policy_lock); + out: + tomoyo_put_name(saved_group_name); + kfree(entry); + return !error ? group : NULL; +} + +/** + * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list. + * + * @data: String to parse. + * @is_delete: True if it is a delete request. + * + * Returns 0 on success, nagative value otherwise. + */ +int tomoyo_write_path_group_policy(char *data, const bool is_delete) +{ + struct tomoyo_path_group *group; + struct tomoyo_path_group_member *member; + struct tomoyo_path_group_member e = { }; + int error = is_delete ? -ENOENT : -ENOMEM; + char *w[2]; + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) + return -EINVAL; + group = tomoyo_get_path_group(w[0]); + if (!group) + return -ENOMEM; + e.member_name = tomoyo_get_name(w[1]); + if (!e.member_name) + goto out; + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + list_for_each_entry_rcu(member, &group->member_list, list) { + if (member->member_name != e.member_name) + continue; + member->is_deleted = is_delete; + error = 0; + break; + } + if (!is_delete && error) { + struct tomoyo_path_group_member *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->list, &group->member_list); + error = 0; + } + } + mutex_unlock(&tomoyo_policy_lock); + out: + tomoyo_put_name(e.member_name); + tomoyo_put_path_group(group); + return error; +} + +/** + * tomoyo_read_path_group_policy - Read "struct tomoyo_path_group" list. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * + * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head) +{ + struct list_head *gpos; + struct list_head *mpos; + list_for_each_cookie(gpos, head->read_var1, &tomoyo_path_group_list) { + struct tomoyo_path_group *group; + group = list_entry(gpos, struct tomoyo_path_group, list); + list_for_each_cookie(mpos, head->read_var2, + &group->member_list) { + struct tomoyo_path_group_member *member; + member = list_entry(mpos, + struct tomoyo_path_group_member, + list); + if (member->is_deleted) + continue; + if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_PATH_GROUP + "%s %s\n", + group->group_name->name, + member->member_name->name)) + return false; + } + } + return true; +} + +/** + * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. + * + * @pathname: The name of pathname. + * @group: Pointer to "struct tomoyo_path_group". + * @may_use_pattern: True if wild card is permitted. + * + * Returns true if @pathname matches pathnames in @group, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_path_group *group, + const bool may_use_pattern) +{ + struct tomoyo_path_group_member *member; + bool matched = false; + list_for_each_entry_rcu(member, &group->member_list, list) { + if (member->is_deleted) + continue; + if (!member->member_name->is_patterned) { + if (tomoyo_pathcmp(pathname, member->member_name)) + continue; + } else if (may_use_pattern) { + if (!tomoyo_path_matches_pattern(pathname, + member->member_name)) + continue; + } else + continue; + matched = true; + break; + } + return matched; +} -- cgit v1.1 From c80901f2755c582e3096e6708028a8daca59e6e2 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 14 May 2010 12:01:26 +0900 Subject: LSM: Add __init to fixup function. register_security() became __init function. So do verify() and security_fixup_ops(). Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/capability.c | 2 +- security/security.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 7f093d5..8168e3e 100644 --- a/security/capability.c +++ b/security/capability.c @@ -854,7 +854,7 @@ static void cap_audit_rule_free(void *lsmrule) } \ } while (0) -void security_fixup_ops(struct security_operations *ops) +void __init security_fixup_ops(struct security_operations *ops) { set_to_cap_if_null(ops, ptrace_access_check); set_to_cap_if_null(ops, ptrace_traceme); diff --git a/security/security.c b/security/security.c index 8585019..351942a 100644 --- a/security/security.c +++ b/security/security.c @@ -23,14 +23,14 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; /* things that live in capability.c */ -extern void security_fixup_ops(struct security_operations *ops); +extern void __init security_fixup_ops(struct security_operations *ops); static struct security_operations *security_ops; static struct security_operations default_security_ops = { .name = "default", }; -static inline int verify(struct security_operations *ops) +static inline int __init verify(struct security_operations *ops) { /* verify the security_operations structure exists */ if (!ops) -- cgit v1.1 From 4d09ec0f705cf88a12add029c058b53f288cfaa2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 May 2010 14:42:35 +0100 Subject: KEYS: Return more accurate error codes We were using the wrong variable here so the error codes weren't being returned properly. The original code returns -ENOKEY. Signed-off-by: Dan Carpenter Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/process_keys.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 06c2ccf..20a38fe 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -508,7 +508,7 @@ try_again: ret = install_thread_keyring(); if (ret < 0) { - key = ERR_PTR(ret); + key_ref = ERR_PTR(ret); goto error; } goto reget_creds; @@ -526,7 +526,7 @@ try_again: ret = install_process_keyring(); if (ret < 0) { - key = ERR_PTR(ret); + key_ref = ERR_PTR(ret); goto error; } goto reget_creds; @@ -585,7 +585,7 @@ try_again: case KEY_SPEC_GROUP_KEYRING: /* group keyrings are not yet supported */ - key = ERR_PTR(-EINVAL); + key_ref = ERR_PTR(-EINVAL); goto error; case KEY_SPEC_REQKEY_AUTH_KEY: -- cgit v1.1