diff options
author | Thomas Graf <tgraf@suug.ch> | 2012-07-05 08:19:56 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2012-07-10 16:35:41 -0400 |
commit | 732d35fd08058a678327ec908528fcc9514c9e48 (patch) | |
tree | e56b55c83c7892461b9c6dc87d9ab9d124d91d7d /net/can | |
parent | 6eaf53ca7bdae4506dbe6f0daaa93656f092383e (diff) |
can: gw: Use nla_policy to validate netlink attributes
Also use nla_get_u32() instead of nla_memcpy() to access u32 attribtues.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'net/can')
-rw-r--r-- | net/can/gw.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/net/can/gw.c b/net/can/gw.c index a3ff980a1754..a1c639c730a3 100644 --- a/net/can/gw.c +++ b/net/can/gw.c | |||
@@ -558,6 +558,18 @@ cont: | |||
558 | return skb->len; | 558 | return skb->len; |
559 | } | 559 | } |
560 | 560 | ||
561 | static const struct nla_policy cgw_policy[CGW_MAX+1] = { | ||
562 | [CGW_MOD_AND] = { .len = sizeof(struct cgw_frame_mod) }, | ||
563 | [CGW_MOD_OR] = { .len = sizeof(struct cgw_frame_mod) }, | ||
564 | [CGW_MOD_XOR] = { .len = sizeof(struct cgw_frame_mod) }, | ||
565 | [CGW_MOD_SET] = { .len = sizeof(struct cgw_frame_mod) }, | ||
566 | [CGW_CS_XOR] = { .len = sizeof(struct cgw_csum_xor) }, | ||
567 | [CGW_CS_CRC8] = { .len = sizeof(struct cgw_csum_crc8) }, | ||
568 | [CGW_SRC_IF] = { .type = NLA_U32 }, | ||
569 | [CGW_DST_IF] = { .type = NLA_U32 }, | ||
570 | [CGW_FILTER] = { .len = sizeof(struct can_filter) }, | ||
571 | }; | ||
572 | |||
561 | /* check for common and gwtype specific attributes */ | 573 | /* check for common and gwtype specific attributes */ |
562 | static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | 574 | static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, |
563 | u8 gwtype, void *gwtypeattr) | 575 | u8 gwtype, void *gwtypeattr) |
@@ -570,14 +582,14 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
570 | /* initialize modification & checksum data space */ | 582 | /* initialize modification & checksum data space */ |
571 | memset(mod, 0, sizeof(*mod)); | 583 | memset(mod, 0, sizeof(*mod)); |
572 | 584 | ||
573 | err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, NULL); | 585 | err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, |
586 | cgw_policy); | ||
574 | if (err < 0) | 587 | if (err < 0) |
575 | return err; | 588 | return err; |
576 | 589 | ||
577 | /* check for AND/OR/XOR/SET modifications */ | 590 | /* check for AND/OR/XOR/SET modifications */ |
578 | 591 | ||
579 | if (tb[CGW_MOD_AND] && | 592 | if (tb[CGW_MOD_AND]) { |
580 | nla_len(tb[CGW_MOD_AND]) == CGW_MODATTR_LEN) { | ||
581 | nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); | 593 | nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); |
582 | 594 | ||
583 | canframecpy(&mod->modframe.and, &mb.cf); | 595 | canframecpy(&mod->modframe.and, &mb.cf); |
@@ -593,8 +605,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
593 | mod->modfunc[modidx++] = mod_and_data; | 605 | mod->modfunc[modidx++] = mod_and_data; |
594 | } | 606 | } |
595 | 607 | ||
596 | if (tb[CGW_MOD_OR] && | 608 | if (tb[CGW_MOD_OR]) { |
597 | nla_len(tb[CGW_MOD_OR]) == CGW_MODATTR_LEN) { | ||
598 | nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); | 609 | nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); |
599 | 610 | ||
600 | canframecpy(&mod->modframe.or, &mb.cf); | 611 | canframecpy(&mod->modframe.or, &mb.cf); |
@@ -610,8 +621,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
610 | mod->modfunc[modidx++] = mod_or_data; | 621 | mod->modfunc[modidx++] = mod_or_data; |
611 | } | 622 | } |
612 | 623 | ||
613 | if (tb[CGW_MOD_XOR] && | 624 | if (tb[CGW_MOD_XOR]) { |
614 | nla_len(tb[CGW_MOD_XOR]) == CGW_MODATTR_LEN) { | ||
615 | nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); | 625 | nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); |
616 | 626 | ||
617 | canframecpy(&mod->modframe.xor, &mb.cf); | 627 | canframecpy(&mod->modframe.xor, &mb.cf); |
@@ -627,8 +637,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
627 | mod->modfunc[modidx++] = mod_xor_data; | 637 | mod->modfunc[modidx++] = mod_xor_data; |
628 | } | 638 | } |
629 | 639 | ||
630 | if (tb[CGW_MOD_SET] && | 640 | if (tb[CGW_MOD_SET]) { |
631 | nla_len(tb[CGW_MOD_SET]) == CGW_MODATTR_LEN) { | ||
632 | nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); | 641 | nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); |
633 | 642 | ||
634 | canframecpy(&mod->modframe.set, &mb.cf); | 643 | canframecpy(&mod->modframe.set, &mb.cf); |
@@ -647,9 +656,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
647 | /* check for checksum operations after CAN frame modifications */ | 656 | /* check for checksum operations after CAN frame modifications */ |
648 | if (modidx) { | 657 | if (modidx) { |
649 | 658 | ||
650 | if (tb[CGW_CS_CRC8] && | 659 | if (tb[CGW_CS_CRC8]) { |
651 | nla_len(tb[CGW_CS_CRC8]) == CGW_CS_CRC8_LEN) { | ||
652 | |||
653 | struct cgw_csum_crc8 *c = (struct cgw_csum_crc8 *)\ | 660 | struct cgw_csum_crc8 *c = (struct cgw_csum_crc8 *)\ |
654 | nla_data(tb[CGW_CS_CRC8]); | 661 | nla_data(tb[CGW_CS_CRC8]); |
655 | 662 | ||
@@ -674,9 +681,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
674 | mod->csumfunc.crc8 = cgw_csum_crc8_neg; | 681 | mod->csumfunc.crc8 = cgw_csum_crc8_neg; |
675 | } | 682 | } |
676 | 683 | ||
677 | if (tb[CGW_CS_XOR] && | 684 | if (tb[CGW_CS_XOR]) { |
678 | nla_len(tb[CGW_CS_XOR]) == CGW_CS_XOR_LEN) { | ||
679 | |||
680 | struct cgw_csum_xor *c = (struct cgw_csum_xor *)\ | 685 | struct cgw_csum_xor *c = (struct cgw_csum_xor *)\ |
681 | nla_data(tb[CGW_CS_XOR]); | 686 | nla_data(tb[CGW_CS_XOR]); |
682 | 687 | ||
@@ -710,8 +715,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
710 | memset(ccgw, 0, sizeof(*ccgw)); | 715 | memset(ccgw, 0, sizeof(*ccgw)); |
711 | 716 | ||
712 | /* check for can_filter in attributes */ | 717 | /* check for can_filter in attributes */ |
713 | if (tb[CGW_FILTER] && | 718 | if (tb[CGW_FILTER]) |
714 | nla_len(tb[CGW_FILTER]) == sizeof(struct can_filter)) | ||
715 | nla_memcpy(&ccgw->filter, tb[CGW_FILTER], | 719 | nla_memcpy(&ccgw->filter, tb[CGW_FILTER], |
716 | sizeof(struct can_filter)); | 720 | sizeof(struct can_filter)); |
717 | 721 | ||
@@ -721,13 +725,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, | |||
721 | if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF]) | 725 | if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF]) |
722 | return err; | 726 | return err; |
723 | 727 | ||
724 | if (nla_len(tb[CGW_SRC_IF]) == sizeof(u32)) | 728 | ccgw->src_idx = nla_get_u32(tb[CGW_SRC_IF]); |
725 | nla_memcpy(&ccgw->src_idx, tb[CGW_SRC_IF], | 729 | ccgw->dst_idx = nla_get_u32(tb[CGW_DST_IF]); |
726 | sizeof(u32)); | ||
727 | |||
728 | if (nla_len(tb[CGW_DST_IF]) == sizeof(u32)) | ||
729 | nla_memcpy(&ccgw->dst_idx, tb[CGW_DST_IF], | ||
730 | sizeof(u32)); | ||
731 | 730 | ||
732 | /* both indices set to 0 for flushing all routing entries */ | 731 | /* both indices set to 0 for flushing all routing entries */ |
733 | if (!ccgw->src_idx && !ccgw->dst_idx) | 732 | if (!ccgw->src_idx && !ccgw->dst_idx) |