[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251216035518.4037331-47-viro@zeniv.linux.org.uk>
Date: Tue, 16 Dec 2025 03:55:05 +0000
From: Al Viro <viro@...iv.linux.org.uk>
To: linux-fsdevel@...r.kernel.org
Cc: torvalds@...ux-foundation.org,
brauner@...nel.org,
jack@...e.cz,
mjguzik@...il.com,
paul@...l-moore.com,
axboe@...nel.dk,
audit@...r.kernel.org,
io-uring@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [RFC PATCH v3 46/59] do_{renameat2,linkat,symlinkat}(): use CLASS(filename_consume)
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@...iv.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 f6b5d6a657da..fbf306fe8414 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5575,23 +5575,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)
@@ -5607,9 +5606,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;
}
@@ -5724,9 +5720,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;
@@ -5734,10 +5732,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.
@@ -5752,7 +5748,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));
@@ -5788,10 +5784,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;
}
@@ -6022,9 +6014,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;
@@ -6032,20 +6026,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);
@@ -6122,9 +6116,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
Powered by blists - more mailing lists