From 8ba29c85e2ef24764a05b557ebeca32f9bfafada Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 19 Nov 2025 17:15:23 -0500 Subject: [PATCH] getname_flags() massage, part 1 In case of long name don't reread what we'd already copied. memmove() it instead. That avoids the possibility of ending up with empty name there and the need to look at the flags on the slow path. Signed-off-by: Al Viro --- fs/namei.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 3ba712032f55..72ee663a9b6b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -174,36 +174,35 @@ getname_flags(const char __user *filename, int flags) */ if (unlikely(len == EMBEDDED_NAME_MAX)) { const size_t size = offsetof(struct filename, iname[1]); - kname = (char *)result; + struct filename *p; /* * size is chosen that way we to guarantee that * result->iname[0] is within the same object and that * kname can't be equal to result->iname, no matter what. */ - result = kzalloc(size, GFP_KERNEL); - if (unlikely(!result)) { - __putname(kname); + p = kzalloc(size, GFP_KERNEL); + if (unlikely(!p)) { + __putname(result); return ERR_PTR(-ENOMEM); } - result->name = kname; - len = strncpy_from_user(kname, filename, PATH_MAX); + memmove(result, &result->iname, EMBEDDED_NAME_MAX); + kname = (char *)result; + p->name = kname; + len = strncpy_from_user(kname + EMBEDDED_NAME_MAX, + filename + EMBEDDED_NAME_MAX, + PATH_MAX - EMBEDDED_NAME_MAX); if (unlikely(len < 0)) { - __putname(kname); - kfree(result); + kfree(p); + __putname(result); return ERR_PTR(len); } - /* The empty path is special. */ - if (unlikely(!len) && !(flags & LOOKUP_EMPTY)) { - __putname(kname); - kfree(result); - return ERR_PTR(-ENOENT); - } - if (unlikely(len == PATH_MAX)) { - __putname(kname); - kfree(result); + if (unlikely(len == PATH_MAX - EMBEDDED_NAME_MAX)) { + kfree(p); + __putname(result); return ERR_PTR(-ENAMETOOLONG); } + result = p; } initname(result); audit_getname(result);