aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-08-21 06:34:25 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-21 06:34:25 -0400
commit5e739d1752aca4e8f3e794d431503bfca3162df4 (patch)
treec5bdef49d12fbd4bb0eae6fca102607346390cb5
parent6a55617ed5d1aa62b850de2cf66f5ede2eef4825 (diff)
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>
-rw-r--r--net/sctp/endpointola.c4
-rw-r--r--net/sctp/socket.c85
2 files changed, 67 insertions, 22 deletions
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/socket.c b/net/sctp/socket.c
index dbb79adf8f3c..bb5c9ef13046 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))
@@ -3085,6 +3088,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
3085 struct sctp_hmacalgo *hmacs; 3088 struct sctp_hmacalgo *hmacs;
3086 int err; 3089 int err;
3087 3090
3091 if (!sctp_auth_enable)
3092 return -EACCES;
3093
3088 if (optlen < sizeof(struct sctp_hmacalgo)) 3094 if (optlen < sizeof(struct sctp_hmacalgo))
3089 return -EINVAL; 3095 return -EINVAL;
3090 3096
@@ -3123,6 +3129,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
3123 struct sctp_association *asoc; 3129 struct sctp_association *asoc;
3124 int ret; 3130 int ret;
3125 3131
3132 if (!sctp_auth_enable)
3133 return -EACCES;
3134
3126 if (optlen <= sizeof(struct sctp_authkey)) 3135 if (optlen <= sizeof(struct sctp_authkey))
3127 return -EINVAL; 3136 return -EINVAL;
3128 3137
@@ -3160,6 +3169,9 @@ static int sctp_setsockopt_active_key(struct sock *sk,
3160 struct sctp_authkeyid val; 3169 struct sctp_authkeyid val;
3161 struct sctp_association *asoc; 3170 struct sctp_association *asoc;
3162 3171
3172 if (!sctp_auth_enable)
3173 return -EACCES;
3174
3163 if (optlen != sizeof(struct sctp_authkeyid)) 3175 if (optlen != sizeof(struct sctp_authkeyid))
3164 return -EINVAL; 3176 return -EINVAL;
3165 if (copy_from_user(&val, optval, optlen)) 3177 if (copy_from_user(&val, optval, optlen))
@@ -3185,6 +3197,9 @@ static int sctp_setsockopt_del_key(struct sock *sk,
3185 struct sctp_authkeyid val; 3197 struct sctp_authkeyid val;
3186 struct sctp_association *asoc; 3198 struct sctp_association *asoc;
3187 3199
3200 if (!sctp_auth_enable)
3201 return -EACCES;
3202
3188 if (optlen != sizeof(struct sctp_authkeyid)) 3203 if (optlen != sizeof(struct sctp_authkeyid))
3189 return -EINVAL; 3204 return -EINVAL;
3190 if (copy_from_user(&val, optval, optlen)) 3205 if (copy_from_user(&val, optval, optlen))
@@ -5197,19 +5212,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
5197static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 5212static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
5198 char __user *optval, int __user *optlen) 5213 char __user *optval, int __user *optlen)
5199{ 5214{
5215 struct sctp_hmacalgo __user *p = (void __user *)optval;
5200 struct sctp_hmac_algo_param *hmacs; 5216 struct sctp_hmac_algo_param *hmacs;
5201 __u16 param_len; 5217 __u16 data_len = 0;
5218 u32 num_idents;
5219
5220 if (!sctp_auth_enable)
5221 return -EACCES;
5202 5222
5203 hmacs = sctp_sk(sk)->ep->auth_hmacs_list; 5223 hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
5204 param_len = ntohs(hmacs->param_hdr.length); 5224 data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t);
5205 5225
5206 if (len < param_len) 5226 if (len < sizeof(struct sctp_hmacalgo) + data_len)
5207 return -EINVAL; 5227 return -EINVAL;
5228
5229 len = sizeof(struct sctp_hmacalgo) + data_len;
5230 num_idents = data_len / sizeof(u16);
5231
5208 if (put_user(len, optlen)) 5232 if (put_user(len, optlen))
5209 return -EFAULT; 5233 return -EFAULT;
5210 if (copy_to_user(optval, hmacs->hmac_ids, len)) 5234 if (put_user(num_idents, &p->shmac_num_idents))
5235 return -EFAULT;
5236 if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
5211 return -EFAULT; 5237 return -EFAULT;
5212
5213 return 0; 5238 return 0;
5214} 5239}
5215 5240
@@ -5219,6 +5244,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
5219 struct sctp_authkeyid val; 5244 struct sctp_authkeyid val;
5220 struct sctp_association *asoc; 5245 struct sctp_association *asoc;
5221 5246
5247 if (!sctp_auth_enable)
5248 return -EACCES;
5249
5222 if (len < sizeof(struct sctp_authkeyid)) 5250 if (len < sizeof(struct sctp_authkeyid))
5223 return -EINVAL; 5251 return -EINVAL;
5224 if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) 5252 if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid)))
@@ -5233,6 +5261,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
5233 else 5261 else
5234 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; 5262 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id;
5235 5263
5264 len = sizeof(struct sctp_authkeyid);
5265 if (put_user(len, optlen))
5266 return -EFAULT;
5267 if (copy_to_user(optval, &val, len))
5268 return -EFAULT;
5269
5236 return 0; 5270 return 0;
5237} 5271}
5238 5272
@@ -5243,13 +5277,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
5243 struct sctp_authchunks val; 5277 struct sctp_authchunks val;
5244 struct sctp_association *asoc; 5278 struct sctp_association *asoc;
5245 struct sctp_chunks_param *ch; 5279 struct sctp_chunks_param *ch;
5246 u32 num_chunks; 5280 u32 num_chunks = 0;
5247 char __user *to; 5281 char __user *to;
5248 5282
5249 if (len <= sizeof(struct sctp_authchunks)) 5283 if (!sctp_auth_enable)
5284 return -EACCES;
5285
5286 if (len < sizeof(struct sctp_authchunks))
5250 return -EINVAL; 5287 return -EINVAL;
5251 5288
5252 if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5289 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5253 return -EFAULT; 5290 return -EFAULT;
5254 5291
5255 to = p->gauth_chunks; 5292 to = p->gauth_chunks;
@@ -5258,20 +5295,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
5258 return -EINVAL; 5295 return -EINVAL;
5259 5296
5260 ch = asoc->peer.peer_chunks; 5297 ch = asoc->peer.peer_chunks;
5298 if (!ch)
5299 goto num;
5261 5300
5262 /* See if the user provided enough room for all the data */ 5301 /* See if the user provided enough room for all the data */
5263 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5302 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
5264 if (len < num_chunks) 5303 if (len < num_chunks)
5265 return -EINVAL; 5304 return -EINVAL;
5266 5305
5267 len = num_chunks; 5306 if (copy_to_user(to, ch->chunks, num_chunks))
5268 if (put_user(len, optlen))
5269 return -EFAULT; 5307 return -EFAULT;
5308num:
5309 len = sizeof(struct sctp_authchunks) + num_chunks;
5310 if (put_user(len, optlen)) return -EFAULT;
5270 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5311 if (put_user(num_chunks, &p->gauth_number_of_chunks))
5271 return -EFAULT; 5312 return -EFAULT;
5272 if (copy_to_user(to, ch->chunks, len))
5273 return -EFAULT;
5274
5275 return 0; 5313 return 0;
5276} 5314}
5277 5315
@@ -5282,13 +5320,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
5282 struct sctp_authchunks val; 5320 struct sctp_authchunks val;
5283 struct sctp_association *asoc; 5321 struct sctp_association *asoc;
5284 struct sctp_chunks_param *ch; 5322 struct sctp_chunks_param *ch;
5285 u32 num_chunks; 5323 u32 num_chunks = 0;
5286 char __user *to; 5324 char __user *to;
5287 5325
5288 if (len <= sizeof(struct sctp_authchunks)) 5326 if (!sctp_auth_enable)
5327 return -EACCES;
5328
5329 if (len < sizeof(struct sctp_authchunks))
5289 return -EINVAL; 5330 return -EINVAL;
5290 5331
5291 if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) 5332 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5292 return -EFAULT; 5333 return -EFAULT;
5293 5334
5294 to = p->gauth_chunks; 5335 to = p->gauth_chunks;
@@ -5301,17 +5342,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
5301 else 5342 else
5302 ch = sctp_sk(sk)->ep->auth_chunk_list; 5343 ch = sctp_sk(sk)->ep->auth_chunk_list;
5303 5344
5345 if (!ch)
5346 goto num;
5347
5304 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); 5348 num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
5305 if (len < num_chunks) 5349 if (len < sizeof(struct sctp_authchunks) + num_chunks)
5306 return -EINVAL; 5350 return -EINVAL;
5307 5351
5308 len = num_chunks; 5352 if (copy_to_user(to, ch->chunks, num_chunks))
5353 return -EFAULT;
5354num:
5355 len = sizeof(struct sctp_authchunks) + num_chunks;
5309 if (put_user(len, optlen)) 5356 if (put_user(len, optlen))
5310 return -EFAULT; 5357 return -EFAULT;
5311 if (put_user(num_chunks, &p->gauth_number_of_chunks)) 5358 if (put_user(num_chunks, &p->gauth_number_of_chunks))
5312 return -EFAULT; 5359 return -EFAULT;
5313 if (copy_to_user(to, ch->chunks, len))
5314 return -EFAULT;
5315 5360
5316 return 0; 5361 return 0;
5317} 5362}