diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch new file mode 100644 index 000000000..ae0f63a18 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch @@ -0,0 +1,117 @@ +From 015b6a4c2564a9385401a6105e80a20c333e1d44 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Tue, 19 Jan 2021 15:21:35 +0100 +Subject: [PATCH] futex: Provide and use pi_state_update_owner() + +commit c5cade200ab9a2a3be9e7f32a752c8d86b502ec7 upstream + +Updating pi_state::owner is done at several places with the same +code. Provide a function for it and use that at the obvious places. + +This is also a preparation for a bug fix to avoid yet another copy of the +same code or alternatively introducing a completely unpenetratable mess of +gotos. + +Originally-by: Peter Zijlstra <peterz@infradead.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 66 +++++++++++++++++++++++++------------------------- + 1 file changed, 33 insertions(+), 33 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 8bfb16258ae7..69f62d0f5851 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -857,6 +857,29 @@ static struct futex_pi_state *alloc_pi_state(void) + return pi_state; + } + ++static void pi_state_update_owner(struct futex_pi_state *pi_state, ++ struct task_struct *new_owner) ++{ ++ struct task_struct *old_owner = pi_state->owner; ++ ++ lockdep_assert_held(&pi_state->pi_mutex.wait_lock); ++ ++ if (old_owner) { ++ raw_spin_lock(&old_owner->pi_lock); ++ WARN_ON(list_empty(&pi_state->list)); ++ list_del_init(&pi_state->list); ++ raw_spin_unlock(&old_owner->pi_lock); ++ } ++ ++ if (new_owner) { ++ raw_spin_lock(&new_owner->pi_lock); ++ WARN_ON(!list_empty(&pi_state->list)); ++ list_add(&pi_state->list, &new_owner->pi_state_list); ++ pi_state->owner = new_owner; ++ raw_spin_unlock(&new_owner->pi_lock); ++ } ++} ++ + static void get_pi_state(struct futex_pi_state *pi_state) + { + WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount)); +@@ -1614,26 +1637,15 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_ + ret = -EINVAL; + } + +- if (ret) +- goto out_unlock; +- +- /* +- * This is a point of no return; once we modify the uval there is no +- * going back and subsequent operations must not fail. +- */ +- +- raw_spin_lock(&pi_state->owner->pi_lock); +- WARN_ON(list_empty(&pi_state->list)); +- list_del_init(&pi_state->list); +- raw_spin_unlock(&pi_state->owner->pi_lock); +- +- raw_spin_lock(&new_owner->pi_lock); +- WARN_ON(!list_empty(&pi_state->list)); +- list_add(&pi_state->list, &new_owner->pi_state_list); +- pi_state->owner = new_owner; +- raw_spin_unlock(&new_owner->pi_lock); +- +- postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); ++ if (!ret) { ++ /* ++ * This is a point of no return; once we modified the uval ++ * there is no going back and subsequent operations must ++ * not fail. ++ */ ++ pi_state_update_owner(pi_state, new_owner); ++ postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); ++ } + + out_unlock: + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); +@@ -2566,19 +2578,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * We fixed up user space. Now we need to fix the pi_state + * itself. + */ +- if (pi_state->owner != NULL) { +- raw_spin_lock(&pi_state->owner->pi_lock); +- WARN_ON(list_empty(&pi_state->list)); +- list_del_init(&pi_state->list); +- raw_spin_unlock(&pi_state->owner->pi_lock); +- } +- +- pi_state->owner = newowner; +- +- raw_spin_lock(&newowner->pi_lock); +- WARN_ON(!list_empty(&pi_state->list)); +- list_add(&pi_state->list, &newowner->pi_state_list); +- raw_spin_unlock(&newowner->pi_lock); ++ pi_state_update_owner(pi_state, newowner); + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + + return argowner == current; +-- +2.17.1 + |