diff options
| -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 c042ce19bd14..86e28a75267f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 345 | case IPV6_DSTOPTS: | 345 | case IPV6_DSTOPTS: |
| 346 | { | 346 | { |
| 347 | struct ipv6_txoptions *opt; | 347 | struct ipv6_txoptions *opt; |
| 348 | |||
| 349 | /* remove any sticky options header with a zero option | ||
| 350 | * length, per RFC3542. | ||
| 351 | */ | ||
| 348 | if (optlen == 0) | 352 | if (optlen == 0) |
| 349 | optval = NULL; | 353 | optval = NULL; |
| 354 | else if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
| 355 | optlen & 0x7 || optlen > 8 * 255) | ||
| 356 | goto e_inval; | ||
| 350 | 357 | ||
| 351 | /* hop-by-hop / destination options are privileged option */ | 358 | /* hop-by-hop / destination options are privileged option */ |
| 352 | retv = -EPERM; | 359 | retv = -EPERM; |
| 353 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 360 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
| 354 | break; | 361 | break; |
| 355 | 362 | ||
| 356 | if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
| 357 | optlen & 0x7 || optlen > 8 * 255) | ||
| 358 | goto e_inval; | ||
| 359 | |||
| 360 | opt = ipv6_renew_options(sk, np->opt, optname, | 363 | opt = ipv6_renew_options(sk, np->opt, optname, |
| 361 | (struct ipv6_opt_hdr __user *)optval, | 364 | (struct ipv6_opt_hdr __user *)optval, |
| 362 | optlen); | 365 | optlen); |
