diff options
author | Baozeng Ding <sploving1@gmail.com> | 2016-05-24 10:33:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-25 15:33:52 -0400 |
commit | 297f7d2cce6a156c174334ee452f2f7a7ba405ca (patch) | |
tree | b9b9d7fe44437f7a2df0330142dc50d60aa17c0a /net | |
parent | ec7c7f5cafdaeea509ad4e7e6f71c2312062c4c6 (diff) |
tipc: fix potential null pointer dereferences in some compat functions
Before calling the nla_parse_nested function, make sure the pointer to the
attribute is not null. This patch fixes several potential null pointer
dereference vulnerabilities in the tipc netlink functions.
Signed-off-by: Baozeng Ding <sploving1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/tipc/netlink_compat.c | 111 |
1 files changed, 93 insertions, 18 deletions
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 4dfc5c14f8c3..f795b1dd0ccd 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -346,9 +346,15 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg, | |||
346 | struct nlattr **attrs) | 346 | struct nlattr **attrs) |
347 | { | 347 | { |
348 | struct nlattr *bearer[TIPC_NLA_BEARER_MAX + 1]; | 348 | struct nlattr *bearer[TIPC_NLA_BEARER_MAX + 1]; |
349 | int err; | ||
350 | |||
351 | if (!attrs[TIPC_NLA_BEARER]) | ||
352 | return -EINVAL; | ||
349 | 353 | ||
350 | nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX, attrs[TIPC_NLA_BEARER], | 354 | err = nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX, |
351 | NULL); | 355 | attrs[TIPC_NLA_BEARER], NULL); |
356 | if (err) | ||
357 | return err; | ||
352 | 358 | ||
353 | return tipc_add_tlv(msg->rep, TIPC_TLV_BEARER_NAME, | 359 | return tipc_add_tlv(msg->rep, TIPC_TLV_BEARER_NAME, |
354 | nla_data(bearer[TIPC_NLA_BEARER_NAME]), | 360 | nla_data(bearer[TIPC_NLA_BEARER_NAME]), |
@@ -460,14 +466,31 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, | |||
460 | struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; | 466 | struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; |
461 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; | 467 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; |
462 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; | 468 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; |
469 | int err; | ||
463 | 470 | ||
464 | nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL); | 471 | if (!attrs[TIPC_NLA_LINK]) |
472 | return -EINVAL; | ||
465 | 473 | ||
466 | nla_parse_nested(prop, TIPC_NLA_PROP_MAX, link[TIPC_NLA_LINK_PROP], | 474 | err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], |
467 | NULL); | 475 | NULL); |
476 | if (err) | ||
477 | return err; | ||
478 | |||
479 | if (!link[TIPC_NLA_LINK_PROP]) | ||
480 | return -EINVAL; | ||
468 | 481 | ||
469 | nla_parse_nested(stats, TIPC_NLA_STATS_MAX, link[TIPC_NLA_LINK_STATS], | 482 | err = nla_parse_nested(prop, TIPC_NLA_PROP_MAX, |
470 | NULL); | 483 | link[TIPC_NLA_LINK_PROP], NULL); |
484 | if (err) | ||
485 | return err; | ||
486 | |||
487 | if (!link[TIPC_NLA_LINK_STATS]) | ||
488 | return -EINVAL; | ||
489 | |||
490 | err = nla_parse_nested(stats, TIPC_NLA_STATS_MAX, | ||
491 | link[TIPC_NLA_LINK_STATS], NULL); | ||
492 | if (err) | ||
493 | return err; | ||
471 | 494 | ||
472 | name = (char *)TLV_DATA(msg->req); | 495 | name = (char *)TLV_DATA(msg->req); |
473 | if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) | 496 | if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) |
@@ -569,8 +592,15 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, | |||
569 | { | 592 | { |
570 | struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; | 593 | struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; |
571 | struct tipc_link_info link_info; | 594 | struct tipc_link_info link_info; |
595 | int err; | ||
572 | 596 | ||
573 | nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL); | 597 | if (!attrs[TIPC_NLA_LINK]) |
598 | return -EINVAL; | ||
599 | |||
600 | err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], | ||
601 | NULL); | ||
602 | if (err) | ||
603 | return err; | ||
574 | 604 | ||
575 | link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); | 605 | link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); |
576 | link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); | 606 | link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); |
@@ -758,12 +788,23 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg, | |||
758 | u32 node, depth, type, lowbound, upbound; | 788 | u32 node, depth, type, lowbound, upbound; |
759 | static const char * const scope_str[] = {"", " zone", " cluster", | 789 | static const char * const scope_str[] = {"", " zone", " cluster", |
760 | " node"}; | 790 | " node"}; |
791 | int err; | ||
761 | 792 | ||
762 | nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX, | 793 | if (!attrs[TIPC_NLA_NAME_TABLE]) |
763 | attrs[TIPC_NLA_NAME_TABLE], NULL); | 794 | return -EINVAL; |
764 | 795 | ||
765 | nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, nt[TIPC_NLA_NAME_TABLE_PUBL], | 796 | err = nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX, |
766 | NULL); | 797 | attrs[TIPC_NLA_NAME_TABLE], NULL); |
798 | if (err) | ||
799 | return err; | ||
800 | |||
801 | if (!nt[TIPC_NLA_NAME_TABLE_PUBL]) | ||
802 | return -EINVAL; | ||
803 | |||
804 | err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, | ||
805 | nt[TIPC_NLA_NAME_TABLE_PUBL], NULL); | ||
806 | if (err) | ||
807 | return err; | ||
767 | 808 | ||
768 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); | 809 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); |
769 | 810 | ||
@@ -815,8 +856,15 @@ static int __tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, | |||
815 | { | 856 | { |
816 | u32 type, lower, upper; | 857 | u32 type, lower, upper; |
817 | struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1]; | 858 | struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1]; |
859 | int err; | ||
818 | 860 | ||
819 | nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], NULL); | 861 | if (!attrs[TIPC_NLA_PUBL]) |
862 | return -EINVAL; | ||
863 | |||
864 | err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], | ||
865 | NULL); | ||
866 | if (err) | ||
867 | return err; | ||
820 | 868 | ||
821 | type = nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]); | 869 | type = nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]); |
822 | lower = nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]); | 870 | lower = nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]); |
@@ -876,7 +924,13 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg, | |||
876 | u32 sock_ref; | 924 | u32 sock_ref; |
877 | struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1]; | 925 | struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1]; |
878 | 926 | ||
879 | nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], NULL); | 927 | if (!attrs[TIPC_NLA_SOCK]) |
928 | return -EINVAL; | ||
929 | |||
930 | err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], | ||
931 | NULL); | ||
932 | if (err) | ||
933 | return err; | ||
880 | 934 | ||
881 | sock_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]); | 935 | sock_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]); |
882 | tipc_tlv_sprintf(msg->rep, "%u:", sock_ref); | 936 | tipc_tlv_sprintf(msg->rep, "%u:", sock_ref); |
@@ -917,9 +971,15 @@ static int tipc_nl_compat_media_dump(struct tipc_nl_compat_msg *msg, | |||
917 | struct nlattr **attrs) | 971 | struct nlattr **attrs) |
918 | { | 972 | { |
919 | struct nlattr *media[TIPC_NLA_MEDIA_MAX + 1]; | 973 | struct nlattr *media[TIPC_NLA_MEDIA_MAX + 1]; |
974 | int err; | ||
975 | |||
976 | if (!attrs[TIPC_NLA_MEDIA]) | ||
977 | return -EINVAL; | ||
920 | 978 | ||
921 | nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, attrs[TIPC_NLA_MEDIA], | 979 | err = nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, attrs[TIPC_NLA_MEDIA], |
922 | NULL); | 980 | NULL); |
981 | if (err) | ||
982 | return err; | ||
923 | 983 | ||
924 | return tipc_add_tlv(msg->rep, TIPC_TLV_MEDIA_NAME, | 984 | return tipc_add_tlv(msg->rep, TIPC_TLV_MEDIA_NAME, |
925 | nla_data(media[TIPC_NLA_MEDIA_NAME]), | 985 | nla_data(media[TIPC_NLA_MEDIA_NAME]), |
@@ -931,8 +991,15 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg, | |||
931 | { | 991 | { |
932 | struct tipc_node_info node_info; | 992 | struct tipc_node_info node_info; |
933 | struct nlattr *node[TIPC_NLA_NODE_MAX + 1]; | 993 | struct nlattr *node[TIPC_NLA_NODE_MAX + 1]; |
994 | int err; | ||
934 | 995 | ||
935 | nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE], NULL); | 996 | if (!attrs[TIPC_NLA_NODE]) |
997 | return -EINVAL; | ||
998 | |||
999 | err = nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE], | ||
1000 | NULL); | ||
1001 | if (err) | ||
1002 | return err; | ||
936 | 1003 | ||
937 | node_info.addr = htonl(nla_get_u32(node[TIPC_NLA_NODE_ADDR])); | 1004 | node_info.addr = htonl(nla_get_u32(node[TIPC_NLA_NODE_ADDR])); |
938 | node_info.up = htonl(nla_get_flag(node[TIPC_NLA_NODE_UP])); | 1005 | node_info.up = htonl(nla_get_flag(node[TIPC_NLA_NODE_UP])); |
@@ -971,8 +1038,16 @@ static int tipc_nl_compat_net_dump(struct tipc_nl_compat_msg *msg, | |||
971 | { | 1038 | { |
972 | __be32 id; | 1039 | __be32 id; |
973 | struct nlattr *net[TIPC_NLA_NET_MAX + 1]; | 1040 | struct nlattr *net[TIPC_NLA_NET_MAX + 1]; |
1041 | int err; | ||
1042 | |||
1043 | if (!attrs[TIPC_NLA_NET]) | ||
1044 | return -EINVAL; | ||
1045 | |||
1046 | err = nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET], | ||
1047 | NULL); | ||
1048 | if (err) | ||
1049 | return err; | ||
974 | 1050 | ||
975 | nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET], NULL); | ||
976 | id = htonl(nla_get_u32(net[TIPC_NLA_NET_ID])); | 1051 | id = htonl(nla_get_u32(net[TIPC_NLA_NET_ID])); |
977 | 1052 | ||
978 | return tipc_add_tlv(msg->rep, TIPC_TLV_UNSIGNED, &id, sizeof(id)); | 1053 | return tipc_add_tlv(msg->rep, TIPC_TLV_UNSIGNED, &id, sizeof(id)); |