diff options
| -rw-r--r-- | include/net/netlabel.h | 11 | ||||
| -rw-r--r-- | net/ipv6/calipso.c | 165 | ||||
| -rw-r--r-- | net/netlabel/netlabel_calipso.c | 82 | ||||
| -rw-r--r-- | net/netlabel/netlabel_calipso.h | 7 | ||||
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 32 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 15 |
6 files changed, 308 insertions, 4 deletions
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index a2408c30a7f7..e0e4ce8f22af 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
| @@ -231,6 +231,10 @@ struct netlbl_lsm_secattr { | |||
| 231 | * @sock_delattr: remove the socket's attr | 231 | * @sock_delattr: remove the socket's attr |
| 232 | * @req_setattr: set the req socket's attr | 232 | * @req_setattr: set the req socket's attr |
| 233 | * @req_delattr: remove the req socket's attr | 233 | * @req_delattr: remove the req socket's attr |
| 234 | * @opt_getattr: retrieve attr from memory block | ||
| 235 | * @skbuff_optptr: find option in packet | ||
| 236 | * @skbuff_setattr: set the skbuff's attr | ||
| 237 | * @skbuff_delattr: remove the skbuff's attr | ||
| 234 | * | 238 | * |
| 235 | * Description: | 239 | * Description: |
| 236 | * This structure is filled out by the CALIPSO engine and passed | 240 | * This structure is filled out by the CALIPSO engine and passed |
| @@ -258,6 +262,13 @@ struct netlbl_calipso_ops { | |||
| 258 | const struct calipso_doi *doi_def, | 262 | const struct calipso_doi *doi_def, |
| 259 | const struct netlbl_lsm_secattr *secattr); | 263 | const struct netlbl_lsm_secattr *secattr); |
| 260 | void (*req_delattr)(struct request_sock *req); | 264 | void (*req_delattr)(struct request_sock *req); |
| 265 | int (*opt_getattr)(const unsigned char *calipso, | ||
| 266 | struct netlbl_lsm_secattr *secattr); | ||
| 267 | unsigned char *(*skbuff_optptr)(const struct sk_buff *skb); | ||
| 268 | int (*skbuff_setattr)(struct sk_buff *skb, | ||
| 269 | const struct calipso_doi *doi_def, | ||
| 270 | const struct netlbl_lsm_secattr *secattr); | ||
| 271 | int (*skbuff_delattr)(struct sk_buff *skb); | ||
| 261 | }; | 272 | }; |
| 262 | 273 | ||
| 263 | /* | 274 | /* |
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index 067a5640ef17..fa371a8827cf 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c | |||
| @@ -62,6 +62,11 @@ | |||
| 62 | */ | 62 | */ |
| 63 | #define CALIPSO_OPT_LEN_MAX_WITH_PAD (3 + CALIPSO_OPT_LEN_MAX + 7) | 63 | #define CALIPSO_OPT_LEN_MAX_WITH_PAD (3 + CALIPSO_OPT_LEN_MAX + 7) |
| 64 | 64 | ||
| 65 | /* Maximium size of u32 aligned buffer required to hold calipso | ||
| 66 | * option. Max of 3 initial pad bytes starting from buffer + 3. | ||
| 67 | * i.e. the worst case is when the previous tlv finishes on 4n + 3. | ||
| 68 | */ | ||
| 69 | #define CALIPSO_MAX_BUFFER (6 + CALIPSO_OPT_LEN_MAX) | ||
| 65 | 70 | ||
| 66 | /* List of available DOI definitions */ | 71 | /* List of available DOI definitions */ |
| 67 | static DEFINE_SPINLOCK(calipso_doi_list_lock); | 72 | static DEFINE_SPINLOCK(calipso_doi_list_lock); |
| @@ -973,6 +978,162 @@ static void calipso_req_delattr(struct request_sock *req) | |||
| 973 | kfree(new); | 978 | kfree(new); |
| 974 | } | 979 | } |
| 975 | 980 | ||
| 981 | /* skbuff functions. | ||
| 982 | */ | ||
| 983 | |||
| 984 | /** | ||
| 985 | * calipso_skbuff_optptr - Find the CALIPSO option in the packet | ||
| 986 | * @skb: the packet | ||
| 987 | * | ||
| 988 | * Description: | ||
| 989 | * Parse the packet's IP header looking for a CALIPSO option. Returns a pointer | ||
| 990 | * to the start of the CALIPSO option on success, NULL if one if not found. | ||
| 991 | * | ||
| 992 | */ | ||
| 993 | static unsigned char *calipso_skbuff_optptr(const struct sk_buff *skb) | ||
| 994 | { | ||
| 995 | const struct ipv6hdr *ip6_hdr = ipv6_hdr(skb); | ||
| 996 | int offset; | ||
| 997 | |||
| 998 | if (ip6_hdr->nexthdr != NEXTHDR_HOP) | ||
| 999 | return NULL; | ||
| 1000 | |||
| 1001 | offset = ipv6_find_tlv(skb, sizeof(*ip6_hdr), IPV6_TLV_CALIPSO); | ||
| 1002 | if (offset >= 0) | ||
| 1003 | return (unsigned char *)ip6_hdr + offset; | ||
| 1004 | |||
| 1005 | return NULL; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /** | ||
| 1009 | * calipso_skbuff_setattr - Set the CALIPSO option on a packet | ||
| 1010 | * @skb: the packet | ||
| 1011 | * @doi_def: the CALIPSO DOI to use | ||
| 1012 | * @secattr: the security attributes | ||
| 1013 | * | ||
| 1014 | * Description: | ||
| 1015 | * Set the CALIPSO option on the given packet based on the security attributes. | ||
| 1016 | * Returns a pointer to the IP header on success and NULL on failure. | ||
| 1017 | * | ||
| 1018 | */ | ||
| 1019 | static int calipso_skbuff_setattr(struct sk_buff *skb, | ||
| 1020 | const struct calipso_doi *doi_def, | ||
| 1021 | const struct netlbl_lsm_secattr *secattr) | ||
| 1022 | { | ||
| 1023 | int ret_val; | ||
| 1024 | struct ipv6hdr *ip6_hdr; | ||
| 1025 | struct ipv6_opt_hdr *hop; | ||
| 1026 | unsigned char buf[CALIPSO_MAX_BUFFER]; | ||
| 1027 | int len_delta, new_end, pad; | ||
| 1028 | unsigned int start, end; | ||
| 1029 | |||
| 1030 | ip6_hdr = ipv6_hdr(skb); | ||
| 1031 | if (ip6_hdr->nexthdr == NEXTHDR_HOP) { | ||
| 1032 | hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); | ||
| 1033 | ret_val = calipso_opt_find(hop, &start, &end); | ||
| 1034 | if (ret_val && ret_val != -ENOENT) | ||
| 1035 | return ret_val; | ||
| 1036 | } else { | ||
| 1037 | start = 0; | ||
| 1038 | end = 0; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | memset(buf, 0, sizeof(buf)); | ||
| 1042 | ret_val = calipso_genopt(buf, start & 3, sizeof(buf), doi_def, secattr); | ||
| 1043 | if (ret_val < 0) | ||
| 1044 | return ret_val; | ||
| 1045 | |||
| 1046 | new_end = start + ret_val; | ||
| 1047 | /* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */ | ||
| 1048 | pad = ((new_end & 4) + (end & 7)) & 7; | ||
| 1049 | len_delta = new_end - (int)end + pad; | ||
| 1050 | ret_val = skb_cow(skb, skb_headroom(skb) + len_delta); | ||
| 1051 | if (ret_val < 0) | ||
| 1052 | return ret_val; | ||
| 1053 | |||
| 1054 | if (len_delta) { | ||
| 1055 | if (len_delta > 0) | ||
| 1056 | skb_push(skb, len_delta); | ||
| 1057 | else | ||
| 1058 | skb_pull(skb, -len_delta); | ||
| 1059 | memmove((char *)ip6_hdr - len_delta, ip6_hdr, | ||
| 1060 | sizeof(*ip6_hdr) + start); | ||
| 1061 | skb_reset_network_header(skb); | ||
| 1062 | ip6_hdr = ipv6_hdr(skb); | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); | ||
| 1066 | if (start == 0) { | ||
| 1067 | struct ipv6_opt_hdr *new_hop = (struct ipv6_opt_hdr *)buf; | ||
| 1068 | |||
| 1069 | new_hop->nexthdr = ip6_hdr->nexthdr; | ||
| 1070 | new_hop->hdrlen = len_delta / 8 - 1; | ||
| 1071 | ip6_hdr->nexthdr = NEXTHDR_HOP; | ||
| 1072 | } else { | ||
| 1073 | hop->hdrlen += len_delta / 8; | ||
| 1074 | } | ||
| 1075 | memcpy((char *)hop + start, buf + (start & 3), new_end - start); | ||
| 1076 | calipso_pad_write((unsigned char *)hop, new_end, pad); | ||
| 1077 | |||
| 1078 | return 0; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /** | ||
| 1082 | * calipso_skbuff_delattr - Delete any CALIPSO options from a packet | ||
| 1083 | * @skb: the packet | ||
| 1084 | * | ||
| 1085 | * Description: | ||
| 1086 | * Removes any and all CALIPSO options from the given packet. Returns zero on | ||
| 1087 | * success, negative values on failure. | ||
| 1088 | * | ||
| 1089 | */ | ||
| 1090 | static int calipso_skbuff_delattr(struct sk_buff *skb) | ||
| 1091 | { | ||
| 1092 | int ret_val; | ||
| 1093 | struct ipv6hdr *ip6_hdr; | ||
| 1094 | struct ipv6_opt_hdr *old_hop; | ||
| 1095 | u32 old_hop_len, start = 0, end = 0, delta, size, pad; | ||
| 1096 | |||
| 1097 | if (!calipso_skbuff_optptr(skb)) | ||
| 1098 | return 0; | ||
| 1099 | |||
| 1100 | /* since we are changing the packet we should make a copy */ | ||
| 1101 | ret_val = skb_cow(skb, skb_headroom(skb)); | ||
| 1102 | if (ret_val < 0) | ||
| 1103 | return ret_val; | ||
| 1104 | |||
| 1105 | ip6_hdr = ipv6_hdr(skb); | ||
| 1106 | old_hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); | ||
| 1107 | old_hop_len = ipv6_optlen(old_hop); | ||
| 1108 | |||
| 1109 | ret_val = calipso_opt_find(old_hop, &start, &end); | ||
| 1110 | if (ret_val) | ||
| 1111 | return ret_val; | ||
| 1112 | |||
| 1113 | if (start == sizeof(*old_hop) && end == old_hop_len) { | ||
| 1114 | /* There's no other option in the header so we delete | ||
| 1115 | * the whole thing. */ | ||
| 1116 | delta = old_hop_len; | ||
| 1117 | size = sizeof(*ip6_hdr); | ||
| 1118 | ip6_hdr->nexthdr = old_hop->nexthdr; | ||
| 1119 | } else { | ||
| 1120 | delta = (end - start) & ~7; | ||
| 1121 | if (delta) | ||
| 1122 | old_hop->hdrlen -= delta / 8; | ||
| 1123 | pad = (end - start) & 7; | ||
| 1124 | size = sizeof(*ip6_hdr) + start + pad; | ||
| 1125 | calipso_pad_write((unsigned char *)old_hop, start, pad); | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | if (delta) { | ||
| 1129 | skb_pull(skb, delta); | ||
| 1130 | memmove((char *)ip6_hdr + delta, ip6_hdr, size); | ||
| 1131 | skb_reset_network_header(skb); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | return 0; | ||
| 1135 | } | ||
| 1136 | |||
| 976 | static const struct netlbl_calipso_ops ops = { | 1137 | static const struct netlbl_calipso_ops ops = { |
| 977 | .doi_add = calipso_doi_add, | 1138 | .doi_add = calipso_doi_add, |
| 978 | .doi_free = calipso_doi_free, | 1139 | .doi_free = calipso_doi_free, |
| @@ -985,6 +1146,10 @@ static const struct netlbl_calipso_ops ops = { | |||
| 985 | .sock_delattr = calipso_sock_delattr, | 1146 | .sock_delattr = calipso_sock_delattr, |
| 986 | .req_setattr = calipso_req_setattr, | 1147 | .req_setattr = calipso_req_setattr, |
| 987 | .req_delattr = calipso_req_delattr, | 1148 | .req_delattr = calipso_req_delattr, |
| 1149 | .opt_getattr = calipso_opt_getattr, | ||
| 1150 | .skbuff_optptr = calipso_skbuff_optptr, | ||
| 1151 | .skbuff_setattr = calipso_skbuff_setattr, | ||
| 1152 | .skbuff_delattr = calipso_skbuff_delattr, | ||
| 988 | }; | 1153 | }; |
| 989 | 1154 | ||
| 990 | /** | 1155 | /** |
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c index 79519e3a6a93..0d02c262dbf6 100644 --- a/net/netlabel/netlabel_calipso.c +++ b/net/netlabel/netlabel_calipso.c | |||
| @@ -618,3 +618,85 @@ void calipso_req_delattr(struct request_sock *req) | |||
| 618 | if (ops) | 618 | if (ops) |
| 619 | ops->req_delattr(req); | 619 | ops->req_delattr(req); |
| 620 | } | 620 | } |
| 621 | |||
| 622 | /** | ||
| 623 | * calipso_optptr - Find the CALIPSO option in the packet | ||
| 624 | * @skb: the packet | ||
| 625 | * | ||
| 626 | * Description: | ||
| 627 | * Parse the packet's IP header looking for a CALIPSO option. Returns a pointer | ||
| 628 | * to the start of the CALIPSO option on success, NULL if one if not found. | ||
| 629 | * | ||
| 630 | */ | ||
| 631 | unsigned char *calipso_optptr(const struct sk_buff *skb) | ||
| 632 | { | ||
| 633 | unsigned char *ret_val = NULL; | ||
| 634 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
| 635 | |||
| 636 | if (ops) | ||
| 637 | ret_val = ops->skbuff_optptr(skb); | ||
| 638 | return ret_val; | ||
| 639 | } | ||
| 640 | |||
| 641 | /** | ||
| 642 | * calipso_getattr - Get the security attributes from a memory block. | ||
| 643 | * @calipso: the CALIPSO option | ||
| 644 | * @secattr: the security attributes | ||
| 645 | * | ||
| 646 | * Description: | ||
| 647 | * Inspect @calipso and return the security attributes in @secattr. | ||
| 648 | * Returns zero on success and negative values on failure. | ||
| 649 | * | ||
| 650 | */ | ||
| 651 | int calipso_getattr(const unsigned char *calipso, | ||
| 652 | struct netlbl_lsm_secattr *secattr) | ||
| 653 | { | ||
| 654 | int ret_val = -ENOMSG; | ||
| 655 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
| 656 | |||
| 657 | if (ops) | ||
| 658 | ret_val = ops->opt_getattr(calipso, secattr); | ||
| 659 | return ret_val; | ||
| 660 | } | ||
| 661 | |||
| 662 | /** | ||
| 663 | * calipso_skbuff_setattr - Set the CALIPSO option on a packet | ||
| 664 | * @skb: the packet | ||
| 665 | * @doi_def: the CALIPSO DOI to use | ||
| 666 | * @secattr: the security attributes | ||
| 667 | * | ||
| 668 | * Description: | ||
| 669 | * Set the CALIPSO option on the given packet based on the security attributes. | ||
| 670 | * Returns a pointer to the IP header on success and NULL on failure. | ||
| 671 | * | ||
| 672 | */ | ||
| 673 | int calipso_skbuff_setattr(struct sk_buff *skb, | ||
| 674 | const struct calipso_doi *doi_def, | ||
| 675 | const struct netlbl_lsm_secattr *secattr) | ||
| 676 | { | ||
| 677 | int ret_val = -ENOMSG; | ||
| 678 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
| 679 | |||
| 680 | if (ops) | ||
| 681 | ret_val = ops->skbuff_setattr(skb, doi_def, secattr); | ||
| 682 | return ret_val; | ||
| 683 | } | ||
| 684 | |||
| 685 | /** | ||
| 686 | * calipso_skbuff_delattr - Delete any CALIPSO options from a packet | ||
| 687 | * @skb: the packet | ||
| 688 | * | ||
| 689 | * Description: | ||
| 690 | * Removes any and all CALIPSO options from the given packet. Returns zero on | ||
| 691 | * success, negative values on failure. | ||
| 692 | * | ||
| 693 | */ | ||
| 694 | int calipso_skbuff_delattr(struct sk_buff *skb) | ||
| 695 | { | ||
| 696 | int ret_val = -ENOMSG; | ||
| 697 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
| 698 | |||
| 699 | if (ops) | ||
| 700 | ret_val = ops->skbuff_delattr(skb); | ||
| 701 | return ret_val; | ||
| 702 | } | ||
diff --git a/net/netlabel/netlabel_calipso.h b/net/netlabel/netlabel_calipso.h index 1372fdd86588..66ba92e9289f 100644 --- a/net/netlabel/netlabel_calipso.h +++ b/net/netlabel/netlabel_calipso.h | |||
| @@ -137,5 +137,12 @@ int calipso_req_setattr(struct request_sock *req, | |||
| 137 | const struct calipso_doi *doi_def, | 137 | const struct calipso_doi *doi_def, |
| 138 | const struct netlbl_lsm_secattr *secattr); | 138 | const struct netlbl_lsm_secattr *secattr); |
| 139 | void calipso_req_delattr(struct request_sock *req); | 139 | void calipso_req_delattr(struct request_sock *req); |
| 140 | unsigned char *calipso_optptr(const struct sk_buff *skb); | ||
| 141 | int calipso_getattr(const unsigned char *calipso, | ||
| 142 | struct netlbl_lsm_secattr *secattr); | ||
| 143 | int calipso_skbuff_setattr(struct sk_buff *skb, | ||
| 144 | const struct calipso_doi *doi_def, | ||
| 145 | const struct netlbl_lsm_secattr *secattr); | ||
| 146 | int calipso_skbuff_delattr(struct sk_buff *skb); | ||
| 140 | 147 | ||
| 141 | #endif | 148 | #endif |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 9b725f75c750..c50a1c5d1e1a 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -1147,13 +1147,17 @@ int netlbl_skbuff_setattr(struct sk_buff *skb, | |||
| 1147 | { | 1147 | { |
| 1148 | int ret_val; | 1148 | int ret_val; |
| 1149 | struct iphdr *hdr4; | 1149 | struct iphdr *hdr4; |
| 1150 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 1151 | struct ipv6hdr *hdr6; | ||
| 1152 | #endif | ||
| 1150 | struct netlbl_dommap_def *entry; | 1153 | struct netlbl_dommap_def *entry; |
| 1151 | 1154 | ||
| 1152 | rcu_read_lock(); | 1155 | rcu_read_lock(); |
| 1153 | switch (family) { | 1156 | switch (family) { |
| 1154 | case AF_INET: | 1157 | case AF_INET: |
| 1155 | hdr4 = ip_hdr(skb); | 1158 | hdr4 = ip_hdr(skb); |
| 1156 | entry = netlbl_domhsh_getentry_af4(secattr->domain,hdr4->daddr); | 1159 | entry = netlbl_domhsh_getentry_af4(secattr->domain, |
| 1160 | hdr4->daddr); | ||
| 1157 | if (entry == NULL) { | 1161 | if (entry == NULL) { |
| 1158 | ret_val = -ENOENT; | 1162 | ret_val = -ENOENT; |
| 1159 | goto skbuff_setattr_return; | 1163 | goto skbuff_setattr_return; |
| @@ -1174,9 +1178,26 @@ int netlbl_skbuff_setattr(struct sk_buff *skb, | |||
| 1174 | break; | 1178 | break; |
| 1175 | #if IS_ENABLED(CONFIG_IPV6) | 1179 | #if IS_ENABLED(CONFIG_IPV6) |
| 1176 | case AF_INET6: | 1180 | case AF_INET6: |
| 1177 | /* since we don't support any IPv6 labeling protocols right | 1181 | hdr6 = ipv6_hdr(skb); |
| 1178 | * now we can optimize everything away until we do */ | 1182 | entry = netlbl_domhsh_getentry_af6(secattr->domain, |
| 1179 | ret_val = 0; | 1183 | &hdr6->daddr); |
| 1184 | if (entry == NULL) { | ||
| 1185 | ret_val = -ENOENT; | ||
| 1186 | goto skbuff_setattr_return; | ||
| 1187 | } | ||
| 1188 | switch (entry->type) { | ||
| 1189 | case NETLBL_NLTYPE_CALIPSO: | ||
| 1190 | ret_val = calipso_skbuff_setattr(skb, entry->calipso, | ||
| 1191 | secattr); | ||
| 1192 | break; | ||
| 1193 | case NETLBL_NLTYPE_UNLABELED: | ||
| 1194 | /* just delete the protocols we support for right now | ||
| 1195 | * but we could remove other protocols if needed */ | ||
| 1196 | ret_val = calipso_skbuff_delattr(skb); | ||
| 1197 | break; | ||
| 1198 | default: | ||
| 1199 | ret_val = -ENOENT; | ||
| 1200 | } | ||
| 1180 | break; | 1201 | break; |
| 1181 | #endif /* IPv6 */ | 1202 | #endif /* IPv6 */ |
| 1182 | default: | 1203 | default: |
| @@ -1215,6 +1236,9 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
| 1215 | break; | 1236 | break; |
| 1216 | #if IS_ENABLED(CONFIG_IPV6) | 1237 | #if IS_ENABLED(CONFIG_IPV6) |
| 1217 | case AF_INET6: | 1238 | case AF_INET6: |
| 1239 | ptr = calipso_optptr(skb); | ||
| 1240 | if (ptr && calipso_getattr(ptr, secattr) == 0) | ||
| 1241 | return 0; | ||
| 1218 | break; | 1242 | break; |
| 1219 | #endif /* IPv6 */ | 1243 | #endif /* IPv6 */ |
| 1220 | } | 1244 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a00ab81ab719..cb7c5c8028e7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -5063,6 +5063,15 @@ static unsigned int selinux_ipv4_output(void *priv, | |||
| 5063 | return selinux_ip_output(skb, PF_INET); | 5063 | return selinux_ip_output(skb, PF_INET); |
| 5064 | } | 5064 | } |
| 5065 | 5065 | ||
| 5066 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 5067 | static unsigned int selinux_ipv6_output(void *priv, | ||
| 5068 | struct sk_buff *skb, | ||
| 5069 | const struct nf_hook_state *state) | ||
| 5070 | { | ||
| 5071 | return selinux_ip_output(skb, PF_INET6); | ||
| 5072 | } | ||
| 5073 | #endif /* IPV6 */ | ||
| 5074 | |||
| 5066 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | 5075 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, |
| 5067 | int ifindex, | 5076 | int ifindex, |
| 5068 | u16 family) | 5077 | u16 family) |
| @@ -6297,6 +6306,12 @@ static struct nf_hook_ops selinux_nf_ops[] = { | |||
| 6297 | .hooknum = NF_INET_FORWARD, | 6306 | .hooknum = NF_INET_FORWARD, |
| 6298 | .priority = NF_IP6_PRI_SELINUX_FIRST, | 6307 | .priority = NF_IP6_PRI_SELINUX_FIRST, |
| 6299 | }, | 6308 | }, |
| 6309 | { | ||
| 6310 | .hook = selinux_ipv6_output, | ||
| 6311 | .pf = NFPROTO_IPV6, | ||
| 6312 | .hooknum = NF_INET_LOCAL_OUT, | ||
| 6313 | .priority = NF_IP6_PRI_SELINUX_FIRST, | ||
| 6314 | }, | ||
| 6300 | #endif /* IPV6 */ | 6315 | #endif /* IPV6 */ |
| 6301 | }; | 6316 | }; |
| 6302 | 6317 | ||
