[LTP] [PATCH] lack of ENAMETOOLONG testcases for pathnames longer than PATH_MAX

Al Viro viro@zeniv.linux.org.uk
Wed Jan 14 15:30:21 CET 2026


On Wed, Jan 14, 2026 at 09:35:48AM +0100, Andrea Cervesato wrote:
> Hi!
> 
> On Tue Jan 13, 2026 at 8:49 PM CET, Al Viro wrote:
> > 	There are different causes of ENAMETOOLONG.  It might come from
> > filesystem rejecting an excessively long pathname component, but there's
> > also "pathname is longer than PATH_MAX bytes, including terminating NUL"
> > and that doesn't get checked anywhere.
> >
> > 	Ran into that when a braino in kernel patch broke that logics
> > (ending up with cutoff too low) and that didn't get caught by LTP run.
> >
> > 	Patch below adds the checks to one of the tests that do deal
> > with the other source of ENAMETOOLONG; it almost certainly not the
> > right use of infrastructure, though.
> 
> The description is not well formatted, spaces at the beginning of the
> phrases should be removed.
> 
> Also, we can make it slightly more clear, by saying that error can be
> caused by a path name that is bigger than NAME_MAX, if relative, or
> bigger than PATH_MAX, if absolute (when we use '/').

Huh?  Absolute pathname is the one that _starts_ with '/'; e.g. "../include"
is relative, not absolute, despite having a '/' in it.

> In this test we only verifies if relative paths are longer than
> NAME_MAX (we give 273 bytes instead of 255 max), but we don't test if
> path name is bigger than PATH_MAX.
> 
> We should correctly distinguish these two cases inside the test with
> proper names as well. Check below..

> https://linux-test-project.readthedocs.io/en/latest/developers/api_c_tests.html#guarded-buffers-introduction
> 
> Many old tests are not using these buffers, but it's better to
> introduce them when a test is refactored or fixed, like in this case.
> 
> You need to define:
> 
> static char *long_rel_path;
> static char *long_abs_path;
> 
> ...
> 
> static void setup(void) {
> 	..
> 	// initialize long_rel_path content
> 	// initialize long_abs_path content
> }
> 
> static struct tst_test test = {
> 	..
> 	.bufs = (struct tst_buffer []) {
> 		{&long_rel_path, .size = NAME_MAX + 10},
> 		{&long_abs_path, .size = PATH_MAX + 10},
> 		{}
> 	}
> };

> > -	TST_EXP_FAIL(chdir(tcases[i].dir), tcases[i].exp_errno, "chdir()");
> > +	if (tcases[i].exp_errno)
> > +		TST_EXP_FAIL(chdir(tcases[i].dir), tcases[i].exp_errno, "chdir()");
> > +	else
> > +		TST_EXP_PASS(chdir(tcases[i].dir), "chdir()");
> 
> In this test we only verify errors, so TST_EXP_PASS is not needed.

Er...  Intent was to verify two things: that anything longer than PATH_MAX triggers
ENAMETOOLONG, but anything up to PATH_MAX does not.  Having a pathname of exactly
4095 '/' (or interleaved . and / in the same amount, etc.) be rejected with ENAMETOOLONG
is just as much of a failure as not triggering ENAMETOOLONG on anything longer...

FWIW, I considered something like
	mkdir("subdirectory", 0700);
concatenating enough copies of "subdirectory/../" to get just under PATH_MAX and appending
"././././././././" to the end, so that truncation to PATH_MAX and to PATH_MAX-1 would
both be otherwise valid paths; decided that it's better to keep it simpler - a pile of
slashes is easier to produce and would resolve to a valid directory if not for the
total length restrictions.


More information about the ltp mailing list