| .. | .. |
|---|
| 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) |
|---|