Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Oct 2011 21:44:05 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Garrett Cooper <yanegomi@gmail.com>
Cc:        freebsd-bugs@freebsd.org, freebsd-gnats-submit@freebsd.org
Subject:   Re: kern/161481: mount fails with ENAMETOOLONG with path shorter than 255 // 1023 characters
Message-ID:  <20111011210038.K5682@besplex.bde.org>
In-Reply-To: <201110110736.p9B7aAP4083318@red.freebsd.org>
References:  <201110110736.p9B7aAP4083318@red.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111011210038.K5682>