1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

vfs: sanity check the length passed to inode_set_cached_link()

This costs a strlen() call when instatianating a symlink.

Preferably it would be hidden behind VFS_WARN_ON (or compatible), but
there is no such facility at the moment. With the facility in place the
call can be patched out in production kernels.

In the meantime, since the cost is being paid unconditionally, use the
result to a fixup the bad caller.

This is not expected to persist in the long run (tm).

Sample splat:
bad length passed for symlink [/tmp/syz-imagegen43743633/file0/file0] (got 131109, expected 37)
[rest of WARN blurp goes here]

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Link: https://lore.kernel.org/r/20250204213207.337980-1-mjguzik@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Mateusz Guzik 2025-02-04 22:32:07 +01:00 committed by Christian Brauner
parent 091ee63e36
commit 37d11cfc63
No known key found for this signature in database
GPG key ID: 91C61BC06578DCA2

View file

@ -790,6 +790,19 @@ struct inode {
static inline void inode_set_cached_link(struct inode *inode, char *link, int linklen)
{
int testlen;
/*
* TODO: patch it into a debug-only check if relevant macros show up.
* In the meantime, since we are suffering strlen even on production kernels
* to find the right length, do a fixup if the wrong value got passed.
*/
testlen = strlen(link);
if (testlen != linklen) {
WARN_ONCE(1, "bad length passed for symlink [%s] (got %d, expected %d)",
link, linklen, testlen);
linklen = testlen;
}
inode->i_link = link;
inode->i_linklen = linklen;
inode->i_opflags |= IOP_CACHED_LINK;