diff mbox series

[3/3] vfs: shave a branch in getname_flags

Message ID 20240604155257.109500-4-mjguzik@gmail.com (mailing list archive)
State New
Headers show
Series whack user_path_at_empty, cleanup getname_flags | expand

Commit Message

Mateusz Guzik June 4, 2024, 3:52 p.m. UTC
Check for an error while copying and no path in one branch.

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
 fs/namei.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

Comments

Christian Brauner June 5, 2024, 3:03 p.m. UTC | #1
On Tue, Jun 04, 2024 at 05:52:57PM +0200, Mateusz Guzik wrote:
> Check for an error while copying and no path in one branch.

Fine to move that check up but we need to redo it after we recopied.
It's extremely unlikely but the contents could've changed iirc. I can
fix that up though.
Mateusz Guzik June 5, 2024, 3:10 p.m. UTC | #2
On Wed, Jun 5, 2024 at 5:03 PM Christian Brauner <brauner@kernel.org> wrote:
>
> On Tue, Jun 04, 2024 at 05:52:57PM +0200, Mateusz Guzik wrote:
> > Check for an error while copying and no path in one branch.
>
> Fine to move that check up but we need to redo it after we recopied.
> It's extremely unlikely but the contents could've changed iirc. I can
> fix that up though.

Oh I see, you mean the buffer might have initially been too big so it
landed in the zmalloc fallback, but by that time userspace might have
played games and slapped a NUL char in there.

Fair, but also trivial to fix up, so I would appreciate if you sorted
it out, especially since you offered :)
Jan Kara June 5, 2024, 3:49 p.m. UTC | #3
On Tue 04-06-24 17:52:57, Mateusz Guzik wrote:
> Check for an error while copying and no path in one branch.
> 
> Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>

Looks good to me modulo the need for rechecking Christian already pointed
out. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>


								Honza

> ---
>  fs/namei.c | 25 ++++++++++++++-----------
>  1 file changed, 14 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/namei.c b/fs/namei.c
> index 950ad6bdd9fe..f25dcb9077dd 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -148,9 +148,20 @@ getname_flags(const char __user *filename, int flags)
>  	result->name = kname;
>  
>  	len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
> -	if (unlikely(len < 0)) {
> -		__putname(result);
> -		return ERR_PTR(len);
> +	/*
> +	 * Handle both empty path and copy failure in one go.
> +	 */
> +	if (unlikely(len <= 0)) {
> +		if (unlikely(len < 0)) {
> +			__putname(result);
> +			return ERR_PTR(len);
> +		}
> +
> +		/* The empty path is special. */
> +		if (!(flags & LOOKUP_EMPTY)) {
> +			__putname(result);
> +			return ERR_PTR(-ENOENT);
> +		}
>  	}
>  
>  	/*
> @@ -188,14 +199,6 @@ getname_flags(const char __user *filename, int flags)
>  	}
>  
>  	atomic_set(&result->refcnt, 1);
> -	/* The empty path is special. */
> -	if (unlikely(!len)) {
> -		if (!(flags & LOOKUP_EMPTY)) {
> -			putname(result);
> -			return ERR_PTR(-ENOENT);
> -		}
> -	}
> -
>  	result->uptr = filename;
>  	result->aname = NULL;
>  	audit_getname(result);
> -- 
> 2.39.2
>
diff mbox series

Patch

diff --git a/fs/namei.c b/fs/namei.c
index 950ad6bdd9fe..f25dcb9077dd 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -148,9 +148,20 @@  getname_flags(const char __user *filename, int flags)
 	result->name = kname;
 
 	len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
-	if (unlikely(len < 0)) {
-		__putname(result);
-		return ERR_PTR(len);
+	/*
+	 * Handle both empty path and copy failure in one go.
+	 */
+	if (unlikely(len <= 0)) {
+		if (unlikely(len < 0)) {
+			__putname(result);
+			return ERR_PTR(len);
+		}
+
+		/* The empty path is special. */
+		if (!(flags & LOOKUP_EMPTY)) {
+			__putname(result);
+			return ERR_PTR(-ENOENT);
+		}
 	}
 
 	/*
@@ -188,14 +199,6 @@  getname_flags(const char __user *filename, int flags)
 	}
 
 	atomic_set(&result->refcnt, 1);
-	/* The empty path is special. */
-	if (unlikely(!len)) {
-		if (!(flags & LOOKUP_EMPTY)) {
-			putname(result);
-			return ERR_PTR(-ENOENT);
-		}
-	}
-
 	result->uptr = filename;
 	result->aname = NULL;
 	audit_getname(result);