diff options
author | Richard Haines <richard_c_haines@btinternet.com> | 2018-02-13 15:56:24 -0500 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2018-02-26 17:45:23 -0500 |
commit | 2277c7cd75e39783eeb7512a6c35f8b4abbe1039 (patch) | |
tree | 247a9b36acd431330a479ccdcb9b277f0b4d4973 /net/sctp | |
parent | b7e10c25b839c0c7579b2b402afc9883c107e09f (diff) |
sctp: Add LSM hooks
Add security hooks allowing security modules to exercise access control
over SCTP.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 12 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 18 | ||||
-rw-r--r-- | net/sctp/socket.c | 62 |
3 files changed, 91 insertions, 1 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index d01475f5f710..70274ae5ac6f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -3071,6 +3071,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
3071 | if (af->is_any(&addr)) | 3071 | if (af->is_any(&addr)) |
3072 | memcpy(&addr, &asconf->source, sizeof(addr)); | 3072 | memcpy(&addr, &asconf->source, sizeof(addr)); |
3073 | 3073 | ||
3074 | if (security_sctp_bind_connect(asoc->ep->base.sk, | ||
3075 | SCTP_PARAM_ADD_IP, | ||
3076 | (struct sockaddr *)&addr, | ||
3077 | af->sockaddr_len)) | ||
3078 | return SCTP_ERROR_REQ_REFUSED; | ||
3079 | |||
3074 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address | 3080 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address |
3075 | * request and does not have the local resources to add this | 3081 | * request and does not have the local resources to add this |
3076 | * new address to the association, it MUST return an Error | 3082 | * new address to the association, it MUST return an Error |
@@ -3137,6 +3143,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
3137 | if (af->is_any(&addr)) | 3143 | if (af->is_any(&addr)) |
3138 | memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); | 3144 | memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); |
3139 | 3145 | ||
3146 | if (security_sctp_bind_connect(asoc->ep->base.sk, | ||
3147 | SCTP_PARAM_SET_PRIMARY, | ||
3148 | (struct sockaddr *)&addr, | ||
3149 | af->sockaddr_len)) | ||
3150 | return SCTP_ERROR_REQ_REFUSED; | ||
3151 | |||
3140 | peer = sctp_assoc_lookup_paddr(asoc, &addr); | 3152 | peer = sctp_assoc_lookup_paddr(asoc, &addr); |
3141 | if (!peer) | 3153 | if (!peer) |
3142 | return SCTP_ERROR_DNS_FAILED; | 3154 | return SCTP_ERROR_DNS_FAILED; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index eb7905ffe5f2..42659ab68c38 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -321,6 +321,11 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, | |||
321 | struct sctp_packet *packet; | 321 | struct sctp_packet *packet; |
322 | int len; | 322 | int len; |
323 | 323 | ||
324 | /* Update socket peer label if first association. */ | ||
325 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
326 | chunk->skb)) | ||
327 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
328 | |||
324 | /* 6.10 Bundling | 329 | /* 6.10 Bundling |
325 | * An endpoint MUST NOT bundle INIT, INIT ACK or | 330 | * An endpoint MUST NOT bundle INIT, INIT ACK or |
326 | * SHUTDOWN COMPLETE with any other chunks. | 331 | * SHUTDOWN COMPLETE with any other chunks. |
@@ -908,6 +913,9 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net, | |||
908 | */ | 913 | */ |
909 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | 914 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
910 | 915 | ||
916 | /* Set peer label for connection. */ | ||
917 | security_inet_conn_established(ep->base.sk, chunk->skb); | ||
918 | |||
911 | /* RFC 2960 5.1 Normal Establishment of an Association | 919 | /* RFC 2960 5.1 Normal Establishment of an Association |
912 | * | 920 | * |
913 | * E) Upon reception of the COOKIE ACK, endpoint "A" will move | 921 | * E) Upon reception of the COOKIE ACK, endpoint "A" will move |
@@ -1436,6 +1444,11 @@ static enum sctp_disposition sctp_sf_do_unexpected_init( | |||
1436 | struct sctp_packet *packet; | 1444 | struct sctp_packet *packet; |
1437 | int len; | 1445 | int len; |
1438 | 1446 | ||
1447 | /* Update socket peer label if first association. */ | ||
1448 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
1449 | chunk->skb)) | ||
1450 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
1451 | |||
1439 | /* 6.10 Bundling | 1452 | /* 6.10 Bundling |
1440 | * An endpoint MUST NOT bundle INIT, INIT ACK or | 1453 | * An endpoint MUST NOT bundle INIT, INIT ACK or |
1441 | * SHUTDOWN COMPLETE with any other chunks. | 1454 | * SHUTDOWN COMPLETE with any other chunks. |
@@ -2106,6 +2119,11 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook( | |||
2106 | } | 2119 | } |
2107 | } | 2120 | } |
2108 | 2121 | ||
2122 | /* Update socket peer label if first association. */ | ||
2123 | if (security_sctp_assoc_request((struct sctp_endpoint *)ep, | ||
2124 | chunk->skb)) | ||
2125 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
2126 | |||
2109 | /* Set temp so that it won't be added into hashtable */ | 2127 | /* Set temp so that it won't be added into hashtable */ |
2110 | new_asoc->temp = 1; | 2128 | new_asoc->temp = 1; |
2111 | 2129 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index eb55c63d1990..73b34a6b5b09 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1043,6 +1043,12 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1043 | /* Do the work. */ | 1043 | /* Do the work. */ |
1044 | switch (op) { | 1044 | switch (op) { |
1045 | case SCTP_BINDX_ADD_ADDR: | 1045 | case SCTP_BINDX_ADD_ADDR: |
1046 | /* Allow security module to validate bindx addresses. */ | ||
1047 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD, | ||
1048 | (struct sockaddr *)kaddrs, | ||
1049 | addrs_size); | ||
1050 | if (err) | ||
1051 | goto out; | ||
1046 | err = sctp_bindx_add(sk, kaddrs, addrcnt); | 1052 | err = sctp_bindx_add(sk, kaddrs, addrcnt); |
1047 | if (err) | 1053 | if (err) |
1048 | goto out; | 1054 | goto out; |
@@ -1252,6 +1258,7 @@ static int __sctp_connect(struct sock *sk, | |||
1252 | 1258 | ||
1253 | if (assoc_id) | 1259 | if (assoc_id) |
1254 | *assoc_id = asoc->assoc_id; | 1260 | *assoc_id = asoc->assoc_id; |
1261 | |||
1255 | err = sctp_wait_for_connect(asoc, &timeo); | 1262 | err = sctp_wait_for_connect(asoc, &timeo); |
1256 | /* Note: the asoc may be freed after the return of | 1263 | /* Note: the asoc may be freed after the return of |
1257 | * sctp_wait_for_connect. | 1264 | * sctp_wait_for_connect. |
@@ -1347,7 +1354,16 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1347 | if (unlikely(IS_ERR(kaddrs))) | 1354 | if (unlikely(IS_ERR(kaddrs))) |
1348 | return PTR_ERR(kaddrs); | 1355 | return PTR_ERR(kaddrs); |
1349 | 1356 | ||
1357 | /* Allow security module to validate connectx addresses. */ | ||
1358 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX, | ||
1359 | (struct sockaddr *)kaddrs, | ||
1360 | addrs_size); | ||
1361 | if (err) | ||
1362 | goto out_free; | ||
1363 | |||
1350 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); | 1364 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1365 | |||
1366 | out_free: | ||
1351 | kvfree(kaddrs); | 1367 | kvfree(kaddrs); |
1352 | 1368 | ||
1353 | return err; | 1369 | return err; |
@@ -1615,6 +1631,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
1615 | struct sctp_transport *transport, *chunk_tp; | 1631 | struct sctp_transport *transport, *chunk_tp; |
1616 | struct sctp_chunk *chunk; | 1632 | struct sctp_chunk *chunk; |
1617 | union sctp_addr to; | 1633 | union sctp_addr to; |
1634 | struct sctp_af *af; | ||
1618 | struct sockaddr *msg_name = NULL; | 1635 | struct sockaddr *msg_name = NULL; |
1619 | struct sctp_sndrcvinfo default_sinfo; | 1636 | struct sctp_sndrcvinfo default_sinfo; |
1620 | struct sctp_sndrcvinfo *sinfo; | 1637 | struct sctp_sndrcvinfo *sinfo; |
@@ -1844,6 +1861,24 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
1844 | } | 1861 | } |
1845 | 1862 | ||
1846 | scope = sctp_scope(&to); | 1863 | scope = sctp_scope(&to); |
1864 | |||
1865 | /* Label connection socket for first association 1-to-many | ||
1866 | * style for client sequence socket()->sendmsg(). This | ||
1867 | * needs to be done before sctp_assoc_add_peer() as that will | ||
1868 | * set up the initial packet that needs to account for any | ||
1869 | * security ip options (CIPSO/CALIPSO) added to the packet. | ||
1870 | */ | ||
1871 | af = sctp_get_af_specific(to.sa.sa_family); | ||
1872 | if (!af) { | ||
1873 | err = -EINVAL; | ||
1874 | goto out_unlock; | ||
1875 | } | ||
1876 | err = security_sctp_bind_connect(sk, SCTP_SENDMSG_CONNECT, | ||
1877 | (struct sockaddr *)&to, | ||
1878 | af->sockaddr_len); | ||
1879 | if (err < 0) | ||
1880 | goto out_unlock; | ||
1881 | |||
1847 | new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | 1882 | new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
1848 | if (!new_asoc) { | 1883 | if (!new_asoc) { |
1849 | err = -ENOMEM; | 1884 | err = -ENOMEM; |
@@ -2909,6 +2944,8 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2909 | { | 2944 | { |
2910 | struct sctp_prim prim; | 2945 | struct sctp_prim prim; |
2911 | struct sctp_transport *trans; | 2946 | struct sctp_transport *trans; |
2947 | struct sctp_af *af; | ||
2948 | int err; | ||
2912 | 2949 | ||
2913 | if (optlen != sizeof(struct sctp_prim)) | 2950 | if (optlen != sizeof(struct sctp_prim)) |
2914 | return -EINVAL; | 2951 | return -EINVAL; |
@@ -2916,6 +2953,17 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2916 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) | 2953 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) |
2917 | return -EFAULT; | 2954 | return -EFAULT; |
2918 | 2955 | ||
2956 | /* Allow security module to validate address but need address len. */ | ||
2957 | af = sctp_get_af_specific(prim.ssp_addr.ss_family); | ||
2958 | if (!af) | ||
2959 | return -EINVAL; | ||
2960 | |||
2961 | err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR, | ||
2962 | (struct sockaddr *)&prim.ssp_addr, | ||
2963 | af->sockaddr_len); | ||
2964 | if (err) | ||
2965 | return err; | ||
2966 | |||
2919 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); | 2967 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); |
2920 | if (!trans) | 2968 | if (!trans) |
2921 | return -EINVAL; | 2969 | return -EINVAL; |
@@ -3247,6 +3295,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
3247 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) | 3295 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) |
3248 | return -EADDRNOTAVAIL; | 3296 | return -EADDRNOTAVAIL; |
3249 | 3297 | ||
3298 | /* Allow security module to validate address. */ | ||
3299 | err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR, | ||
3300 | (struct sockaddr *)&prim.sspp_addr, | ||
3301 | af->sockaddr_len); | ||
3302 | if (err) | ||
3303 | return err; | ||
3304 | |||
3250 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ | 3305 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ |
3251 | chunk = sctp_make_asconf_set_prim(asoc, | 3306 | chunk = sctp_make_asconf_set_prim(asoc, |
3252 | (union sctp_addr *)&prim.sspp_addr); | 3307 | (union sctp_addr *)&prim.sspp_addr); |
@@ -8346,6 +8401,8 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8346 | { | 8401 | { |
8347 | struct inet_sock *inet = inet_sk(sk); | 8402 | struct inet_sock *inet = inet_sk(sk); |
8348 | struct inet_sock *newinet; | 8403 | struct inet_sock *newinet; |
8404 | struct sctp_sock *sp = sctp_sk(sk); | ||
8405 | struct sctp_endpoint *ep = sp->ep; | ||
8349 | 8406 | ||
8350 | newsk->sk_type = sk->sk_type; | 8407 | newsk->sk_type = sk->sk_type; |
8351 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | 8408 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; |
@@ -8388,7 +8445,10 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8388 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) | 8445 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) |
8389 | net_enable_timestamp(); | 8446 | net_enable_timestamp(); |
8390 | 8447 | ||
8391 | security_sk_clone(sk, newsk); | 8448 | /* Set newsk security attributes from orginal sk and connection |
8449 | * security attribute from ep. | ||
8450 | */ | ||
8451 | security_sctp_sk_clone(ep, sk, newsk); | ||
8392 | } | 8452 | } |
8393 | 8453 | ||
8394 | static inline void sctp_copy_descendant(struct sock *sk_to, | 8454 | static inline void sctp_copy_descendant(struct sock *sk_to, |