From nobody@FreeBSD.org  Tue Oct 11 07:36:10 2011
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 C4364106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 11 Oct 2011 07:36:10 +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 B3B018FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 11 Oct 2011 07:36:10 +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 p9B7aAxw083319
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 11 Oct 2011 07:36:10 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id p9B7aAP4083318;
	Tue, 11 Oct 2011 07:36:10 GMT
	(envelope-from nobody)
Message-Id: <201110110736.p9B7aAP4083318@red.freebsd.org>
Date: Tue, 11 Oct 2011 07:36:10 GMT
From: Garrett Cooper <yaneurabeya@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: mount fails with ENAMETOOLONG with path shorter than 255 // 1023 characters
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         161481
>Category:       kern
>Synopsis:       [libc] mount(2) fails with ENAMETOOLONG with path shorter than 255 // 1023 characters
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Oct 11 07:40:01 UTC 2011
>Closed-Date:    
>Last-Modified:  Sun Feb 03 22:29:39 UTC 2013
>Originator:     Garrett Cooper
>Release:        10-CURRENT
>Organization:
n/a
>Environment:
FreeBSD fallout.local 10.0-CURRENT FreeBSD 10.0-CURRENT #2 r226242M: Mon Oct 10 20:50:51 PDT 2011     gcooper@fallout.local:/usr/obj/usr/src/sys/FALLOUT  amd64
>Description:
mount(2) claims that it should fail with ENAMETOOLONG if the path is <= 255 or 1023 characters:

     [ENAMETOOLONG]     A component of a pathname exceeded 255 characters, or
                        the entire length of a path name exceeded 1023 charac-
                        ters.

In practice, that isn't true:

# mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles
mount_nullfs: File name too long
# echo mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles/ /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles | awk '{ print length($(NF - 1)), length($NF) }'
83 90
#

It's failing a bounds check in nmount and its callees. I've seen this issue with both nullfs and UFS, so it's most likely a problem in vfs_mount.c, etc.

I've seen this issue on 8.2-RELEASE (FreeNAS), as well as 9-CURRENT and 10-CURRENT.
>How-To-Repeat:
#!/bin/sh

set -e

mkdir -p /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles/
md=$(mdconfig -a -t swap -s 512m)
newfs /dev/$md
mount /dev/$md /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles/
>Fix:


>Release-Note:
>Audit-Trail:

From: Garrett Cooper <yaneurabeya@gmail.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc: Garrett Cooper <yaneurabeya@gmail.com>
Subject: Re: kern/161481: mount fails with ENAMETOOLONG with path shorter
 than 255 // 1023 characters
Date: Tue, 11 Oct 2011 00:57:44 -0700 (PDT)

 I looked into this more closely after I submitted the bug and the problem 
 is the arbitrarily short value attached to MNAMELEN:
 
 122537   mckusick #define       MNAMELEN        88              /* size of 
 on/from name bufs */
 
 The value has changed over the years (all the way back to the mid-90s) 
 from 90 to 70 to 80 to 88, but each time the author doesn't clearly state 
 why the change was required.
 
 Testing out a kernel with the newly imposed limits to determine if the new 
 limit is functional and/or there's a major performance regression with the 
 new limit.
 
 Thanks,
 -Garrett

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/161481: mount fails with ENAMETOOLONG with path shorter
 than 255 // 1023 characters
Date: Tue, 11 Oct 2011 21:44:05 +1100 (EST)

 On Tue, 11 Oct 2011, Garrett Cooper wrote:
 
 >> Description:
 > mount(2) claims that it should fail with ENAMETOOLONG if the path is <= 255 or 1023 characters:
 >
 >     [ENAMETOOLONG]     A component of a pathname exceeded 255 characters, or
 >                        the entire length of a path name exceeded 1023 charac-
 >                        ters.
 >
 > In practice, that isn't true:
 >
 > # mount -t nullfs -o noatime /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/ports/distfiles /nfs/scratch/freenas-2/freenas/projects/freenas8-plugins/obj.amd64/_.w/usr/ports/distfiles
 > mount_nullfs: File name too long
 
 There are limit of MNAMELEN = 88 and OMNAMELEN (a bit smaller) for mount().
 
 This seems to be a new bug.  In FreeBSD[1-4], mount() used normal pathname
 stuff and there were no references to MNAMELEN in vfs, and file systems
 like ffs silently ignored the ENAMETOOLONG error for copyinstr() of
 the user pathname to mp->mnt_stat.f_mntonname[] (which has size MNAMELEN).
 (This copyinstr() isn't quite normal pathname stuff either.  copyinstr()
 to the namei buffer and using that for everything in the kernel would be
 normal.  ffs_mount() also handles namei initialization and I think it
 uses a separate copyinstr() for f_mntonname[] in at least some cases
 because namei initialization occurs later.)
 
 This seems to have been broken somewhere in FreeBSD-5, probably
 collaterally with nmount().  FreeBSD-5.2 has up-front checks that the
 pathname fits in a buffer of size MNAMELEN, in both nmount(9) and mount(9).
 For nmount(), the pathname is far from normal, since it is passed as
 an option string.  For mount(), the pathname starts as normal, but it is
 copyinstr()'ed into a malloc buffer of size MNAMELEN to join up with
 nmount().  ffs no longer (still in 5.2) copyinstr()'s the user path to
 mp->mnt_stat.f_mntonname[], but it still does an NDINIT() on args.fspec
 with arg UIO_USERSPACE; that now seems to work only accidentally, since
 the path is actually in UIO_SYSSPACE.  Now in -current, even more of the
 initialization has been moved up to vfs;  ffs still does the NDINIT() but
 it uses arg UIO_SYSSPACE.
 
 ISTR old PRs about almost the opposite problem, that you could mount things
 with paths so long that you couldn't easily unmount them, because the
 pathname in mp->mnt_stat.f_mntonname[] is truncated.
 
 Bruce
>Unformatted:
