From nobody@FreeBSD.org  Sat May  5 12:51:34 2012
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id C6C281065672
	for <freebsd-gnats-submit@FreeBSD.org>; Sat,  5 May 2012 12:51:34 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 986788FC17
	for <freebsd-gnats-submit@FreeBSD.org>; Sat,  5 May 2012 12:51:34 +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 q45CpYNZ052900
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 5 May 2012 12:51:34 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q45CpYa1052899;
	Sat, 5 May 2012 12:51:34 GMT
	(envelope-from nobody)
Message-Id: <201205051251.q45CpYa1052899@red.freebsd.org>
Date: Sat, 5 May 2012 12:51:34 GMT
From: Jukka Ukkonen <jau@iki.fi>
To: freebsd-gnats-submit@FreeBSD.org
Subject: The portal file system gets stuck inside portal_open(). ("1 extra fds")
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         167612
>Category:       kern
>Synopsis:       [portalfs] The portal file system gets stuck inside portal_open(). ("1 extra fds")
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-fs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat May 05 13:00:21 UTC 2012
>Closed-Date:    
>Last-Modified:  Sun Jun  3 06:40:17 UTC 2012
>Originator:     Jukka Ukkonen
>Release:        9.0-STABLE
>Organization:
---
>Environment:
FreeBSD sleipnir 9.0-STABLE FreeBSD 9.0-STABLE #0: Sat May  5 10:19:05 EEST 2012     root@sleipnir:/usr/obj/usr/src/sys/Sleipnir  amd64
>Description:
All attempts to refer to any file under the mounted portal file system end up waiting indefinitely.
Actually the portal ends up reading STDIN while it should be reading from a command.
E.g. the following command should simply list the output from who, but instead it does nothing until ctrl-D is given on the tty...

cat /p/pipe/usr/bin/who

At the same time the following complaint gets written to syslog...

May  5 15:28:36 sleipnir kernel: portal_open: 1 extra fds

Apparently the faulty takes place and gets also partially handled within the following snippet of code in portal_vnops.c ...

        cmsg = mtod(cm, struct cmsghdr *);
        newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
        if (newfds == 0) {
                error = ECONNREFUSED;
                goto bad;
        }
        /*
         * At this point the rights message consists of a control message
         * header, followed by a data region containing a vector of
         * integer file descriptors.  The fds were allocated by the action
         * of receiving the control message.
         */
        ip = (int *) (cmsg + 1);
        fd = *ip++;
        if (newfds > 1) {
                /*
                 * Close extra fds.
                 */
                int i;
                printf("portal_open: %d extra fds\n", newfds - 1);
                for (i = 1; i < newfds; i++) {
                        portal_closefd(td, *ip);
                        ip++;
                }
        }

It seems that newfds gets calculated wrong and fd gets picked too early in the message.
After that the correct fd gets treated as extra and closed.

>How-To-Repeat:
See full description above.

>Fix:
Apparently some further jugglery with the control message is needed to get the data alignment right.
At the time of this writing I do not have a patch.


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-fs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon May 7 18:55:01 UTC 2012 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: "Jukka A. Ukkonen" <jau@iki.fi>
To: bug-followup@FreeBSD.org, jau@iki.fi
Cc:  
Subject: kern/167612: [portalfs] The portal file system gets stuck inside
 portal_open(). ("1 extra fds")
Date: Thu, 10 May 2012 18:33:49 +0300

 This is a multi-part message in MIME format.
 --------------060204070501010607040700
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 
 This really was an alignment issue.
 
 The old code was not in sync with the alignment done in
 
 the CMSG_* macros.
 
 
 Find a patch attached.
 
 --jau
 
 
 
 --------------060204070501010607040700
 Content-Type: text/plain; charset=UTF-8;
  name="portal_vnops.c.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="portal_vnops.c.diff"
 
 --- portal_vnops.c.orig	2012-05-08 18:43:17.000000000 +0300
 +++ portal_vnops.c	2012-05-10 17:07:55.000000000 +0300
 @@ -397,19 +397,47 @@
  	 * than a single mbuf in it.  What to do?
  	 */
  	cmsg = mtod(cm, struct cmsghdr *);
 -	newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
 +
 +	/*
 +	 * Just in case the sender no longer does what we expect
 +	 * and sends something else before or in the worst case
 +	 * instead of the file descriptor we expect...
 +	 */
 +
 +	if ((cmsg->cmsg_level != SOL_SOCKET)
 +	    || (cmsg->cmsg_type != SCM_RIGHTS)) {
 +		error = ECONNREFUSED;
 +		goto bad;
 +	}
 +
 +	/*
 +	 * Use the flippin' CMSG_DATA() macro to make sure we use
 +	 * the same alignment as the sender.
 +	 * Otherwise things go pear shape very easily.
 +	 * The bad news is that even faulty code may work on some
 +	 * CPU architectures.
 +	 */
 +
 +	ip = (int *) CMSG_DATA (cmsg);
 +
 +	newfds = (cmsg->cmsg_len - 
 +		  ((unsigned char *) ip -
 +		   (unsigned char *) cmsg)) / sizeof (int);
 +
  	if (newfds == 0) {
  		error = ECONNREFUSED;
  		goto bad;
  	}
 +
  	/*
  	 * At this point the rights message consists of a control message
  	 * header, followed by a data region containing a vector of
  	 * integer file descriptors.  The fds were allocated by the action
  	 * of receiving the control message.
  	 */
 -	ip = (int *) (cmsg + 1);
 +
  	fd = *ip++;
 +
  	if (newfds > 1) {
  		/*
  		 * Close extra fds.
 
 --------------060204070501010607040700--

From: "Jukka A. Ukkonen" <jau@oxit.fi>
To: bug-followup@FreeBSD.org, jau@iki.fi
Cc:  
Subject: Re: kern/167612: [portalfs] The portal file system gets stuck inside
 portal_open(). (&quot;1 extra fds&quot;)
Date: Sun, 03 Jun 2012 09:25:40 +0300

 Now the patch has been tested to work on...
 - AMD64
 - Sparc64
 
 
>Unformatted:
