diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2014-06-03 12:27:08 +0000 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-07-17 18:31:11 +0200 |
commit | 31d2f7c2e27abd2f39a283825a07edb8d5bfe86e (patch) | |
tree | 3641d686d8f8d3f1e064c81b3c816c8177f21b3c /arch/x86_64/kernel | |
parent | 5f1b41cf98dd0d0d6014f6896cb2a4185fc73147 (diff) | |
download | kernel_goldelico_gta04-31d2f7c2e27abd2f39a283825a07edb8d5bfe86e.zip kernel_goldelico_gta04-31d2f7c2e27abd2f39a283825a07edb8d5bfe86e.tar.gz kernel_goldelico_gta04-31d2f7c2e27abd2f39a283825a07edb8d5bfe86e.tar.bz2 |
futex: Make lookup_pi_state more robustHEADreplicant-4.2-0004replicant-4.2-0003replicant-4.2
commit 54a217887a7b658e2650c3feff22756ab80c7339 upstream.
The current implementation of lookup_pi_state has ambigous handling of
the TID value 0 in the user space futex. We can get into the kernel
even if the TID value is 0, because either there is a stale waiters bit
or the owner died bit is set or we are called from the requeue_pi path
or from user space just for fun.
The current code avoids an explicit sanity check for pid = 0 in case
that kernel internal state (waiters) are found for the user space
address. This can lead to state leakage and worse under some
circumstances.
Handle the cases explicit:
Waiter | pi_state | pi->owner | uTID | uODIED | ?
[1] NULL | --- | --- | 0 | 0/1 | Valid
[2] NULL | --- | --- | >0 | 0/1 | Valid
[3] Found | NULL | -- | Any | 0/1 | Invalid
[4] Found | Found | NULL | 0 | 1 | Valid
[5] Found | Found | NULL | >0 | 1 | Invalid
[6] Found | Found | task | 0 | 1 | Valid
[7] Found | Found | NULL | Any | 0 | Invalid
[8] Found | Found | task | ==taskTID | 0/1 | Valid
[9] Found | Found | task | 0 | 0 | Invalid
[10] Found | Found | task | !=taskTID | 0/1 | Invalid
[1] Indicates that the kernel can acquire the futex atomically. We
came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
[2] Valid, if TID does not belong to a kernel thread. If no matching
thread is found then it indicates that the owner TID has died.
[3] Invalid. The waiter is queued on a non PI futex
[4] Valid state after exit_robust_list(), which sets the user space
value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
[5] The user space value got manipulated between exit_robust_list()
and exit_pi_state_list()
[6] Valid state after exit_pi_state_list() which sets the new owner in
the pi_state but cannot access the user space value.
[7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
[8] Owner and user space value match
[9] There is no transient state which sets the user space TID to 0
except exit_robust_list(), but this is indicated by the
FUTEX_OWNER_DIED bit. See [4]
[10] There is no transient state which leaves owner and user space
TID out of sync.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Drewry <wad@chromium.org>
Cc: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'arch/x86_64/kernel')
0 files changed, 0 insertions, 0 deletions