Summary: | ping(8) crashes with SIGSEGV - Out-of-Bounds Read of size 2 (global-buffer-overflow) | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Product: | Base System | Reporter: | Neeraj <neerajpal09> | ||||||||
Component: | bin | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||||||
Status: | New --- | ||||||||||
Severity: | Affects Many People | CC: | ckyzee, maxim, neerajpal09 | ||||||||
Priority: | --- | Keywords: | crash, patch, security | ||||||||
Version: | CURRENT | ||||||||||
Hardware: | Any | ||||||||||
OS: | Any | ||||||||||
Attachments: |
|
Description
Neeraj
2019-08-19 21:48:24 UTC
Created attachment 206713 [details]
proposed patch
Confirmed that the proposed patches from Neeraj on 2019-08-19 in both Bug 239975 and Bug 239974 work. To clear the segmentation fault, additional patch required for /usr/src/sbin/ping/tests/in_cksum_test.c as attached. Created attachment 211225 [details]
Additional patch
Comment on attachment 211225 [details] Additional patch >diff --git a/sbin/ping/tests/in_cksum_test.c b/sbin/ping/tests/in_cksum_test.c >index fc266545b43..d172a4cabc1 100644 >--- a/sbin/ping/tests/in_cksum_test.c >+++ b/sbin/ping/tests/in_cksum_test.c >@@ -1,146 +1,149 @@ > /*- > * SPDX-License-Identifier: BSD-2-Clause-FreeBSD > * > * Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org> > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in the > * documentation and/or other materials provided with the distribution. > * > * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > */ > > #include <sys/cdefs.h> > __FBSDID("$FreeBSD$"); > > #include <sys/param.h> > > #include <atf-c.h> > >+#include <sys/socket.h> >+#include "../../../include/protocols/routed.h" > > #include "../utils.h" > > /* > * Test cases. > */ > > ATF_TC_WITHOUT_HEAD(aligned_even_length_big_endian); > ATF_TC_BODY(aligned_even_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x12, 0x34, 0x56, 0x78}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0x5397); > } > > ATF_TC_WITHOUT_HEAD(aligned_odd_length_big_endian); > ATF_TC_BODY(aligned_odd_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x12, 0x34, 0x56, 0x78, 0x9a}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0x52fd); > } > > ATF_TC_WITHOUT_HEAD(aligned_even_length_little_endian); > ATF_TC_BODY(aligned_even_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x34, 0x12, 0x78, 0x56}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE_MSG(sum == 0x9753, "%d", sum); > } > > ATF_TC_WITHOUT_HEAD(aligned_odd_length_little_endian); > ATF_TC_BODY(aligned_odd_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x34, 0x12, 0x78, 0x56, 0x00, 0x9a}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0xfd52); > } > > ATF_TC_WITHOUT_HEAD(unaligned_even_length_big_endian); > ATF_TC_BODY(unaligned_even_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x12, 0x34, 0x56, 0x78}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0x5397); > } > > ATF_TC_WITHOUT_HEAD(unaligned_odd_length_big_endian); > ATF_TC_BODY(unaligned_odd_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x12, 0x34, 0x56, 0x78, 0x9a}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0x52fd); > } > > ATF_TC_WITHOUT_HEAD(unaligned_even_length_little_endian); > ATF_TC_BODY(unaligned_even_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x34, 0x12, 0x78, 0x56}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE_MSG(sum == 0x9753, "%d", sum); > } > > ATF_TC_WITHOUT_HEAD(unaligned_odd_length_little_endian); > ATF_TC_BODY(unaligned_odd_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x34, 0x12, 0x78, 0x56, 0x00, 0x9a}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0xfd52); > } > > /* > * Main. > */ > > ATF_TP_ADD_TCS(tp) > { > ATF_TP_ADD_TC(tp, aligned_even_length_big_endian); > ATF_TP_ADD_TC(tp, aligned_odd_length_big_endian); > ATF_TP_ADD_TC(tp, aligned_even_length_little_endian); > ATF_TP_ADD_TC(tp, aligned_odd_length_little_endian); > ATF_TP_ADD_TC(tp, unaligned_even_length_big_endian); > ATF_TP_ADD_TC(tp, unaligned_odd_length_big_endian); > ATF_TP_ADD_TC(tp, unaligned_even_length_little_endian); > ATF_TP_ADD_TC(tp, unaligned_odd_length_little_endian); > > return (atf_no_error()); > } Comment on attachment 211225 [details] Additional patch >diff --git a/sbin/ping/tests/in_cksum_test.c b/sbin/ping/tests/in_cksum_test.c >index fc266545b43..d172a4cabc1 100644 >--- a/sbin/ping/tests/in_cksum_test.c >+++ b/sbin/ping/tests/in_cksum_test.c >@@ -1,146 +1,149 @@ > /*- > * SPDX-License-Identifier: BSD-2-Clause-FreeBSD > * > * Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org> > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in the > * documentation and/or other materials provided with the distribution. > * > * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > */ > > #include <sys/cdefs.h> > __FBSDID("$FreeBSD$"); > > #include <sys/param.h> > > #include <atf-c.h> > >+#include <sys/socket.h> >+#include "../../../include/protocols/routed.h" > > #include "../utils.h" > > /* > * Test cases. > */ > > ATF_TC_WITHOUT_HEAD(aligned_even_length_big_endian); > ATF_TC_BODY(aligned_even_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x12, 0x34, 0x56, 0x78}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0x5397); > } > > ATF_TC_WITHOUT_HEAD(aligned_odd_length_big_endian); > ATF_TC_BODY(aligned_odd_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x12, 0x34, 0x56, 0x78, 0x9a}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0x52fd); > } > > ATF_TC_WITHOUT_HEAD(aligned_even_length_little_endian); > ATF_TC_BODY(aligned_even_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x34, 0x12, 0x78, 0x56}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE_MSG(sum == 0x9753, "%d", sum); > } > > ATF_TC_WITHOUT_HEAD(aligned_odd_length_little_endian); > ATF_TC_BODY(aligned_odd_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x34, 0x12, 0x78, 0x56, 0x00, 0x9a}; > u_short sum; > >- sum = in_cksum(data, nitems(data)); >+ sum = in_cksum(data, sizeof(struct rip), MAXPACKETSIZE, nitems(data)); > ATF_REQUIRE(sum == 0xfd52); > } > > ATF_TC_WITHOUT_HEAD(unaligned_even_length_big_endian); > ATF_TC_BODY(unaligned_even_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x12, 0x34, 0x56, 0x78}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0x5397); > } > > ATF_TC_WITHOUT_HEAD(unaligned_odd_length_big_endian); > ATF_TC_BODY(unaligned_odd_length_big_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x12, 0x34, 0x56, 0x78, 0x9a}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0x52fd); > } > > ATF_TC_WITHOUT_HEAD(unaligned_even_length_little_endian); > ATF_TC_BODY(unaligned_even_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x34, 0x12, 0x78, 0x56}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE_MSG(sum == 0x9753, "%d", sum); > } > > ATF_TC_WITHOUT_HEAD(unaligned_odd_length_little_endian); > ATF_TC_BODY(unaligned_odd_length_little_endian, tc) > { > u_char data[] __aligned(sizeof(u_short)) = > {0x00, 0x34, 0x12, 0x78, 0x56, 0x00, 0x9a}; > u_short sum; > >- sum = in_cksum(data + 1, nitems(data) - 1); >+ sum = in_cksum(data + 1, sizeof(struct rip), MAXPACKETSIZE, nitems(data) - 1); > ATF_REQUIRE(sum == 0xfd52); > } > > /* > * Main. > */ > > ATF_TP_ADD_TCS(tp) > { > ATF_TP_ADD_TC(tp, aligned_even_length_big_endian); > ATF_TP_ADD_TC(tp, aligned_odd_length_big_endian); > ATF_TP_ADD_TC(tp, aligned_even_length_little_endian); > ATF_TP_ADD_TC(tp, aligned_odd_length_little_endian); > ATF_TP_ADD_TC(tp, unaligned_even_length_big_endian); > ATF_TP_ADD_TC(tp, unaligned_odd_length_big_endian); > ATF_TP_ADD_TC(tp, unaligned_even_length_little_endian); > ATF_TP_ADD_TC(tp, unaligned_odd_length_little_endian); > > return (atf_no_error()); > } (In reply to Colin Zee from comment #2) thank you for confirming the patches. And, could you please let me know about how it is not clearing the segfault behaviors. Because the aditional patch that you have attached is responsible for ping test suite modification as from my patch I have modified the in_cksum code a bit, not the test suite code. So, as per my observation segfaults/crash has already cleared. but, also to clear the compilation issues for ping test suite, one additional patch might be required as I haven't modified that one. I have seen that the ping code is modified as compare to the last time when the issue was reported so attaching the modified patch as per the code revision 363556 Index: sbin/ping/ping.c =================================================================== --- sbin/ping/ping.c (revision 363566) +++ sbin/ping/ping.c (working copy) @@ -1066,7 +1066,7 @@ cc = ICMP_MINLEN + phdr_len + datalen; /* compute ICMP checksum here */ - icp.icmp_cksum = in_cksum(outpack, cc); + icp.icmp_cksum = in_cksum(outpack, sizeof(struct icmp), IP_MAXPACKET, cc); /* Update icmp_cksum in the raw packet data buffer. */ memcpy(outpack + offsetof(struct icmp, icmp_cksum), &icp.icmp_cksum, sizeof(icp.icmp_cksum)); @@ -1079,7 +1079,7 @@ /* Update ip_len in the raw packet data buffer. */ memcpy(outpackhdr + offsetof(struct ip, ip_len), &ip.ip_len, sizeof(ip.ip_len)); - ip.ip_sum = in_cksum(outpackhdr, cc); + ip.ip_sum = in_cksum(outpackhdr, sizeof(struct ip), IP_MAXPACKET, cc); /* Update ip_sum in the raw packet data buffer. */ memcpy(outpackhdr + offsetof(struct ip, ip_sum), &ip.ip_sum, sizeof(ip.ip_sum)); Index: sbin/ping/utils.c =================================================================== --- sbin/ping/utils.c (revision 363566) +++ sbin/ping/utils.c (working copy) @@ -55,7 +55,7 @@ * Checksum routine for Internet Protocol family headers (C Version) */ u_short -in_cksum(u_char *addr, int len) +in_cksum(u_char *addr, size_t struct_size, int ip_maxpacket, int len) { int nleft, sum; u_char *w; @@ -74,7 +74,7 @@ * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ - while (nleft > 1) { + while ((nleft > 1) && (w < &addr[ip_maxpacket - struct_size - sizeof(u_short)])) { u_short data; memcpy(&data, w, sizeof(data)); Index: sbin/ping/utils.h =================================================================== --- sbin/ping/utils.h (revision 363566) +++ sbin/ping/utils.h (working copy) @@ -33,6 +33,6 @@ #include <sys/types.h> -u_short in_cksum(u_char *, int); +u_short in_cksum(u_char *, size_t, int, int); #endif Created attachment 216784 [details]
latest modified patch as per the lastest code revision 363556 due to some variables modified
Hi Neeraj, Mark suggested less intrusive changes in https://reviews.freebsd.org/D25622 which also fixes other issues reported by you: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=239974 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=239978 Maxim |