diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 507 |
1 files changed, 390 insertions, 117 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a143328f75eb..54fb3a1d8953 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/msg.h> | 41 | #include <linux/msg.h> |
42 | #include <linux/shm.h> | 42 | #include <linux/shm.h> |
43 | #include <linux/binfmts.h> | 43 | #include <linux/binfmts.h> |
44 | #include <linux/parser.h> | ||
44 | #include "smack.h" | 45 | #include "smack.h" |
45 | 46 | ||
46 | #define TRANS_TRUE "TRUE" | 47 | #define TRANS_TRUE "TRUE" |
@@ -50,9 +51,9 @@ | |||
50 | #define SMK_RECEIVING 1 | 51 | #define SMK_RECEIVING 1 |
51 | #define SMK_SENDING 2 | 52 | #define SMK_SENDING 2 |
52 | 53 | ||
53 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 54 | #ifdef SMACK_IPV6_PORT_LABELING |
54 | LIST_HEAD(smk_ipv6_port_list); | 55 | LIST_HEAD(smk_ipv6_port_list); |
55 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 56 | #endif |
56 | static struct kmem_cache *smack_inode_cache; | 57 | static struct kmem_cache *smack_inode_cache; |
57 | int smack_enabled; | 58 | int smack_enabled; |
58 | 59 | ||
@@ -64,6 +65,15 @@ static char *smk_bu_mess[] = { | |||
64 | "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ | 65 | "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ |
65 | }; | 66 | }; |
66 | 67 | ||
68 | static const match_table_t tokens = { | ||
69 | {Opt_fsdefault, SMK_FSDEFAULT "%s"}, | ||
70 | {Opt_fsfloor, SMK_FSFLOOR "%s"}, | ||
71 | {Opt_fshat, SMK_FSHAT "%s"}, | ||
72 | {Opt_fsroot, SMK_FSROOT "%s"}, | ||
73 | {Opt_fstransmute, SMK_FSTRANS "%s"}, | ||
74 | {Opt_error, NULL}, | ||
75 | }; | ||
76 | |||
67 | static void smk_bu_mode(int mode, char *s) | 77 | static void smk_bu_mode(int mode, char *s) |
68 | { | 78 | { |
69 | int i = 0; | 79 | int i = 0; |
@@ -281,7 +291,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, | |||
281 | * | 291 | * |
282 | * Returns the new blob or NULL if there's no memory available | 292 | * Returns the new blob or NULL if there's no memory available |
283 | */ | 293 | */ |
284 | struct inode_smack *new_inode_smack(struct smack_known *skp) | 294 | static struct inode_smack *new_inode_smack(struct smack_known *skp) |
285 | { | 295 | { |
286 | struct inode_smack *isp; | 296 | struct inode_smack *isp; |
287 | 297 | ||
@@ -577,76 +587,193 @@ static int smack_sb_copy_data(char *orig, char *smackopts) | |||
577 | } | 587 | } |
578 | 588 | ||
579 | /** | 589 | /** |
580 | * smack_sb_kern_mount - Smack specific mount processing | 590 | * smack_parse_opts_str - parse Smack specific mount options |
591 | * @options: mount options string | ||
592 | * @opts: where to store converted mount opts | ||
593 | * | ||
594 | * Returns 0 on success or -ENOMEM on error. | ||
595 | * | ||
596 | * converts Smack specific mount options to generic security option format | ||
597 | */ | ||
598 | static int smack_parse_opts_str(char *options, | ||
599 | struct security_mnt_opts *opts) | ||
600 | { | ||
601 | char *p; | ||
602 | char *fsdefault = NULL, *fsfloor = NULL; | ||
603 | char *fshat = NULL, *fsroot = NULL, *fstransmute = NULL; | ||
604 | int rc = -ENOMEM, num_mnt_opts = 0; | ||
605 | |||
606 | opts->num_mnt_opts = 0; | ||
607 | |||
608 | if (!options) | ||
609 | return 0; | ||
610 | |||
611 | while ((p = strsep(&options, ",")) != NULL) { | ||
612 | int token; | ||
613 | substring_t args[MAX_OPT_ARGS]; | ||
614 | |||
615 | if (!*p) | ||
616 | continue; | ||
617 | |||
618 | token = match_token(p, tokens, args); | ||
619 | |||
620 | switch (token) { | ||
621 | case Opt_fsdefault: | ||
622 | if (fsdefault) | ||
623 | goto out_opt_err; | ||
624 | fsdefault = match_strdup(&args[0]); | ||
625 | if (!fsdefault) | ||
626 | goto out_err; | ||
627 | break; | ||
628 | case Opt_fsfloor: | ||
629 | if (fsfloor) | ||
630 | goto out_opt_err; | ||
631 | fsfloor = match_strdup(&args[0]); | ||
632 | if (!fsfloor) | ||
633 | goto out_err; | ||
634 | break; | ||
635 | case Opt_fshat: | ||
636 | if (fshat) | ||
637 | goto out_opt_err; | ||
638 | fshat = match_strdup(&args[0]); | ||
639 | if (!fshat) | ||
640 | goto out_err; | ||
641 | break; | ||
642 | case Opt_fsroot: | ||
643 | if (fsroot) | ||
644 | goto out_opt_err; | ||
645 | fsroot = match_strdup(&args[0]); | ||
646 | if (!fsroot) | ||
647 | goto out_err; | ||
648 | break; | ||
649 | case Opt_fstransmute: | ||
650 | if (fstransmute) | ||
651 | goto out_opt_err; | ||
652 | fstransmute = match_strdup(&args[0]); | ||
653 | if (!fstransmute) | ||
654 | goto out_err; | ||
655 | break; | ||
656 | default: | ||
657 | rc = -EINVAL; | ||
658 | pr_warn("Smack: unknown mount option\n"); | ||
659 | goto out_err; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC); | ||
664 | if (!opts->mnt_opts) | ||
665 | goto out_err; | ||
666 | |||
667 | opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), | ||
668 | GFP_ATOMIC); | ||
669 | if (!opts->mnt_opts_flags) { | ||
670 | kfree(opts->mnt_opts); | ||
671 | goto out_err; | ||
672 | } | ||
673 | |||
674 | if (fsdefault) { | ||
675 | opts->mnt_opts[num_mnt_opts] = fsdefault; | ||
676 | opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT; | ||
677 | } | ||
678 | if (fsfloor) { | ||
679 | opts->mnt_opts[num_mnt_opts] = fsfloor; | ||
680 | opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT; | ||
681 | } | ||
682 | if (fshat) { | ||
683 | opts->mnt_opts[num_mnt_opts] = fshat; | ||
684 | opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT; | ||
685 | } | ||
686 | if (fsroot) { | ||
687 | opts->mnt_opts[num_mnt_opts] = fsroot; | ||
688 | opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT; | ||
689 | } | ||
690 | if (fstransmute) { | ||
691 | opts->mnt_opts[num_mnt_opts] = fstransmute; | ||
692 | opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT; | ||
693 | } | ||
694 | |||
695 | opts->num_mnt_opts = num_mnt_opts; | ||
696 | return 0; | ||
697 | |||
698 | out_opt_err: | ||
699 | rc = -EINVAL; | ||
700 | pr_warn("Smack: duplicate mount options\n"); | ||
701 | |||
702 | out_err: | ||
703 | kfree(fsdefault); | ||
704 | kfree(fsfloor); | ||
705 | kfree(fshat); | ||
706 | kfree(fsroot); | ||
707 | kfree(fstransmute); | ||
708 | return rc; | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * smack_set_mnt_opts - set Smack specific mount options | ||
581 | * @sb: the file system superblock | 713 | * @sb: the file system superblock |
582 | * @flags: the mount flags | 714 | * @opts: Smack mount options |
583 | * @data: the smack mount options | 715 | * @kern_flags: mount option from kernel space or user space |
716 | * @set_kern_flags: where to store converted mount opts | ||
584 | * | 717 | * |
585 | * Returns 0 on success, an error code on failure | 718 | * Returns 0 on success, an error code on failure |
719 | * | ||
720 | * Allow filesystems with binary mount data to explicitly set Smack mount | ||
721 | * labels. | ||
586 | */ | 722 | */ |
587 | static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | 723 | static int smack_set_mnt_opts(struct super_block *sb, |
724 | struct security_mnt_opts *opts, | ||
725 | unsigned long kern_flags, | ||
726 | unsigned long *set_kern_flags) | ||
588 | { | 727 | { |
589 | struct dentry *root = sb->s_root; | 728 | struct dentry *root = sb->s_root; |
590 | struct inode *inode = d_backing_inode(root); | 729 | struct inode *inode = d_backing_inode(root); |
591 | struct superblock_smack *sp = sb->s_security; | 730 | struct superblock_smack *sp = sb->s_security; |
592 | struct inode_smack *isp; | 731 | struct inode_smack *isp; |
593 | struct smack_known *skp; | 732 | struct smack_known *skp; |
594 | char *op; | 733 | int i; |
595 | char *commap; | 734 | int num_opts = opts->num_mnt_opts; |
596 | int transmute = 0; | 735 | int transmute = 0; |
597 | int specified = 0; | ||
598 | 736 | ||
599 | if (sp->smk_initialized) | 737 | if (sp->smk_initialized) |
600 | return 0; | 738 | return 0; |
601 | 739 | ||
602 | sp->smk_initialized = 1; | 740 | sp->smk_initialized = 1; |
603 | 741 | ||
604 | for (op = data; op != NULL; op = commap) { | 742 | for (i = 0; i < num_opts; i++) { |
605 | commap = strchr(op, ','); | 743 | switch (opts->mnt_opts_flags[i]) { |
606 | if (commap != NULL) | 744 | case FSDEFAULT_MNT: |
607 | *commap++ = '\0'; | 745 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
608 | |||
609 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | ||
610 | op += strlen(SMK_FSHAT); | ||
611 | skp = smk_import_entry(op, 0); | ||
612 | if (IS_ERR(skp)) | 746 | if (IS_ERR(skp)) |
613 | return PTR_ERR(skp); | 747 | return PTR_ERR(skp); |
614 | sp->smk_hat = skp; | 748 | sp->smk_default = skp; |
615 | specified = 1; | 749 | break; |
616 | 750 | case FSFLOOR_MNT: | |
617 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 751 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
618 | op += strlen(SMK_FSFLOOR); | ||
619 | skp = smk_import_entry(op, 0); | ||
620 | if (IS_ERR(skp)) | 752 | if (IS_ERR(skp)) |
621 | return PTR_ERR(skp); | 753 | return PTR_ERR(skp); |
622 | sp->smk_floor = skp; | 754 | sp->smk_floor = skp; |
623 | specified = 1; | 755 | break; |
624 | 756 | case FSHAT_MNT: | |
625 | } else if (strncmp(op, SMK_FSDEFAULT, | 757 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
626 | strlen(SMK_FSDEFAULT)) == 0) { | ||
627 | op += strlen(SMK_FSDEFAULT); | ||
628 | skp = smk_import_entry(op, 0); | ||
629 | if (IS_ERR(skp)) | 758 | if (IS_ERR(skp)) |
630 | return PTR_ERR(skp); | 759 | return PTR_ERR(skp); |
631 | sp->smk_default = skp; | 760 | sp->smk_hat = skp; |
632 | specified = 1; | 761 | break; |
633 | 762 | case FSROOT_MNT: | |
634 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 763 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
635 | op += strlen(SMK_FSROOT); | ||
636 | skp = smk_import_entry(op, 0); | ||
637 | if (IS_ERR(skp)) | 764 | if (IS_ERR(skp)) |
638 | return PTR_ERR(skp); | 765 | return PTR_ERR(skp); |
639 | sp->smk_root = skp; | 766 | sp->smk_root = skp; |
640 | specified = 1; | 767 | break; |
641 | 768 | case FSTRANS_MNT: | |
642 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 769 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
643 | op += strlen(SMK_FSTRANS); | ||
644 | skp = smk_import_entry(op, 0); | ||
645 | if (IS_ERR(skp)) | 770 | if (IS_ERR(skp)) |
646 | return PTR_ERR(skp); | 771 | return PTR_ERR(skp); |
647 | sp->smk_root = skp; | 772 | sp->smk_root = skp; |
648 | transmute = 1; | 773 | transmute = 1; |
649 | specified = 1; | 774 | break; |
775 | default: | ||
776 | break; | ||
650 | } | 777 | } |
651 | } | 778 | } |
652 | 779 | ||
@@ -654,7 +781,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
654 | /* | 781 | /* |
655 | * Unprivileged mounts don't get to specify Smack values. | 782 | * Unprivileged mounts don't get to specify Smack values. |
656 | */ | 783 | */ |
657 | if (specified) | 784 | if (num_opts) |
658 | return -EPERM; | 785 | return -EPERM; |
659 | /* | 786 | /* |
660 | * Unprivileged mounts get root and default from the caller. | 787 | * Unprivileged mounts get root and default from the caller. |
@@ -663,6 +790,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
663 | sp->smk_root = skp; | 790 | sp->smk_root = skp; |
664 | sp->smk_default = skp; | 791 | sp->smk_default = skp; |
665 | } | 792 | } |
793 | |||
666 | /* | 794 | /* |
667 | * Initialize the root inode. | 795 | * Initialize the root inode. |
668 | */ | 796 | */ |
@@ -682,6 +810,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
682 | } | 810 | } |
683 | 811 | ||
684 | /** | 812 | /** |
813 | * smack_sb_kern_mount - Smack specific mount processing | ||
814 | * @sb: the file system superblock | ||
815 | * @flags: the mount flags | ||
816 | * @data: the smack mount options | ||
817 | * | ||
818 | * Returns 0 on success, an error code on failure | ||
819 | */ | ||
820 | static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | ||
821 | { | ||
822 | int rc = 0; | ||
823 | char *options = data; | ||
824 | struct security_mnt_opts opts; | ||
825 | |||
826 | security_init_mnt_opts(&opts); | ||
827 | |||
828 | if (!options) | ||
829 | goto out; | ||
830 | |||
831 | rc = smack_parse_opts_str(options, &opts); | ||
832 | if (rc) | ||
833 | goto out_err; | ||
834 | |||
835 | out: | ||
836 | rc = smack_set_mnt_opts(sb, &opts, 0, NULL); | ||
837 | |||
838 | out_err: | ||
839 | security_free_mnt_opts(&opts); | ||
840 | return rc; | ||
841 | } | ||
842 | |||
843 | /** | ||
685 | * smack_sb_statfs - Smack check on statfs | 844 | * smack_sb_statfs - Smack check on statfs |
686 | * @dentry: identifies the file system in question | 845 | * @dentry: identifies the file system in question |
687 | * | 846 | * |
@@ -2113,7 +2272,7 @@ static void smack_sk_free_security(struct sock *sk) | |||
2113 | } | 2272 | } |
2114 | 2273 | ||
2115 | /** | 2274 | /** |
2116 | * smack_host_label - check host based restrictions | 2275 | * smack_ipv4host_label - check host based restrictions |
2117 | * @sip: the object end | 2276 | * @sip: the object end |
2118 | * | 2277 | * |
2119 | * looks for host based access restrictions | 2278 | * looks for host based access restrictions |
@@ -2124,30 +2283,96 @@ static void smack_sk_free_security(struct sock *sk) | |||
2124 | * | 2283 | * |
2125 | * Returns the label of the far end or NULL if it's not special. | 2284 | * Returns the label of the far end or NULL if it's not special. |
2126 | */ | 2285 | */ |
2127 | static struct smack_known *smack_host_label(struct sockaddr_in *sip) | 2286 | static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip) |
2128 | { | 2287 | { |
2129 | struct smk_netlbladdr *snp; | 2288 | struct smk_net4addr *snp; |
2130 | struct in_addr *siap = &sip->sin_addr; | 2289 | struct in_addr *siap = &sip->sin_addr; |
2131 | 2290 | ||
2132 | if (siap->s_addr == 0) | 2291 | if (siap->s_addr == 0) |
2133 | return NULL; | 2292 | return NULL; |
2134 | 2293 | ||
2135 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) | 2294 | list_for_each_entry_rcu(snp, &smk_net4addr_list, list) |
2295 | /* | ||
2296 | * we break after finding the first match because | ||
2297 | * the list is sorted from longest to shortest mask | ||
2298 | * so we have found the most specific match | ||
2299 | */ | ||
2300 | if (snp->smk_host.s_addr == | ||
2301 | (siap->s_addr & snp->smk_mask.s_addr)) | ||
2302 | return snp->smk_label; | ||
2303 | |||
2304 | return NULL; | ||
2305 | } | ||
2306 | |||
2307 | #if IS_ENABLED(CONFIG_IPV6) | ||
2308 | /* | ||
2309 | * smk_ipv6_localhost - Check for local ipv6 host address | ||
2310 | * @sip: the address | ||
2311 | * | ||
2312 | * Returns boolean true if this is the localhost address | ||
2313 | */ | ||
2314 | static bool smk_ipv6_localhost(struct sockaddr_in6 *sip) | ||
2315 | { | ||
2316 | __be16 *be16p = (__be16 *)&sip->sin6_addr; | ||
2317 | __be32 *be32p = (__be32 *)&sip->sin6_addr; | ||
2318 | |||
2319 | if (be32p[0] == 0 && be32p[1] == 0 && be32p[2] == 0 && be16p[6] == 0 && | ||
2320 | ntohs(be16p[7]) == 1) | ||
2321 | return true; | ||
2322 | return false; | ||
2323 | } | ||
2324 | |||
2325 | /** | ||
2326 | * smack_ipv6host_label - check host based restrictions | ||
2327 | * @sip: the object end | ||
2328 | * | ||
2329 | * looks for host based access restrictions | ||
2330 | * | ||
2331 | * This version will only be appropriate for really small sets of single label | ||
2332 | * hosts. The caller is responsible for ensuring that the RCU read lock is | ||
2333 | * taken before calling this function. | ||
2334 | * | ||
2335 | * Returns the label of the far end or NULL if it's not special. | ||
2336 | */ | ||
2337 | static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip) | ||
2338 | { | ||
2339 | struct smk_net6addr *snp; | ||
2340 | struct in6_addr *sap = &sip->sin6_addr; | ||
2341 | int i; | ||
2342 | int found = 0; | ||
2343 | |||
2344 | /* | ||
2345 | * It's local. Don't look for a host label. | ||
2346 | */ | ||
2347 | if (smk_ipv6_localhost(sip)) | ||
2348 | return NULL; | ||
2349 | |||
2350 | list_for_each_entry_rcu(snp, &smk_net6addr_list, list) { | ||
2136 | /* | 2351 | /* |
2137 | * we break after finding the first match because | 2352 | * we break after finding the first match because |
2138 | * the list is sorted from longest to shortest mask | 2353 | * the list is sorted from longest to shortest mask |
2139 | * so we have found the most specific match | 2354 | * so we have found the most specific match |
2140 | */ | 2355 | */ |
2141 | if ((&snp->smk_host.sin_addr)->s_addr == | 2356 | for (found = 1, i = 0; i < 8; i++) { |
2142 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { | 2357 | /* |
2143 | /* we have found the special CIPSO option */ | 2358 | * If the label is NULL the entry has |
2144 | if (snp->smk_label == &smack_cipso_option) | 2359 | * been renounced. Ignore it. |
2145 | return NULL; | 2360 | */ |
2146 | return snp->smk_label; | 2361 | if (snp->smk_label == NULL) |
2362 | continue; | ||
2363 | if ((sap->s6_addr16[i] & snp->smk_mask.s6_addr16[i]) != | ||
2364 | snp->smk_host.s6_addr16[i]) { | ||
2365 | found = 0; | ||
2366 | break; | ||
2367 | } | ||
2147 | } | 2368 | } |
2369 | if (found) | ||
2370 | return snp->smk_label; | ||
2371 | } | ||
2148 | 2372 | ||
2149 | return NULL; | 2373 | return NULL; |
2150 | } | 2374 | } |
2375 | #endif /* CONFIG_IPV6 */ | ||
2151 | 2376 | ||
2152 | /** | 2377 | /** |
2153 | * smack_netlabel - Set the secattr on a socket | 2378 | * smack_netlabel - Set the secattr on a socket |
@@ -2211,7 +2436,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
2211 | struct smk_audit_info ad; | 2436 | struct smk_audit_info ad; |
2212 | 2437 | ||
2213 | rcu_read_lock(); | 2438 | rcu_read_lock(); |
2214 | hkp = smack_host_label(sap); | 2439 | hkp = smack_ipv4host_label(sap); |
2215 | if (hkp != NULL) { | 2440 | if (hkp != NULL) { |
2216 | #ifdef CONFIG_AUDIT | 2441 | #ifdef CONFIG_AUDIT |
2217 | struct lsm_network_audit net; | 2442 | struct lsm_network_audit net; |
@@ -2236,7 +2461,42 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
2236 | return smack_netlabel(sk, sk_lbl); | 2461 | return smack_netlabel(sk, sk_lbl); |
2237 | } | 2462 | } |
2238 | 2463 | ||
2239 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 2464 | #if IS_ENABLED(CONFIG_IPV6) |
2465 | /** | ||
2466 | * smk_ipv6_check - check Smack access | ||
2467 | * @subject: subject Smack label | ||
2468 | * @object: object Smack label | ||
2469 | * @address: address | ||
2470 | * @act: the action being taken | ||
2471 | * | ||
2472 | * Check an IPv6 access | ||
2473 | */ | ||
2474 | static int smk_ipv6_check(struct smack_known *subject, | ||
2475 | struct smack_known *object, | ||
2476 | struct sockaddr_in6 *address, int act) | ||
2477 | { | ||
2478 | #ifdef CONFIG_AUDIT | ||
2479 | struct lsm_network_audit net; | ||
2480 | #endif | ||
2481 | struct smk_audit_info ad; | ||
2482 | int rc; | ||
2483 | |||
2484 | #ifdef CONFIG_AUDIT | ||
2485 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2486 | ad.a.u.net->family = PF_INET6; | ||
2487 | ad.a.u.net->dport = ntohs(address->sin6_port); | ||
2488 | if (act == SMK_RECEIVING) | ||
2489 | ad.a.u.net->v6info.saddr = address->sin6_addr; | ||
2490 | else | ||
2491 | ad.a.u.net->v6info.daddr = address->sin6_addr; | ||
2492 | #endif | ||
2493 | rc = smk_access(subject, object, MAY_WRITE, &ad); | ||
2494 | rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc); | ||
2495 | return rc; | ||
2496 | } | ||
2497 | #endif /* CONFIG_IPV6 */ | ||
2498 | |||
2499 | #ifdef SMACK_IPV6_PORT_LABELING | ||
2240 | /** | 2500 | /** |
2241 | * smk_ipv6_port_label - Smack port access table management | 2501 | * smk_ipv6_port_label - Smack port access table management |
2242 | * @sock: socket | 2502 | * @sock: socket |
@@ -2320,48 +2580,43 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) | |||
2320 | static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | 2580 | static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, |
2321 | int act) | 2581 | int act) |
2322 | { | 2582 | { |
2323 | __be16 *bep; | ||
2324 | __be32 *be32p; | ||
2325 | struct smk_port_label *spp; | 2583 | struct smk_port_label *spp; |
2326 | struct socket_smack *ssp = sk->sk_security; | 2584 | struct socket_smack *ssp = sk->sk_security; |
2327 | struct smack_known *skp; | 2585 | struct smack_known *skp = NULL; |
2328 | unsigned short port = 0; | 2586 | unsigned short port; |
2329 | struct smack_known *object; | 2587 | struct smack_known *object; |
2330 | struct smk_audit_info ad; | ||
2331 | int rc; | ||
2332 | #ifdef CONFIG_AUDIT | ||
2333 | struct lsm_network_audit net; | ||
2334 | #endif | ||
2335 | 2588 | ||
2336 | if (act == SMK_RECEIVING) { | 2589 | if (act == SMK_RECEIVING) { |
2337 | skp = smack_net_ambient; | 2590 | skp = smack_ipv6host_label(address); |
2338 | object = ssp->smk_in; | 2591 | object = ssp->smk_in; |
2339 | } else { | 2592 | } else { |
2340 | skp = ssp->smk_out; | 2593 | skp = ssp->smk_out; |
2341 | object = smack_net_ambient; | 2594 | object = smack_ipv6host_label(address); |
2342 | } | 2595 | } |
2343 | 2596 | ||
2344 | /* | 2597 | /* |
2345 | * Get the IP address and port from the address. | 2598 | * The other end is a single label host. |
2346 | */ | 2599 | */ |
2347 | port = ntohs(address->sin6_port); | 2600 | if (skp != NULL && object != NULL) |
2348 | bep = (__be16 *)(&address->sin6_addr); | 2601 | return smk_ipv6_check(skp, object, address, act); |
2349 | be32p = (__be32 *)(&address->sin6_addr); | 2602 | if (skp == NULL) |
2603 | skp = smack_net_ambient; | ||
2604 | if (object == NULL) | ||
2605 | object = smack_net_ambient; | ||
2350 | 2606 | ||
2351 | /* | 2607 | /* |
2352 | * It's remote, so port lookup does no good. | 2608 | * It's remote, so port lookup does no good. |
2353 | */ | 2609 | */ |
2354 | if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1) | 2610 | if (!smk_ipv6_localhost(address)) |
2355 | goto auditout; | 2611 | return smk_ipv6_check(skp, object, address, act); |
2356 | 2612 | ||
2357 | /* | 2613 | /* |
2358 | * It's local so the send check has to have passed. | 2614 | * It's local so the send check has to have passed. |
2359 | */ | 2615 | */ |
2360 | if (act == SMK_RECEIVING) { | 2616 | if (act == SMK_RECEIVING) |
2361 | skp = &smack_known_web; | 2617 | return 0; |
2362 | goto auditout; | ||
2363 | } | ||
2364 | 2618 | ||
2619 | port = ntohs(address->sin6_port); | ||
2365 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | 2620 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { |
2366 | if (spp->smk_port != port) | 2621 | if (spp->smk_port != port) |
2367 | continue; | 2622 | continue; |
@@ -2371,22 +2626,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
2371 | break; | 2626 | break; |
2372 | } | 2627 | } |
2373 | 2628 | ||
2374 | auditout: | 2629 | return smk_ipv6_check(skp, object, address, act); |
2375 | |||
2376 | #ifdef CONFIG_AUDIT | ||
2377 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2378 | ad.a.u.net->family = sk->sk_family; | ||
2379 | ad.a.u.net->dport = port; | ||
2380 | if (act == SMK_RECEIVING) | ||
2381 | ad.a.u.net->v6info.saddr = address->sin6_addr; | ||
2382 | else | ||
2383 | ad.a.u.net->v6info.daddr = address->sin6_addr; | ||
2384 | #endif | ||
2385 | rc = smk_access(skp, object, MAY_WRITE, &ad); | ||
2386 | rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); | ||
2387 | return rc; | ||
2388 | } | 2630 | } |
2389 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 2631 | #endif /* SMACK_IPV6_PORT_LABELING */ |
2390 | 2632 | ||
2391 | /** | 2633 | /** |
2392 | * smack_inode_setsecurity - set smack xattrs | 2634 | * smack_inode_setsecurity - set smack xattrs |
@@ -2447,10 +2689,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
2447 | } else | 2689 | } else |
2448 | return -EOPNOTSUPP; | 2690 | return -EOPNOTSUPP; |
2449 | 2691 | ||
2450 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 2692 | #ifdef SMACK_IPV6_PORT_LABELING |
2451 | if (sock->sk->sk_family == PF_INET6) | 2693 | if (sock->sk->sk_family == PF_INET6) |
2452 | smk_ipv6_port_label(sock, NULL); | 2694 | smk_ipv6_port_label(sock, NULL); |
2453 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 2695 | #endif |
2454 | 2696 | ||
2455 | return 0; | 2697 | return 0; |
2456 | } | 2698 | } |
@@ -2492,7 +2734,7 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
2492 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 2734 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
2493 | } | 2735 | } |
2494 | 2736 | ||
2495 | #ifndef CONFIG_SECURITY_SMACK_NETFILTER | 2737 | #ifdef SMACK_IPV6_PORT_LABELING |
2496 | /** | 2738 | /** |
2497 | * smack_socket_bind - record port binding information. | 2739 | * smack_socket_bind - record port binding information. |
2498 | * @sock: the socket | 2740 | * @sock: the socket |
@@ -2506,14 +2748,11 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
2506 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, | 2748 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, |
2507 | int addrlen) | 2749 | int addrlen) |
2508 | { | 2750 | { |
2509 | #if IS_ENABLED(CONFIG_IPV6) | ||
2510 | if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) | 2751 | if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) |
2511 | smk_ipv6_port_label(sock, address); | 2752 | smk_ipv6_port_label(sock, address); |
2512 | #endif | ||
2513 | |||
2514 | return 0; | 2753 | return 0; |
2515 | } | 2754 | } |
2516 | #endif /* !CONFIG_SECURITY_SMACK_NETFILTER */ | 2755 | #endif /* SMACK_IPV6_PORT_LABELING */ |
2517 | 2756 | ||
2518 | /** | 2757 | /** |
2519 | * smack_socket_connect - connect access check | 2758 | * smack_socket_connect - connect access check |
@@ -2529,6 +2768,13 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | |||
2529 | int addrlen) | 2768 | int addrlen) |
2530 | { | 2769 | { |
2531 | int rc = 0; | 2770 | int rc = 0; |
2771 | #if IS_ENABLED(CONFIG_IPV6) | ||
2772 | struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; | ||
2773 | #endif | ||
2774 | #ifdef SMACK_IPV6_SECMARK_LABELING | ||
2775 | struct smack_known *rsp; | ||
2776 | struct socket_smack *ssp = sock->sk->sk_security; | ||
2777 | #endif | ||
2532 | 2778 | ||
2533 | if (sock->sk == NULL) | 2779 | if (sock->sk == NULL) |
2534 | return 0; | 2780 | return 0; |
@@ -2542,10 +2788,15 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | |||
2542 | case PF_INET6: | 2788 | case PF_INET6: |
2543 | if (addrlen < sizeof(struct sockaddr_in6)) | 2789 | if (addrlen < sizeof(struct sockaddr_in6)) |
2544 | return -EINVAL; | 2790 | return -EINVAL; |
2545 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 2791 | #ifdef SMACK_IPV6_SECMARK_LABELING |
2546 | rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, | 2792 | rsp = smack_ipv6host_label(sip); |
2793 | if (rsp != NULL) | ||
2794 | rc = smk_ipv6_check(ssp->smk_out, rsp, sip, | ||
2547 | SMK_CONNECTING); | 2795 | SMK_CONNECTING); |
2548 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 2796 | #endif |
2797 | #ifdef SMACK_IPV6_PORT_LABELING | ||
2798 | rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); | ||
2799 | #endif | ||
2549 | break; | 2800 | break; |
2550 | } | 2801 | } |
2551 | return rc; | 2802 | return rc; |
@@ -3431,9 +3682,13 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
3431 | int size) | 3682 | int size) |
3432 | { | 3683 | { |
3433 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; | 3684 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; |
3434 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 3685 | #if IS_ENABLED(CONFIG_IPV6) |
3435 | struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; | 3686 | struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; |
3436 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 3687 | #endif |
3688 | #ifdef SMACK_IPV6_SECMARK_LABELING | ||
3689 | struct socket_smack *ssp = sock->sk->sk_security; | ||
3690 | struct smack_known *rsp; | ||
3691 | #endif | ||
3437 | int rc = 0; | 3692 | int rc = 0; |
3438 | 3693 | ||
3439 | /* | 3694 | /* |
@@ -3447,9 +3702,15 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
3447 | rc = smack_netlabel_send(sock->sk, sip); | 3702 | rc = smack_netlabel_send(sock->sk, sip); |
3448 | break; | 3703 | break; |
3449 | case AF_INET6: | 3704 | case AF_INET6: |
3450 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | 3705 | #ifdef SMACK_IPV6_SECMARK_LABELING |
3706 | rsp = smack_ipv6host_label(sap); | ||
3707 | if (rsp != NULL) | ||
3708 | rc = smk_ipv6_check(ssp->smk_out, rsp, sap, | ||
3709 | SMK_CONNECTING); | ||
3710 | #endif | ||
3711 | #ifdef SMACK_IPV6_PORT_LABELING | ||
3451 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); | 3712 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); |
3452 | #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ | 3713 | #endif |
3453 | break; | 3714 | break; |
3454 | } | 3715 | } |
3455 | return rc; | 3716 | return rc; |
@@ -3663,10 +3924,12 @@ access_check: | |||
3663 | proto = smk_skb_to_addr_ipv6(skb, &sadd); | 3924 | proto = smk_skb_to_addr_ipv6(skb, &sadd); |
3664 | if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) | 3925 | if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) |
3665 | break; | 3926 | break; |
3666 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | 3927 | #ifdef SMACK_IPV6_SECMARK_LABELING |
3667 | if (skb && skb->secmark != 0) | 3928 | if (skb && skb->secmark != 0) |
3668 | skp = smack_from_secid(skb->secmark); | 3929 | skp = smack_from_secid(skb->secmark); |
3669 | else | 3930 | else |
3931 | skp = smack_ipv6host_label(&sadd); | ||
3932 | if (skp == NULL) | ||
3670 | skp = smack_net_ambient; | 3933 | skp = smack_net_ambient; |
3671 | #ifdef CONFIG_AUDIT | 3934 | #ifdef CONFIG_AUDIT |
3672 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3935 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
@@ -3677,9 +3940,10 @@ access_check: | |||
3677 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); | 3940 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
3678 | rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in, | 3941 | rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in, |
3679 | MAY_WRITE, rc); | 3942 | MAY_WRITE, rc); |
3680 | #else /* CONFIG_SECURITY_SMACK_NETFILTER */ | 3943 | #endif /* SMACK_IPV6_SECMARK_LABELING */ |
3944 | #ifdef SMACK_IPV6_PORT_LABELING | ||
3681 | rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); | 3945 | rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); |
3682 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | 3946 | #endif /* SMACK_IPV6_PORT_LABELING */ |
3683 | break; | 3947 | break; |
3684 | #endif /* CONFIG_IPV6 */ | 3948 | #endif /* CONFIG_IPV6 */ |
3685 | } | 3949 | } |
@@ -3777,13 +4041,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3777 | } | 4041 | } |
3778 | netlbl_secattr_destroy(&secattr); | 4042 | netlbl_secattr_destroy(&secattr); |
3779 | break; | 4043 | break; |
3780 | #if IS_ENABLED(CONFIG_IPV6) | ||
3781 | case PF_INET6: | 4044 | case PF_INET6: |
3782 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | 4045 | #ifdef SMACK_IPV6_SECMARK_LABELING |
3783 | s = skb->secmark; | 4046 | s = skb->secmark; |
3784 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | 4047 | #endif |
3785 | break; | 4048 | break; |
3786 | #endif /* CONFIG_IPV6 */ | ||
3787 | } | 4049 | } |
3788 | *secid = s; | 4050 | *secid = s; |
3789 | if (s == 0) | 4051 | if (s == 0) |
@@ -3906,7 +4168,7 @@ access_check: | |||
3906 | hdr = ip_hdr(skb); | 4168 | hdr = ip_hdr(skb); |
3907 | addr.sin_addr.s_addr = hdr->saddr; | 4169 | addr.sin_addr.s_addr = hdr->saddr; |
3908 | rcu_read_lock(); | 4170 | rcu_read_lock(); |
3909 | hskp = smack_host_label(&addr); | 4171 | hskp = smack_ipv4host_label(&addr); |
3910 | rcu_read_unlock(); | 4172 | rcu_read_unlock(); |
3911 | 4173 | ||
3912 | if (hskp == NULL) | 4174 | if (hskp == NULL) |
@@ -4254,7 +4516,7 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | |||
4254 | return 0; | 4516 | return 0; |
4255 | } | 4517 | } |
4256 | 4518 | ||
4257 | struct security_hook_list smack_hooks[] = { | 4519 | static struct security_hook_list smack_hooks[] = { |
4258 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), | 4520 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), |
4259 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), | 4521 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), |
4260 | LSM_HOOK_INIT(syslog, smack_syslog), | 4522 | LSM_HOOK_INIT(syslog, smack_syslog), |
@@ -4264,6 +4526,8 @@ struct security_hook_list smack_hooks[] = { | |||
4264 | LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), | 4526 | LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), |
4265 | LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), | 4527 | LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), |
4266 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), | 4528 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), |
4529 | LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), | ||
4530 | LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str), | ||
4267 | 4531 | ||
4268 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), | 4532 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), |
4269 | LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), | 4533 | LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), |
@@ -4356,9 +4620,9 @@ struct security_hook_list smack_hooks[] = { | |||
4356 | LSM_HOOK_INIT(unix_may_send, smack_unix_may_send), | 4620 | LSM_HOOK_INIT(unix_may_send, smack_unix_may_send), |
4357 | 4621 | ||
4358 | LSM_HOOK_INIT(socket_post_create, smack_socket_post_create), | 4622 | LSM_HOOK_INIT(socket_post_create, smack_socket_post_create), |
4359 | #ifndef CONFIG_SECURITY_SMACK_NETFILTER | 4623 | #ifdef SMACK_IPV6_PORT_LABELING |
4360 | LSM_HOOK_INIT(socket_bind, smack_socket_bind), | 4624 | LSM_HOOK_INIT(socket_bind, smack_socket_bind), |
4361 | #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ | 4625 | #endif |
4362 | LSM_HOOK_INIT(socket_connect, smack_socket_connect), | 4626 | LSM_HOOK_INIT(socket_connect, smack_socket_connect), |
4363 | LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg), | 4627 | LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg), |
4364 | LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb), | 4628 | LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb), |
@@ -4453,7 +4717,16 @@ static __init int smack_init(void) | |||
4453 | return -ENOMEM; | 4717 | return -ENOMEM; |
4454 | } | 4718 | } |
4455 | 4719 | ||
4456 | printk(KERN_INFO "Smack: Initializing.\n"); | 4720 | pr_info("Smack: Initializing.\n"); |
4721 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | ||
4722 | pr_info("Smack: Netfilter enabled.\n"); | ||
4723 | #endif | ||
4724 | #ifdef SMACK_IPV6_PORT_LABELING | ||
4725 | pr_info("Smack: IPv6 port labeling enabled.\n"); | ||
4726 | #endif | ||
4727 | #ifdef SMACK_IPV6_SECMARK_LABELING | ||
4728 | pr_info("Smack: IPv6 Netfilter enabled.\n"); | ||
4729 | #endif | ||
4457 | 4730 | ||
4458 | /* | 4731 | /* |
4459 | * Set the security state for the initial task. | 4732 | * Set the security state for the initial task. |