diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 96 | 
1 files changed, 74 insertions, 22 deletions
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, | |||
| 5197 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | 5219 | static 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; | 
| 5315 | num: | ||
| 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; | ||
| 5361 | num: | ||
| 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 | } | 
