diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 178 |
1 files changed, 162 insertions, 16 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 77ec16a3b68b..b5c8f9237008 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pipe_fs_i.h> | 26 | #include <linux/pipe_fs_i.h> |
27 | #include <net/netlabel.h> | 27 | #include <net/netlabel.h> |
28 | #include <net/cipso_ipv4.h> | 28 | #include <net/cipso_ipv4.h> |
29 | #include <linux/audit.h> | ||
29 | 30 | ||
30 | #include "smack.h" | 31 | #include "smack.h" |
31 | 32 | ||
@@ -574,8 +575,8 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
574 | * | 575 | * |
575 | * Returns 0 if access is permitted, an error code otherwise | 576 | * Returns 0 if access is permitted, an error code otherwise |
576 | */ | 577 | */ |
577 | static int smack_inode_setxattr(struct dentry *dentry, char *name, | 578 | static int smack_inode_setxattr(struct dentry *dentry, const char *name, |
578 | void *value, size_t size, int flags) | 579 | const void *value, size_t size, int flags) |
579 | { | 580 | { |
580 | int rc = 0; | 581 | int rc = 0; |
581 | 582 | ||
@@ -604,8 +605,8 @@ static int smack_inode_setxattr(struct dentry *dentry, char *name, | |||
604 | * Set the pointer in the inode blob to the entry found | 605 | * Set the pointer in the inode blob to the entry found |
605 | * in the master label list. | 606 | * in the master label list. |
606 | */ | 607 | */ |
607 | static void smack_inode_post_setxattr(struct dentry *dentry, char *name, | 608 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, |
608 | void *value, size_t size, int flags) | 609 | const void *value, size_t size, int flags) |
609 | { | 610 | { |
610 | struct inode_smack *isp; | 611 | struct inode_smack *isp; |
611 | char *nsp; | 612 | char *nsp; |
@@ -641,7 +642,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, char *name, | |||
641 | * | 642 | * |
642 | * Returns 0 if access is permitted, an error code otherwise | 643 | * Returns 0 if access is permitted, an error code otherwise |
643 | */ | 644 | */ |
644 | static int smack_inode_getxattr(struct dentry *dentry, char *name) | 645 | static int smack_inode_getxattr(struct dentry *dentry, const char *name) |
645 | { | 646 | { |
646 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); | 647 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); |
647 | } | 648 | } |
@@ -655,7 +656,7 @@ static int smack_inode_getxattr(struct dentry *dentry, char *name) | |||
655 | * | 656 | * |
656 | * Returns 0 if access is permitted, an error code otherwise | 657 | * Returns 0 if access is permitted, an error code otherwise |
657 | */ | 658 | */ |
658 | static int smack_inode_removexattr(struct dentry *dentry, char *name) | 659 | static int smack_inode_removexattr(struct dentry *dentry, const char *name) |
659 | { | 660 | { |
660 | int rc = 0; | 661 | int rc = 0; |
661 | 662 | ||
@@ -752,6 +753,18 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer, | |||
752 | return -EINVAL; | 753 | return -EINVAL; |
753 | } | 754 | } |
754 | 755 | ||
756 | /** | ||
757 | * smack_inode_getsecid - Extract inode's security id | ||
758 | * @inode: inode to extract the info from | ||
759 | * @secid: where result will be saved | ||
760 | */ | ||
761 | static void smack_inode_getsecid(const struct inode *inode, u32 *secid) | ||
762 | { | ||
763 | struct inode_smack *isp = inode->i_security; | ||
764 | |||
765 | *secid = smack_to_secid(isp->smk_inode); | ||
766 | } | ||
767 | |||
755 | /* | 768 | /* |
756 | * File Hooks | 769 | * File Hooks |
757 | */ | 770 | */ |
@@ -1118,15 +1131,6 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1118 | int sig, u32 secid) | 1131 | int sig, u32 secid) |
1119 | { | 1132 | { |
1120 | /* | 1133 | /* |
1121 | * Special cases where signals really ought to go through | ||
1122 | * in spite of policy. Stephen Smalley suggests it may | ||
1123 | * make sense to change the caller so that it doesn't | ||
1124 | * bother with the LSM hook in these cases. | ||
1125 | */ | ||
1126 | if (info != SEND_SIG_NOINFO && | ||
1127 | (is_si_special(info) || SI_FROMKERNEL(info))) | ||
1128 | return 0; | ||
1129 | /* | ||
1130 | * Sending a signal requires that the sender | 1134 | * Sending a signal requires that the sender |
1131 | * can write the receiver. | 1135 | * can write the receiver. |
1132 | */ | 1136 | */ |
@@ -1805,6 +1809,18 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | |||
1805 | return smk_curacc(isp, may); | 1809 | return smk_curacc(isp, may); |
1806 | } | 1810 | } |
1807 | 1811 | ||
1812 | /** | ||
1813 | * smack_ipc_getsecid - Extract smack security id | ||
1814 | * @ipcp: the object permissions | ||
1815 | * @secid: where result will be saved | ||
1816 | */ | ||
1817 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) | ||
1818 | { | ||
1819 | char *smack = ipp->security; | ||
1820 | |||
1821 | *secid = smack_to_secid(smack); | ||
1822 | } | ||
1823 | |||
1808 | /* module stacking operations */ | 1824 | /* module stacking operations */ |
1809 | 1825 | ||
1810 | /** | 1826 | /** |
@@ -2382,6 +2398,124 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2382 | #endif /* CONFIG_KEYS */ | 2398 | #endif /* CONFIG_KEYS */ |
2383 | 2399 | ||
2384 | /* | 2400 | /* |
2401 | * Smack Audit hooks | ||
2402 | * | ||
2403 | * Audit requires a unique representation of each Smack specific | ||
2404 | * rule. This unique representation is used to distinguish the | ||
2405 | * object to be audited from remaining kernel objects and also | ||
2406 | * works as a glue between the audit hooks. | ||
2407 | * | ||
2408 | * Since repository entries are added but never deleted, we'll use | ||
2409 | * the smack_known label address related to the given audit rule as | ||
2410 | * the needed unique representation. This also better fits the smack | ||
2411 | * model where nearly everything is a label. | ||
2412 | */ | ||
2413 | #ifdef CONFIG_AUDIT | ||
2414 | |||
2415 | /** | ||
2416 | * smack_audit_rule_init - Initialize a smack audit rule | ||
2417 | * @field: audit rule fields given from user-space (audit.h) | ||
2418 | * @op: required testing operator (=, !=, >, <, ...) | ||
2419 | * @rulestr: smack label to be audited | ||
2420 | * @vrule: pointer to save our own audit rule representation | ||
2421 | * | ||
2422 | * Prepare to audit cases where (@field @op @rulestr) is true. | ||
2423 | * The label to be audited is created if necessay. | ||
2424 | */ | ||
2425 | static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | ||
2426 | { | ||
2427 | char **rule = (char **)vrule; | ||
2428 | *rule = NULL; | ||
2429 | |||
2430 | if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) | ||
2431 | return -EINVAL; | ||
2432 | |||
2433 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) | ||
2434 | return -EINVAL; | ||
2435 | |||
2436 | *rule = smk_import(rulestr, 0); | ||
2437 | |||
2438 | return 0; | ||
2439 | } | ||
2440 | |||
2441 | /** | ||
2442 | * smack_audit_rule_known - Distinguish Smack audit rules | ||
2443 | * @krule: rule of interest, in Audit kernel representation format | ||
2444 | * | ||
2445 | * This is used to filter Smack rules from remaining Audit ones. | ||
2446 | * If it's proved that this rule belongs to us, the | ||
2447 | * audit_rule_match hook will be called to do the final judgement. | ||
2448 | */ | ||
2449 | static int smack_audit_rule_known(struct audit_krule *krule) | ||
2450 | { | ||
2451 | struct audit_field *f; | ||
2452 | int i; | ||
2453 | |||
2454 | for (i = 0; i < krule->field_count; i++) { | ||
2455 | f = &krule->fields[i]; | ||
2456 | |||
2457 | if (f->type == AUDIT_SUBJ_USER || f->type == AUDIT_OBJ_USER) | ||
2458 | return 1; | ||
2459 | } | ||
2460 | |||
2461 | return 0; | ||
2462 | } | ||
2463 | |||
2464 | /** | ||
2465 | * smack_audit_rule_match - Audit given object ? | ||
2466 | * @secid: security id for identifying the object to test | ||
2467 | * @field: audit rule flags given from user-space | ||
2468 | * @op: required testing operator | ||
2469 | * @vrule: smack internal rule presentation | ||
2470 | * @actx: audit context associated with the check | ||
2471 | * | ||
2472 | * The core Audit hook. It's used to take the decision of | ||
2473 | * whether to audit or not to audit a given object. | ||
2474 | */ | ||
2475 | static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | ||
2476 | struct audit_context *actx) | ||
2477 | { | ||
2478 | char *smack; | ||
2479 | char *rule = vrule; | ||
2480 | |||
2481 | if (!rule) { | ||
2482 | audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR, | ||
2483 | "Smack: missing rule\n"); | ||
2484 | return -ENOENT; | ||
2485 | } | ||
2486 | |||
2487 | if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) | ||
2488 | return 0; | ||
2489 | |||
2490 | smack = smack_from_secid(secid); | ||
2491 | |||
2492 | /* | ||
2493 | * No need to do string comparisons. If a match occurs, | ||
2494 | * both pointers will point to the same smack_known | ||
2495 | * label. | ||
2496 | */ | ||
2497 | if (op == AUDIT_EQUAL) | ||
2498 | return (rule == smack); | ||
2499 | if (op == AUDIT_NOT_EQUAL) | ||
2500 | return (rule != smack); | ||
2501 | |||
2502 | return 0; | ||
2503 | } | ||
2504 | |||
2505 | /** | ||
2506 | * smack_audit_rule_free - free smack rule representation | ||
2507 | * @vrule: rule to be freed. | ||
2508 | * | ||
2509 | * No memory was allocated. | ||
2510 | */ | ||
2511 | static void smack_audit_rule_free(void *vrule) | ||
2512 | { | ||
2513 | /* No-op */ | ||
2514 | } | ||
2515 | |||
2516 | #endif /* CONFIG_AUDIT */ | ||
2517 | |||
2518 | /* | ||
2385 | * smack_secid_to_secctx - return the smack label for a secid | 2519 | * smack_secid_to_secctx - return the smack label for a secid |
2386 | * @secid: incoming integer | 2520 | * @secid: incoming integer |
2387 | * @secdata: destination | 2521 | * @secdata: destination |
@@ -2406,7 +2540,7 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
2406 | * | 2540 | * |
2407 | * Exists for audit and networking code. | 2541 | * Exists for audit and networking code. |
2408 | */ | 2542 | */ |
2409 | static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | 2543 | static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
2410 | { | 2544 | { |
2411 | *secid = smack_to_secid(secdata); | 2545 | *secid = smack_to_secid(secdata); |
2412 | return 0; | 2546 | return 0; |
@@ -2467,6 +2601,7 @@ struct security_operations smack_ops = { | |||
2467 | .inode_getsecurity = smack_inode_getsecurity, | 2601 | .inode_getsecurity = smack_inode_getsecurity, |
2468 | .inode_setsecurity = smack_inode_setsecurity, | 2602 | .inode_setsecurity = smack_inode_setsecurity, |
2469 | .inode_listsecurity = smack_inode_listsecurity, | 2603 | .inode_listsecurity = smack_inode_listsecurity, |
2604 | .inode_getsecid = smack_inode_getsecid, | ||
2470 | 2605 | ||
2471 | .file_permission = smack_file_permission, | 2606 | .file_permission = smack_file_permission, |
2472 | .file_alloc_security = smack_file_alloc_security, | 2607 | .file_alloc_security = smack_file_alloc_security, |
@@ -2498,6 +2633,7 @@ struct security_operations smack_ops = { | |||
2498 | .task_prctl = cap_task_prctl, | 2633 | .task_prctl = cap_task_prctl, |
2499 | 2634 | ||
2500 | .ipc_permission = smack_ipc_permission, | 2635 | .ipc_permission = smack_ipc_permission, |
2636 | .ipc_getsecid = smack_ipc_getsecid, | ||
2501 | 2637 | ||
2502 | .msg_msg_alloc_security = smack_msg_msg_alloc_security, | 2638 | .msg_msg_alloc_security = smack_msg_msg_alloc_security, |
2503 | .msg_msg_free_security = smack_msg_msg_free_security, | 2639 | .msg_msg_free_security = smack_msg_msg_free_security, |
@@ -2542,12 +2678,22 @@ struct security_operations smack_ops = { | |||
2542 | .sk_free_security = smack_sk_free_security, | 2678 | .sk_free_security = smack_sk_free_security, |
2543 | .sock_graft = smack_sock_graft, | 2679 | .sock_graft = smack_sock_graft, |
2544 | .inet_conn_request = smack_inet_conn_request, | 2680 | .inet_conn_request = smack_inet_conn_request, |
2681 | |||
2545 | /* key management security hooks */ | 2682 | /* key management security hooks */ |
2546 | #ifdef CONFIG_KEYS | 2683 | #ifdef CONFIG_KEYS |
2547 | .key_alloc = smack_key_alloc, | 2684 | .key_alloc = smack_key_alloc, |
2548 | .key_free = smack_key_free, | 2685 | .key_free = smack_key_free, |
2549 | .key_permission = smack_key_permission, | 2686 | .key_permission = smack_key_permission, |
2550 | #endif /* CONFIG_KEYS */ | 2687 | #endif /* CONFIG_KEYS */ |
2688 | |||
2689 | /* Audit hooks */ | ||
2690 | #ifdef CONFIG_AUDIT | ||
2691 | .audit_rule_init = smack_audit_rule_init, | ||
2692 | .audit_rule_known = smack_audit_rule_known, | ||
2693 | .audit_rule_match = smack_audit_rule_match, | ||
2694 | .audit_rule_free = smack_audit_rule_free, | ||
2695 | #endif /* CONFIG_AUDIT */ | ||
2696 | |||
2551 | .secid_to_secctx = smack_secid_to_secctx, | 2697 | .secid_to_secctx = smack_secid_to_secctx, |
2552 | .secctx_to_secid = smack_secctx_to_secid, | 2698 | .secctx_to_secid = smack_secctx_to_secid, |
2553 | .release_secctx = smack_release_secctx, | 2699 | .release_secctx = smack_release_secctx, |