]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
getname_flags() massage, part 1
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 19 Nov 2025 22:15:23 +0000 (17:15 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 13 Jan 2026 20:16:44 +0000 (15:16 -0500)
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 <viro@zeniv.linux.org.uk>
fs/namei.c

index 3ba712032f5582b18e7cc8d37e9310f80cf7381e..72ee663a9b6b59dbe5588a85e32b6d5cdb72ea38 100644 (file)
@@ -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);