aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/associola.c9
-rw-r--r--net/sctp/auth.c7
-rw-r--r--net/sctp/endpointola.c4
-rw-r--r--net/sctp/ipv6.c3
-rw-r--r--net/sctp/output.c3
-rw-r--r--net/sctp/sm_make_chunk.c52
-rw-r--r--net/sctp/sm_statefuns.c48
-rw-r--r--net/sctp/socket.c96
8 files changed, 162 insertions, 60 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8472b8b349c4..abd51cef2413 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
599 /* Check to see if this is a duplicate. */ 599 /* Check to see if this is a duplicate. */
600 peer = sctp_assoc_lookup_paddr(asoc, addr); 600 peer = sctp_assoc_lookup_paddr(asoc, addr);
601 if (peer) { 601 if (peer) {
602 /* An UNKNOWN state is only set on transports added by
603 * user in sctp_connectx() call. Such transports should be
604 * considered CONFIRMED per RFC 4960, Section 5.4.
605 */
602 if (peer->state == SCTP_UNKNOWN) { 606 if (peer->state == SCTP_UNKNOWN) {
603 if (peer_state == SCTP_ACTIVE) 607 peer->state = SCTP_ACTIVE;
604 peer->state = SCTP_ACTIVE;
605 if (peer_state == SCTP_UNCONFIRMED)
606 peer->state = SCTP_UNCONFIRMED;
607 } 608 }
608 return peer; 609 return peer;
609 } 610 }
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 675a5c3e68a6..52db5f60daa0 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -80,6 +80,10 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp)
80{ 80{
81 struct sctp_auth_bytes *key; 81 struct sctp_auth_bytes *key;
82 82
83 /* Verify that we are not going to overflow INT_MAX */
84 if ((INT_MAX - key_len) < sizeof(struct sctp_auth_bytes))
85 return NULL;
86
83 /* Allocate the shared key */ 87 /* Allocate the shared key */
84 key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp); 88 key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp);
85 if (!key) 89 if (!key)
@@ -782,6 +786,9 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
782 for (i = 0; i < hmacs->shmac_num_idents; i++) { 786 for (i = 0; i < hmacs->shmac_num_idents; i++) {
783 id = hmacs->shmac_idents[i]; 787 id = hmacs->shmac_idents[i];
784 788
789 if (id > SCTP_AUTH_HMAC_ID_MAX)
790 return -EOPNOTSUPP;
791
785 if (SCTP_AUTH_HMAC_ID_SHA1 == id) 792 if (SCTP_AUTH_HMAC_ID_SHA1 == id)
786 has_sha1 = 1; 793 has_sha1 = 1;
787 794
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index e39a0cdef184..4c8d9f45ce09 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -103,6 +103,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
103 103
104 /* Initialize the CHUNKS parameter */ 104 /* Initialize the CHUNKS parameter */
105 auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; 105 auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
106 auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t));
106 107
107 /* If the Add-IP functionality is enabled, we must 108 /* If the Add-IP functionality is enabled, we must
108 * authenticate, ASCONF and ASCONF-ACK chunks 109 * authenticate, ASCONF and ASCONF-ACK chunks
@@ -110,8 +111,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
110 if (sctp_addip_enable) { 111 if (sctp_addip_enable) {
111 auth_chunks->chunks[0] = SCTP_CID_ASCONF; 112 auth_chunks->chunks[0] = SCTP_CID_ASCONF;
112 auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; 113 auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
113 auth_chunks->param_hdr.length = 114 auth_chunks->param_hdr.length += htons(2);
114 htons(sizeof(sctp_paramhdr_t) + 2);
115 } 115 }
116 } 116 }
117 117
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 483a01d0740a..47f91afa0211 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk,
319 __func__, asoc, dst, NIP6(daddr->v6.sin6_addr)); 319 __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
320 320
321 if (!asoc) { 321 if (!asoc) {
322 ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, 322 ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)),
323 dst ? ip6_dst_idev(dst)->dev : NULL,
323 &daddr->v6.sin6_addr, 324 &daddr->v6.sin6_addr,
324 inet6_sk(&sk->inet.sk)->srcprefs, 325 inet6_sk(&sk->inet.sk)->srcprefs,
325 &saddr->v6.sin6_addr); 326 &saddr->v6.sin6_addr);
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 0dc4a7dfb234..225c7123c41f 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
533 if (!(dst->dev->features & NETIF_F_NO_CSUM)) { 533 if (!(dst->dev->features & NETIF_F_NO_CSUM)) {
534 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); 534 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
535 crc32 = sctp_end_cksum(crc32); 535 crc32 = sctp_end_cksum(crc32);
536 } 536 } else
537 nskb->ip_summed = CHECKSUM_UNNECESSARY;
537 538
538 /* 3) Put the resultant value into the checksum field in the 539 /* 3) Put the resultant value into the checksum field in the
539 * common header, and leave the rest of the bits unchanged. 540 * common header, and leave the rest of the bits unchanged.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index e8ca4e54981f..d68869f966c3 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1012,6 +1012,29 @@ end:
1012 return retval; 1012 return retval;
1013} 1013}
1014 1014
1015struct sctp_chunk *sctp_make_violation_paramlen(
1016 const struct sctp_association *asoc,
1017 const struct sctp_chunk *chunk,
1018 struct sctp_paramhdr *param)
1019{
1020 struct sctp_chunk *retval;
1021 static const char error[] = "The following parameter had invalid length:";
1022 size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) +
1023 sizeof(sctp_paramhdr_t);
1024
1025 retval = sctp_make_abort(asoc, chunk, payload_len);
1026 if (!retval)
1027 goto nodata;
1028
1029 sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION,
1030 sizeof(error) + sizeof(sctp_paramhdr_t));
1031 sctp_addto_chunk(retval, sizeof(error), error);
1032 sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
1033
1034nodata:
1035 return retval;
1036}
1037
1015/* Make a HEARTBEAT chunk. */ 1038/* Make a HEARTBEAT chunk. */
1016struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, 1039struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
1017 const struct sctp_transport *transport, 1040 const struct sctp_transport *transport,
@@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
1782 const struct sctp_chunk *chunk, 1805 const struct sctp_chunk *chunk,
1783 struct sctp_chunk **errp) 1806 struct sctp_chunk **errp)
1784{ 1807{
1785 static const char error[] = "The following parameter had invalid length:";
1786 size_t payload_len = WORD_ROUND(sizeof(error)) +
1787 sizeof(sctp_paramhdr_t);
1788
1789
1790 /* This is a fatal error. Any accumulated non-fatal errors are 1808 /* This is a fatal error. Any accumulated non-fatal errors are
1791 * not reported. 1809 * not reported.
1792 */ 1810 */
@@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
1794 sctp_chunk_free(*errp); 1812 sctp_chunk_free(*errp);
1795 1813
1796 /* Create an error chunk and fill it in with our payload. */ 1814 /* Create an error chunk and fill it in with our payload. */
1797 *errp = sctp_make_op_error_space(asoc, chunk, payload_len); 1815 *errp = sctp_make_violation_paramlen(asoc, chunk, param);
1798
1799 if (*errp) {
1800 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
1801 sizeof(error) + sizeof(sctp_paramhdr_t));
1802 sctp_addto_chunk(*errp, sizeof(error), error);
1803 sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);
1804 }
1805 1816
1806 return 0; 1817 return 0;
1807} 1818}
@@ -1886,11 +1897,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
1886 /* if the peer reports AUTH, assume that he 1897 /* if the peer reports AUTH, assume that he
1887 * supports AUTH. 1898 * supports AUTH.
1888 */ 1899 */
1889 asoc->peer.auth_capable = 1; 1900 if (sctp_auth_enable)
1901 asoc->peer.auth_capable = 1;
1890 break; 1902 break;
1891 case SCTP_CID_ASCONF: 1903 case SCTP_CID_ASCONF:
1892 case SCTP_CID_ASCONF_ACK: 1904 case SCTP_CID_ASCONF_ACK:
1893 asoc->peer.asconf_capable = 1; 1905 if (sctp_addip_enable)
1906 asoc->peer.asconf_capable = 1;
1894 break; 1907 break;
1895 default: 1908 default:
1896 break; 1909 break;
@@ -2319,12 +2332,10 @@ clean_up:
2319 /* Release the transport structures. */ 2332 /* Release the transport structures. */
2320 list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { 2333 list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
2321 transport = list_entry(pos, struct sctp_transport, transports); 2334 transport = list_entry(pos, struct sctp_transport, transports);
2322 list_del_init(pos); 2335 if (transport->state != SCTP_ACTIVE)
2323 sctp_transport_free(transport); 2336 sctp_assoc_rm_peer(asoc, transport);
2324 } 2337 }
2325 2338
2326 asoc->peer.transport_count = 0;
2327
2328nomem: 2339nomem:
2329 return 0; 2340 return 0;
2330} 2341}
@@ -2460,6 +2471,9 @@ do_addr_param:
2460 break; 2471 break;
2461 2472
2462 case SCTP_PARAM_SET_PRIMARY: 2473 case SCTP_PARAM_SET_PRIMARY:
2474 if (!sctp_addip_enable)
2475 goto fall_through;
2476
2463 addr_param = param.v + sizeof(sctp_addip_param_t); 2477 addr_param = param.v + sizeof(sctp_addip_param_t);
2464 2478
2465 af = sctp_get_af_specific(param_type2af(param.p->type)); 2479 af = sctp_get_af_specific(param_type2af(param.p->type));
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8848d329aa2c..7c622af2ce55 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
119 const struct sctp_endpoint *ep, 119 const struct sctp_endpoint *ep,
120 const struct sctp_association *asoc, 120 const struct sctp_association *asoc,
121 const sctp_subtype_t type, 121 const sctp_subtype_t type,
122 void *arg, 122 void *arg, void *ext,
123 sctp_cmd_seq_t *commands); 123 sctp_cmd_seq_t *commands);
124 124
125static sctp_disposition_t sctp_sf_violation_ctsn( 125static sctp_disposition_t sctp_sf_violation_ctsn(
@@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3425 addr_param = (union sctp_addr_param *)hdr->params; 3425 addr_param = (union sctp_addr_param *)hdr->params;
3426 length = ntohs(addr_param->p.length); 3426 length = ntohs(addr_param->p.length);
3427 if (length < sizeof(sctp_paramhdr_t)) 3427 if (length < sizeof(sctp_paramhdr_t))
3428 return sctp_sf_violation_paramlen(ep, asoc, type, 3428 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3429 (void *)addr_param, commands); 3429 (void *)addr_param, commands);
3430 3430
3431 /* Verify the ASCONF chunk before processing it. */ 3431 /* Verify the ASCONF chunk before processing it. */
@@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3433 (sctp_paramhdr_t *)((void *)addr_param + length), 3433 (sctp_paramhdr_t *)((void *)addr_param + length),
3434 (void *)chunk->chunk_end, 3434 (void *)chunk->chunk_end,
3435 &err_param)) 3435 &err_param))
3436 return sctp_sf_violation_paramlen(ep, asoc, type, 3436 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3437 (void *)&err_param, commands); 3437 (void *)err_param, commands);
3438 3438
3439 /* ADDIP 5.2 E1) Compare the value of the serial number to the value 3439 /* ADDIP 5.2 E1) Compare the value of the serial number to the value
3440 * the endpoint stored in a new association variable 3440 * the endpoint stored in a new association variable
@@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3542 (sctp_paramhdr_t *)addip_hdr->params, 3542 (sctp_paramhdr_t *)addip_hdr->params,
3543 (void *)asconf_ack->chunk_end, 3543 (void *)asconf_ack->chunk_end,
3544 &err_param)) 3544 &err_param))
3545 return sctp_sf_violation_paramlen(ep, asoc, type, 3545 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3546 (void *)&err_param, commands); 3546 (void *)err_param, commands);
3547 3547
3548 if (last_asconf) { 3548 if (last_asconf) {
3549 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; 3549 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
@@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
4240 const struct sctp_endpoint *ep, 4240 const struct sctp_endpoint *ep,
4241 const struct sctp_association *asoc, 4241 const struct sctp_association *asoc,
4242 const sctp_subtype_t type, 4242 const sctp_subtype_t type,
4243 void *arg, 4243 void *arg, void *ext,
4244 sctp_cmd_seq_t *commands) { 4244 sctp_cmd_seq_t *commands)
4245 static const char err_str[] = "The following parameter had invalid length:"; 4245{
4246 struct sctp_chunk *chunk = arg;
4247 struct sctp_paramhdr *param = ext;
4248 struct sctp_chunk *abort = NULL;
4246 4249
4247 return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, 4250 if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
4248 sizeof(err_str)); 4251 goto discard;
4252
4253 /* Make the abort chunk. */
4254 abort = sctp_make_violation_paramlen(asoc, chunk, param);
4255 if (!abort)
4256 goto nomem;
4257
4258 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4259 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
4260
4261 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
4262 SCTP_ERROR(ECONNABORTED));
4263 sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
4264 SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
4265 SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
4266
4267discard:
4268 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
4269
4270 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
4271
4272 return SCTP_DISPOSITION_ABORT;
4273nomem:
4274 return SCTP_DISPOSITION_NOMEM;
4249} 4275}
4250 4276
4251/* Handle a protocol violation when the peer trying to advance the 4277/* Handle a protocol violation when the peer trying to advance the
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index dbb79adf8f3c..5ffb9dec1c3f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3055,6 +3055,9 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
3055{ 3055{
3056 struct sctp_authchunk val; 3056 struct sctp_authchunk val;
3057 3057
3058 if (!sctp_auth_enable)
3059 return -EACCES;
3060
3058 if (optlen != sizeof(struct sctp_authchunk)) 3061 if (optlen != sizeof(struct sctp_authchunk))
3059 return -EINVAL; 3062 return -EINVAL;
3060 if (copy_from_user(&val, optval, optlen)) 3063 if (copy_from_user(&val, optval, optlen))
@@ -3083,8 +3086,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
3083 int optlen) 3086 int optlen)
3084{ 3087{
3085 struct sctp_hmacalgo *hmacs; 3088 struct sctp_hmacalgo *hmacs;
3089 u32 idents;
3086 int err; 3090 int err;
3087 3091
3092 if (!sctp_auth_enable)
3093 return -EACCES;
3094
3088 if (optlen < sizeof(struct sctp_hmacalgo)) 3095 if (optlen < sizeof(struct sctp_hmacalgo))
3089 return -EINVAL; 3096 return -EINVAL;
3090 3097
@@ -3097,8 +3104,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
3097 goto out; 3104 goto out;
3098 } 3105 }
3099 3106
3100 if (hmacs->shmac_num_idents == 0 || 3107 idents = hmacs->shmac_num_idents;
3101 hmacs->shmac_num_idents > SCTP_AUTH_NUM_HMACS) { 3108 if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS ||
3109 (idents * sizeof(u16)) > (optlen - sizeof(struct sctp_hmacalgo))) {
3102 err = -EINVAL; 3110 err = -EINVAL;
3103 goto out; 3111 goto out;
3104 } 3112 }
@@ -3123,6 +3131,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
3123 struct sctp_association *asoc; 3131 struct sctp_association *asoc;
3124 int ret; 3132 int ret;
3125 3133
3134 if (!sctp_auth_enable)
3135 return -EACCES;
3136
3126 if (optlen <= sizeof(struct sctp_authkey)) 3137 if (optlen <= sizeof(struct sctp_authkey))
3127 return -EINVAL; 3138 return -EINVAL;
3128 3139
@@ -3135,6 +3146,11 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
3135 goto out; 3146 goto out;
3136 } 3147 }
3137 3148
3149 if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) {
3150 ret = -EINVAL;
3151 goto out;
3152 }
3153
3138 asoc = sctp_id2assoc(sk, authkey->sca_assoc_id); 3154 asoc = sctp_id2assoc(sk, authkey->sca_assoc_id);
3139 if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) { 3155 if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) {
3140 ret = -EINVAL; 3156 ret = -EINVAL;
@@ -3160,6 +3176,9 @@ static int sctp_setsockopt_active_key(struct sock *sk,
3160 struct sctp_authkeyid val; 3176 struct sctp_authkeyid val;
3161 struct sctp_association *asoc; 3177 struct sctp_association *asoc;
3162 3178
3179 if (!sctp_auth_enable)
3180 return -EACCES;
3181
3163 if (optlen != sizeof(struct sctp_authkeyid)) 3182 if (optlen != sizeof(struct sctp_authkeyid))
3164 return -EINVAL; 3183 return -EINVAL;
3165 if (copy_from_user(&val, optval, optlen)) 3184 if (copy_from_user(&val, optval, optlen))
@@ -3185,6 +3204,9 @@ static int sctp_setsockopt_del_key(struct sock *sk,
3185 struct sctp_authkeyid val; 3204 struct sctp_authkeyid val;
3186 struct sctp_association *asoc; 3205 struct sctp_association *asoc;
3187 3206
3207 if (!sctp_auth_enable)
3208 return -EACCES;
3209
3188 if (optlen != sizeof(struct sctp_authkeyid)) 3210 if (optlen != sizeof(struct sctp_authkeyid))
3189 return -EINVAL; 3211 return -EINVAL;
3190 if (copy_from_user(&val, optval, optlen)) 3212 if (copy_from_user(&val, optval, optlen))
@@ -5197,19 +5219,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
5197static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 5219static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
5198 char __user *optval, int __user *optlen) 5220 char __user *optval, int __user *optlen)
5199{ 5221{
5222 struct sctp_hmacalgo __user *p = (void __user *)optval;
5200 struct sctp_hmac_algo_param *hmacs; 5223 struct sctp_hmac_algo_param *hmacs;
5201 __u16 param_len; 5224 __u16 data_len = 0;
5225 u32 num_idents;
5226
5227 if (!sctp_auth_enable)
5228 return -EACCES;
5202 5229
5203 hmacs = sctp_sk(sk)->ep->auth_hmacs_list; 5230 hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
5204 param_len = ntohs(hmacs->param_hdr.length); 5231 data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t);
5205 5232
5206 if (len < param_len) 5233 if (len < sizeof(struct sctp_hmacalgo) + data_len)
5207 return -EINVAL; 5234 return -EINVAL;
5235
5236 len = sizeof(struct sctp_hmacalgo) + data_len;
5237 num_idents = data_len / sizeof(u16);
5238
5208 if (put_user(len, optlen)) 5239 if (put_user(len, optlen))
5209 return -EFAULT; 5240 return -EFAULT;
5210 if (copy_to_user(optval, hmacs->hmac_ids, len)) 5241 if (put_user(num_idents, &p->shmac_num_idents))
5242 return -EFAULT;
5243 if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
5211 return -EFAULT; 5244 return -EFAULT;
5212
5213 return 0; 5245 return 0;
5214} 5246}
5215 5247
@@ -5219,6 +5251,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
5219 struct sctp_authkeyid val; 5251 struct sctp_authkeyid val;
5220 struct sctp_association *asoc; 5252 struct sctp_association *asoc;
5221 5253
5254 if (!sctp_auth_enable)
5255 return -EACCES;
5256
5222 if (len < sizeof(struct sctp_authkeyid)) 5257 if (len < sizeof(struct sctp_authkeyid))
5223 return -EINVAL; 5258 return -EINVAL;
5224 if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) 5259 if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid)))
@@ -5233,6 +5268,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
5233 else 5268 else
5234 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; 5269 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id;
5235 5270
5271 len = sizeof(struct sctp_authkeyid);
5272 if (put_user(len, optlen))
5273 return -EFAULT;
5274 if (copy_to_user(optval, &val, len))
5275 return -EFAULT;
5276
5236 return 0; 5277 return 0;
5237} 5278}
5238 5279
@@ -5243,13 +5284,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
5243 struct sctp_authchunks val; 5284 struct sctp_authchunks val;
5244 struct sctp_association *asoc; 5285 struct sctp_association *asoc;
5245 struct sctp_chunks_param *ch; 5286 struct sctp_chunks_param *ch;
5246 u32 num_chunks; 5287 u32 num_chunks = 0;
5247 char __user *to; 5288 char __user *to;
5248 5289
5249 if (len <= sizeof(struct sctp_authchunks)) 5290 if (!sctp_auth_enable)
5291 return -EACCES;
5292
5293 if (len < sizeof(struct sctp_authchunks))
5250 return -EINVAL; 5294 return -EINVAL;
5251 5295
5252 if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5296 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5253 return -EFAULT; 5297 return -EFAULT;
5254 5298
5255 to = p->gauth_chunks; 5299 to = p->gauth_chunks;
@@ -5258,20 +5302,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
5258 return -EINVAL; 5302 return -EINVAL;
5259 5303
5260 ch = asoc->peer.peer_chunks; 5304 ch = asoc->peer.peer_chunks;
5305 if (!ch)
5306 goto num;
5261 5307
5262 /* See if the user provided enough room for all the data */ 5308 /* See if the user provided enough room for all the data */
5263 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5309 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
5264 if (len < num_chunks) 5310 if (len < num_chunks)
5265 return -EINVAL; 5311 return -EINVAL;
5266 5312
5267 len = num_chunks; 5313 if (copy_to_user(to, ch->chunks, num_chunks))
5268 if (put_user(len, optlen))
5269 return -EFAULT; 5314 return -EFAULT;
5315num:
5316 len = sizeof(struct sctp_authchunks) + num_chunks;
5317 if (put_user(len, optlen)) return -EFAULT;
5270 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5318 if (put_user(num_chunks, &p->gauth_number_of_chunks))
5271 return -EFAULT; 5319 return -EFAULT;
5272 if (copy_to_user(to, ch->chunks, len))
5273 return -EFAULT;
5274
5275 return 0; 5320 return 0;
5276} 5321}
5277 5322
@@ -5282,13 +5327,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
5282 struct sctp_authchunks val; 5327 struct sctp_authchunks val;
5283 struct sctp_association *asoc; 5328 struct sctp_association *asoc;
5284 struct sctp_chunks_param *ch; 5329 struct sctp_chunks_param *ch;
5285 u32 num_chunks; 5330 u32 num_chunks = 0;
5286 char __user *to; 5331 char __user *to;
5287 5332
5288 if (len <= sizeof(struct sctp_authchunks)) 5333 if (!sctp_auth_enable)
5334 return -EACCES;
5335
5336 if (len < sizeof(struct sctp_authchunks))
5289 return -EINVAL; 5337 return -EINVAL;
5290 5338
5291 if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5339 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5292 return -EFAULT; 5340 return -EFAULT;
5293 5341
5294 to = p->gauth_chunks; 5342 to = p->gauth_chunks;
@@ -5301,17 +5349,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
5301 else 5349 else
5302 ch = sctp_sk(sk)->ep->auth_chunk_list; 5350 ch = sctp_sk(sk)->ep->auth_chunk_list;
5303 5351
5352 if (!ch)
5353 goto num;
5354
5304 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5355 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
5305 if (len < num_chunks) 5356 if (len < sizeof(struct sctp_authchunks) + num_chunks)
5306 return -EINVAL; 5357 return -EINVAL;
5307 5358
5308 len = num_chunks; 5359 if (copy_to_user(to, ch->chunks, num_chunks))
5360 return -EFAULT;
5361num:
5362 len = sizeof(struct sctp_authchunks) + num_chunks;
5309 if (put_user(len, optlen)) 5363 if (put_user(len, optlen))
5310 return -EFAULT; 5364 return -EFAULT;
5311 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5365 if (put_user(num_chunks, &p->gauth_number_of_chunks))
5312 return -EFAULT; 5366 return -EFAULT;
5313 if (copy_to_user(to, ch->chunks, len))
5314 return -EFAULT;
5315 5367
5316 return 0; 5368 return 0;
5317} 5369}