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