From bsd@dhke.de  Wed Jul  4 20:43:56 2012
Return-Path: <bsd@dhke.de>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id CE783106564A
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  4 Jul 2012 20:43:56 +0000 (UTC)
	(envelope-from bsd@dhke.de)
Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.17.9])
	by mx1.freebsd.org (Postfix) with ESMTP id 61CEF8FC0C
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  4 Jul 2012 20:43:56 +0000 (UTC)
Received: from kaliope.home (nrbg-4d075efe.pool.mediaWays.net [77.7.94.254])
	by mrelayeu.kundenserver.de (node=mreu4) with ESMTP (Nemesis)
	id 0MTaYl-1SLsuC1CcB-00SSC9; Wed, 04 Jul 2012 22:43:55 +0200
Received: by kaliope.home (Postfix, from userid 10001)
	id 7F33CA3; Wed,  4 Jul 2012 22:43:54 +0200 (CEST)
Message-Id: <20120704204354.7F33CA3@kaliope.home>
Date: Wed,  4 Jul 2012 22:43:54 +0200 (CEST)
From: Peter Wullinger <bsd@dhke.de>
Reply-To: Peter Wullinger <bsd@dhke.de>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: fexecve() and hashbang-scripts
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         169651
>Category:       kern
>Synopsis:       fexecve() and hashbang-scripts
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    mjg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 04 20:50:04 UTC 2012
>Closed-Date:    Wed Jul 18 04:55:25 UTC 2012
>Last-Modified:  Wed Jul 18 05:00:28 UTC 2012
>Originator:     Peter Wullinger
>Release:        FreeBSD 9.0-STABLE amd64
>Organization:
>Environment:
System: FreeBSD kaliope 9.0-STABLE FreeBSD 9.0-STABLE #13 r237164: Sat Jun 16 18:31:08 CEST 2012 src@kaliope:/usr/obj/usr/src/sys/KALIOPE_MONO amd64


	
>Description:

The fexecve() does not seem to work as described.

I was able identify to cases
1) opening the file descriptor passwd to 
   fexecve() with O_EXEC does not work.
   (see test case 1), below.
2) passing a readonly file descriptor
   to fexecve() with the target file
   being an interpreted script with
   a #! marker causes error message

   cannot open /dev/fd/n: No such file or directory

   to be raised from the target interpreter.

>How-To-Repeat:

Test case 1)
extern char **environ;

int
main(int argc, char *argv[])
{
    int fd = open("/bin/ls" , O_EXEC);
    fexecve(fd, argv, environ);
    perror("fexecve");
}

Yields
fexecve: Bad file descriptor

Changing O_EXEC to O_RDONLY works.

Test case 2)

extern char **environ;

int
main(int argc, char *argv[])
{
    int fd = open("/usr/bin/man" , O_RDONLY); 
	fexecve(fd, argv, environ);
	perror("fexecve");
}

Yields:
cannot open /dev/fd/3: No such file or directory

(/usr/bin/man is a shell script)

>Fix:

no fix known yet.

>Release-Note:
>Audit-Trail:

From: Mateusz Guzik <mjguzik@gmail.com>
To: bug-followup@FreeBSD.org, bsd@dhke.de
Cc:  
Subject: Re: kern/169651: fexecve() and hashbang-scripts
Date: Thu, 5 Jul 2012 01:38:52 +0200

 Hi,
 
 for the first problem try this patch:
 http://people.freebsd.org/~mjg/patches/fexec-fgetvp.patch
 
 And for the second try mounting fdescfs(5).
 
 -- 
 Mateusz Guzik <mjguzik gmail.com>
Responsible-Changed-From-To: freebsd-bugs->mjg 
Responsible-Changed-By: mjg 
Responsible-Changed-When: Wed Jul 4 23:46:03 UTC 2012 
Responsible-Changed-Why:  
I'll take it. 

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

From: Peter Wullinger <bsd@dhke.de>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/169651: fexecve() and hashbang-scripts
Date: Thu, 5 Jul 2012 08:20:42 +0200

 Hi,
 
 I realized my own error with the second one
 after more close reading of the man page.
 Mounting fdescfs fixes the second problem.
 
 Attached patch fixes the first problem.
 I have not tested with capsicum, though.
 
 Thanks
Responsible-Changed-From-To: mjg->kib 
Responsible-Changed-By: kib 
Responsible-Changed-When: Sat Jul 7 22:14:36 UTC 2012 
Responsible-Changed-Why:  
I think it is time to use the specific permission check routine for 
fexecve. Please see the patch at 
http://people.freebsd.org/~kib/misc/fexec_o_exec.1.patch 

Note that O_EXEC-opened shebang script cannot be executed, since 
interpreter needs to read from the script file. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=169651 
Responsible-Changed-From-To: kib->mjg 
Responsible-Changed-By: mjg 
Responsible-Changed-When: Sun Jul 8 00:53:05 UTC 2012 
Responsible-Changed-Why:  
Re-take, I'm committing the fix. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=169651 
State-Changed-From-To: open->patched 
State-Changed-By: mjg 
State-Changed-When: Sun Jul 8 00:53:41 UTC 2012 
State-Changed-Why:  
Fix committed as r238220, will MFC in 1 week. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/169651: commit references a PR
Date: Sun,  8 Jul 2012 00:51:52 +0000 (UTC)

 Author: mjg
 Date: Sun Jul  8 00:51:38 2012
 New Revision: 238220
 URL: http://svn.freebsd.org/changeset/base/238220
 
 Log:
   Unbreak handling of descriptors opened with O_EXEC by fexecve(2).
   
   While here return EBADF for descriptors opened for writing (previously it was ETXTBSY).
   
   Add fgetvp_exec function which performs appropriate checks.
   
   PR:		kern/169651
   In collaboration with:	kib
   Approved by:	trasz (mentor)
   MFC after:	1 week
 
 Modified:
   head/sys/kern/kern_descrip.c
   head/sys/kern/kern_exec.c
   head/sys/sys/file.h
 
 Modified: head/sys/kern/kern_descrip.c
 ==============================================================================
 --- head/sys/kern/kern_descrip.c	Sat Jul  7 22:22:13 2012	(r238219)
 +++ head/sys/kern/kern_descrip.c	Sun Jul  8 00:51:38 2012	(r238220)
 @@ -2340,11 +2340,11 @@ _fget(struct thread *td, int fd, struct 
  
  	/*
  	 * FREAD and FWRITE failure return EBADF as per POSIX.
 -	 *
 -	 * Only one flag, or 0, may be specified.
  	 */
  	if ((flags == FREAD && (fp->f_flag & FREAD) == 0) ||
 -	    (flags == FWRITE && (fp->f_flag & FWRITE) == 0)) {
 +	    (flags == FWRITE && (fp->f_flag & FWRITE) == 0) ||
 +	    (flags == (FREAD | FEXEC) &&
 +	    (((fp->f_flag & flags) == 0) || ((fp->f_flag & FWRITE) != 0)))) {
  		fdrop(fp, td);
  		return (EBADF);
  	}
 @@ -2444,6 +2444,13 @@ fgetvp_read(struct thread *td, int fd, c
  	return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
  }
  
 +int
 +fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
 +{
 +
 +	return (_fgetvp(td, fd, FREAD | FEXEC, rights, NULL, vpp));
 +}
 +
  #ifdef notyet
  int
  fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
 
 Modified: head/sys/kern/kern_exec.c
 ==============================================================================
 --- head/sys/kern/kern_exec.c	Sat Jul  7 22:22:13 2012	(r238219)
 +++ head/sys/kern/kern_exec.c	Sun Jul  8 00:51:38 2012	(r238220)
 @@ -443,8 +443,10 @@ interpret:
  		/*
  		 * Some might argue that CAP_READ and/or CAP_MMAP should also
  		 * be required here; such arguments will be entertained.
 +		 *
 +		 * Descriptors opened only with O_EXEC or O_RDONLY are allowed.
  		 */
 -		error = fgetvp_read(td, args->fd, CAP_FEXECVE, &binvp);
 +		error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
  		if (error)
  			goto exec_fail;
  		vfslocked = VFS_LOCK_GIANT(binvp->v_mount);
 
 Modified: head/sys/sys/file.h
 ==============================================================================
 --- head/sys/sys/file.h	Sat Jul  7 22:22:13 2012	(r238219)
 +++ head/sys/sys/file.h	Sun Jul  8 00:51:38 2012	(r238220)
 @@ -238,6 +238,8 @@ fo_chown_t	invfo_chown;
  
  void finit(struct file *, u_int, short, void *, struct fileops *);
  int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
 +int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
 +    struct vnode **vpp);
  int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
      cap_rights_t *have, struct vnode **vpp);
  int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,
 _______________________________________________
 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"
 
State-Changed-From-To: patched->closed 
State-Changed-By: mjg 
State-Changed-When: Wed Jul 18 04:55:24 UTC 2012 
State-Changed-Why:  
MFCed to stable/9 as r238560. Thanks for reporting! 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/169651: commit references a PR
Date: Wed, 18 Jul 2012 04:52:53 +0000 (UTC)

 Author: mjg
 Date: Wed Jul 18 04:52:37 2012
 New Revision: 238560
 URL: http://svn.freebsd.org/changeset/base/238560
 
 Log:
   MFC r238220, r238272:
   
   Unbreak handling of descriptors opened with O_EXEC by fexecve(2).
   
   While here return EBADF for descriptors opened for writing (previously it was ETXTBSY).
   
   Add fgetvp_exec function which performs appropriate checks.
   
   ==
   
   Follow-up commit to r238220:
   
   Pass only FEXEC (instead of FREAD|FEXEC) in fgetvp_exec. _fget has to check for
   !FWRITE anyway and may as well know about FREAD.
   
   Make _fget code a bit more readable by converting permission checking from if()
   to switch(). Assert that correct permission flags are passed.
   
   PR:		kern/169651
   In collaboration with:	kib
   Approved by:	re (hrs), trasz (mentor)
 
 Modified:
   stable/9/sys/kern/kern_descrip.c
   stable/9/sys/kern/kern_exec.c
   stable/9/sys/sys/file.h
 Directory Properties:
   stable/9/sys/   (props changed)
 
 Modified: stable/9/sys/kern/kern_descrip.c
 ==============================================================================
 --- stable/9/sys/kern/kern_descrip.c	Tue Jul 17 22:16:10 2012	(r238559)
 +++ stable/9/sys/kern/kern_descrip.c	Wed Jul 18 04:52:37 2012	(r238560)
 @@ -2329,8 +2329,8 @@ _fget(struct thread *td, int fd, struct 
  	struct file *fp;
  #ifdef CAPABILITIES
  	struct file *fp_fromcap;
 -	int error;
  #endif
 +	int error;
  
  	*fpp = NULL;
  	if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
 @@ -2369,7 +2369,7 @@ _fget(struct thread *td, int fd, struct 
  		else
  			error = cap_funwrap_mmap(fp, needrights, maxprotp,
  			    &fp_fromcap);
 -		if (error) {
 +		if (error != 0) {
  			fdrop(fp, td);
  			return (error);
  		}
 @@ -2394,14 +2394,30 @@ _fget(struct thread *td, int fd, struct 
  
  	/*
  	 * FREAD and FWRITE failure return EBADF as per POSIX.
 -	 *
 -	 * Only one flag, or 0, may be specified.
  	 */
 -	if ((flags == FREAD && (fp->f_flag & FREAD) == 0) ||
 -	    (flags == FWRITE && (fp->f_flag & FWRITE) == 0)) {
 +	error = 0;
 +	switch (flags) {
 +	case FREAD:
 +	case FWRITE:
 +		if ((fp->f_flag & flags) == 0)
 +			error = EBADF;
 +		break;
 +	case FEXEC:
 +	    	if ((fp->f_flag & (FREAD | FEXEC)) == 0 ||
 +		    ((fp->f_flag & FWRITE) != 0))
 +			error = EBADF;
 +		break;
 +	case 0:
 +		break;
 +	default:
 +		KASSERT(0, ("wrong flags"));
 +	}
 +
 +	if (error != 0) {
  		fdrop(fp, td);
 -		return (EBADF);
 +		return (error);
  	}
 +
  	*fpp = fp;
  	return (0);
  }
 @@ -2498,6 +2514,13 @@ fgetvp_read(struct thread *td, int fd, c
  	return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
  }
  
 +int
 +fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
 +{
 +
 +	return (_fgetvp(td, fd, FEXEC, rights, NULL, vpp));
 +}
 +
  #ifdef notyet
  int
  fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
 
 Modified: stable/9/sys/kern/kern_exec.c
 ==============================================================================
 --- stable/9/sys/kern/kern_exec.c	Tue Jul 17 22:16:10 2012	(r238559)
 +++ stable/9/sys/kern/kern_exec.c	Wed Jul 18 04:52:37 2012	(r238560)
 @@ -443,8 +443,10 @@ interpret:
  		/*
  		 * Some might argue that CAP_READ and/or CAP_MMAP should also
  		 * be required here; such arguments will be entertained.
 +		 *
 +		 * Descriptors opened only with O_EXEC or O_RDONLY are allowed.
  		 */
 -		error = fgetvp_read(td, args->fd, CAP_FEXECVE, &binvp);
 +		error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
  		if (error)
  			goto exec_fail;
  		vfslocked = VFS_LOCK_GIANT(binvp->v_mount);
 
 Modified: stable/9/sys/sys/file.h
 ==============================================================================
 --- stable/9/sys/sys/file.h	Tue Jul 17 22:16:10 2012	(r238559)
 +++ stable/9/sys/sys/file.h	Wed Jul 18 04:52:37 2012	(r238560)
 @@ -225,6 +225,8 @@ fo_chown_t	invfo_chown;
  
  void finit(struct file *, u_int, short, void *, struct fileops *);
  int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
 +int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
 +    struct vnode **vpp);
  int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
      cap_rights_t *have, struct vnode **vpp);
  int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,
 _______________________________________________
 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"
 
>Unformatted:
