From nobody@FreeBSD.org  Thu Aug  8 02:11:49 2013
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTP id B8FD87EA
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  8 Aug 2013 02:11:49 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from oldred.freebsd.org (oldred.freebsd.org [8.8.178.121])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by mx1.freebsd.org (Postfix) with ESMTPS id 971B82BBF
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  8 Aug 2013 02:11:49 +0000 (UTC)
Received: from oldred.freebsd.org ([127.0.1.6])
	by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id r782BngU000119
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 8 Aug 2013 02:11:49 GMT
	(envelope-from nobody@oldred.freebsd.org)
Received: (from nobody@localhost)
	by oldred.freebsd.org (8.14.5/8.14.5/Submit) id r782BnsS000117;
	Thu, 8 Aug 2013 02:11:49 GMT
	(envelope-from nobody)
Message-Id: <201308080211.r782BnsS000117@oldred.freebsd.org>
Date: Thu, 8 Aug 2013 02:11:49 GMT
From: Garrett Cooper <yaneurabeya@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH] set{domain,host}name doesn't permit NUL terminated strings that are MAXHOSTNAMELEN long
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         181127
>Category:       kern
>Synopsis:       [libc] [patch] set{domain,host}name doesn't permit NUL terminated strings that are MAXHOSTNAMELEN long
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Aug 08 02:20:00 UTC 2013
>Closed-Date:    
>Last-Modified:  Fri Aug 09 01:30:50 UTC 2013
>Originator:     Garrett Cooper
>Release:        10-CURRENT
>Organization:
EMC Isilon
>Environment:
FreeBSD gran-tourismo.west.isilon.com 10.0-CURRENT FreeBSD 10.0-CURRENT #8 bc57ffb: Fri Aug  2 15:14:32 PDT 2013     root@:/usr/obj/usr/src/sys/GRAN-TOURISMO  amd64
>Description:
The noted link/patch fixes POSIX and generic requirement compliance for set{domain,host}name per the manpages by accounting for the fact that the string
must be NUL terminated.

Found with the NetBSD t_set{domain,host}name testcases:

Before:

$ pwd
/usr/tests/lib/libc/gen
$ sudo atf-run t_setdomainname | atf-report
t_setdomainname (1/1): 3 test cases
    setdomainname_basic: [0.019497s] Failed: /usr/src/lib/libc/tests/gen/t_setdomainname.c:66: setdomainname(domains[i],sizeof(domains[i])) == 0 not met
    setdomainname_limit: [0.004173s] Passed.
    setdomainname_perm: [0.005297s] Passed.
[0.029872s]

Failed test cases:
    t_setdomainname:setdomainname_basic

Summary for 1 test programs:
    2 passed test cases.
    1 failed test cases.
    0 expected failed test cases.
    0 skipped test cases.

After:

# atf-run t_setdomainname t_sethostname | atf-report t_setdomainname (1/2): 3 test cases
    setdomainname_basic: [0.004606s] Passed.
    setdomainname_limit: [0.004276s] Passed.
    setdomainname_perm: [0.004848s] Passed.
[0.014680s]

t_sethostname (2/2): 3 test cases
    sethostname_basic: [0.003908s] Passed.
    sethostname_limit: [0.004842s] Passed.
    sethostname_perm: [0.004738s] Passed.
[0.014337s]

Summary for 2 test programs:
    6 passed test cases.
    0 failed test cases.
    0 expected failed test cases.
    0 skipped test cases.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

From 1b8333ca810b682d8ef049887a3b6cc9abd80807 Mon Sep 17 00:00:00 2001
From: Garrett Cooper <yanegomi@gmail.com>
Date: Wed, 7 Aug 2013 18:59:44 -0700
Subject: [PATCH] Permit setting hostnames that are MAX_HOSTNAMELEN long and
 are NUL terminated

Sponsored-by: EMC Isilon
---
 sys/kern/kern_mib.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index c84d4b2..384c14d 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -266,7 +266,7 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 {
 	struct prison *pr, *cpr;
 	size_t pr_offset;
-	char tmpname[MAXHOSTNAMELEN];
+	char tmpname[MAXHOSTNAMELEN+1];
 	int descend, error, len;
 
 	/*
@@ -314,11 +314,11 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 
 SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
-    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN,
+    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN+1,
     sysctl_hostname, "A", "Hostname");
 SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname,
     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
-    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN,
+    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN+1,
     sysctl_hostname, "A", "Name of the current YP/NIS domain");
 SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid,
     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
-- 
1.8.3.4



>Release-Note:
>Audit-Trail:

From: Bruce Evans <brde@optusnet.com.au>
To: Garrett Cooper <yaneurabeya@gmail.com>
Cc: freebsd-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org
Subject: Re: kern/181127: [PATCH] set{domain, host}name doesn't permit NUL
 terminated strings that are MAXHOSTNAMELEN long
Date: Thu, 8 Aug 2013 21:35:45 +1000 (EST)

 On Thu, 8 Aug 2013, Garrett Cooper wrote:
 
 >> Synopsis:       [PATCH] set{domain,host}name doesn't permit NUL terminated strings that are MAXHOSTNAMELEN long
 > ...
 >> Description:
 > The noted link/patch fixes POSIX and generic requirement compliance for set{domain,host}name per the manpages by accounting for the fact that the string
 > must be NUL terminated.
 
 The bugs seem to be mainly in the tests, so the proposed fix enlarges them.
 MAXHOSTNAMELEN is already 1 larger than the POSIX limit {HOST_NAME_MAX}
 (see the sysconf(3) sources).
 
 > Found with the NetBSD t_set{domain,host}name testcases:
 >
 > Before:
 >
 > $ pwd
 > /usr/tests/lib/libc/gen
 > $ sudo atf-run t_setdomainname | atf-report
 > t_setdomainname (1/1): 3 test cases
 >    setdomainname_basic: [0.019497s] Failed: /usr/src/lib/libc/tests/gen/t_setdomainname.c:66: setdomainname(domains[i],sizeof(domains[i])) == 0 not met
 >    setdomainname_limit: [0.004173s] Passed.
 >    setdomainname_perm: [0.005297s] Passed.
 > [0.029872s]
 
 I'm not sure what these do, but according to the Synopsis,
 set{domain,host}name correctly doesn't permit NUL terminated strings that
 are MAXHOSTNAMELEN long (not counting space for the NUL).  MAXHOSTNAMELEN
 counts space for the NUL and is 1 larger than {HOST_NAME_MAX}.
 
 > diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
 > index c84d4b2..384c14d 100644
 > --- a/sys/kern/kern_mib.c
 > +++ b/sys/kern/kern_mib.c
 > @@ -266,7 +266,7 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 > {
 > 	struct prison *pr, *cpr;
 > 	size_t pr_offset;
 > -	char tmpname[MAXHOSTNAMELEN];
 > +	char tmpname[MAXHOSTNAMELEN+1];
 > 	int descend, error, len;
 >
 > 	/*
 
 The patch also adds some style bugs (missing spaces around binary operator
 '+').
 
 > @@ -314,11 +314,11 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 >
 > SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
 >     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 > -    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN,
 > +    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN+1,
 >     sysctl_hostname, "A", "Hostname");
 > SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname,
 >     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 > -    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN,
 > +    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN+1,
 >     sysctl_hostname, "A", "Name of the current YP/NIS domain");
 > SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid,
 >     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 
 The sysctls were originally simple SYSCTL_STRING()s and I think they
 worked then.  Now they are quite complicated, to  support jails, etc.,
 but they still use sysctl_handle_string() so I think they handle
 (non)strings and (non)termination the same.  Note that
 sysctl_handle_string() doesn't actually return strings unless the
 buffer is large enough to hold the NUL terminator.  It just truncates.
 This is reflected in the gethostname(3) API.  The name length for
 gethostname() must be 1 larger than {HOST_NAME_MAX} to ensure
 getting a string.  OTOH, the name length for sethostname(3) should
 not include space for the NUL, so it must not be larger than
 {HOST_NAME_MAX}.  If it is larger than {HOST_NAME_MAX}, then the
 syscall will just fail.  If it is larger than the string length
 (to include the NUL and possibly more) but not larger than
 {HOST_NAME_MAX}, then the syscall will succeed and the string will
 just be terminated more than once.  (It would be safer to write NULs
 from the end of the string until the end of the buffer in all cases.)
 
 Bruce

From: Garrett Cooper <yaneurabeya@gmail.com>
To: Bruce Evans <brde@optusnet.com.au>
Cc: freebsd-gnats-submit@freebsd.org,
 freebsd-bugs@freebsd.org
Subject: Re: kern/181127: [PATCH] set{domain, host}name doesn't permit NUL terminated strings that are MAXHOSTNAMELEN long
Date: Thu, 8 Aug 2013 16:00:53 -0700

 On Aug 8, 2013, at 4:35 AM, Bruce Evans wrote:
 
 > On Thu, 8 Aug 2013, Garrett Cooper wrote:
 >=20
 >>> Synopsis:       [PATCH] set{domain,host}name doesn't permit NUL =
 terminated strings that are MAXHOSTNAMELEN long
 >> ...
 >>> Description:
 >> The noted link/patch fixes POSIX and generic requirement compliance =
 for set{domain,host}name per the manpages by accounting for the fact =
 that the string
 >> must be NUL terminated.
 >=20
 > The bugs seem to be mainly in the tests, so the proposed fix enlarges =
 them.
 > MAXHOSTNAMELEN is already 1 larger than the POSIX limit =
 {HOST_NAME_MAX}
 > (see the sysconf(3) sources).
 
 So the fix is bogus. Ok, missed that MAXHOSTNAMELEN was '\0' inclusive.
 
 >> Found with the NetBSD t_set{domain,host}name testcases:
 >>=20
 >> Before:
 >>=20
 >> $ pwd
 >> /usr/tests/lib/libc/gen
 >> $ sudo atf-run t_setdomainname | atf-report
 >> t_setdomainname (1/1): 3 test cases
 >>   setdomainname_basic: [0.019497s] Failed: =
 /usr/src/lib/libc/tests/gen/t_setdomainname.c:66: =
 setdomainname(domains[i],sizeof(domains[i])) =3D=3D 0 not met
 >>   setdomainname_limit: [0.004173s] Passed.
 >>   setdomainname_perm: [0.005297s] Passed.
 >> [0.029872s]
 >=20
 > I'm not sure what these do, but according to the Synopsis,
 > set{domain,host}name correctly doesn't permit NUL terminated strings =
 that
 > are MAXHOSTNAMELEN long (not counting space for the NUL).  =
 MAXHOSTNAMELEN
 > counts space for the NUL and is 1 larger than {HOST_NAME_MAX}.
 
 Yes. It's kind of odd why NetBSD passes here, but this should work on =
 FreeBSD as well as they aren't doing anything going out-of-bounds in the =
 testcases (see =
 https://github.com/yaneurabeya/freebsd/blob/master/lib/libc/tests/gen/t_se=
 tdomainname.c , =
 https://github.com/yaneurabeya/freebsd/blob/master/lib/libc/tests/gen/t_se=
 thostname.c if you're curious).
 
 ...
 
 >> @@ -314,11 +314,11 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 >>=20
 >> SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
 >>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >> -    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN,
 >> +    (void *)(offsetof(struct prison, pr_hostname)), =
 MAXHOSTNAMELEN+1,
 >>    sysctl_hostname, "A", "Hostname");
 >> SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname,
 >>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >> -    (void *)(offsetof(struct prison, pr_domainname)), =
 MAXHOSTNAMELEN,
 >> +    (void *)(offsetof(struct prison, pr_domainname)), =
 MAXHOSTNAMELEN+1,
 >>    sysctl_hostname, "A", "Name of the current YP/NIS domain");
 >> SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid,
 >>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >=20
 > The sysctls were originally simple SYSCTL_STRING()s and I think they
 > worked then.  Now they are quite complicated, to  support jails, etc.,
 > but they still use sysctl_handle_string() so I think they handle
 > (non)strings and (non)termination the same.  Note that
 > sysctl_handle_string() doesn't actually return strings unless the
 > buffer is large enough to hold the NUL terminator.  It just truncates.
 > This is reflected in the gethostname(3) API.  The name length for
 > gethostname() must be 1 larger than {HOST_NAME_MAX} to ensure
 > getting a string.  OTOH, the name length for sethostname(3) should
 > not include space for the NUL, so it must not be larger than
 > {HOST_NAME_MAX}.  If it is larger than {HOST_NAME_MAX}, then the
 > syscall will just fail.  If it is larger than the string length
 > (to include the NUL and possibly more) but not larger than
 > {HOST_NAME_MAX}, then the syscall will succeed and the string will
 > just be terminated more than once.  (It would be safer to write NULs
 > from the end of the string until the end of the buffer in all cases.)
 
 So translation is: is there's a bug in the sysctl handler after jail =
 support was added and there's no reasonable way to fix it without =
 reverting things back to their sane forms?
 
 Thanks...=

From: Bruce Evans <brde@optusnet.com.au>
To: Garrett Cooper <yaneurabeya@gmail.com>
Cc: Bruce Evans <brde@optusnet.com.au>, freebsd-gnats-submit@freebsd.org, 
    freebsd-bugs@freebsd.org
Subject: Re: kern/181127: [PATCH] set{domain, host}name doesn't permit NUL
 terminated strings that are MAXHOSTNAMELEN long
Date: Fri, 9 Aug 2013 10:39:37 +1000 (EST)

 On Thu, 8 Aug 2013, Garrett Cooper wrote:
 
 > On Aug 8, 2013, at 4:35 AM, Bruce Evans wrote:
 >
 >> On Thu, 8 Aug 2013, Garrett Cooper wrote:
 >>
 >>>> Synopsis:       [PATCH] set{domain,host}name doesn't permit NUL terminated strings that are MAXHOSTNAMELEN long
 >>> ...
 >>>> Description:
 >>> The noted link/patch fixes POSIX and generic requirement compliance for set{domain,host}name per the manpages by accounting for the fact that the string
 >>> must be NUL terminated.
 >>
 >> The bugs seem to be mainly in the tests, so the proposed fix enlarges them.
 >> MAXHOSTNAMELEN is already 1 larger than the POSIX limit {HOST_NAME_MAX}
 >> (see the sysconf(3) sources).
 >
 > So the fix is bogus. Ok, missed that MAXHOSTNAMELEN was '\0' inclusive.
 >
 >>> Found with the NetBSD t_set{domain,host}name testcases:
 >>>
 >>> Before:
 >>>
 >>> $ pwd
 >>> /usr/tests/lib/libc/gen
 >>> $ sudo atf-run t_setdomainname | atf-report
 >>> t_setdomainname (1/1): 3 test cases
 >>>   setdomainname_basic: [0.019497s] Failed: /usr/src/lib/libc/tests/gen/t_setdomainname.c:66: setdomainname(domains[i],sizeof(domains[i])) == 0 not met
 >>>   setdomainname_limit: [0.004173s] Passed.
 >>>   setdomainname_perm: [0.005297s] Passed.
 >>> [0.029872s]
 >>
 >> I'm not sure what these do, but according to the Synopsis,
 >> set{domain,host}name correctly doesn't permit NUL terminated strings that
 >> are MAXHOSTNAMELEN long (not counting space for the NUL).  MAXHOSTNAMELEN
 >> counts space for the NUL and is 1 larger than {HOST_NAME_MAX}.
 >
 > Yes. It's kind of odd why NetBSD passes here, but this should work on FreeBSD as well as they aren't doing anything going out-of-bounds in the testcases (see https://github.com/yaneurabeya/freebsd/blob/master/lib/libc/tests/gen/t_setdomainname.c , https://github.com/yaneurabeya/freebsd/blob/master/lib/libc/tests/gen/t_sethostname.c if you're curious).
 
 It uses MAXHOSTNAMELEN + 1 in (only) 1 place, and then seems to check that
 setdomainname() on a null name with "length" MAXHOSTNAMELEN + 1 fails.
 It doesn't seem to test any strings of nearly length MAXHOSTNAMELEN.
 
 > ...
 >
 >>> @@ -314,11 +314,11 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
 >>>
 >>> SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
 >>>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >>> -    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN,
 >>> +    (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN+1,
 >>>    sysctl_hostname, "A", "Hostname");
 >>> SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname,
 >>>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >>> -    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN,
 >>> +    (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN+1,
 >>>    sysctl_hostname, "A", "Name of the current YP/NIS domain");
 >>> SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid,
 >>>    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
 >>
 >> The sysctls were originally simple SYSCTL_STRING()s and I think they
 >> worked then.  Now they are quite complicated, to  support jails, etc.,
 >> but they still use sysctl_handle_string() so I think they handle
 >> (non)strings and (non)termination the same.  Note that
 >> sysctl_handle_string() doesn't actually return strings unless the
 >> buffer is large enough to hold the NUL terminator.  It just truncates.
 >> This is reflected in the gethostname(3) API.  The name length for
 >> gethostname() must be 1 larger than {HOST_NAME_MAX} to ensure
 >> getting a string.  OTOH, the name length for sethostname(3) should
 >> not include space for the NUL, so it must not be larger than
 >> {HOST_NAME_MAX}.  If it is larger than {HOST_NAME_MAX}, then the
 >> syscall will just fail.  If it is larger than the string length
 >> (to include the NUL and possibly more) but not larger than
 >> {HOST_NAME_MAX}, then the syscall will succeed and the string will
 >> just be terminated more than once.  (It would be safer to write NULs
 >> from the end of the string until the end of the buffer in all cases.)
 >
 > So translation is: is there's a bug in the sysctl handler after jail support was added and there's no reasonable way to fix it without reverting things back to their sane forms?
 
 No.  I suspected a bug in the jail support, but couldn't see any.  You will
 have to check with name and string lengths of nearly MAXHOSTNAMELEN + 1 on
 (or whatever the kernel buffer size is for plain SYSCTL_STRING()) to see if
 the jail support gives any differences.
 
 Bruce
>Unformatted:
