sctp: fix potential panics in the SCTP-AUTH API.

All of the SCTP-AUTH socket options could cause a panic
if the extension is disabled and the API is envoked.

Additionally, there were some additional assumptions that
certain pointers would always be valid which may not
always be the case.

This patch hardens the API and address all of the crash
scenarios.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Vlad Yasevich and committed by David S. Miller 5e739d17 6a55617e

+67 -22
+2 -2
net/sctp/endpointola.c
··· 103 104 /* Initialize the CHUNKS parameter */ 105 auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; 106 107 /* If the Add-IP functionality is enabled, we must 108 * authenticate, ASCONF and ASCONF-ACK chunks ··· 111 if (sctp_addip_enable) { 112 auth_chunks->chunks[0] = SCTP_CID_ASCONF; 113 auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; 114 - auth_chunks->param_hdr.length = 115 - htons(sizeof(sctp_paramhdr_t) + 2); 116 } 117 } 118
··· 103 104 /* Initialize the CHUNKS parameter */ 105 auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; 106 + auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t)); 107 108 /* If the Add-IP functionality is enabled, we must 109 * authenticate, ASCONF and ASCONF-ACK chunks ··· 110 if (sctp_addip_enable) { 111 auth_chunks->chunks[0] = SCTP_CID_ASCONF; 112 auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; 113 + auth_chunks->param_hdr.length += htons(2); 114 } 115 } 116
+65 -20
net/sctp/socket.c
··· 3055 { 3056 struct sctp_authchunk val; 3057 3058 if (optlen != sizeof(struct sctp_authchunk)) 3059 return -EINVAL; 3060 if (copy_from_user(&val, optval, optlen)) ··· 3087 { 3088 struct sctp_hmacalgo *hmacs; 3089 int err; 3090 3091 if (optlen < sizeof(struct sctp_hmacalgo)) 3092 return -EINVAL; ··· 3129 struct sctp_association *asoc; 3130 int ret; 3131 3132 if (optlen <= sizeof(struct sctp_authkey)) 3133 return -EINVAL; 3134 ··· 3169 struct sctp_authkeyid val; 3170 struct sctp_association *asoc; 3171 3172 if (optlen != sizeof(struct sctp_authkeyid)) 3173 return -EINVAL; 3174 if (copy_from_user(&val, optval, optlen)) ··· 3196 { 3197 struct sctp_authkeyid val; 3198 struct sctp_association *asoc; 3199 3200 if (optlen != sizeof(struct sctp_authkeyid)) 3201 return -EINVAL; ··· 5212 static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 5213 char __user *optval, int __user *optlen) 5214 { 5215 struct sctp_hmac_algo_param *hmacs; 5216 - __u16 param_len; 5217 5218 hmacs = sctp_sk(sk)->ep->auth_hmacs_list; 5219 - param_len = ntohs(hmacs->param_hdr.length); 5220 5221 - if (len < param_len) 5222 return -EINVAL; 5223 if (put_user(len, optlen)) 5224 return -EFAULT; 5225 - if (copy_to_user(optval, hmacs->hmac_ids, len)) 5226 return -EFAULT; 5227 - 5228 return 0; 5229 } 5230 ··· 5243 { 5244 struct sctp_authkeyid val; 5245 struct sctp_association *asoc; 5246 5247 if (len < sizeof(struct sctp_authkeyid)) 5248 return -EINVAL; ··· 5261 else 5262 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; 5263 5264 return 0; 5265 } 5266 ··· 5277 struct sctp_authchunks val; 5278 struct sctp_association *asoc; 5279 struct sctp_chunks_param *ch; 5280 - u32 num_chunks; 5281 char __user *to; 5282 5283 - if (len <= sizeof(struct sctp_authchunks)) 5284 return -EINVAL; 5285 5286 - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5287 return -EFAULT; 5288 5289 to = p->gauth_chunks; ··· 5295 return -EINVAL; 5296 5297 ch = asoc->peer.peer_chunks; 5298 5299 /* See if the user provided enough room for all the data */ 5300 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5301 if (len < num_chunks) 5302 return -EINVAL; 5303 5304 - len = num_chunks; 5305 - if (put_user(len, optlen)) 5306 return -EFAULT; 5307 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5308 return -EFAULT; 5309 - if (copy_to_user(to, ch->chunks, len)) 5310 - return -EFAULT; 5311 - 5312 return 0; 5313 } 5314 ··· 5320 struct sctp_authchunks val; 5321 struct sctp_association *asoc; 5322 struct sctp_chunks_param *ch; 5323 - u32 num_chunks; 5324 char __user *to; 5325 5326 - if (len <= sizeof(struct sctp_authchunks)) 5327 return -EINVAL; 5328 5329 - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5330 return -EFAULT; 5331 5332 to = p->gauth_chunks; ··· 5342 else 5343 ch = sctp_sk(sk)->ep->auth_chunk_list; 5344 5345 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5346 - if (len < num_chunks) 5347 return -EINVAL; 5348 5349 - len = num_chunks; 5350 if (put_user(len, optlen)) 5351 return -EFAULT; 5352 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5353 - return -EFAULT; 5354 - if (copy_to_user(to, ch->chunks, len)) 5355 return -EFAULT; 5356 5357 return 0;
··· 3055 { 3056 struct sctp_authchunk val; 3057 3058 + if (!sctp_auth_enable) 3059 + return -EACCES; 3060 + 3061 if (optlen != sizeof(struct sctp_authchunk)) 3062 return -EINVAL; 3063 if (copy_from_user(&val, optval, optlen)) ··· 3084 { 3085 struct sctp_hmacalgo *hmacs; 3086 int err; 3087 + 3088 + if (!sctp_auth_enable) 3089 + return -EACCES; 3090 3091 if (optlen < sizeof(struct sctp_hmacalgo)) 3092 return -EINVAL; ··· 3123 struct sctp_association *asoc; 3124 int ret; 3125 3126 + if (!sctp_auth_enable) 3127 + return -EACCES; 3128 + 3129 if (optlen <= sizeof(struct sctp_authkey)) 3130 return -EINVAL; 3131 ··· 3160 struct sctp_authkeyid val; 3161 struct sctp_association *asoc; 3162 3163 + if (!sctp_auth_enable) 3164 + return -EACCES; 3165 + 3166 if (optlen != sizeof(struct sctp_authkeyid)) 3167 return -EINVAL; 3168 if (copy_from_user(&val, optval, optlen)) ··· 3184 { 3185 struct sctp_authkeyid val; 3186 struct sctp_association *asoc; 3187 + 3188 + if (!sctp_auth_enable) 3189 + return -EACCES; 3190 3191 if (optlen != sizeof(struct sctp_authkeyid)) 3192 return -EINVAL; ··· 5197 static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 5198 char __user *optval, int __user *optlen) 5199 { 5200 + struct sctp_hmacalgo __user *p = (void __user *)optval; 5201 struct sctp_hmac_algo_param *hmacs; 5202 + __u16 data_len = 0; 5203 + u32 num_idents; 5204 + 5205 + if (!sctp_auth_enable) 5206 + return -EACCES; 5207 5208 hmacs = sctp_sk(sk)->ep->auth_hmacs_list; 5209 + data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); 5210 5211 + if (len < sizeof(struct sctp_hmacalgo) + data_len) 5212 return -EINVAL; 5213 + 5214 + len = sizeof(struct sctp_hmacalgo) + data_len; 5215 + num_idents = data_len / sizeof(u16); 5216 + 5217 if (put_user(len, optlen)) 5218 return -EFAULT; 5219 + if (put_user(num_idents, &p->shmac_num_idents)) 5220 return -EFAULT; 5221 + if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) 5222 + return -EFAULT; 5223 return 0; 5224 } 5225 ··· 5218 { 5219 struct sctp_authkeyid val; 5220 struct sctp_association *asoc; 5221 + 5222 + if (!sctp_auth_enable) 5223 + return -EACCES; 5224 5225 if (len < sizeof(struct sctp_authkeyid)) 5226 return -EINVAL; ··· 5233 else 5234 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; 5235 5236 + len = sizeof(struct sctp_authkeyid); 5237 + if (put_user(len, optlen)) 5238 + return -EFAULT; 5239 + if (copy_to_user(optval, &val, len)) 5240 + return -EFAULT; 5241 + 5242 return 0; 5243 } 5244 ··· 5243 struct sctp_authchunks val; 5244 struct sctp_association *asoc; 5245 struct sctp_chunks_param *ch; 5246 + u32 num_chunks = 0; 5247 char __user *to; 5248 5249 + if (!sctp_auth_enable) 5250 + return -EACCES; 5251 + 5252 + if (len < sizeof(struct sctp_authchunks)) 5253 return -EINVAL; 5254 5255 + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) 5256 return -EFAULT; 5257 5258 to = p->gauth_chunks; ··· 5258 return -EINVAL; 5259 5260 ch = asoc->peer.peer_chunks; 5261 + if (!ch) 5262 + goto num; 5263 5264 /* See if the user provided enough room for all the data */ 5265 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5266 if (len < num_chunks) 5267 return -EINVAL; 5268 5269 + if (copy_to_user(to, ch->chunks, num_chunks)) 5270 return -EFAULT; 5271 + num: 5272 + len = sizeof(struct sctp_authchunks) + num_chunks; 5273 + if (put_user(len, optlen)) return -EFAULT; 5274 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5275 return -EFAULT; 5276 return 0; 5277 } 5278 ··· 5282 struct sctp_authchunks val; 5283 struct sctp_association *asoc; 5284 struct sctp_chunks_param *ch; 5285 + u32 num_chunks = 0; 5286 char __user *to; 5287 5288 + if (!sctp_auth_enable) 5289 + return -EACCES; 5290 + 5291 + if (len < sizeof(struct sctp_authchunks)) 5292 return -EINVAL; 5293 5294 + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) 5295 return -EFAULT; 5296 5297 to = p->gauth_chunks; ··· 5301 else 5302 ch = sctp_sk(sk)->ep->auth_chunk_list; 5303 5304 + if (!ch) 5305 + goto num; 5306 + 5307 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5308 + if (len < sizeof(struct sctp_authchunks) + num_chunks) 5309 return -EINVAL; 5310 5311 + if (copy_to_user(to, ch->chunks, num_chunks)) 5312 + return -EFAULT; 5313 + num: 5314 + len = sizeof(struct sctp_authchunks) + num_chunks; 5315 if (put_user(len, optlen)) 5316 return -EFAULT; 5317 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5318 return -EFAULT; 5319 5320 return 0;