History

Merge tag 'locking_urgent_for_v6.17_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Borislav Petkov: - Make sure sanity checks down in the mutex lock path happen on the correct type of task so that they don't trigger falsely - Use the write unsafe user access pairs when writing a futex value to prevent an error on PowerPC which does user read and write accesses differently * tag 'locking_urgent_for_v6.17_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking: Fix __clear_task_blocked_on() warning from __ww_mutex_wound() path futex: Use user_write_access_begin/_end() in futex_put_value()

Linus Torvalds committed 1 year ago

Commit 0a9ee9c2 parents 99bade3 21924af3 files · +25 −16Browse files

Unified · Split

3 files
  1. include/linux/sched.h +17 −12
  2. kernel/futex/futex.h +3 −3
  3. kernel/locking/ww_mutex.h +5 −1
include/linux/sched.h+17−12
@@ -2152,6 +2152,8 @@ static inline struct mutex *__get_task_blocked_on(struct task_struct *p) · 2151 unmodified lines
21522152
21532153 static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m)
21542154 {
2155+ struct mutex *blocked_on = READ_ONCE(p->blocked_on);
2156+
21552157 WARN_ON_ONCE(!m);
21562158 /* The task should only be setting itself as blocked */
21572159 WARN_ON_ONCE(p != current);
@@ -2162,8 +2164,8 @@ static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m) · 4 unmodified lines
21622164 * with a different mutex. Note, setting it to the same
21632165 * lock repeatedly is ok.
21642166 */
2165− WARN_ON_ONCE(p->blocked_on && p->blocked_on != m);
2166− p->blocked_on = m;
2167+ WARN_ON_ONCE(blocked_on && blocked_on != m);
2168+ WRITE_ONCE(p->blocked_on, m);
21672169 }
21682170
21692171 static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m)
@@ -2174,16 +2176,19 @@ static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m) · 4 unmodified lines
21742176
21752177 static inline void __clear_task_blocked_on(struct task_struct *p, struct mutex *m)
21762178 {
2177− WARN_ON_ONCE(!m);
2178− /* Currently we serialize blocked_on under the mutex::wait_lock */
2179− lockdep_assert_held_once(&m->wait_lock);
2180− /*
2181− * There may be cases where we re-clear already cleared
2182− * blocked_on relationships, but make sure we are not
2183− * clearing the relationship with a different lock.
2184− */
2185− WARN_ON_ONCE(m && p->blocked_on && p->blocked_on != m);
2186− p->blocked_on = NULL;
2179+ if (m) {
2180+ struct mutex *blocked_on = READ_ONCE(p->blocked_on);
2181+
2182+ /* Currently we serialize blocked_on under the mutex::wait_lock */
2183+ lockdep_assert_held_once(&m->wait_lock);
2184+ /*
2185+ * There may be cases where we re-clear already cleared
2186+ * blocked_on relationships, but make sure we are not
2187+ * clearing the relationship with a different lock.
2188+ */
2189+ WARN_ON_ONCE(blocked_on && blocked_on != m);
2190+ }
2191+ WRITE_ONCE(p->blocked_on, NULL);
21872192 }
21882193
21892194 static inline void clear_task_blocked_on(struct task_struct *p, struct mutex *m)
kernel/futex/futex.h+3−3
@@ -319,13 +319,13 @@ static __always_inline int futex_put_value(u32 val, u32 __user *to) · 318 unmodified lines
319319 {
320320 if (can_do_masked_user_access())
321321 to = masked_user_access_begin(to);
322− else if (!user_read_access_begin(to, sizeof(*to)))
322+ else if (!user_write_access_begin(to, sizeof(*to)))
323323 return -EFAULT;
324324 unsafe_put_user(val, to, Efault);
325− user_read_access_end();
325+ user_write_access_end();
326326 return 0;
327327 Efault:
328− user_read_access_end();
328+ user_write_access_end();
329329 return -EFAULT;
330330 }
331331
kernel/locking/ww_mutex.h+5−1
@@ -342,8 +342,12 @@ static bool __ww_mutex_wound(struct MUTEX *lock, · 341 unmodified lines
342342 * When waking up the task to wound, be sure to clear the
343343 * blocked_on pointer. Otherwise we can see circular
344344 * blocked_on relationships that can't resolve.
345+ *
346+ * NOTE: We pass NULL here instead of lock, because we
347+ * are waking the mutex owner, who may be currently
348+ * blocked on a different mutex.
345349 */
346− __clear_task_blocked_on(owner, lock);
350+ __clear_task_blocked_on(owner, NULL);
347351 wake_q_add(wake_q, owner);
348352 }
349353 return true;