From nobody@FreeBSD.org  Thu Jun 14 09:30:28 2012
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 7A5DA106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 14 Jun 2012 09:30:28 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [69.147.83.34])
	by mx1.freebsd.org (Postfix) with ESMTP id 66DB08FC15
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 14 Jun 2012 09:30:28 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q5E9USg4051299
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 14 Jun 2012 09:30:28 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q5E9USBl051298;
	Thu, 14 Jun 2012 09:30:28 GMT
	(envelope-from nobody)
Message-Id: <201206140930.q5E9USBl051298@red.freebsd.org>
Date: Thu, 14 Jun 2012 09:30:28 GMT
From: Garrett Cooper <yaneurabeya@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] sysctl*(3) cannot fail with EFAULT if name contains an invalid address
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         169056
>Category:       docs
>Synopsis:       [patch] sysctl*(3) cannot fail with EFAULT if name contains an invalid address
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    trhodes
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 14 09:40:01 UTC 2012
>Closed-Date:    
>Last-Modified:  Sun Feb 03 22:30:37 UTC 2013
>Originator:     Garrett Cooper
>Release:        10-CURRENT
>Organization:
EMC Isilon
>Environment:
FreeBSD fuji-dtrace-current.local 10.0-CURRENT FreeBSD 10.0-CURRENT #2 r236393M: Sun Jun  3 01:19:51 PDT 2012     root@fuji-dtrace-current.local:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
Based on code inspection in lib/libc/gen/sysctl.c, the requirement that states that EFAULT will be raised if name was an invalid memory address is bogus. Furthermore, it generates a segfault (or other random memory corruption issues) if the value passed in to name is invalid, due to the following line in sysctl.c:

 49 int
 50 sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
 51     const void *newp, size_t newlen)
 52 {
 53         if (name[0] != CTL_USER)
 54                 return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen)    );

Example:

$ cat ~/bad_sysctl.c 
#include <sys/param.h>
#include <sys/sysctl.h>

int
main(void)
{
	return sysctl((int*)-1, 2, NULL, NULL, NULL, 0) == 0 ? 0 : 1;
}
$ gcc -Wall -o ~/bad_sysctl ~/bad_sysctl.c
$ ~/bad_sysctl
Segmentation fault: 11 (core dumped)
$

The attached patch removes bogus requirement in sysctl(3). Whether or not the segfault in libc should be `fixed` is another topic entirely.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

Index: lib/libc/gen/sysctl.3
===================================================================
--- lib/libc/gen/sysctl.3	(revision 236827)
+++ lib/libc/gen/sysctl.3	(working copy)
@@ -814,7 +814,6 @@
 .Bl -tag -width Er
 .It Bq Er EFAULT
 The buffer
-.Fa name ,
 .Fa oldp ,
 .Fa newp ,
 or length pointer


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-doc->trhodes 
Responsible-Changed-By: trhodes 
Responsible-Changed-When: Sun Jul 22 13:30:40 UTC 2012 
Responsible-Changed-Why:  
Take - I spoke to Mr. Cooper about this in email. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=169056 

From: John Baldwin <jhb@freebsd.org>
To: bug-followup@freebsd.org,
 yanegomi@gmail.com
Cc:  
Subject: Re: docs/169056: [patch] sysctl*(3) cannot fail with EFAULT if name contains an invalid address
Date: Wed, 29 Aug 2012 08:47:31 -0400

 FYI, I think I said this in e-mail already, but I think the proper fix for 
 this is to always call __sysctl() and only check for CTL_USER if the sysctl 
 fails with ENOENT.
 
 -- 
 John Baldwin

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: docs/169056: commit references a PR
Date: Thu,  6 Sep 2012 20:15:54 +0000 (UTC)

 Author: trhodes
 Date: Thu Sep  6 20:15:44 2012
 New Revision: 240176
 URL: http://svn.freebsd.org/changeset/base/240176
 
 Log:
   Avoid segfault if name is invalid.  Basically, only
   check for CTL_USER if the sysctl fails with ENOENT.
   
   PR:		169056
   Reviewed by:	jhb
 
 Modified:
   head/lib/libc/gen/sysctl.c
 
 Modified: head/lib/libc/gen/sysctl.c
 ==============================================================================
 --- head/lib/libc/gen/sysctl.c	Thu Sep  6 19:26:59 2012	(r240175)
 +++ head/lib/libc/gen/sysctl.c	Thu Sep  6 20:15:44 2012	(r240176)
 @@ -50,8 +50,11 @@ int
  sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
      const void *newp, size_t newlen)
  {
 -	if (name[0] != CTL_USER)
 -		return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
 +	int retval;
 +
 +	retval = __sysctl(name, namelen, oldp, oldlenp, newp, newlen);
 +	if (retval != -1 || errno != ENOENT || name[0] != CTL_USER)
 +		return (retval);
  
  	if (newp != NULL) {
  		errno = EPERM;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: Jilles Tjoelker <jilles@stack.nl>
To: bug-followup@FreeBSD.org, yanegomi@gmail.com,
	John Baldwin <jhb@freebsd.org>
Cc:  
Subject: Re: docs/169056: [patch] sysctl*(3) cannot fail with EFAULT if name
 contains an invalid address
Date: Fri, 7 Sep 2012 13:35:22 +0200

 > [sysctl() crashes if passes an invalid 'name' pointer]
 
 I don't really agree with r240176. If an application passes an invalid
 pointer to a function, the behaviour is undefined per POSIX and both
 [EFAULT] and a segfault are valid.
 
 A segfault seems the best response here, given that it has always been
 that way. It also makes things slightly faster for well-behaved
 applications because a system call is not done for CTL_USER names.
 
 Furthermore, this situation occurs more frequently and it may not always
 be possible to avoid a segfault efficiently. For example, while the
 sigaction() system call will fail with [EFAULT] if passed an invalid
 pointer, libthr's wrapper will read and write from userland and
 therefore segfault if passed an invalid pointer.
 
 I don't really like [EFAULT] in general because it is easily ignored and
 because the system call often commits anyway (leaving the application
 without important information that would have been written to the bad
 pointer).
 
 -- 
 Jilles Tjoelker

From: Tom Rhodes <trhodes@FreeBSD.org>
To: Jilles Tjoelker <jilles@stack.nl>
Cc: John Baldwin <jhb@FreeBSD.org>, bug-followup@FreeBSD.org,
 yanegomi@gmail.com
Subject: Re: docs/169056: [patch] sysctl*(3) cannot fail with EFAULT if name
 contains an invalid address
Date: Fri, 7 Sep 2012 10:18:48 -0400

 On Fri, 7 Sep 2012 11:40:11 GMT
 Jilles Tjoelker <jilles@stack.nl> wrote:
 
 > The following reply was made to PR docs/169056; it has been noted by GNATS.
 > 
 > From: Jilles Tjoelker <jilles@stack.nl>
 > To: bug-followup@FreeBSD.org, yanegomi@gmail.com,
 > 	John Baldwin <jhb@freebsd.org>
 > Cc:  
 > Subject: Re: docs/169056: [patch] sysctl*(3) cannot fail with EFAULT if name
 >  contains an invalid address
 > Date: Fri, 7 Sep 2012 13:35:22 +0200
 > 
 >  > [sysctl() crashes if passes an invalid 'name' pointer]
 >  
 >  I don't really agree with r240176. If an application passes an invalid
 >  pointer to a function, the behaviour is undefined per POSIX and both
 >  [EFAULT] and a segfault are valid.
 
 Then why let it crash at all for the user?  Why not just return EFAULT
 and have done with it?
 
 >  
 >  A segfault seems the best response here, given that it has always been
 >  that way. It also makes things slightly faster for well-behaved
 >  applications because a system call is not done for CTL_USER names.
 
 Slightly faster?  I don't think an additional if statement is that damaging
 to performance.
 
 >  
 >  Furthermore, this situation occurs more frequently and it may not always
 >  be possible to avoid a segfault efficiently. For example, while the
 >  sigaction() system call will fail with [EFAULT] if passed an invalid
 >  pointer, libthr's wrapper will read and write from userland and
 >  therefore segfault if passed an invalid pointer.
 
 I would suggest an additional check there too; however, I'm starting
 to be concerned that we would spend too much time "protecting
 the developer from themselves" here.
 
 >  
 >  I don't really like [EFAULT] in general because it is easily ignored and
 >  because the system call often commits anyway (leaving the application
 >  without important information that would have been written to the bad
 >  pointer).
 
 Noted.  If you strongly about this, I'll back it out.  But I would recommend
 Garrett's manual page patch in the backout case.  Cheers,
 
 --
 Tom Rhodes
>Unformatted:
