All of lore.kernel.org
 help / color / mirror / Atom feed
From: Darren Hart <dvhart@infradead.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Cheng Jian <cj.chengjian@huawei.com>,
	tglx@linutronix.de, mingo@redhat.com,
	linux-kernel@vger.kernel.org, xiexiuqi@huawei.com,
	huawei.libin@huawei.com
Subject: Re: [PATCH] futex: use fault_in to avoid infinite loop
Date: Thu, 7 Dec 2017 21:21:36 -0800	[thread overview]
Message-ID: <20171208052136.GA28773@fury> (raw)
In-Reply-To: <20171206214007.GI3857@worktop>

On Wed, Dec 06, 2017 at 10:40:08PM +0100, Peter Zijlstra wrote:
> On Wed, Dec 06, 2017 at 05:04:00PM +0100, Peter Zijlstra wrote:
> > On Wed, Dec 06, 2017 at 10:21:07PM +0800, Cheng Jian wrote:
> > > It will cause softlockup(infinite loop) in kernel
> > > space when we use SYS_set_robust_list in futex which
> > > incoming a misaligned address from user space.
> > 
> > Urgh, we should not allow that in the first place.
> > 
> > See how get_futex_key() does:
> > 
> >   if (unlikely(address % sizeof(u32)))
> > 	return -EINVAL;
> > 
> > That same should also be true for the robust list. Using unaligned
> > variables is insane.
> 
> Something a little like so perhaps..
> 
> ---
> Subject: futex: Sanitize user address in set_robust_list()
> 
> Passing in unaligned variables messes up cmpxchg on a whole bunch of
> architectures. Also, not respecting the natural alignment of data
> structures is pretty dumb to begin with.
> 
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---
>  include/uapi/asm-generic/errno.h | 1 +
>  kernel/futex.c                   | 5 +++++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/include/uapi/asm-generic/errno.h b/include/uapi/asm-generic/errno.h
> index cf9c51ac49f9..4cb80d4ac160 100644
> --- a/include/uapi/asm-generic/errno.h
> +++ b/include/uapi/asm-generic/errno.h
> @@ -119,5 +119,6 @@
>  #define ERFKILL		132	/* Operation not possible due to RF-kill */
>  
>  #define EHWPOISON	133	/* Memory page has hardware error */
> +#define EMORON		134	/* User did something particularly silly */

It's baaa-aaack...

(sadly I suspect -EINVAL would be the consistent approach ;-)

>  
>  #endif
> diff --git a/kernel/futex.c b/kernel/futex.c
> index 76ed5921117a..e2c1a818f88f 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -3262,6 +3262,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
>  SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head,
>  		size_t, len)
>  {
> +	unsigned long address = (unsigned long)head;
> +
>  	if (!futex_cmpxchg_enabled)
>  		return -ENOSYS;
>  	/*
> @@ -3270,6 +3272,9 @@ SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head,
>  	if (unlikely(len != sizeof(*head)))
>  		return -EINVAL;
>  
> +	if (unlikely(address % __alignof__(*head)))
> +		return -EMORON;

Seeing as how this is performing the test as early as possible, would it make
sense to also catch unaligned uaddr and uaddr2 as early as possible too - in
sys_futex?

Something like:

diff --git a/kernel/futex.c b/kernel/futex.c
index 76ed592..c3ee6c4 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -509,8 +509,6 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 	 * The futex address must be "naturally" aligned.
 	 */
 	key->both.offset = address % PAGE_SIZE;
-	if (unlikely((address % sizeof(u32)) != 0))
-		return -EINVAL;
 	address -= key->both.offset;
 
 	if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
@@ -3525,6 +3523,11 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
 	u32 val2 = 0;
 	int cmd = op & FUTEX_CMD_MASK;
 
+	/* Only allow for aligned uaddr variables */
+	if (unlikely((unsigned long)uaddr % sizeof(u32) != 0 ||
+		     (unsigned long)uaddr2 % sizeof(u32) != 0))
+		return -EINVAL;
+
 	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
 		      cmd == FUTEX_WAIT_BITSET ||
 		      cmd == FUTEX_WAIT_REQUEUE_PI)) {

I didn't see a need to do anything of the sort to sys_get_robust_list()

-- 
Darren Hart
VMware Open Source Technology Center

  reply	other threads:[~2017-12-08  5:21 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-06 14:21 [PATCH] futex: use fault_in to avoid infinite loop Cheng Jian
2017-12-06 16:04 ` Peter Zijlstra
2017-12-06 21:40   ` Peter Zijlstra
2017-12-08  5:21     ` Darren Hart [this message]
2017-12-08 10:50       ` Peter Zijlstra
2017-12-08 12:42     ` chengjian (D)
2017-12-28 14:21     ` [tip:locking/urgent] futex: Sanitize user address in set_robust_list() tip-bot for Peter Zijlstra
2017-12-30  7:40     ` [PATCH] futex: use fault_in to avoid infinite loop Michael Kerrisk

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=20171208052136.GA28773@fury \
    --to=dvhart@infradead.org \
    --cc=cj.chengjian@huawei.com \
    --cc=huawei.libin@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=xiexiuqi@huawei.com \
    /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.