diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7a10ae3c3d82..2a2e094560de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1046,6 +1046,12 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
1046 | /* Do the work. */ | 1046 | /* Do the work. */ |
1047 | switch (op) { | 1047 | switch (op) { |
1048 | case SCTP_BINDX_ADD_ADDR: | 1048 | case SCTP_BINDX_ADD_ADDR: |
1049 | /* Allow security module to validate bindx addresses. */ | ||
1050 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD, | ||
1051 | (struct sockaddr *)kaddrs, | ||
1052 | addrs_size); | ||
1053 | if (err) | ||
1054 | goto out; | ||
1049 | err = sctp_bindx_add(sk, kaddrs, addrcnt); | 1055 | err = sctp_bindx_add(sk, kaddrs, addrcnt); |
1050 | if (err) | 1056 | if (err) |
1051 | goto out; | 1057 | goto out; |
@@ -1255,6 +1261,7 @@ static int __sctp_connect(struct sock *sk, | |||
1255 | 1261 | ||
1256 | if (assoc_id) | 1262 | if (assoc_id) |
1257 | *assoc_id = asoc->assoc_id; | 1263 | *assoc_id = asoc->assoc_id; |
1264 | |||
1258 | err = sctp_wait_for_connect(asoc, &timeo); | 1265 | err = sctp_wait_for_connect(asoc, &timeo); |
1259 | /* Note: the asoc may be freed after the return of | 1266 | /* Note: the asoc may be freed after the return of |
1260 | * sctp_wait_for_connect. | 1267 | * sctp_wait_for_connect. |
@@ -1350,7 +1357,16 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1350 | if (unlikely(IS_ERR(kaddrs))) | 1357 | if (unlikely(IS_ERR(kaddrs))) |
1351 | return PTR_ERR(kaddrs); | 1358 | return PTR_ERR(kaddrs); |
1352 | 1359 | ||
1360 | /* Allow security module to validate connectx addresses. */ | ||
1361 | err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX, | ||
1362 | (struct sockaddr *)kaddrs, | ||
1363 | addrs_size); | ||
1364 | if (err) | ||
1365 | goto out_free; | ||
1366 | |||
1353 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); | 1367 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1368 | |||
1369 | out_free: | ||
1354 | kvfree(kaddrs); | 1370 | kvfree(kaddrs); |
1355 | 1371 | ||
1356 | return err; | 1372 | return err; |
@@ -1680,6 +1696,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, | |||
1680 | struct sctp_association *asoc; | 1696 | struct sctp_association *asoc; |
1681 | enum sctp_scope scope; | 1697 | enum sctp_scope scope; |
1682 | struct cmsghdr *cmsg; | 1698 | struct cmsghdr *cmsg; |
1699 | struct sctp_af *af; | ||
1683 | int err; | 1700 | int err; |
1684 | 1701 | ||
1685 | *tp = NULL; | 1702 | *tp = NULL; |
@@ -1705,6 +1722,21 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, | |||
1705 | 1722 | ||
1706 | scope = sctp_scope(daddr); | 1723 | scope = sctp_scope(daddr); |
1707 | 1724 | ||
1725 | /* Label connection socket for first association 1-to-many | ||
1726 | * style for client sequence socket()->sendmsg(). This | ||
1727 | * needs to be done before sctp_assoc_add_peer() as that will | ||
1728 | * set up the initial packet that needs to account for any | ||
1729 | * security ip options (CIPSO/CALIPSO) added to the packet. | ||
1730 | */ | ||
1731 | af = sctp_get_af_specific(daddr->sa.sa_family); | ||
1732 | if (!af) | ||
1733 | return -EINVAL; | ||
1734 | err = security_sctp_bind_connect(sk, SCTP_SENDMSG_CONNECT, | ||
1735 | (struct sockaddr *)daddr, | ||
1736 | af->sockaddr_len); | ||
1737 | if (err < 0) | ||
1738 | return err; | ||
1739 | |||
1708 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | 1740 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
1709 | if (!asoc) | 1741 | if (!asoc) |
1710 | return -ENOMEM; | 1742 | return -ENOMEM; |
@@ -2932,6 +2964,8 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2932 | { | 2964 | { |
2933 | struct sctp_prim prim; | 2965 | struct sctp_prim prim; |
2934 | struct sctp_transport *trans; | 2966 | struct sctp_transport *trans; |
2967 | struct sctp_af *af; | ||
2968 | int err; | ||
2935 | 2969 | ||
2936 | if (optlen != sizeof(struct sctp_prim)) | 2970 | if (optlen != sizeof(struct sctp_prim)) |
2937 | return -EINVAL; | 2971 | return -EINVAL; |
@@ -2939,6 +2973,17 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, | |||
2939 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) | 2973 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) |
2940 | return -EFAULT; | 2974 | return -EFAULT; |
2941 | 2975 | ||
2976 | /* Allow security module to validate address but need address len. */ | ||
2977 | af = sctp_get_af_specific(prim.ssp_addr.ss_family); | ||
2978 | if (!af) | ||
2979 | return -EINVAL; | ||
2980 | |||
2981 | err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR, | ||
2982 | (struct sockaddr *)&prim.ssp_addr, | ||
2983 | af->sockaddr_len); | ||
2984 | if (err) | ||
2985 | return err; | ||
2986 | |||
2942 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); | 2987 | trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); |
2943 | if (!trans) | 2988 | if (!trans) |
2944 | return -EINVAL; | 2989 | return -EINVAL; |
@@ -3161,6 +3206,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign | |||
3161 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) | 3206 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) |
3162 | { | 3207 | { |
3163 | struct sctp_sock *sp = sctp_sk(sk); | 3208 | struct sctp_sock *sp = sctp_sk(sk); |
3209 | struct sctp_af *af = sp->pf->af; | ||
3164 | struct sctp_assoc_value params; | 3210 | struct sctp_assoc_value params; |
3165 | struct sctp_association *asoc; | 3211 | struct sctp_association *asoc; |
3166 | int val; | 3212 | int val; |
@@ -3185,7 +3231,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned | |||
3185 | if (val) { | 3231 | if (val) { |
3186 | int min_len, max_len; | 3232 | int min_len, max_len; |
3187 | 3233 | ||
3188 | min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len; | 3234 | min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len; |
3235 | min_len -= af->ip_options_len(sk); | ||
3189 | min_len -= sizeof(struct sctphdr) + | 3236 | min_len -= sizeof(struct sctphdr) + |
3190 | sizeof(struct sctp_data_chunk); | 3237 | sizeof(struct sctp_data_chunk); |
3191 | 3238 | ||
@@ -3198,7 +3245,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned | |||
3198 | asoc = sctp_id2assoc(sk, params.assoc_id); | 3245 | asoc = sctp_id2assoc(sk, params.assoc_id); |
3199 | if (asoc) { | 3246 | if (asoc) { |
3200 | if (val == 0) { | 3247 | if (val == 0) { |
3201 | val = asoc->pathmtu - sp->pf->af->net_header_len; | 3248 | val = asoc->pathmtu - af->net_header_len; |
3249 | val -= af->ip_options_len(sk); | ||
3202 | val -= sizeof(struct sctphdr) + | 3250 | val -= sizeof(struct sctphdr) + |
3203 | sctp_datachk_len(&asoc->stream); | 3251 | sctp_datachk_len(&asoc->stream); |
3204 | } | 3252 | } |
@@ -3267,6 +3315,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
3267 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) | 3315 | if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) |
3268 | return -EADDRNOTAVAIL; | 3316 | return -EADDRNOTAVAIL; |
3269 | 3317 | ||
3318 | /* Allow security module to validate address. */ | ||
3319 | err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR, | ||
3320 | (struct sockaddr *)&prim.sspp_addr, | ||
3321 | af->sockaddr_len); | ||
3322 | if (err) | ||
3323 | return err; | ||
3324 | |||
3270 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ | 3325 | /* Create an ASCONF chunk with SET_PRIMARY parameter */ |
3271 | chunk = sctp_make_asconf_set_prim(asoc, | 3326 | chunk = sctp_make_asconf_set_prim(asoc, |
3272 | (union sctp_addr *)&prim.sspp_addr); | 3327 | (union sctp_addr *)&prim.sspp_addr); |
@@ -5140,9 +5195,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) | |||
5140 | sctp_copy_sock(sock->sk, sk, asoc); | 5195 | sctp_copy_sock(sock->sk, sk, asoc); |
5141 | 5196 | ||
5142 | /* Make peeled-off sockets more like 1-1 accepted sockets. | 5197 | /* Make peeled-off sockets more like 1-1 accepted sockets. |
5143 | * Set the daddr and initialize id to something more random | 5198 | * Set the daddr and initialize id to something more random and also |
5199 | * copy over any ip options. | ||
5144 | */ | 5200 | */ |
5145 | sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); | 5201 | sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); |
5202 | sp->pf->copy_ip_options(sk, sock->sk); | ||
5146 | 5203 | ||
5147 | /* Populate the fields of the newsk from the oldsk and migrate the | 5204 | /* Populate the fields of the newsk from the oldsk and migrate the |
5148 | * asoc to the newsk. | 5205 | * asoc to the newsk. |
@@ -8465,6 +8522,8 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8465 | { | 8522 | { |
8466 | struct inet_sock *inet = inet_sk(sk); | 8523 | struct inet_sock *inet = inet_sk(sk); |
8467 | struct inet_sock *newinet; | 8524 | struct inet_sock *newinet; |
8525 | struct sctp_sock *sp = sctp_sk(sk); | ||
8526 | struct sctp_endpoint *ep = sp->ep; | ||
8468 | 8527 | ||
8469 | newsk->sk_type = sk->sk_type; | 8528 | newsk->sk_type = sk->sk_type; |
8470 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | 8529 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; |
@@ -8507,7 +8566,10 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
8507 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) | 8566 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) |
8508 | net_enable_timestamp(); | 8567 | net_enable_timestamp(); |
8509 | 8568 | ||
8510 | security_sk_clone(sk, newsk); | 8569 | /* Set newsk security attributes from orginal sk and connection |
8570 | * security attribute from ep. | ||
8571 | */ | ||
8572 | security_sctp_sk_clone(ep, sk, newsk); | ||
8511 | } | 8573 | } |
8512 | 8574 | ||
8513 | static inline void sctp_copy_descendant(struct sock *sk_to, | 8575 | static inline void sctp_copy_descendant(struct sock *sk_to, |