diff options
author | Lorenz <12514511+RincewindsHat@users.noreply.github.com> | 2022-03-15 21:00:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-15 21:00:55 (GMT) |
commit | 605405557102c04e740fc3249675cc5154436d11 (patch) | |
tree | 5c4ff8a018d3ccc1bc784a6ea0bbf6514f91ff85 /plugins-root/check_icmp.c | |
parent | 6c8b45a1691f4ce98f1c559a1e9cd1fef68c0fe2 (diff) | |
download | monitoring-plugins-605405557102c04e740fc3249675cc5154436d11.tar.gz |
check_icmp: buffer offerflow (#1733)
* Fix different overflows
* Less includes
* Add testcases
* Remove unused variable
* Remove unused and commented includes
Diffstat (limited to 'plugins-root/check_icmp.c')
-rw-r--r-- | plugins-root/check_icmp.c | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index f97b0ed..6119823 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c | |||
@@ -50,19 +50,11 @@ const char *email = "devel@monitoring-plugins.org"; | |||
50 | #if HAVE_SYS_SOCKIO_H | 50 | #if HAVE_SYS_SOCKIO_H |
51 | #include <sys/sockio.h> | 51 | #include <sys/sockio.h> |
52 | #endif | 52 | #endif |
53 | #include <sys/ioctl.h> | 53 | |
54 | #include <sys/time.h> | 54 | #include <sys/time.h> |
55 | #include <sys/types.h> | ||
56 | #include <stdio.h> | ||
57 | #include <stdlib.h> | ||
58 | #include <stdarg.h> | ||
59 | #include <unistd.h> | ||
60 | #include <stddef.h> | ||
61 | #include <errno.h> | 55 | #include <errno.h> |
62 | #include <string.h> | 56 | #include <signal.h> |
63 | #include <ctype.h> | 57 | #include <ctype.h> |
64 | #include <netdb.h> | ||
65 | #include <sys/socket.h> | ||
66 | #include <net/if.h> | 58 | #include <net/if.h> |
67 | #include <netinet/in_systm.h> | 59 | #include <netinet/in_systm.h> |
68 | #include <netinet/in.h> | 60 | #include <netinet/in.h> |
@@ -71,8 +63,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
71 | #include <netinet/ip_icmp.h> | 63 | #include <netinet/ip_icmp.h> |
72 | #include <netinet/icmp6.h> | 64 | #include <netinet/icmp6.h> |
73 | #include <arpa/inet.h> | 65 | #include <arpa/inet.h> |
74 | #include <signal.h> | ||
75 | #include <float.h> | ||
76 | 66 | ||
77 | 67 | ||
78 | /** sometimes undefined system macros (quite a few, actually) **/ | 68 | /** sometimes undefined system macros (quite a few, actually) **/ |
@@ -207,7 +197,7 @@ static int add_target(char *); | |||
207 | static int add_target_ip(char *, struct sockaddr_storage *); | 197 | static int add_target_ip(char *, struct sockaddr_storage *); |
208 | static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); | 198 | static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); |
209 | static void parse_address(struct sockaddr_storage *, char *, int); | 199 | static void parse_address(struct sockaddr_storage *, char *, int); |
210 | static unsigned short icmp_checksum(unsigned short *, int); | 200 | static unsigned short icmp_checksum(uint16_t *, size_t); |
211 | static void finish(int); | 201 | static void finish(int); |
212 | static void crash(const char *, ...); | 202 | static void crash(const char *, ...); |
213 | 203 | ||
@@ -465,7 +455,6 @@ main(int argc, char **argv) | |||
465 | /* Parse protocol arguments first */ | 455 | /* Parse protocol arguments first */ |
466 | for(i = 1; i < argc; i++) { | 456 | for(i = 1; i < argc; i++) { |
467 | while((arg = getopt(argc, argv, opts_str)) != EOF) { | 457 | while((arg = getopt(argc, argv, opts_str)) != EOF) { |
468 | unsigned short size; | ||
469 | switch(arg) { | 458 | switch(arg) { |
470 | case '4': | 459 | case '4': |
471 | if (address_family != -1) | 460 | if (address_family != -1) |
@@ -488,10 +477,10 @@ main(int argc, char **argv) | |||
488 | /* Reset argument scanning */ | 477 | /* Reset argument scanning */ |
489 | optind = 1; | 478 | optind = 1; |
490 | 479 | ||
480 | unsigned short size; | ||
491 | /* parse the arguments */ | 481 | /* parse the arguments */ |
492 | for(i = 1; i < argc; i++) { | 482 | for(i = 1; i < argc; i++) { |
493 | while((arg = getopt(argc, argv, opts_str)) != EOF) { | 483 | while((arg = getopt(argc, argv, opts_str)) != EOF) { |
494 | unsigned short size; | ||
495 | switch(arg) { | 484 | switch(arg) { |
496 | case 'v': | 485 | case 'v': |
497 | debug++; | 486 | debug++; |
@@ -720,7 +709,7 @@ main(int argc, char **argv) | |||
720 | static void | 709 | static void |
721 | run_checks() | 710 | run_checks() |
722 | { | 711 | { |
723 | u_int i, t, result; | 712 | u_int i, t; |
724 | u_int final_wait, time_passed; | 713 | u_int final_wait, time_passed; |
725 | 714 | ||
726 | /* this loop might actually violate the pkt_interval or target_interval | 715 | /* this loop might actually violate the pkt_interval or target_interval |
@@ -738,9 +727,9 @@ run_checks() | |||
738 | 727 | ||
739 | /* we're still in the game, so send next packet */ | 728 | /* we're still in the game, so send next packet */ |
740 | (void)send_icmp_ping(icmp_sock, table[t]); | 729 | (void)send_icmp_ping(icmp_sock, table[t]); |
741 | result = wait_for_reply(icmp_sock, target_interval); | 730 | wait_for_reply(icmp_sock, target_interval); |
742 | } | 731 | } |
743 | result = wait_for_reply(icmp_sock, pkt_interval * targets); | 732 | wait_for_reply(icmp_sock, pkt_interval * targets); |
744 | } | 733 | } |
745 | 734 | ||
746 | if(icmp_pkts_en_route && targets_alive) { | 735 | if(icmp_pkts_en_route && targets_alive) { |
@@ -760,7 +749,7 @@ run_checks() | |||
760 | * haven't yet */ | 749 | * haven't yet */ |
761 | if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", | 750 | if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", |
762 | final_wait, (float)final_wait / 1000); | 751 | final_wait, (float)final_wait / 1000); |
763 | result = wait_for_reply(icmp_sock, final_wait); | 752 | wait_for_reply(icmp_sock, final_wait); |
764 | } | 753 | } |
765 | } | 754 | } |
766 | 755 | ||
@@ -779,7 +768,7 @@ static int | |||
779 | wait_for_reply(int sock, u_int t) | 768 | wait_for_reply(int sock, u_int t) |
780 | { | 769 | { |
781 | int n, hlen; | 770 | int n, hlen; |
782 | static unsigned char buf[4096]; | 771 | static unsigned char buf[65536]; |
783 | struct sockaddr_storage resp_addr; | 772 | struct sockaddr_storage resp_addr; |
784 | union ip_hdr *ip; | 773 | union ip_hdr *ip; |
785 | union icmp_packet packet; | 774 | union icmp_packet packet; |
@@ -916,9 +905,27 @@ wait_for_reply(int sock, u_int t) | |||
916 | if(debug) { | 905 | if(debug) { |
917 | char address[INET6_ADDRSTRLEN]; | 906 | char address[INET6_ADDRSTRLEN]; |
918 | parse_address(&resp_addr, address, sizeof(address)); | 907 | parse_address(&resp_addr, address, sizeof(address)); |
919 | printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", | 908 | |
920 | (float)tdiff / 1000, address, | 909 | switch(address_family) { |
921 | ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); | 910 | case AF_INET: { |
911 | printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", | ||
912 | (float)tdiff / 1000, | ||
913 | address, | ||
914 | ttl, | ||
915 | ip->ip.ip_ttl, | ||
916 | (float)host->rtmax / 1000, | ||
917 | (float)host->rtmin / 1000); | ||
918 | break; | ||
919 | }; | ||
920 | case AF_INET6: { | ||
921 | printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n", | ||
922 | (float)tdiff / 1000, | ||
923 | address, | ||
924 | ttl, | ||
925 | (float)host->rtmax / 1000, | ||
926 | (float)host->rtmin / 1000); | ||
927 | }; | ||
928 | } | ||
922 | } | 929 | } |
923 | 930 | ||
924 | /* if we're in hostcheck mode, exit with limited printouts */ | 931 | /* if we're in hostcheck mode, exit with limited printouts */ |
@@ -980,7 +987,7 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
980 | icp->icmp_cksum = 0; | 987 | icp->icmp_cksum = 0; |
981 | icp->icmp_id = htons(pid); | 988 | icp->icmp_id = htons(pid); |
982 | icp->icmp_seq = htons(host->id++); | 989 | icp->icmp_seq = htons(host->id++); |
983 | icp->icmp_cksum = icmp_checksum((unsigned short*)buf, icmp_pkt_size); | 990 | icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size); |
984 | 991 | ||
985 | if (debug > 2) | 992 | if (debug > 2) |
986 | printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", | 993 | printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", |
@@ -1517,18 +1524,19 @@ get_threshold(char *str, threshold *th) | |||
1517 | } | 1524 | } |
1518 | 1525 | ||
1519 | unsigned short | 1526 | unsigned short |
1520 | icmp_checksum(unsigned short *p, int n) | 1527 | icmp_checksum(uint16_t *p, size_t n) |
1521 | { | 1528 | { |
1522 | unsigned short cksum; | 1529 | unsigned short cksum; |
1523 | long sum = 0; | 1530 | long sum = 0; |
1524 | 1531 | ||
1525 | while(n > 2) { | 1532 | /* sizeof(uint16_t) == 2 */ |
1526 | sum += *p++; | 1533 | while(n >= 2) { |
1527 | n -= sizeof(unsigned short); | 1534 | sum += *(p++); |
1535 | n -= 2; | ||
1528 | } | 1536 | } |
1529 | 1537 | ||
1530 | /* mop up the occasional odd byte */ | 1538 | /* mop up the occasional odd byte */ |
1531 | if(n == 1) sum += (unsigned char)*p; | 1539 | if(n == 1) sum += *((uint8_t *)p -1); |
1532 | 1540 | ||
1533 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | 1541 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ |
1534 | sum += (sum >> 16); /* add carry */ | 1542 | sum += (sum >> 16); /* add carry */ |