[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