diff options
Diffstat (limited to 'net/tipc/netlink_compat.c')
| -rw-r--r-- | net/tipc/netlink_compat.c | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 40f5cae623a7..4ad3586da8f0 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
| @@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb) | |||
| 87 | return limit; | 87 | return limit; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv) | ||
| 91 | { | ||
| 92 | return TLV_GET_LEN(tlv) - TLV_SPACE(0); | ||
| 93 | } | ||
| 94 | |||
| 90 | static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) | 95 | static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) |
| 91 | { | 96 | { |
| 92 | struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb); | 97 | struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb); |
| @@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str) | |||
| 166 | return buf; | 171 | return buf; |
| 167 | } | 172 | } |
| 168 | 173 | ||
| 174 | static inline bool string_is_valid(char *s, int len) | ||
| 175 | { | ||
| 176 | return memchr(s, '\0', len) ? true : false; | ||
| 177 | } | ||
| 178 | |||
| 169 | static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | 179 | static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, |
| 170 | struct tipc_nl_compat_msg *msg, | 180 | struct tipc_nl_compat_msg *msg, |
| 171 | struct sk_buff *arg) | 181 | struct sk_buff *arg) |
| @@ -379,6 +389,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 379 | struct nlattr *prop; | 389 | struct nlattr *prop; |
| 380 | struct nlattr *bearer; | 390 | struct nlattr *bearer; |
| 381 | struct tipc_bearer_config *b; | 391 | struct tipc_bearer_config *b; |
| 392 | int len; | ||
| 382 | 393 | ||
| 383 | b = (struct tipc_bearer_config *)TLV_DATA(msg->req); | 394 | b = (struct tipc_bearer_config *)TLV_DATA(msg->req); |
| 384 | 395 | ||
| @@ -386,6 +397,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 386 | if (!bearer) | 397 | if (!bearer) |
| 387 | return -EMSGSIZE; | 398 | return -EMSGSIZE; |
| 388 | 399 | ||
| 400 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME); | ||
| 401 | if (!string_is_valid(b->name, len)) | ||
| 402 | return -EINVAL; | ||
| 403 | |||
| 389 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name)) | 404 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name)) |
| 390 | return -EMSGSIZE; | 405 | return -EMSGSIZE; |
| 391 | 406 | ||
| @@ -411,6 +426,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 411 | { | 426 | { |
| 412 | char *name; | 427 | char *name; |
| 413 | struct nlattr *bearer; | 428 | struct nlattr *bearer; |
| 429 | int len; | ||
| 414 | 430 | ||
| 415 | name = (char *)TLV_DATA(msg->req); | 431 | name = (char *)TLV_DATA(msg->req); |
| 416 | 432 | ||
| @@ -418,6 +434,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 418 | if (!bearer) | 434 | if (!bearer) |
| 419 | return -EMSGSIZE; | 435 | return -EMSGSIZE; |
| 420 | 436 | ||
| 437 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME); | ||
| 438 | if (!string_is_valid(name, len)) | ||
| 439 | return -EINVAL; | ||
| 440 | |||
| 421 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name)) | 441 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name)) |
| 422 | return -EMSGSIZE; | 442 | return -EMSGSIZE; |
| 423 | 443 | ||
| @@ -478,6 +498,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, | |||
| 478 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; | 498 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; |
| 479 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; | 499 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; |
| 480 | int err; | 500 | int err; |
| 501 | int len; | ||
| 481 | 502 | ||
| 482 | if (!attrs[TIPC_NLA_LINK]) | 503 | if (!attrs[TIPC_NLA_LINK]) |
| 483 | return -EINVAL; | 504 | return -EINVAL; |
| @@ -504,6 +525,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, | |||
| 504 | return err; | 525 | return err; |
| 505 | 526 | ||
| 506 | name = (char *)TLV_DATA(msg->req); | 527 | name = (char *)TLV_DATA(msg->req); |
| 528 | |||
| 529 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME); | ||
| 530 | if (!string_is_valid(name, len)) | ||
| 531 | return -EINVAL; | ||
| 532 | |||
| 507 | if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) | 533 | if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) |
| 508 | return 0; | 534 | return 0; |
| 509 | 535 | ||
| @@ -644,6 +670,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb, | |||
| 644 | struct nlattr *prop; | 670 | struct nlattr *prop; |
| 645 | struct nlattr *media; | 671 | struct nlattr *media; |
| 646 | struct tipc_link_config *lc; | 672 | struct tipc_link_config *lc; |
| 673 | int len; | ||
| 647 | 674 | ||
| 648 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | 675 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); |
| 649 | 676 | ||
| @@ -651,6 +678,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb, | |||
| 651 | if (!media) | 678 | if (!media) |
| 652 | return -EMSGSIZE; | 679 | return -EMSGSIZE; |
| 653 | 680 | ||
| 681 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME); | ||
| 682 | if (!string_is_valid(lc->name, len)) | ||
| 683 | return -EINVAL; | ||
| 684 | |||
| 654 | if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name)) | 685 | if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name)) |
| 655 | return -EMSGSIZE; | 686 | return -EMSGSIZE; |
| 656 | 687 | ||
| @@ -671,6 +702,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb, | |||
| 671 | struct nlattr *prop; | 702 | struct nlattr *prop; |
| 672 | struct nlattr *bearer; | 703 | struct nlattr *bearer; |
| 673 | struct tipc_link_config *lc; | 704 | struct tipc_link_config *lc; |
| 705 | int len; | ||
| 674 | 706 | ||
| 675 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | 707 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); |
| 676 | 708 | ||
| @@ -678,6 +710,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb, | |||
| 678 | if (!bearer) | 710 | if (!bearer) |
| 679 | return -EMSGSIZE; | 711 | return -EMSGSIZE; |
| 680 | 712 | ||
| 713 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME); | ||
| 714 | if (!string_is_valid(lc->name, len)) | ||
| 715 | return -EINVAL; | ||
| 716 | |||
| 681 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name)) | 717 | if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name)) |
| 682 | return -EMSGSIZE; | 718 | return -EMSGSIZE; |
| 683 | 719 | ||
| @@ -726,9 +762,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 726 | struct tipc_link_config *lc; | 762 | struct tipc_link_config *lc; |
| 727 | struct tipc_bearer *bearer; | 763 | struct tipc_bearer *bearer; |
| 728 | struct tipc_media *media; | 764 | struct tipc_media *media; |
| 765 | int len; | ||
| 729 | 766 | ||
| 730 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); | 767 | lc = (struct tipc_link_config *)TLV_DATA(msg->req); |
| 731 | 768 | ||
| 769 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME); | ||
| 770 | if (!string_is_valid(lc->name, len)) | ||
| 771 | return -EINVAL; | ||
| 772 | |||
| 732 | media = tipc_media_find(lc->name); | 773 | media = tipc_media_find(lc->name); |
| 733 | if (media) { | 774 | if (media) { |
| 734 | cmd->doit = &__tipc_nl_media_set; | 775 | cmd->doit = &__tipc_nl_media_set; |
| @@ -750,6 +791,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 750 | { | 791 | { |
| 751 | char *name; | 792 | char *name; |
| 752 | struct nlattr *link; | 793 | struct nlattr *link; |
| 794 | int len; | ||
| 753 | 795 | ||
| 754 | name = (char *)TLV_DATA(msg->req); | 796 | name = (char *)TLV_DATA(msg->req); |
| 755 | 797 | ||
| @@ -757,6 +799,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 757 | if (!link) | 799 | if (!link) |
| 758 | return -EMSGSIZE; | 800 | return -EMSGSIZE; |
| 759 | 801 | ||
| 802 | len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME); | ||
| 803 | if (!string_is_valid(name, len)) | ||
| 804 | return -EINVAL; | ||
| 805 | |||
| 760 | if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name)) | 806 | if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name)) |
| 761 | return -EMSGSIZE; | 807 | return -EMSGSIZE; |
| 762 | 808 | ||
| @@ -778,6 +824,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg) | |||
| 778 | }; | 824 | }; |
| 779 | 825 | ||
| 780 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); | 826 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); |
| 827 | if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query)) | ||
| 828 | return -EINVAL; | ||
| 781 | 829 | ||
| 782 | depth = ntohl(ntq->depth); | 830 | depth = ntohl(ntq->depth); |
| 783 | 831 | ||
| @@ -904,8 +952,10 @@ static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock) | |||
| 904 | 952 | ||
| 905 | hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI, | 953 | hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI, |
| 906 | TIPC_NL_PUBL_GET); | 954 | TIPC_NL_PUBL_GET); |
| 907 | if (!hdr) | 955 | if (!hdr) { |
| 956 | kfree_skb(args); | ||
| 908 | return -EMSGSIZE; | 957 | return -EMSGSIZE; |
| 958 | } | ||
| 909 | 959 | ||
| 910 | nest = nla_nest_start(args, TIPC_NLA_SOCK); | 960 | nest = nla_nest_start(args, TIPC_NLA_SOCK); |
| 911 | if (!nest) { | 961 | if (!nest) { |
| @@ -1206,7 +1256,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
| 1206 | } | 1256 | } |
| 1207 | 1257 | ||
| 1208 | len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); | 1258 | len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); |
| 1209 | if (len && !TLV_OK(msg.req, len)) { | 1259 | if (!len || !TLV_OK(msg.req, len)) { |
| 1210 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); | 1260 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); |
| 1211 | err = -EOPNOTSUPP; | 1261 | err = -EOPNOTSUPP; |
| 1212 | goto send; | 1262 | goto send; |
