diff options
-rw-r--r-- | include/net/netlabel.h | 6 | ||||
-rw-r--r-- | net/ipv6/calipso.c | 86 | ||||
-rw-r--r-- | net/netlabel/netlabel_calipso.c | 40 | ||||
-rw-r--r-- | net/netlabel/netlabel_calipso.h | 4 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 33 | ||||
-rw-r--r-- | security/selinux/netlabel.c | 2 |
6 files changed, 163 insertions, 8 deletions
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 918a6044c89c..a2408c30a7f7 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
@@ -229,6 +229,8 @@ struct netlbl_lsm_secattr { | |||
229 | * @sock_getattr: retrieve the socket's attr | 229 | * @sock_getattr: retrieve the socket's attr |
230 | * @sock_setattr: set the socket's attr | 230 | * @sock_setattr: set the socket's attr |
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 | ||
233 | * @req_delattr: remove the req socket's attr | ||
232 | * | 234 | * |
233 | * Description: | 235 | * Description: |
234 | * This structure is filled out by the CALIPSO engine and passed | 236 | * This structure is filled out by the CALIPSO engine and passed |
@@ -252,6 +254,10 @@ struct netlbl_calipso_ops { | |||
252 | const struct calipso_doi *doi_def, | 254 | const struct calipso_doi *doi_def, |
253 | const struct netlbl_lsm_secattr *secattr); | 255 | const struct netlbl_lsm_secattr *secattr); |
254 | void (*sock_delattr)(struct sock *sk); | 256 | void (*sock_delattr)(struct sock *sk); |
257 | int (*req_setattr)(struct request_sock *req, | ||
258 | const struct calipso_doi *doi_def, | ||
259 | const struct netlbl_lsm_secattr *secattr); | ||
260 | void (*req_delattr)(struct request_sock *req); | ||
255 | }; | 261 | }; |
256 | 262 | ||
257 | /* | 263 | /* |
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index 959db5268b38..067a5640ef17 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c | |||
@@ -889,6 +889,90 @@ done: | |||
889 | txopt_put(txopts); | 889 | txopt_put(txopts); |
890 | } | 890 | } |
891 | 891 | ||
892 | /* request sock functions. | ||
893 | */ | ||
894 | |||
895 | /** | ||
896 | * calipso_req_setattr - Add a CALIPSO option to a connection request socket | ||
897 | * @req: the connection request socket | ||
898 | * @doi_def: the CALIPSO DOI to use | ||
899 | * @secattr: the specific security attributes of the socket | ||
900 | * | ||
901 | * Description: | ||
902 | * Set the CALIPSO option on the given socket using the DOI definition and | ||
903 | * security attributes passed to the function. Returns zero on success and | ||
904 | * negative values on failure. | ||
905 | * | ||
906 | */ | ||
907 | static int calipso_req_setattr(struct request_sock *req, | ||
908 | const struct calipso_doi *doi_def, | ||
909 | const struct netlbl_lsm_secattr *secattr) | ||
910 | { | ||
911 | struct ipv6_txoptions *txopts; | ||
912 | struct inet_request_sock *req_inet = inet_rsk(req); | ||
913 | struct ipv6_opt_hdr *old, *new; | ||
914 | struct sock *sk = sk_to_full_sk(req_to_sk(req)); | ||
915 | |||
916 | if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt) | ||
917 | old = req_inet->ipv6_opt->hopopt; | ||
918 | else | ||
919 | old = NULL; | ||
920 | |||
921 | new = calipso_opt_insert(old, doi_def, secattr); | ||
922 | if (IS_ERR(new)) | ||
923 | return PTR_ERR(new); | ||
924 | |||
925 | txopts = ipv6_renew_options_kern(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, | ||
926 | new, new ? ipv6_optlen(new) : 0); | ||
927 | |||
928 | kfree(new); | ||
929 | |||
930 | if (IS_ERR(txopts)) | ||
931 | return PTR_ERR(txopts); | ||
932 | |||
933 | txopts = xchg(&req_inet->ipv6_opt, txopts); | ||
934 | if (txopts) { | ||
935 | atomic_sub(txopts->tot_len, &sk->sk_omem_alloc); | ||
936 | txopt_put(txopts); | ||
937 | } | ||
938 | |||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | /** | ||
943 | * calipso_req_delattr - Delete the CALIPSO option from a request socket | ||
944 | * @reg: the request socket | ||
945 | * | ||
946 | * Description: | ||
947 | * Removes the CALIPSO option from a request socket, if present. | ||
948 | * | ||
949 | */ | ||
950 | static void calipso_req_delattr(struct request_sock *req) | ||
951 | { | ||
952 | struct inet_request_sock *req_inet = inet_rsk(req); | ||
953 | struct ipv6_opt_hdr *new; | ||
954 | struct ipv6_txoptions *txopts; | ||
955 | struct sock *sk = sk_to_full_sk(req_to_sk(req)); | ||
956 | |||
957 | if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt) | ||
958 | return; | ||
959 | |||
960 | if (calipso_opt_del(req_inet->ipv6_opt->hopopt, &new)) | ||
961 | return; /* Nothing to do */ | ||
962 | |||
963 | txopts = ipv6_renew_options_kern(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, | ||
964 | new, new ? ipv6_optlen(new) : 0); | ||
965 | |||
966 | if (!IS_ERR(txopts)) { | ||
967 | txopts = xchg(&req_inet->ipv6_opt, txopts); | ||
968 | if (txopts) { | ||
969 | atomic_sub(txopts->tot_len, &sk->sk_omem_alloc); | ||
970 | txopt_put(txopts); | ||
971 | } | ||
972 | } | ||
973 | kfree(new); | ||
974 | } | ||
975 | |||
892 | static const struct netlbl_calipso_ops ops = { | 976 | static const struct netlbl_calipso_ops ops = { |
893 | .doi_add = calipso_doi_add, | 977 | .doi_add = calipso_doi_add, |
894 | .doi_free = calipso_doi_free, | 978 | .doi_free = calipso_doi_free, |
@@ -899,6 +983,8 @@ static const struct netlbl_calipso_ops ops = { | |||
899 | .sock_getattr = calipso_sock_getattr, | 983 | .sock_getattr = calipso_sock_getattr, |
900 | .sock_setattr = calipso_sock_setattr, | 984 | .sock_setattr = calipso_sock_setattr, |
901 | .sock_delattr = calipso_sock_delattr, | 985 | .sock_delattr = calipso_sock_delattr, |
986 | .req_setattr = calipso_req_setattr, | ||
987 | .req_delattr = calipso_req_delattr, | ||
902 | }; | 988 | }; |
903 | 989 | ||
904 | /** | 990 | /** |
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c index 6f9c6589a022..79519e3a6a93 100644 --- a/net/netlabel/netlabel_calipso.c +++ b/net/netlabel/netlabel_calipso.c | |||
@@ -578,3 +578,43 @@ void calipso_sock_delattr(struct sock *sk) | |||
578 | if (ops) | 578 | if (ops) |
579 | ops->sock_delattr(sk); | 579 | ops->sock_delattr(sk); |
580 | } | 580 | } |
581 | |||
582 | /** | ||
583 | * calipso_req_setattr - Add a CALIPSO option to a connection request socket | ||
584 | * @req: the connection request socket | ||
585 | * @doi_def: the CALIPSO DOI to use | ||
586 | * @secattr: the specific security attributes of the socket | ||
587 | * | ||
588 | * Description: | ||
589 | * Set the CALIPSO option on the given socket using the DOI definition and | ||
590 | * security attributes passed to the function. Returns zero on success and | ||
591 | * negative values on failure. | ||
592 | * | ||
593 | */ | ||
594 | int calipso_req_setattr(struct request_sock *req, | ||
595 | const struct calipso_doi *doi_def, | ||
596 | const struct netlbl_lsm_secattr *secattr) | ||
597 | { | ||
598 | int ret_val = -ENOMSG; | ||
599 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
600 | |||
601 | if (ops) | ||
602 | ret_val = ops->req_setattr(req, doi_def, secattr); | ||
603 | return ret_val; | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * calipso_req_delattr - Delete the CALIPSO option from a request socket | ||
608 | * @reg: the request socket | ||
609 | * | ||
610 | * Description: | ||
611 | * Removes the CALIPSO option from a request socket, if present. | ||
612 | * | ||
613 | */ | ||
614 | void calipso_req_delattr(struct request_sock *req) | ||
615 | { | ||
616 | const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); | ||
617 | |||
618 | if (ops) | ||
619 | ops->req_delattr(req); | ||
620 | } | ||
diff --git a/net/netlabel/netlabel_calipso.h b/net/netlabel/netlabel_calipso.h index 49bc116705c4..1372fdd86588 100644 --- a/net/netlabel/netlabel_calipso.h +++ b/net/netlabel/netlabel_calipso.h | |||
@@ -133,5 +133,9 @@ int calipso_sock_setattr(struct sock *sk, | |||
133 | const struct calipso_doi *doi_def, | 133 | const struct calipso_doi *doi_def, |
134 | const struct netlbl_lsm_secattr *secattr); | 134 | const struct netlbl_lsm_secattr *secattr); |
135 | void calipso_sock_delattr(struct sock *sk); | 135 | void calipso_sock_delattr(struct sock *sk); |
136 | int calipso_req_setattr(struct request_sock *req, | ||
137 | const struct calipso_doi *doi_def, | ||
138 | const struct netlbl_lsm_secattr *secattr); | ||
139 | void calipso_req_delattr(struct request_sock *req); | ||
136 | 140 | ||
137 | #endif | 141 | #endif |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 00bab51c291e..9b725f75c750 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -1053,12 +1053,13 @@ int netlbl_req_setattr(struct request_sock *req, | |||
1053 | { | 1053 | { |
1054 | int ret_val; | 1054 | int ret_val; |
1055 | struct netlbl_dommap_def *entry; | 1055 | struct netlbl_dommap_def *entry; |
1056 | struct inet_request_sock *ireq = inet_rsk(req); | ||
1056 | 1057 | ||
1057 | rcu_read_lock(); | 1058 | rcu_read_lock(); |
1058 | switch (req->rsk_ops->family) { | 1059 | switch (req->rsk_ops->family) { |
1059 | case AF_INET: | 1060 | case AF_INET: |
1060 | entry = netlbl_domhsh_getentry_af4(secattr->domain, | 1061 | entry = netlbl_domhsh_getentry_af4(secattr->domain, |
1061 | inet_rsk(req)->ir_rmt_addr); | 1062 | ireq->ir_rmt_addr); |
1062 | if (entry == NULL) { | 1063 | if (entry == NULL) { |
1063 | ret_val = -ENOENT; | 1064 | ret_val = -ENOENT; |
1064 | goto req_setattr_return; | 1065 | goto req_setattr_return; |
@@ -1069,9 +1070,7 @@ int netlbl_req_setattr(struct request_sock *req, | |||
1069 | entry->cipso, secattr); | 1070 | entry->cipso, secattr); |
1070 | break; | 1071 | break; |
1071 | case NETLBL_NLTYPE_UNLABELED: | 1072 | case NETLBL_NLTYPE_UNLABELED: |
1072 | /* just delete the protocols we support for right now | 1073 | netlbl_req_delattr(req); |
1073 | * but we could remove other protocols if needed */ | ||
1074 | cipso_v4_req_delattr(req); | ||
1075 | ret_val = 0; | 1074 | ret_val = 0; |
1076 | break; | 1075 | break; |
1077 | default: | 1076 | default: |
@@ -1080,9 +1079,24 @@ int netlbl_req_setattr(struct request_sock *req, | |||
1080 | break; | 1079 | break; |
1081 | #if IS_ENABLED(CONFIG_IPV6) | 1080 | #if IS_ENABLED(CONFIG_IPV6) |
1082 | case AF_INET6: | 1081 | case AF_INET6: |
1083 | /* since we don't support any IPv6 labeling protocols right | 1082 | entry = netlbl_domhsh_getentry_af6(secattr->domain, |
1084 | * now we can optimize everything away until we do */ | 1083 | &ireq->ir_v6_rmt_addr); |
1085 | ret_val = 0; | 1084 | if (entry == NULL) { |
1085 | ret_val = -ENOENT; | ||
1086 | goto req_setattr_return; | ||
1087 | } | ||
1088 | switch (entry->type) { | ||
1089 | case NETLBL_NLTYPE_CALIPSO: | ||
1090 | ret_val = calipso_req_setattr(req, | ||
1091 | entry->calipso, secattr); | ||
1092 | break; | ||
1093 | case NETLBL_NLTYPE_UNLABELED: | ||
1094 | netlbl_req_delattr(req); | ||
1095 | ret_val = 0; | ||
1096 | break; | ||
1097 | default: | ||
1098 | ret_val = -ENOENT; | ||
1099 | } | ||
1086 | break; | 1100 | break; |
1087 | #endif /* IPv6 */ | 1101 | #endif /* IPv6 */ |
1088 | default: | 1102 | default: |
@@ -1108,6 +1122,11 @@ void netlbl_req_delattr(struct request_sock *req) | |||
1108 | case AF_INET: | 1122 | case AF_INET: |
1109 | cipso_v4_req_delattr(req); | 1123 | cipso_v4_req_delattr(req); |
1110 | break; | 1124 | break; |
1125 | #if IS_ENABLED(CONFIG_IPV6) | ||
1126 | case AF_INET6: | ||
1127 | calipso_req_delattr(req); | ||
1128 | break; | ||
1129 | #endif /* IPv6 */ | ||
1111 | } | 1130 | } |
1112 | } | 1131 | } |
1113 | 1132 | ||
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2477a75f16e7..ca220c3fbcf9 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -284,7 +284,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) | |||
284 | int rc; | 284 | int rc; |
285 | struct netlbl_lsm_secattr secattr; | 285 | struct netlbl_lsm_secattr secattr; |
286 | 286 | ||
287 | if (family != PF_INET) | 287 | if (family != PF_INET && family != PF_INET6) |
288 | return 0; | 288 | return 0; |
289 | 289 | ||
290 | netlbl_secattr_init(&secattr); | 290 | netlbl_secattr_init(&secattr); |