From nobody@FreeBSD.org Mon Jan 22 14:45:28 2007 Return-Path: Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 2C86216A405 for ; Mon, 22 Jan 2007 14:45:28 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [69.147.83.33]) by mx1.freebsd.org (Postfix) with ESMTP id 1C11213C4C3 for ; Mon, 22 Jan 2007 14:45:28 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l0MEjRSD090792 for ; Mon, 22 Jan 2007 14:45:27 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id l0MEjRFA090791; Mon, 22 Jan 2007 14:45:27 GMT (envelope-from nobody) Message-Id: <200701221445.l0MEjRFA090791@www.freebsd.org> Date: Mon, 22 Jan 2007 14:45:27 GMT From: Yong Tang To: freebsd-gnats-submit@FreeBSD.org Subject: potentially a bug for inet_aton in sys/netinet/libalias/alias_proxy.c X-Send-Pr-Version: www-3.0 >Number: 108211 >Category: kern >Synopsis: [netinet] potentially a bug for inet_aton in sys/netinet/libalias/alias_proxy.c >Confidential: no >Severity: non-critical >Priority: low >Responsible: maxim >State: closed >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Jan 22 14:50:18 GMT 2007 >Closed-Date: Mon May 14 17:32:15 GMT 2007 >Last-Modified: Mon May 14 17:32:15 GMT 2007 >Originator: Yong Tang >Release: 6.1 >Organization: Sunbelt Software >Environment: >Description: In sys/netinet/libalias/alias_proxy.c, The following code exist. 158 #ifdef _KERNEL 159 static int 160 inet_aton(cp, addr) 161 const char *cp; 162 struct in_addr *addr; 163 { 180 l = strtoul(c, &endptr, 0); 181 182 if (l == ULONG_MAX || l == 0) 183 return (0); However, if the input cp is "0.0.0.0", then it seems this function will return (0) which is considered as an error. The reason is because 180: l = strtoul(c, &endptr, 0); l will return a 0 when the c is "0". Not quite sure if this is done purposely in FreeBSD but I have never experience similiar cases in other unix-platforms. Possible solution: change 182 (l == ULONG_MAX || l == 0) into 182 (l == ULONG_MAX || (l == 0 && (endptr == c)) >How-To-Repeat: review the code 180-182 in sys/netinet/libalias/alias_proxy.c >Fix: Possible solution: change 182 (l == ULONG_MAX || l == 0) into 182 (l == ULONG_MAX || (l == 0 && (endptr == c)) >Release-Note: >Audit-Trail: From: Bruce Evans To: Yong Tang Cc: freebsd-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org, green@freebsd.org Subject: Re: misc/108211: potentially a bug for inet_aton in sys/netinet/libalias/alias_proxy.c Date: Tue, 23 Jan 2007 17:11:27 +1100 (EST) On Mon, 22 Jan 2007, Yong Tang wrote: >> Description: > In sys/netinet/libalias/alias_proxy.c, > The following code exist. > > 158 #ifdef _KERNEL > 159 static int > 160 inet_aton(cp, addr) > 161 const char *cp; > 162 struct in_addr *addr; > 163 { > > > 180 l = strtoul(c, &endptr, 0); > 181 > 182 if (l == ULONG_MAX || l == 0) > 183 return (0); > > However, if the input cp is "0.0.0.0", then it seems this function will return (0) which is considered as an error. Bleah, yet another example of how not to check for errors in the strto* family. > The reason is because 180: > l = strtoul(c, &endptr, 0); > l will return a 0 when the c is "0". > > Not quite sure if this is done purposely in FreeBSD but I have never experience similiar cases in other unix-platforms. > > Possible solution: > > change > 182 (l == ULONG_MAX || l == 0) > > into > 182 (l == ULONG_MAX || (l == 0 && (endptr == c)) Why not just use libc's inet_aton()? Well, there is a problem -- this is for the kernel, so inet_aton() must be duplicated, but it can't be duplicated literally since the strto* family is fundamentally broken in the kernel. strto*'s API depends on errno for reporting errors correctly, and errno doesn't exist in the kernel. This kernel version is a literal duplicate of the libc version except for massive bitrot. It is identical to an old libc version (libc/net/inet_addr.c 1.16) except for small changes to avoid avoid checking errno and thus implement the bug, and minor bitrot in the libc version (const poisoning has only been done in the kernel). The massive bitrot in the current libc version (libc/inet/inet_addr.c 1.3) is mainly to implement a home made broken version of strtoul() inline. Perhaps strtoul() is too inflexible, but I doubt it. The must obvious bug in the new version is the usual overflow in home made implementations of atoi/strto*: "val = val * base + 'c' - '0'" may overflow, but there is no overflow checking. Thus the garbage input "4294967297.1.1.1" is now treated as "1.1.1.1" on systems with 32-bit unsigned longs although it is detected as being garbage on systems with 64-bit unsigned longs. Some style bugs are also obvious. Possibly simpler solution for 1 kernel version and 2 userland versions: - remove all traces of errno and related bogus checks for (l == ULONG_MAX) and (l == 0). Checking (errno == ERANGE) isn't wrong, but it isn't needed since the value will be ULONG_MAX after a range error, and since ULONG_MAX is too large for part of a dotted quad address it will be detected as an error later. Checking (l == ULONG_MAX) is wrong in general since it might not be a the result of a range error, but here the range is smaller so the check isn't wrong. However, the check is unnecessary since all values between 256 and ULONG_MAX inclusive will be dected as errors later. Checking (l == 0) is just a bug since 0 is within range. - remove broken home made strtol() in libc version, and otherwise merge versions and fix bitrot. The "new" libc version is actually not newer, but just bitrot back to the vendor version. FreeBSD fixed "old" version to use strtoul() in rev.1.8 in 1999, but the changes were lost when the vendor-version was reimported in a different directory in 2006. FreeBSD also made a few fixes to the old version between 1.8 and 1.16. The main one is related: 1.8 showed yet another way of how not to check for errors in strto* -- it checked (l == ERANGE) instead of (errno == ERANGE). Some of its other changes are not quite right. Bruce Responsible-Changed-From-To: freebsd-bugs->freebsd-net Responsible-Changed-By: linimon Responsible-Changed-When: Tue Apr 24 04:25:22 UTC 2007 Responsible-Changed-Why: Over to maintainer(s). http://www.freebsd.org/cgi/query-pr.cgi?pr=108211 State-Changed-From-To: open->patched State-Changed-By: maxim State-Changed-When: Mon Apr 30 20:22:26 UTC 2007 State-Changed-Why: Fixed in HEAD. Thanks! Responsible-Changed-From-To: freebsd-net->maxim Responsible-Changed-By: maxim Responsible-Changed-When: Mon Apr 30 20:22:26 UTC 2007 Responsible-Changed-Why: MFC reminder. http://www.freebsd.org/cgi/query-pr.cgi?pr=108211 From: dfilter@FreeBSD.ORG (dfilter service) To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/108211: commit references a PR Date: Mon, 30 Apr 2007 20:22:18 +0000 (UTC) maxim 2007-04-30 20:22:11 UTC FreeBSD src repository Modified files: sys/netinet/libalias alias_proxy.c Log: o Fix strtoul() error conditions check. PR: kern/108211 Submitted by: Yong Tang MFC after: 2 weeks Revision Changes Path 1.30 +1 -1 src/sys/netinet/libalias/alias_proxy.c _______________________________________________ cvs-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/cvs-all To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org" State-Changed-From-To: patched->closed State-Changed-By: maxim State-Changed-When: Mon May 14 17:32:00 UTC 2007 State-Changed-Why: Merged to RELENG_6. http://www.freebsd.org/cgi/query-pr.cgi?pr=108211 >Unformatted: