.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * SR-IPv6 implementation |
---|
3 | 4 | * |
---|
4 | 5 | * Author: |
---|
5 | 6 | * David Lebrun <david.lebrun@uclouvain.be> |
---|
6 | | - * |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or |
---|
9 | | - * modify it under the terms of the GNU General Public License |
---|
10 | | - * as published by the Free Software Foundation; either version |
---|
11 | | - * 2 of the License, or (at your option) any later version. |
---|
12 | 7 | */ |
---|
13 | 8 | |
---|
14 | 9 | #include <linux/errno.h> |
---|
.. | .. |
---|
30 | 25 | #include <net/seg6_hmac.h> |
---|
31 | 26 | #endif |
---|
32 | 27 | |
---|
33 | | -bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len) |
---|
| 28 | +bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced) |
---|
34 | 29 | { |
---|
35 | | - int trailing; |
---|
36 | 30 | unsigned int tlv_offset; |
---|
| 31 | + int max_last_entry; |
---|
| 32 | + int trailing; |
---|
37 | 33 | |
---|
38 | 34 | if (srh->type != IPV6_SRCRT_TYPE_4) |
---|
39 | 35 | return false; |
---|
.. | .. |
---|
41 | 37 | if (((srh->hdrlen + 1) << 3) != len) |
---|
42 | 38 | return false; |
---|
43 | 39 | |
---|
44 | | - if (srh->segments_left > srh->first_segment) |
---|
| 40 | + if (!reduced && srh->segments_left > srh->first_segment) { |
---|
45 | 41 | return false; |
---|
| 42 | + } else { |
---|
| 43 | + max_last_entry = (srh->hdrlen / 2) - 1; |
---|
| 44 | + |
---|
| 45 | + if (srh->first_segment > max_last_entry) |
---|
| 46 | + return false; |
---|
| 47 | + |
---|
| 48 | + if (srh->segments_left > srh->first_segment + 1) |
---|
| 49 | + return false; |
---|
| 50 | + } |
---|
46 | 51 | |
---|
47 | 52 | tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4); |
---|
48 | 53 | |
---|
.. | .. |
---|
126 | 131 | } |
---|
127 | 132 | |
---|
128 | 133 | if (!info->attrs[SEG6_ATTR_SECRET]) { |
---|
| 134 | + err = -EINVAL; |
---|
| 135 | + goto out_unlock; |
---|
| 136 | + } |
---|
| 137 | + |
---|
| 138 | + if (slen > nla_len(info->attrs[SEG6_ATTR_SECRET])) { |
---|
129 | 139 | err = -EINVAL; |
---|
130 | 140 | goto out_unlock; |
---|
131 | 141 | } |
---|
.. | .. |
---|
398 | 408 | static const struct genl_ops seg6_genl_ops[] = { |
---|
399 | 409 | { |
---|
400 | 410 | .cmd = SEG6_CMD_SETHMAC, |
---|
| 411 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
401 | 412 | .doit = seg6_genl_sethmac, |
---|
402 | | - .policy = seg6_genl_policy, |
---|
403 | 413 | .flags = GENL_ADMIN_PERM, |
---|
404 | 414 | }, |
---|
405 | 415 | { |
---|
406 | 416 | .cmd = SEG6_CMD_DUMPHMAC, |
---|
| 417 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
407 | 418 | .start = seg6_genl_dumphmac_start, |
---|
408 | 419 | .dumpit = seg6_genl_dumphmac, |
---|
409 | 420 | .done = seg6_genl_dumphmac_done, |
---|
410 | | - .policy = seg6_genl_policy, |
---|
411 | 421 | .flags = GENL_ADMIN_PERM, |
---|
412 | 422 | }, |
---|
413 | 423 | { |
---|
414 | 424 | .cmd = SEG6_CMD_SET_TUNSRC, |
---|
| 425 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
415 | 426 | .doit = seg6_genl_set_tunsrc, |
---|
416 | | - .policy = seg6_genl_policy, |
---|
417 | 427 | .flags = GENL_ADMIN_PERM, |
---|
418 | 428 | }, |
---|
419 | 429 | { |
---|
420 | 430 | .cmd = SEG6_CMD_GET_TUNSRC, |
---|
| 431 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
421 | 432 | .doit = seg6_genl_get_tunsrc, |
---|
422 | | - .policy = seg6_genl_policy, |
---|
423 | 433 | .flags = GENL_ADMIN_PERM, |
---|
424 | 434 | }, |
---|
425 | 435 | }; |
---|
.. | .. |
---|
429 | 439 | .name = SEG6_GENL_NAME, |
---|
430 | 440 | .version = SEG6_GENL_VERSION, |
---|
431 | 441 | .maxattr = SEG6_ATTR_MAX, |
---|
| 442 | + .policy = seg6_genl_policy, |
---|
432 | 443 | .netnsok = true, |
---|
433 | 444 | .parallel_ops = true, |
---|
434 | 445 | .ops = seg6_genl_ops, |
---|
.. | .. |
---|
438 | 449 | |
---|
439 | 450 | int __init seg6_init(void) |
---|
440 | 451 | { |
---|
441 | | - int err = -ENOMEM; |
---|
| 452 | + int err; |
---|
442 | 453 | |
---|
443 | 454 | err = genl_register_family(&seg6_genl_family); |
---|
444 | 455 | if (err) |
---|