diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/exports.c | 42 | ||||
-rw-r--r-- | security/selinux/hooks.c | 34 | ||||
-rw-r--r-- | security/selinux/include/audit.h | 65 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 45 |
4 files changed, 131 insertions, 55 deletions
diff --git a/security/selinux/exports.c b/security/selinux/exports.c index 87d2bb3ea355..64af2d3409ef 100644 --- a/security/selinux/exports.c +++ b/security/selinux/exports.c | |||
@@ -25,48 +25,6 @@ | |||
25 | /* SECMARK reference count */ | 25 | /* SECMARK reference count */ |
26 | extern atomic_t selinux_secmark_refcount; | 26 | extern atomic_t selinux_secmark_refcount; |
27 | 27 | ||
28 | int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) | ||
29 | { | ||
30 | if (selinux_enabled) | ||
31 | return security_sid_to_context(sid, ctx, ctxlen); | ||
32 | else { | ||
33 | *ctx = NULL; | ||
34 | *ctxlen = 0; | ||
35 | } | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | void selinux_get_inode_sid(const struct inode *inode, u32 *sid) | ||
41 | { | ||
42 | if (selinux_enabled) { | ||
43 | struct inode_security_struct *isec = inode->i_security; | ||
44 | *sid = isec->sid; | ||
45 | return; | ||
46 | } | ||
47 | *sid = 0; | ||
48 | } | ||
49 | |||
50 | void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid) | ||
51 | { | ||
52 | if (selinux_enabled) { | ||
53 | struct ipc_security_struct *isec = ipcp->security; | ||
54 | *sid = isec->sid; | ||
55 | return; | ||
56 | } | ||
57 | *sid = 0; | ||
58 | } | ||
59 | |||
60 | void selinux_get_task_sid(struct task_struct *tsk, u32 *sid) | ||
61 | { | ||
62 | if (selinux_enabled) { | ||
63 | struct task_security_struct *tsec = tsk->security; | ||
64 | *sid = tsec->sid; | ||
65 | return; | ||
66 | } | ||
67 | *sid = 0; | ||
68 | } | ||
69 | |||
70 | int selinux_string_to_sid(char *str, u32 *sid) | 28 | int selinux_string_to_sid(char *str, u32 *sid) |
71 | { | 29 | { |
72 | if (selinux_enabled) | 30 | if (selinux_enabled) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 34f2d46c7984..f9927f02bc3d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -83,6 +83,7 @@ | |||
83 | #include "netport.h" | 83 | #include "netport.h" |
84 | #include "xfrm.h" | 84 | #include "xfrm.h" |
85 | #include "netlabel.h" | 85 | #include "netlabel.h" |
86 | #include "audit.h" | ||
86 | 87 | ||
87 | #define XATTR_SELINUX_SUFFIX "selinux" | 88 | #define XATTR_SELINUX_SUFFIX "selinux" |
88 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | 89 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX |
@@ -2792,6 +2793,12 @@ static int selinux_inode_killpriv(struct dentry *dentry) | |||
2792 | return secondary_ops->inode_killpriv(dentry); | 2793 | return secondary_ops->inode_killpriv(dentry); |
2793 | } | 2794 | } |
2794 | 2795 | ||
2796 | static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) | ||
2797 | { | ||
2798 | struct inode_security_struct *isec = inode->i_security; | ||
2799 | *secid = isec->sid; | ||
2800 | } | ||
2801 | |||
2795 | /* file security operations */ | 2802 | /* file security operations */ |
2796 | 2803 | ||
2797 | static int selinux_revalidate_file_permission(struct file *file, int mask) | 2804 | static int selinux_revalidate_file_permission(struct file *file, int mask) |
@@ -3183,7 +3190,8 @@ static int selinux_task_getsid(struct task_struct *p) | |||
3183 | 3190 | ||
3184 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) | 3191 | static void selinux_task_getsecid(struct task_struct *p, u32 *secid) |
3185 | { | 3192 | { |
3186 | selinux_get_task_sid(p, secid); | 3193 | struct task_security_struct *tsec = p->security; |
3194 | *secid = tsec->sid; | ||
3187 | } | 3195 | } |
3188 | 3196 | ||
3189 | static int selinux_task_setgroups(struct group_info *group_info) | 3197 | static int selinux_task_setgroups(struct group_info *group_info) |
@@ -4149,7 +4157,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * | |||
4149 | goto out; | 4157 | goto out; |
4150 | 4158 | ||
4151 | if (sock && family == PF_UNIX) | 4159 | if (sock && family == PF_UNIX) |
4152 | selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); | 4160 | selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid); |
4153 | else if (skb) | 4161 | else if (skb) |
4154 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); | 4162 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); |
4155 | 4163 | ||
@@ -5026,6 +5034,12 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | |||
5026 | return ipc_has_perm(ipcp, av); | 5034 | return ipc_has_perm(ipcp, av); |
5027 | } | 5035 | } |
5028 | 5036 | ||
5037 | static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | ||
5038 | { | ||
5039 | struct ipc_security_struct *isec = ipcp->security; | ||
5040 | *secid = isec->sid; | ||
5041 | } | ||
5042 | |||
5029 | /* module stacking operations */ | 5043 | /* module stacking operations */ |
5030 | static int selinux_register_security (const char *name, struct security_operations *ops) | 5044 | static int selinux_register_security (const char *name, struct security_operations *ops) |
5031 | { | 5045 | { |
@@ -5281,6 +5295,8 @@ static int selinux_key_permission(key_ref_t key_ref, | |||
5281 | #endif | 5295 | #endif |
5282 | 5296 | ||
5283 | static struct security_operations selinux_ops = { | 5297 | static struct security_operations selinux_ops = { |
5298 | .name = "selinux", | ||
5299 | |||
5284 | .ptrace = selinux_ptrace, | 5300 | .ptrace = selinux_ptrace, |
5285 | .capget = selinux_capget, | 5301 | .capget = selinux_capget, |
5286 | .capset_check = selinux_capset_check, | 5302 | .capset_check = selinux_capset_check, |
@@ -5342,6 +5358,7 @@ static struct security_operations selinux_ops = { | |||
5342 | .inode_listsecurity = selinux_inode_listsecurity, | 5358 | .inode_listsecurity = selinux_inode_listsecurity, |
5343 | .inode_need_killpriv = selinux_inode_need_killpriv, | 5359 | .inode_need_killpriv = selinux_inode_need_killpriv, |
5344 | .inode_killpriv = selinux_inode_killpriv, | 5360 | .inode_killpriv = selinux_inode_killpriv, |
5361 | .inode_getsecid = selinux_inode_getsecid, | ||
5345 | 5362 | ||
5346 | .file_permission = selinux_file_permission, | 5363 | .file_permission = selinux_file_permission, |
5347 | .file_alloc_security = selinux_file_alloc_security, | 5364 | .file_alloc_security = selinux_file_alloc_security, |
@@ -5382,6 +5399,7 @@ static struct security_operations selinux_ops = { | |||
5382 | .task_to_inode = selinux_task_to_inode, | 5399 | .task_to_inode = selinux_task_to_inode, |
5383 | 5400 | ||
5384 | .ipc_permission = selinux_ipc_permission, | 5401 | .ipc_permission = selinux_ipc_permission, |
5402 | .ipc_getsecid = selinux_ipc_getsecid, | ||
5385 | 5403 | ||
5386 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, | 5404 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, |
5387 | .msg_msg_free_security = selinux_msg_msg_free_security, | 5405 | .msg_msg_free_security = selinux_msg_msg_free_security, |
@@ -5463,12 +5481,24 @@ static struct security_operations selinux_ops = { | |||
5463 | .key_free = selinux_key_free, | 5481 | .key_free = selinux_key_free, |
5464 | .key_permission = selinux_key_permission, | 5482 | .key_permission = selinux_key_permission, |
5465 | #endif | 5483 | #endif |
5484 | |||
5485 | #ifdef CONFIG_AUDIT | ||
5486 | .audit_rule_init = selinux_audit_rule_init, | ||
5487 | .audit_rule_known = selinux_audit_rule_known, | ||
5488 | .audit_rule_match = selinux_audit_rule_match, | ||
5489 | .audit_rule_free = selinux_audit_rule_free, | ||
5490 | #endif | ||
5466 | }; | 5491 | }; |
5467 | 5492 | ||
5468 | static __init int selinux_init(void) | 5493 | static __init int selinux_init(void) |
5469 | { | 5494 | { |
5470 | struct task_security_struct *tsec; | 5495 | struct task_security_struct *tsec; |
5471 | 5496 | ||
5497 | if (!security_module_enable(&selinux_ops)) { | ||
5498 | selinux_enabled = 0; | ||
5499 | return 0; | ||
5500 | } | ||
5501 | |||
5472 | if (!selinux_enabled) { | 5502 | if (!selinux_enabled) { |
5473 | printk(KERN_INFO "SELinux: Disabled at boot.\n"); | 5503 | printk(KERN_INFO "SELinux: Disabled at boot.\n"); |
5474 | return 0; | 5504 | return 0; |
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h new file mode 100644 index 000000000000..6c8b9ef15579 --- /dev/null +++ b/security/selinux/include/audit.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * SELinux support for the Audit LSM hooks | ||
3 | * | ||
4 | * Most of below header was moved from include/linux/selinux.h which | ||
5 | * is released under below copyrights: | ||
6 | * | ||
7 | * Author: James Morris <jmorris@redhat.com> | ||
8 | * | ||
9 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> | ||
10 | * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | ||
11 | * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2, | ||
15 | * as published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #ifndef _SELINUX_AUDIT_H | ||
19 | #define _SELINUX_AUDIT_H | ||
20 | |||
21 | /** | ||
22 | * selinux_audit_rule_init - alloc/init an selinux audit rule structure. | ||
23 | * @field: the field this rule refers to | ||
24 | * @op: the operater the rule uses | ||
25 | * @rulestr: the text "target" of the rule | ||
26 | * @rule: pointer to the new rule structure returned via this | ||
27 | * | ||
28 | * Returns 0 if successful, -errno if not. On success, the rule structure | ||
29 | * will be allocated internally. The caller must free this structure with | ||
30 | * selinux_audit_rule_free() after use. | ||
31 | */ | ||
32 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule); | ||
33 | |||
34 | /** | ||
35 | * selinux_audit_rule_free - free an selinux audit rule structure. | ||
36 | * @rule: pointer to the audit rule to be freed | ||
37 | * | ||
38 | * This will free all memory associated with the given rule. | ||
39 | * If @rule is NULL, no operation is performed. | ||
40 | */ | ||
41 | void selinux_audit_rule_free(void *rule); | ||
42 | |||
43 | /** | ||
44 | * selinux_audit_rule_match - determine if a context ID matches a rule. | ||
45 | * @sid: the context ID to check | ||
46 | * @field: the field this rule refers to | ||
47 | * @op: the operater the rule uses | ||
48 | * @rule: pointer to the audit rule to check against | ||
49 | * @actx: the audit context (can be NULL) associated with the check | ||
50 | * | ||
51 | * Returns 1 if the context id matches the rule, 0 if it does not, and | ||
52 | * -errno on failure. | ||
53 | */ | ||
54 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, | ||
55 | struct audit_context *actx); | ||
56 | |||
57 | /** | ||
58 | * selinux_audit_rule_known - check to see if rule contains selinux fields. | ||
59 | * @rule: rule to be checked | ||
60 | * Returns 1 if there are selinux fields specified in the rule, 0 otherwise. | ||
61 | */ | ||
62 | int selinux_audit_rule_known(struct audit_krule *krule); | ||
63 | |||
64 | #endif /* _SELINUX_AUDIT_H */ | ||
65 | |||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 33425b1ac8d6..b341b8fd8c7c 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include "netlabel.h" | 57 | #include "netlabel.h" |
58 | #include "xfrm.h" | 58 | #include "xfrm.h" |
59 | #include "ebitmap.h" | 59 | #include "ebitmap.h" |
60 | #include "audit.h" | ||
60 | 61 | ||
61 | extern void selnl_notify_policyload(u32 seqno); | 62 | extern void selnl_notify_policyload(u32 seqno); |
62 | unsigned int policydb_loaded_version; | 63 | unsigned int policydb_loaded_version; |
@@ -2296,21 +2297,23 @@ struct selinux_audit_rule { | |||
2296 | struct context au_ctxt; | 2297 | struct context au_ctxt; |
2297 | }; | 2298 | }; |
2298 | 2299 | ||
2299 | void selinux_audit_rule_free(struct selinux_audit_rule *rule) | 2300 | void selinux_audit_rule_free(void *vrule) |
2300 | { | 2301 | { |
2302 | struct selinux_audit_rule *rule = vrule; | ||
2303 | |||
2301 | if (rule) { | 2304 | if (rule) { |
2302 | context_destroy(&rule->au_ctxt); | 2305 | context_destroy(&rule->au_ctxt); |
2303 | kfree(rule); | 2306 | kfree(rule); |
2304 | } | 2307 | } |
2305 | } | 2308 | } |
2306 | 2309 | ||
2307 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | 2310 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) |
2308 | struct selinux_audit_rule **rule) | ||
2309 | { | 2311 | { |
2310 | struct selinux_audit_rule *tmprule; | 2312 | struct selinux_audit_rule *tmprule; |
2311 | struct role_datum *roledatum; | 2313 | struct role_datum *roledatum; |
2312 | struct type_datum *typedatum; | 2314 | struct type_datum *typedatum; |
2313 | struct user_datum *userdatum; | 2315 | struct user_datum *userdatum; |
2316 | struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule; | ||
2314 | int rc = 0; | 2317 | int rc = 0; |
2315 | 2318 | ||
2316 | *rule = NULL; | 2319 | *rule = NULL; |
@@ -2397,12 +2400,37 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
2397 | return rc; | 2400 | return rc; |
2398 | } | 2401 | } |
2399 | 2402 | ||
2400 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, | 2403 | /* Check to see if the rule contains any selinux fields */ |
2401 | struct selinux_audit_rule *rule, | 2404 | int selinux_audit_rule_known(struct audit_krule *rule) |
2405 | { | ||
2406 | int i; | ||
2407 | |||
2408 | for (i = 0; i < rule->field_count; i++) { | ||
2409 | struct audit_field *f = &rule->fields[i]; | ||
2410 | switch (f->type) { | ||
2411 | case AUDIT_SUBJ_USER: | ||
2412 | case AUDIT_SUBJ_ROLE: | ||
2413 | case AUDIT_SUBJ_TYPE: | ||
2414 | case AUDIT_SUBJ_SEN: | ||
2415 | case AUDIT_SUBJ_CLR: | ||
2416 | case AUDIT_OBJ_USER: | ||
2417 | case AUDIT_OBJ_ROLE: | ||
2418 | case AUDIT_OBJ_TYPE: | ||
2419 | case AUDIT_OBJ_LEV_LOW: | ||
2420 | case AUDIT_OBJ_LEV_HIGH: | ||
2421 | return 1; | ||
2422 | } | ||
2423 | } | ||
2424 | |||
2425 | return 0; | ||
2426 | } | ||
2427 | |||
2428 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | ||
2402 | struct audit_context *actx) | 2429 | struct audit_context *actx) |
2403 | { | 2430 | { |
2404 | struct context *ctxt; | 2431 | struct context *ctxt; |
2405 | struct mls_level *level; | 2432 | struct mls_level *level; |
2433 | struct selinux_audit_rule *rule = vrule; | ||
2406 | int match = 0; | 2434 | int match = 0; |
2407 | 2435 | ||
2408 | if (!rule) { | 2436 | if (!rule) { |
@@ -2509,7 +2537,7 @@ out: | |||
2509 | return match; | 2537 | return match; |
2510 | } | 2538 | } |
2511 | 2539 | ||
2512 | static int (*aurule_callback)(void) = NULL; | 2540 | static int (*aurule_callback)(void) = audit_update_lsm_rules; |
2513 | 2541 | ||
2514 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | 2542 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, |
2515 | u16 class, u32 perms, u32 *retained) | 2543 | u16 class, u32 perms, u32 *retained) |
@@ -2534,11 +2562,6 @@ static int __init aurule_init(void) | |||
2534 | } | 2562 | } |
2535 | __initcall(aurule_init); | 2563 | __initcall(aurule_init); |
2536 | 2564 | ||
2537 | void selinux_audit_set_callback(int (*callback)(void)) | ||
2538 | { | ||
2539 | aurule_callback = callback; | ||
2540 | } | ||
2541 | |||
2542 | #ifdef CONFIG_NETLABEL | 2565 | #ifdef CONFIG_NETLABEL |
2543 | /** | 2566 | /** |
2544 | * security_netlbl_cache_add - Add an entry to the NetLabel cache | 2567 | * security_netlbl_cache_add - Add an entry to the NetLabel cache |