All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Imre Deak <imre.deak@intel.com>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] dcache: fix dpath buffer corruption for too small buffers
Date: Sun, 23 Mar 2014 04:36:43 +0000	[thread overview]
Message-ID: <20140323043643.GA25566@ZenIV.linux.org.uk> (raw)
In-Reply-To: <1394666986-24727-1-git-send-email-imre.deak@intel.com>

On Thu, Mar 13, 2014 at 01:29:46AM +0200, Imre Deak wrote:
> During dentry path lookups we can end up corrupting memory if the
> destination path buffer is too small. This is because prepend_path()
> and prepend() adjust the passed buffer length unconditionally, allowing
> for the buffer length to go negative. Then a later prepend_name() call
> will receive a negative length and convert this to unsigned before
> comparing it against the source string length leading to a possible
> memory corruption preceeding the destination buffer.
> 
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 265e0ce..4015fd9 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -2833,7 +2833,8 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
>  	u32 dlen = ACCESS_ONCE(name->len);
>  	char *p;
>  
> -	if (*buflen < dlen + 1)
> +	/* make sure we don't convert a negative value to unsigned int */
> +	if (*buflen < 0 || *buflen < dlen + 1)
>  		return -ENAMETOOLONG;
>  	*buflen -= dlen + 1;

It's much easier to fix, actually.  Look at the callers of prepend_name();
when it returns a negative value, they either discard the value left in
*buflen (__dentry_path()) or pass it back to their caller and return a
negative value themselves (prepend_path()).  The same is true for
prepend_path() (discared in __d_path(), d_absolute_path(), sys_getcwd();
passed to caller with negative return value in path_with_deleted()) and
path_with_deleted() (the only caller is d_path() and it always discards).

In other words, when prepend_name() returns -ENAMETOOLONG, it is free to
leave whatever it wants in *buflen.  So let's do what prepend() does -
subtract from *buflen, then check if the result has become negative.
Generates a better code than the original, actually...

  reply	other threads:[~2014-03-23  4:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-12 23:29 [PATCH] dcache: fix dpath buffer corruption for too small buffers Imre Deak
2014-03-23  4:36 ` Al Viro [this message]
2014-03-23 16:07   ` Imre Deak
2014-03-24 12:17 ` [PATCH v2] " Imre Deak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140323043643.GA25566@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=imre.deak@intel.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.