diff options
author | James Morris <james.l.morris@oracle.com> | 2015-08-10 21:18:53 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2015-08-10 21:18:53 -0400 |
commit | 5ab16579020edb79e215b401399f88c7e07fdaf9 (patch) | |
tree | 5fdb2e49d543af7de6b129d6c87abb1967000a6b /security | |
parent | 459c15e53cf7e4e88a78ecfb109af5a267c5500a (diff) | |
parent | 41a2d5751616e38d1e293e3cb35a6e2bc7a03473 (diff) |
Merge branch 'smack-for-4.3' of https://github.com/cschaufler/smack-next into next
Diffstat (limited to 'security')
-rw-r--r-- | security/smack/smack.h | 66 | ||||
-rw-r--r-- | security/smack/smack_access.c | 6 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 507 | ||||
-rw-r--r-- | security/smack/smackfs.c | 436 |
4 files changed, 807 insertions, 208 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 244e035e5a99..fff0c612bbb7 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -17,12 +17,27 @@ | |||
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/lsm_hooks.h> | 18 | #include <linux/lsm_hooks.h> |
19 | #include <linux/in.h> | 19 | #include <linux/in.h> |
20 | #if IS_ENABLED(CONFIG_IPV6) | ||
21 | #include <linux/in6.h> | ||
22 | #endif /* CONFIG_IPV6 */ | ||
20 | #include <net/netlabel.h> | 23 | #include <net/netlabel.h> |
21 | #include <linux/list.h> | 24 | #include <linux/list.h> |
22 | #include <linux/rculist.h> | 25 | #include <linux/rculist.h> |
23 | #include <linux/lsm_audit.h> | 26 | #include <linux/lsm_audit.h> |
24 | 27 | ||
25 | /* | 28 | /* |
29 | * Use IPv6 port labeling if IPv6 is enabled and secmarks | ||
30 | * are not being used. | ||
31 | */ | ||
32 | #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
33 | #define SMACK_IPV6_PORT_LABELING 1 | ||
34 | #endif | ||
35 | |||
36 | #if IS_ENABLED(CONFIG_IPV6) && defined(CONFIG_SECURITY_SMACK_NETFILTER) | ||
37 | #define SMACK_IPV6_SECMARK_LABELING 1 | ||
38 | #endif | ||
39 | |||
40 | /* | ||
26 | * Smack labels were limited to 23 characters for a long time. | 41 | * Smack labels were limited to 23 characters for a long time. |
27 | */ | 42 | */ |
28 | #define SMK_LABELLEN 24 | 43 | #define SMK_LABELLEN 24 |
@@ -118,15 +133,30 @@ struct smack_rule { | |||
118 | }; | 133 | }; |
119 | 134 | ||
120 | /* | 135 | /* |
121 | * An entry in the table identifying hosts. | 136 | * An entry in the table identifying IPv4 hosts. |
122 | */ | 137 | */ |
123 | struct smk_netlbladdr { | 138 | struct smk_net4addr { |
124 | struct list_head list; | 139 | struct list_head list; |
125 | struct sockaddr_in smk_host; /* network address */ | 140 | struct in_addr smk_host; /* network address */ |
126 | struct in_addr smk_mask; /* network mask */ | 141 | struct in_addr smk_mask; /* network mask */ |
142 | int smk_masks; /* mask size */ | ||
143 | struct smack_known *smk_label; /* label */ | ||
144 | }; | ||
145 | |||
146 | #if IS_ENABLED(CONFIG_IPV6) | ||
147 | /* | ||
148 | * An entry in the table identifying IPv6 hosts. | ||
149 | */ | ||
150 | struct smk_net6addr { | ||
151 | struct list_head list; | ||
152 | struct in6_addr smk_host; /* network address */ | ||
153 | struct in6_addr smk_mask; /* network mask */ | ||
154 | int smk_masks; /* mask size */ | ||
127 | struct smack_known *smk_label; /* label */ | 155 | struct smack_known *smk_label; /* label */ |
128 | }; | 156 | }; |
157 | #endif /* CONFIG_IPV6 */ | ||
129 | 158 | ||
159 | #ifdef SMACK_IPV6_PORT_LABELING | ||
130 | /* | 160 | /* |
131 | * An entry in the table identifying ports. | 161 | * An entry in the table identifying ports. |
132 | */ | 162 | */ |
@@ -137,12 +167,31 @@ struct smk_port_label { | |||
137 | struct smack_known *smk_in; /* inbound label */ | 167 | struct smack_known *smk_in; /* inbound label */ |
138 | struct smack_known *smk_out; /* outgoing label */ | 168 | struct smack_known *smk_out; /* outgoing label */ |
139 | }; | 169 | }; |
170 | #endif /* SMACK_IPV6_PORT_LABELING */ | ||
140 | 171 | ||
141 | struct smack_onlycap { | 172 | struct smack_onlycap { |
142 | struct list_head list; | 173 | struct list_head list; |
143 | struct smack_known *smk_label; | 174 | struct smack_known *smk_label; |
144 | }; | 175 | }; |
145 | 176 | ||
177 | /* Super block security struct flags for mount options */ | ||
178 | #define FSDEFAULT_MNT 0x01 | ||
179 | #define FSFLOOR_MNT 0x02 | ||
180 | #define FSHAT_MNT 0x04 | ||
181 | #define FSROOT_MNT 0x08 | ||
182 | #define FSTRANS_MNT 0x10 | ||
183 | |||
184 | #define NUM_SMK_MNT_OPTS 5 | ||
185 | |||
186 | enum { | ||
187 | Opt_error = -1, | ||
188 | Opt_fsdefault = 1, | ||
189 | Opt_fsfloor = 2, | ||
190 | Opt_fshat = 3, | ||
191 | Opt_fsroot = 4, | ||
192 | Opt_fstransmute = 5, | ||
193 | }; | ||
194 | |||
146 | /* | 195 | /* |
147 | * Mount options | 196 | * Mount options |
148 | */ | 197 | */ |
@@ -152,6 +201,7 @@ struct smack_onlycap { | |||
152 | #define SMK_FSROOT "smackfsroot=" | 201 | #define SMK_FSROOT "smackfsroot=" |
153 | #define SMK_FSTRANS "smackfstransmute=" | 202 | #define SMK_FSTRANS "smackfstransmute=" |
154 | 203 | ||
204 | #define SMACK_DELETE_OPTION "-DELETE" | ||
155 | #define SMACK_CIPSO_OPTION "-CIPSO" | 205 | #define SMACK_CIPSO_OPTION "-CIPSO" |
156 | 206 | ||
157 | /* | 207 | /* |
@@ -234,10 +284,6 @@ struct smk_audit_info { | |||
234 | struct smack_audit_data sad; | 284 | struct smack_audit_data sad; |
235 | #endif | 285 | #endif |
236 | }; | 286 | }; |
237 | /* | ||
238 | * These functions are in smack_lsm.c | ||
239 | */ | ||
240 | struct inode_smack *new_inode_smack(struct smack_known *); | ||
241 | 287 | ||
242 | /* | 288 | /* |
243 | * These functions are in smack_access.c | 289 | * These functions are in smack_access.c |
@@ -267,7 +313,6 @@ extern struct smack_known *smack_syslog_label; | |||
267 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 313 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
268 | extern struct smack_known *smack_unconfined; | 314 | extern struct smack_known *smack_unconfined; |
269 | #endif | 315 | #endif |
270 | extern struct smack_known smack_cipso_option; | ||
271 | extern int smack_ptrace_rule; | 316 | extern int smack_ptrace_rule; |
272 | 317 | ||
273 | extern struct smack_known smack_known_floor; | 318 | extern struct smack_known smack_known_floor; |
@@ -279,7 +324,10 @@ extern struct smack_known smack_known_web; | |||
279 | 324 | ||
280 | extern struct mutex smack_known_lock; | 325 | extern struct mutex smack_known_lock; |
281 | extern struct list_head smack_known_list; | 326 | extern struct list_head smack_known_list; |
282 | extern struct list_head smk_netlbladdr_list; | 327 | extern struct list_head smk_net4addr_list; |
328 | #if IS_ENABLED(CONFIG_IPV6) | ||
329 | extern struct list_head smk_net6addr_list; | ||
330 | #endif /* CONFIG_IPV6 */ | ||
283 | 331 | ||
284 | extern struct mutex smack_onlycap_lock; | 332 | extern struct mutex smack_onlycap_lock; |
285 | extern struct list_head smack_onlycap_list; | 333 | extern struct list_head smack_onlycap_list; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 00f6b38bffbd..bc1053fb5d1d 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -639,6 +639,12 @@ int smack_privileged(int cap) | |||
639 | struct smack_known *skp = smk_of_current(); | 639 | struct smack_known *skp = smk_of_current(); |
640 | struct smack_onlycap *sop; | 640 | struct smack_onlycap *sop; |
641 | 641 | ||
642 | /* | ||
643 | * All kernel tasks are privileged | ||
644 | */ | ||
645 | if (unlikely(current->flags & PF_KTHREAD)) | ||
646 | return 1; | ||
647 | |||
642 | if (!capable(cap)) | 648 | if (!capable(cap)) |
643 | return 0; | 649 | return 0; |
644 | 650 | ||
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. |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 2716d02119f3..c20b154a33f2 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/magic.h> | 29 | #include <linux/magic.h> |
30 | #include "smack.h" | 30 | #include "smack.h" |
31 | 31 | ||
32 | #define BEBITS (sizeof(__be32) * 8) | ||
32 | /* | 33 | /* |
33 | * smackfs pseudo filesystem. | 34 | * smackfs pseudo filesystem. |
34 | */ | 35 | */ |
@@ -40,7 +41,7 @@ enum smk_inos { | |||
40 | SMK_DOI = 5, /* CIPSO DOI */ | 41 | SMK_DOI = 5, /* CIPSO DOI */ |
41 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ | 42 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ |
42 | SMK_AMBIENT = 7, /* internet ambient label */ | 43 | SMK_AMBIENT = 7, /* internet ambient label */ |
43 | SMK_NETLBLADDR = 8, /* single label hosts */ | 44 | SMK_NET4ADDR = 8, /* single label hosts */ |
44 | SMK_ONLYCAP = 9, /* the only "capable" label */ | 45 | SMK_ONLYCAP = 9, /* the only "capable" label */ |
45 | SMK_LOGGING = 10, /* logging */ | 46 | SMK_LOGGING = 10, /* logging */ |
46 | SMK_LOAD_SELF = 11, /* task specific rules */ | 47 | SMK_LOAD_SELF = 11, /* task specific rules */ |
@@ -57,6 +58,9 @@ enum smk_inos { | |||
57 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 58 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
58 | SMK_UNCONFINED = 22, /* define an unconfined label */ | 59 | SMK_UNCONFINED = 22, /* define an unconfined label */ |
59 | #endif | 60 | #endif |
61 | #if IS_ENABLED(CONFIG_IPV6) | ||
62 | SMK_NET6ADDR = 23, /* single label IPv6 hosts */ | ||
63 | #endif /* CONFIG_IPV6 */ | ||
60 | }; | 64 | }; |
61 | 65 | ||
62 | /* | 66 | /* |
@@ -64,7 +68,10 @@ enum smk_inos { | |||
64 | */ | 68 | */ |
65 | static DEFINE_MUTEX(smack_cipso_lock); | 69 | static DEFINE_MUTEX(smack_cipso_lock); |
66 | static DEFINE_MUTEX(smack_ambient_lock); | 70 | static DEFINE_MUTEX(smack_ambient_lock); |
67 | static DEFINE_MUTEX(smk_netlbladdr_lock); | 71 | static DEFINE_MUTEX(smk_net4addr_lock); |
72 | #if IS_ENABLED(CONFIG_IPV6) | ||
73 | static DEFINE_MUTEX(smk_net6addr_lock); | ||
74 | #endif /* CONFIG_IPV6 */ | ||
68 | 75 | ||
69 | /* | 76 | /* |
70 | * This is the "ambient" label for network traffic. | 77 | * This is the "ambient" label for network traffic. |
@@ -118,7 +125,10 @@ int smack_ptrace_rule = SMACK_PTRACE_DEFAULT; | |||
118 | * can write to the specified label. | 125 | * can write to the specified label. |
119 | */ | 126 | */ |
120 | 127 | ||
121 | LIST_HEAD(smk_netlbladdr_list); | 128 | LIST_HEAD(smk_net4addr_list); |
129 | #if IS_ENABLED(CONFIG_IPV6) | ||
130 | LIST_HEAD(smk_net6addr_list); | ||
131 | #endif /* CONFIG_IPV6 */ | ||
122 | 132 | ||
123 | /* | 133 | /* |
124 | * Rule lists are maintained for each label. | 134 | * Rule lists are maintained for each label. |
@@ -129,7 +139,7 @@ struct smack_master_list { | |||
129 | struct smack_rule *smk_rule; | 139 | struct smack_rule *smk_rule; |
130 | }; | 140 | }; |
131 | 141 | ||
132 | LIST_HEAD(smack_rule_list); | 142 | static LIST_HEAD(smack_rule_list); |
133 | 143 | ||
134 | struct smack_parsed_rule { | 144 | struct smack_parsed_rule { |
135 | struct smack_known *smk_subject; | 145 | struct smack_known *smk_subject; |
@@ -140,11 +150,6 @@ struct smack_parsed_rule { | |||
140 | 150 | ||
141 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 151 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
142 | 152 | ||
143 | struct smack_known smack_cipso_option = { | ||
144 | .smk_known = SMACK_CIPSO_OPTION, | ||
145 | .smk_secid = 0, | ||
146 | }; | ||
147 | |||
148 | /* | 153 | /* |
149 | * Values for parsing cipso rules | 154 | * Values for parsing cipso rules |
150 | * SMK_DIGITLEN: Length of a digit field in a rule. | 155 | * SMK_DIGITLEN: Length of a digit field in a rule. |
@@ -1047,92 +1052,90 @@ static const struct file_operations smk_cipso2_ops = { | |||
1047 | * Seq_file read operations for /smack/netlabel | 1052 | * Seq_file read operations for /smack/netlabel |
1048 | */ | 1053 | */ |
1049 | 1054 | ||
1050 | static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) | 1055 | static void *net4addr_seq_start(struct seq_file *s, loff_t *pos) |
1051 | { | 1056 | { |
1052 | return smk_seq_start(s, pos, &smk_netlbladdr_list); | 1057 | return smk_seq_start(s, pos, &smk_net4addr_list); |
1053 | } | 1058 | } |
1054 | 1059 | ||
1055 | static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) | 1060 | static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos) |
1056 | { | 1061 | { |
1057 | return smk_seq_next(s, v, pos, &smk_netlbladdr_list); | 1062 | return smk_seq_next(s, v, pos, &smk_net4addr_list); |
1058 | } | 1063 | } |
1059 | #define BEBITS (sizeof(__be32) * 8) | ||
1060 | 1064 | ||
1061 | /* | 1065 | /* |
1062 | * Print host/label pairs | 1066 | * Print host/label pairs |
1063 | */ | 1067 | */ |
1064 | static int netlbladdr_seq_show(struct seq_file *s, void *v) | 1068 | static int net4addr_seq_show(struct seq_file *s, void *v) |
1065 | { | 1069 | { |
1066 | struct list_head *list = v; | 1070 | struct list_head *list = v; |
1067 | struct smk_netlbladdr *skp = | 1071 | struct smk_net4addr *skp = |
1068 | list_entry_rcu(list, struct smk_netlbladdr, list); | 1072 | list_entry_rcu(list, struct smk_net4addr, list); |
1069 | unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; | 1073 | char *kp = SMACK_CIPSO_OPTION; |
1070 | int maskn; | ||
1071 | u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); | ||
1072 | |||
1073 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); | ||
1074 | 1074 | ||
1075 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", | 1075 | if (skp->smk_label != NULL) |
1076 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known); | 1076 | kp = skp->smk_label->smk_known; |
1077 | seq_printf(s, "%pI4/%d %s\n", &skp->smk_host.s_addr, | ||
1078 | skp->smk_masks, kp); | ||
1077 | 1079 | ||
1078 | return 0; | 1080 | return 0; |
1079 | } | 1081 | } |
1080 | 1082 | ||
1081 | static const struct seq_operations netlbladdr_seq_ops = { | 1083 | static const struct seq_operations net4addr_seq_ops = { |
1082 | .start = netlbladdr_seq_start, | 1084 | .start = net4addr_seq_start, |
1083 | .next = netlbladdr_seq_next, | 1085 | .next = net4addr_seq_next, |
1084 | .show = netlbladdr_seq_show, | 1086 | .show = net4addr_seq_show, |
1085 | .stop = smk_seq_stop, | 1087 | .stop = smk_seq_stop, |
1086 | }; | 1088 | }; |
1087 | 1089 | ||
1088 | /** | 1090 | /** |
1089 | * smk_open_netlbladdr - open() for /smack/netlabel | 1091 | * smk_open_net4addr - open() for /smack/netlabel |
1090 | * @inode: inode structure representing file | 1092 | * @inode: inode structure representing file |
1091 | * @file: "netlabel" file pointer | 1093 | * @file: "netlabel" file pointer |
1092 | * | 1094 | * |
1093 | * Connect our netlbladdr_seq_* operations with /smack/netlabel | 1095 | * Connect our net4addr_seq_* operations with /smack/netlabel |
1094 | * file_operations | 1096 | * file_operations |
1095 | */ | 1097 | */ |
1096 | static int smk_open_netlbladdr(struct inode *inode, struct file *file) | 1098 | static int smk_open_net4addr(struct inode *inode, struct file *file) |
1097 | { | 1099 | { |
1098 | return seq_open(file, &netlbladdr_seq_ops); | 1100 | return seq_open(file, &net4addr_seq_ops); |
1099 | } | 1101 | } |
1100 | 1102 | ||
1101 | /** | 1103 | /** |
1102 | * smk_netlbladdr_insert | 1104 | * smk_net4addr_insert |
1103 | * @new : netlabel to insert | 1105 | * @new : netlabel to insert |
1104 | * | 1106 | * |
1105 | * This helper insert netlabel in the smack_netlbladdrs list | 1107 | * This helper insert netlabel in the smack_net4addrs list |
1106 | * sorted by netmask length (longest to smallest) | 1108 | * sorted by netmask length (longest to smallest) |
1107 | * locked by &smk_netlbladdr_lock in smk_write_netlbladdr | 1109 | * locked by &smk_net4addr_lock in smk_write_net4addr |
1108 | * | 1110 | * |
1109 | */ | 1111 | */ |
1110 | static void smk_netlbladdr_insert(struct smk_netlbladdr *new) | 1112 | static void smk_net4addr_insert(struct smk_net4addr *new) |
1111 | { | 1113 | { |
1112 | struct smk_netlbladdr *m, *m_next; | 1114 | struct smk_net4addr *m; |
1115 | struct smk_net4addr *m_next; | ||
1113 | 1116 | ||
1114 | if (list_empty(&smk_netlbladdr_list)) { | 1117 | if (list_empty(&smk_net4addr_list)) { |
1115 | list_add_rcu(&new->list, &smk_netlbladdr_list); | 1118 | list_add_rcu(&new->list, &smk_net4addr_list); |
1116 | return; | 1119 | return; |
1117 | } | 1120 | } |
1118 | 1121 | ||
1119 | m = list_entry_rcu(smk_netlbladdr_list.next, | 1122 | m = list_entry_rcu(smk_net4addr_list.next, |
1120 | struct smk_netlbladdr, list); | 1123 | struct smk_net4addr, list); |
1121 | 1124 | ||
1122 | /* the comparison '>' is a bit hacky, but works */ | 1125 | /* the comparison '>' is a bit hacky, but works */ |
1123 | if (new->smk_mask.s_addr > m->smk_mask.s_addr) { | 1126 | if (new->smk_masks > m->smk_masks) { |
1124 | list_add_rcu(&new->list, &smk_netlbladdr_list); | 1127 | list_add_rcu(&new->list, &smk_net4addr_list); |
1125 | return; | 1128 | return; |
1126 | } | 1129 | } |
1127 | 1130 | ||
1128 | list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) { | 1131 | list_for_each_entry_rcu(m, &smk_net4addr_list, list) { |
1129 | if (list_is_last(&m->list, &smk_netlbladdr_list)) { | 1132 | if (list_is_last(&m->list, &smk_net4addr_list)) { |
1130 | list_add_rcu(&new->list, &m->list); | 1133 | list_add_rcu(&new->list, &m->list); |
1131 | return; | 1134 | return; |
1132 | } | 1135 | } |
1133 | m_next = list_entry_rcu(m->list.next, | 1136 | m_next = list_entry_rcu(m->list.next, |
1134 | struct smk_netlbladdr, list); | 1137 | struct smk_net4addr, list); |
1135 | if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) { | 1138 | if (new->smk_masks > m_next->smk_masks) { |
1136 | list_add_rcu(&new->list, &m->list); | 1139 | list_add_rcu(&new->list, &m->list); |
1137 | return; | 1140 | return; |
1138 | } | 1141 | } |
@@ -1141,28 +1144,29 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new) | |||
1141 | 1144 | ||
1142 | 1145 | ||
1143 | /** | 1146 | /** |
1144 | * smk_write_netlbladdr - write() for /smack/netlabel | 1147 | * smk_write_net4addr - write() for /smack/netlabel |
1145 | * @file: file pointer, not actually used | 1148 | * @file: file pointer, not actually used |
1146 | * @buf: where to get the data from | 1149 | * @buf: where to get the data from |
1147 | * @count: bytes sent | 1150 | * @count: bytes sent |
1148 | * @ppos: where to start | 1151 | * @ppos: where to start |
1149 | * | 1152 | * |
1150 | * Accepts only one netlbladdr per write call. | 1153 | * Accepts only one net4addr per write call. |
1151 | * Returns number of bytes written or error code, as appropriate | 1154 | * Returns number of bytes written or error code, as appropriate |
1152 | */ | 1155 | */ |
1153 | static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | 1156 | static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, |
1154 | size_t count, loff_t *ppos) | 1157 | size_t count, loff_t *ppos) |
1155 | { | 1158 | { |
1156 | struct smk_netlbladdr *snp; | 1159 | struct smk_net4addr *snp; |
1157 | struct sockaddr_in newname; | 1160 | struct sockaddr_in newname; |
1158 | char *smack; | 1161 | char *smack; |
1159 | struct smack_known *skp; | 1162 | struct smack_known *skp = NULL; |
1160 | char *data; | 1163 | char *data; |
1161 | char *host = (char *)&newname.sin_addr.s_addr; | 1164 | char *host = (char *)&newname.sin_addr.s_addr; |
1162 | int rc; | 1165 | int rc; |
1163 | struct netlbl_audit audit_info; | 1166 | struct netlbl_audit audit_info; |
1164 | struct in_addr mask; | 1167 | struct in_addr mask; |
1165 | unsigned int m; | 1168 | unsigned int m; |
1169 | unsigned int masks; | ||
1166 | int found; | 1170 | int found; |
1167 | u32 mask_bits = (1<<31); | 1171 | u32 mask_bits = (1<<31); |
1168 | __be32 nsa; | 1172 | __be32 nsa; |
@@ -1200,7 +1204,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1200 | data[count] = '\0'; | 1204 | data[count] = '\0'; |
1201 | 1205 | ||
1202 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s", | 1206 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s", |
1203 | &host[0], &host[1], &host[2], &host[3], &m, smack); | 1207 | &host[0], &host[1], &host[2], &host[3], &masks, smack); |
1204 | if (rc != 6) { | 1208 | if (rc != 6) { |
1205 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", | 1209 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", |
1206 | &host[0], &host[1], &host[2], &host[3], smack); | 1210 | &host[0], &host[1], &host[2], &host[3], smack); |
@@ -1209,8 +1213,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1209 | goto free_out; | 1213 | goto free_out; |
1210 | } | 1214 | } |
1211 | m = BEBITS; | 1215 | m = BEBITS; |
1216 | masks = 32; | ||
1212 | } | 1217 | } |
1213 | if (m > BEBITS) { | 1218 | if (masks > BEBITS) { |
1214 | rc = -EINVAL; | 1219 | rc = -EINVAL; |
1215 | goto free_out; | 1220 | goto free_out; |
1216 | } | 1221 | } |
@@ -1225,16 +1230,16 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1225 | goto free_out; | 1230 | goto free_out; |
1226 | } | 1231 | } |
1227 | } else { | 1232 | } else { |
1228 | /* check known options */ | 1233 | /* |
1229 | if (strcmp(smack, smack_cipso_option.smk_known) == 0) | 1234 | * Only the -CIPSO option is supported for IPv4 |
1230 | skp = &smack_cipso_option; | 1235 | */ |
1231 | else { | 1236 | if (strcmp(smack, SMACK_CIPSO_OPTION) != 0) { |
1232 | rc = -EINVAL; | 1237 | rc = -EINVAL; |
1233 | goto free_out; | 1238 | goto free_out; |
1234 | } | 1239 | } |
1235 | } | 1240 | } |
1236 | 1241 | ||
1237 | for (temp_mask = 0; m > 0; m--) { | 1242 | for (m = masks, temp_mask = 0; m > 0; m--) { |
1238 | temp_mask |= mask_bits; | 1243 | temp_mask |= mask_bits; |
1239 | mask_bits >>= 1; | 1244 | mask_bits >>= 1; |
1240 | } | 1245 | } |
@@ -1245,14 +1250,13 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1245 | * Only allow one writer at a time. Writes should be | 1250 | * Only allow one writer at a time. Writes should be |
1246 | * quite rare and small in any case. | 1251 | * quite rare and small in any case. |
1247 | */ | 1252 | */ |
1248 | mutex_lock(&smk_netlbladdr_lock); | 1253 | mutex_lock(&smk_net4addr_lock); |
1249 | 1254 | ||
1250 | nsa = newname.sin_addr.s_addr; | 1255 | nsa = newname.sin_addr.s_addr; |
1251 | /* try to find if the prefix is already in the list */ | 1256 | /* try to find if the prefix is already in the list */ |
1252 | found = 0; | 1257 | found = 0; |
1253 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) { | 1258 | list_for_each_entry_rcu(snp, &smk_net4addr_list, list) { |
1254 | if (snp->smk_host.sin_addr.s_addr == nsa && | 1259 | if (snp->smk_host.s_addr == nsa && snp->smk_masks == masks) { |
1255 | snp->smk_mask.s_addr == mask.s_addr) { | ||
1256 | found = 1; | 1260 | found = 1; |
1257 | break; | 1261 | break; |
1258 | } | 1262 | } |
@@ -1265,17 +1269,20 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1265 | rc = -ENOMEM; | 1269 | rc = -ENOMEM; |
1266 | else { | 1270 | else { |
1267 | rc = 0; | 1271 | rc = 0; |
1268 | snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; | 1272 | snp->smk_host.s_addr = newname.sin_addr.s_addr; |
1269 | snp->smk_mask.s_addr = mask.s_addr; | 1273 | snp->smk_mask.s_addr = mask.s_addr; |
1270 | snp->smk_label = skp; | 1274 | snp->smk_label = skp; |
1271 | smk_netlbladdr_insert(snp); | 1275 | snp->smk_masks = masks; |
1276 | smk_net4addr_insert(snp); | ||
1272 | } | 1277 | } |
1273 | } else { | 1278 | } else { |
1274 | /* we delete the unlabeled entry, only if the previous label | 1279 | /* |
1275 | * wasn't the special CIPSO option */ | 1280 | * Delete the unlabeled entry, only if the previous label |
1276 | if (snp->smk_label != &smack_cipso_option) | 1281 | * wasn't the special CIPSO option |
1282 | */ | ||
1283 | if (snp->smk_label != NULL) | ||
1277 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, | 1284 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, |
1278 | &snp->smk_host.sin_addr, &snp->smk_mask, | 1285 | &snp->smk_host, &snp->smk_mask, |
1279 | PF_INET, &audit_info); | 1286 | PF_INET, &audit_info); |
1280 | else | 1287 | else |
1281 | rc = 0; | 1288 | rc = 0; |
@@ -1287,15 +1294,15 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1287 | * this host so that incoming packets get labeled. | 1294 | * this host so that incoming packets get labeled. |
1288 | * but only if we didn't get the special CIPSO option | 1295 | * but only if we didn't get the special CIPSO option |
1289 | */ | 1296 | */ |
1290 | if (rc == 0 && skp != &smack_cipso_option) | 1297 | if (rc == 0 && skp != NULL) |
1291 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, | 1298 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, |
1292 | &snp->smk_host.sin_addr, &snp->smk_mask, PF_INET, | 1299 | &snp->smk_host, &snp->smk_mask, PF_INET, |
1293 | snp->smk_label->smk_secid, &audit_info); | 1300 | snp->smk_label->smk_secid, &audit_info); |
1294 | 1301 | ||
1295 | if (rc == 0) | 1302 | if (rc == 0) |
1296 | rc = count; | 1303 | rc = count; |
1297 | 1304 | ||
1298 | mutex_unlock(&smk_netlbladdr_lock); | 1305 | mutex_unlock(&smk_net4addr_lock); |
1299 | 1306 | ||
1300 | free_out: | 1307 | free_out: |
1301 | kfree(smack); | 1308 | kfree(smack); |
@@ -1305,14 +1312,279 @@ free_data_out: | |||
1305 | return rc; | 1312 | return rc; |
1306 | } | 1313 | } |
1307 | 1314 | ||
1308 | static const struct file_operations smk_netlbladdr_ops = { | 1315 | static const struct file_operations smk_net4addr_ops = { |
1309 | .open = smk_open_netlbladdr, | 1316 | .open = smk_open_net4addr, |
1310 | .read = seq_read, | 1317 | .read = seq_read, |
1311 | .llseek = seq_lseek, | 1318 | .llseek = seq_lseek, |
1312 | .write = smk_write_netlbladdr, | 1319 | .write = smk_write_net4addr, |
1313 | .release = seq_release, | 1320 | .release = seq_release, |
1314 | }; | 1321 | }; |
1315 | 1322 | ||
1323 | #if IS_ENABLED(CONFIG_IPV6) | ||
1324 | /* | ||
1325 | * Seq_file read operations for /smack/netlabel6 | ||
1326 | */ | ||
1327 | |||
1328 | static void *net6addr_seq_start(struct seq_file *s, loff_t *pos) | ||
1329 | { | ||
1330 | return smk_seq_start(s, pos, &smk_net6addr_list); | ||
1331 | } | ||
1332 | |||
1333 | static void *net6addr_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
1334 | { | ||
1335 | return smk_seq_next(s, v, pos, &smk_net6addr_list); | ||
1336 | } | ||
1337 | |||
1338 | /* | ||
1339 | * Print host/label pairs | ||
1340 | */ | ||
1341 | static int net6addr_seq_show(struct seq_file *s, void *v) | ||
1342 | { | ||
1343 | struct list_head *list = v; | ||
1344 | struct smk_net6addr *skp = | ||
1345 | list_entry(list, struct smk_net6addr, list); | ||
1346 | |||
1347 | if (skp->smk_label != NULL) | ||
1348 | seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, skp->smk_masks, | ||
1349 | skp->smk_label->smk_known); | ||
1350 | |||
1351 | return 0; | ||
1352 | } | ||
1353 | |||
1354 | static const struct seq_operations net6addr_seq_ops = { | ||
1355 | .start = net6addr_seq_start, | ||
1356 | .next = net6addr_seq_next, | ||
1357 | .show = net6addr_seq_show, | ||
1358 | .stop = smk_seq_stop, | ||
1359 | }; | ||
1360 | |||
1361 | /** | ||
1362 | * smk_open_net6addr - open() for /smack/netlabel | ||
1363 | * @inode: inode structure representing file | ||
1364 | * @file: "netlabel" file pointer | ||
1365 | * | ||
1366 | * Connect our net6addr_seq_* operations with /smack/netlabel | ||
1367 | * file_operations | ||
1368 | */ | ||
1369 | static int smk_open_net6addr(struct inode *inode, struct file *file) | ||
1370 | { | ||
1371 | return seq_open(file, &net6addr_seq_ops); | ||
1372 | } | ||
1373 | |||
1374 | /** | ||
1375 | * smk_net6addr_insert | ||
1376 | * @new : entry to insert | ||
1377 | * | ||
1378 | * This inserts an entry in the smack_net6addrs list | ||
1379 | * sorted by netmask length (longest to smallest) | ||
1380 | * locked by &smk_net6addr_lock in smk_write_net6addr | ||
1381 | * | ||
1382 | */ | ||
1383 | static void smk_net6addr_insert(struct smk_net6addr *new) | ||
1384 | { | ||
1385 | struct smk_net6addr *m_next; | ||
1386 | struct smk_net6addr *m; | ||
1387 | |||
1388 | if (list_empty(&smk_net6addr_list)) { | ||
1389 | list_add_rcu(&new->list, &smk_net6addr_list); | ||
1390 | return; | ||
1391 | } | ||
1392 | |||
1393 | m = list_entry_rcu(smk_net6addr_list.next, | ||
1394 | struct smk_net6addr, list); | ||
1395 | |||
1396 | if (new->smk_masks > m->smk_masks) { | ||
1397 | list_add_rcu(&new->list, &smk_net6addr_list); | ||
1398 | return; | ||
1399 | } | ||
1400 | |||
1401 | list_for_each_entry_rcu(m, &smk_net6addr_list, list) { | ||
1402 | if (list_is_last(&m->list, &smk_net6addr_list)) { | ||
1403 | list_add_rcu(&new->list, &m->list); | ||
1404 | return; | ||
1405 | } | ||
1406 | m_next = list_entry_rcu(m->list.next, | ||
1407 | struct smk_net6addr, list); | ||
1408 | if (new->smk_masks > m_next->smk_masks) { | ||
1409 | list_add_rcu(&new->list, &m->list); | ||
1410 | return; | ||
1411 | } | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | |||
1416 | /** | ||
1417 | * smk_write_net6addr - write() for /smack/netlabel | ||
1418 | * @file: file pointer, not actually used | ||
1419 | * @buf: where to get the data from | ||
1420 | * @count: bytes sent | ||
1421 | * @ppos: where to start | ||
1422 | * | ||
1423 | * Accepts only one net6addr per write call. | ||
1424 | * Returns number of bytes written or error code, as appropriate | ||
1425 | */ | ||
1426 | static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, | ||
1427 | size_t count, loff_t *ppos) | ||
1428 | { | ||
1429 | struct smk_net6addr *snp; | ||
1430 | struct in6_addr newname; | ||
1431 | struct in6_addr fullmask; | ||
1432 | struct smack_known *skp = NULL; | ||
1433 | char *smack; | ||
1434 | char *data; | ||
1435 | int rc = 0; | ||
1436 | int found = 0; | ||
1437 | int i; | ||
1438 | unsigned int scanned[8]; | ||
1439 | unsigned int m; | ||
1440 | unsigned int mask = 128; | ||
1441 | |||
1442 | /* | ||
1443 | * Must have privilege. | ||
1444 | * No partial writes. | ||
1445 | * Enough data must be present. | ||
1446 | * "<addr/mask, as a:b:c:d:e:f:g:h/e><space><label>" | ||
1447 | * "<addr, as a:b:c:d:e:f:g:h><space><label>" | ||
1448 | */ | ||
1449 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
1450 | return -EPERM; | ||
1451 | if (*ppos != 0) | ||
1452 | return -EINVAL; | ||
1453 | if (count < SMK_NETLBLADDRMIN) | ||
1454 | return -EINVAL; | ||
1455 | |||
1456 | data = kzalloc(count + 1, GFP_KERNEL); | ||
1457 | if (data == NULL) | ||
1458 | return -ENOMEM; | ||
1459 | |||
1460 | if (copy_from_user(data, buf, count) != 0) { | ||
1461 | rc = -EFAULT; | ||
1462 | goto free_data_out; | ||
1463 | } | ||
1464 | |||
1465 | smack = kzalloc(count + 1, GFP_KERNEL); | ||
1466 | if (smack == NULL) { | ||
1467 | rc = -ENOMEM; | ||
1468 | goto free_data_out; | ||
1469 | } | ||
1470 | |||
1471 | data[count] = '\0'; | ||
1472 | |||
1473 | i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x/%u %s", | ||
1474 | &scanned[0], &scanned[1], &scanned[2], &scanned[3], | ||
1475 | &scanned[4], &scanned[5], &scanned[6], &scanned[7], | ||
1476 | &mask, smack); | ||
1477 | if (i != 10) { | ||
1478 | i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x %s", | ||
1479 | &scanned[0], &scanned[1], &scanned[2], | ||
1480 | &scanned[3], &scanned[4], &scanned[5], | ||
1481 | &scanned[6], &scanned[7], smack); | ||
1482 | if (i != 9) { | ||
1483 | rc = -EINVAL; | ||
1484 | goto free_out; | ||
1485 | } | ||
1486 | } | ||
1487 | if (mask > 128) { | ||
1488 | rc = -EINVAL; | ||
1489 | goto free_out; | ||
1490 | } | ||
1491 | for (i = 0; i < 8; i++) { | ||
1492 | if (scanned[i] > 0xffff) { | ||
1493 | rc = -EINVAL; | ||
1494 | goto free_out; | ||
1495 | } | ||
1496 | newname.s6_addr16[i] = htons(scanned[i]); | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | * If smack begins with '-', it is an option, don't import it | ||
1501 | */ | ||
1502 | if (smack[0] != '-') { | ||
1503 | skp = smk_import_entry(smack, 0); | ||
1504 | if (skp == NULL) { | ||
1505 | rc = -EINVAL; | ||
1506 | goto free_out; | ||
1507 | } | ||
1508 | } else { | ||
1509 | /* | ||
1510 | * Only -DELETE is supported for IPv6 | ||
1511 | */ | ||
1512 | if (strcmp(smack, SMACK_DELETE_OPTION) != 0) { | ||
1513 | rc = -EINVAL; | ||
1514 | goto free_out; | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | for (i = 0, m = mask; i < 8; i++) { | ||
1519 | if (m >= 16) { | ||
1520 | fullmask.s6_addr16[i] = 0xffff; | ||
1521 | m -= 16; | ||
1522 | } else if (m > 0) { | ||
1523 | fullmask.s6_addr16[i] = (1 << m) - 1; | ||
1524 | m = 0; | ||
1525 | } else | ||
1526 | fullmask.s6_addr16[i] = 0; | ||
1527 | newname.s6_addr16[i] &= fullmask.s6_addr16[i]; | ||
1528 | } | ||
1529 | |||
1530 | /* | ||
1531 | * Only allow one writer at a time. Writes should be | ||
1532 | * quite rare and small in any case. | ||
1533 | */ | ||
1534 | mutex_lock(&smk_net6addr_lock); | ||
1535 | /* | ||
1536 | * Try to find the prefix in the list | ||
1537 | */ | ||
1538 | list_for_each_entry_rcu(snp, &smk_net6addr_list, list) { | ||
1539 | if (mask != snp->smk_masks) | ||
1540 | continue; | ||
1541 | for (found = 1, i = 0; i < 8; i++) { | ||
1542 | if (newname.s6_addr16[i] != | ||
1543 | snp->smk_host.s6_addr16[i]) { | ||
1544 | found = 0; | ||
1545 | break; | ||
1546 | } | ||
1547 | } | ||
1548 | if (found == 1) | ||
1549 | break; | ||
1550 | } | ||
1551 | if (found == 0) { | ||
1552 | snp = kzalloc(sizeof(*snp), GFP_KERNEL); | ||
1553 | if (snp == NULL) | ||
1554 | rc = -ENOMEM; | ||
1555 | else { | ||
1556 | snp->smk_host = newname; | ||
1557 | snp->smk_mask = fullmask; | ||
1558 | snp->smk_masks = mask; | ||
1559 | snp->smk_label = skp; | ||
1560 | smk_net6addr_insert(snp); | ||
1561 | } | ||
1562 | } else { | ||
1563 | snp->smk_label = skp; | ||
1564 | } | ||
1565 | |||
1566 | if (rc == 0) | ||
1567 | rc = count; | ||
1568 | |||
1569 | mutex_unlock(&smk_net6addr_lock); | ||
1570 | |||
1571 | free_out: | ||
1572 | kfree(smack); | ||
1573 | free_data_out: | ||
1574 | kfree(data); | ||
1575 | |||
1576 | return rc; | ||
1577 | } | ||
1578 | |||
1579 | static const struct file_operations smk_net6addr_ops = { | ||
1580 | .open = smk_open_net6addr, | ||
1581 | .read = seq_read, | ||
1582 | .llseek = seq_lseek, | ||
1583 | .write = smk_write_net6addr, | ||
1584 | .release = seq_release, | ||
1585 | }; | ||
1586 | #endif /* CONFIG_IPV6 */ | ||
1587 | |||
1316 | /** | 1588 | /** |
1317 | * smk_read_doi - read() for /smack/doi | 1589 | * smk_read_doi - read() for /smack/doi |
1318 | * @filp: file pointer, not actually used | 1590 | * @filp: file pointer, not actually used |
@@ -2320,11 +2592,7 @@ static const struct file_operations smk_revoke_subj_ops = { | |||
2320 | */ | 2592 | */ |
2321 | static int smk_init_sysfs(void) | 2593 | static int smk_init_sysfs(void) |
2322 | { | 2594 | { |
2323 | int err; | 2595 | return sysfs_create_mount_point(fs_kobj, "smackfs"); |
2324 | err = sysfs_create_mount_point(fs_kobj, "smackfs"); | ||
2325 | if (err) | ||
2326 | return err; | ||
2327 | return 0; | ||
2328 | } | 2596 | } |
2329 | 2597 | ||
2330 | /** | 2598 | /** |
@@ -2519,8 +2787,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2519 | "direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, | 2787 | "direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, |
2520 | [SMK_AMBIENT] = { | 2788 | [SMK_AMBIENT] = { |
2521 | "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 2789 | "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
2522 | [SMK_NETLBLADDR] = { | 2790 | [SMK_NET4ADDR] = { |
2523 | "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, | 2791 | "netlabel", &smk_net4addr_ops, S_IRUGO|S_IWUSR}, |
2524 | [SMK_ONLYCAP] = { | 2792 | [SMK_ONLYCAP] = { |
2525 | "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | 2793 | "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, |
2526 | [SMK_LOGGING] = { | 2794 | [SMK_LOGGING] = { |
@@ -2552,6 +2820,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2552 | [SMK_UNCONFINED] = { | 2820 | [SMK_UNCONFINED] = { |
2553 | "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR}, | 2821 | "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR}, |
2554 | #endif | 2822 | #endif |
2823 | #if IS_ENABLED(CONFIG_IPV6) | ||
2824 | [SMK_NET6ADDR] = { | ||
2825 | "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, | ||
2826 | #endif /* CONFIG_IPV6 */ | ||
2555 | /* last one */ | 2827 | /* last one */ |
2556 | {""} | 2828 | {""} |
2557 | }; | 2829 | }; |