[PATCH v4 45/59] do_{renameat2,linkat,symlinkat}(): use CLASS(filename_consume)

Al Viro
2026-01-08T07:36:57Z

more explicit in what we do, lower odds of ending up with a leak,
fewer gotos...

... and if at some point in the future we decide to make some of those
non-consuming, it would be less noisy.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/namei.c | 51 +++++++++++++++++++++------------------------------
1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 9beb667f0307..86e2467c5460 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5572,23 +5572,22 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
}
EXPORT_SYMBOL(vfs_symlink);

-int do_symlinkat(struct filename *from, int newdfd, struct filename *to)
+int do_symlinkat(struct filename *__from, int newdfd, struct filename *__to)
{
+ CLASS(filename_consume, from)(__from);
+ CLASS(filename_consume, to)(__to);
int error;
struct dentry *dentry;
struct path path;
unsigned int lookup_flags = 0;
struct delegated_inode delegated_inode = { };

- if (IS_ERR(from)) {
- error = PTR_ERR(from);
- goto out_putnames;
- }
+ if (IS_ERR(from))
+ return PTR_ERR(from);
retry:
dentry = filename_create(newdfd, to, &path, lookup_flags);
- error = PTR_ERR(dentry);
if (IS_ERR(dentry))
- goto out_putnames;
+ return PTR_ERR(dentry);

error = security_path_symlink(&path, dentry, from->name);
if (!error)
@@ -5604,9 +5603,6 @@ int do_symlinkat(struct filename *from, int newdfd, struct filename *to)
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
-out_putnames:
- putname(to);
- putname(from);
return error;
}

@@ -5721,9 +5717,11 @@ EXPORT_SYMBOL(vfs_link);
* with linux 2.0, and to avoid hard-linking to directories
* and other special files. --ADM
*/
-int do_linkat(int olddfd, struct filename *old, int newdfd,
- struct filename *new, int flags)
+int do_linkat(int olddfd, struct filename *__old, int newdfd,
+ struct filename *__new, int flags)
{
+ CLASS(filename_consume, old)(__old);
+ CLASS(filename_consume, new)(__new);
struct mnt_idmap *idmap;
struct dentry *new_dentry;
struct path old_path, new_path;
@@ -5731,10 +5729,8 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
int how = 0;
int error;

- if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) {
- error = -EINVAL;
- goto out_putnames;
- }
+ if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
+ return -EINVAL;
/*
* To use null names we require CAP_DAC_READ_SEARCH or
* that the open-time creds of the dfd matches current.
@@ -5749,7 +5745,7 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
retry:
error = filename_lookup(olddfd, old, how, &old_path, NULL);
if (error)
- goto out_putnames;
+ return error;

new_dentry = filename_create(newdfd, new, &new_path,
(how & LOOKUP_REVAL));
@@ -5785,10 +5781,6 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
}
out_putpath:
path_put(&old_path);
-out_putnames:
- putname(old);
- putname(new);
-
return error;
}

@@ -6019,9 +6011,11 @@ int vfs_rename(struct renamedata *rd)
}
EXPORT_SYMBOL(vfs_rename);

-int do_renameat2(int olddfd, struct filename *from, int newdfd,
- struct filename *to, unsigned int flags)
+int do_renameat2(int olddfd, struct filename *__from, int newdfd,
+ struct filename *__to, unsigned int flags)
{
+ CLASS(filename_consume, from)(__from);
+ CLASS(filename_consume, to)(__to);
struct renamedata rd;
struct path old_path, new_path;
struct qstr old_last, new_last;
@@ -6029,20 +6023,20 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
struct delegated_inode delegated_inode = { };
unsigned int lookup_flags = 0;
bool should_retry = false;
- int error = -EINVAL;
+ int error;

if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
- goto put_names;
+ return -EINVAL;

if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
(flags & RENAME_EXCHANGE))
- goto put_names;
+ return -EINVAL;

retry:
error = filename_parentat(olddfd, from, lookup_flags, &old_path,
&old_last, &old_type);
if (error)
- goto put_names;
+ return error;

error = filename_parentat(newdfd, to, lookup_flags, &new_path, &new_last,
&new_type);
@@ -6119,9 +6113,6 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
-put_names:
- putname(from);
- putname(to);
return error;
}

--
2.47.3