diff options
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a9988841172a..030c0c956f9d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -343,18 +343,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
343 | case IPV6_DSTOPTS: | 343 | case IPV6_DSTOPTS: |
344 | { | 344 | { |
345 | struct ipv6_txoptions *opt; | 345 | struct ipv6_txoptions *opt; |
346 | |||
347 | /* remove any sticky options header with a zero option | ||
348 | * length, per RFC3542. | ||
349 | */ | ||
346 | if (optlen == 0) | 350 | if (optlen == 0) |
347 | optval = NULL; | 351 | optval = NULL; |
352 | else if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
353 | optlen & 0x7 || optlen > 8 * 255) | ||
354 | goto e_inval; | ||
348 | 355 | ||
349 | /* hop-by-hop / destination options are privileged option */ | 356 | /* hop-by-hop / destination options are privileged option */ |
350 | retv = -EPERM; | 357 | retv = -EPERM; |
351 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 358 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
352 | break; | 359 | break; |
353 | 360 | ||
354 | if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
355 | optlen & 0x7 || optlen > 8 * 255) | ||
356 | goto e_inval; | ||
357 | |||
358 | opt = ipv6_renew_options(sk, np->opt, optname, | 361 | opt = ipv6_renew_options(sk, np->opt, optname, |
359 | (struct ipv6_opt_hdr __user *)optval, | 362 | (struct ipv6_opt_hdr __user *)optval, |
360 | optlen); | 363 | optlen); |