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
2152 2152
2153static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m)2153static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m)
2154{2154{
2155 struct mutex *blocked_on = READ_ONCE(p->blocked_on);
2156
2155 WARN_ON_ONCE(!m);2157 WARN_ON_ONCE(!m);
2156 /* The task should only be setting itself as blocked */2158 /* The task should only be setting itself as blocked */
2157 WARN_ON_ONCE(p != current);2159 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
2162 * with a different mutex. Note, setting it to the same2164 * with a different mutex. Note, setting it to the same
2163 * lock repeatedly is ok.2165 * lock repeatedly is ok.
2164 */2166 */
2165 WARN_ON_ONCE(p->blocked_on && p->blocked_on != m);2167 WARN_ON_ONCE(blocked_on && blocked_on != m);
2166 p->blocked_on = m;2168 WRITE_ONCE(p->blocked_on, m);
2167}2169}
2168 2170
2169static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m)2171static 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
2174 2176
2175static inline void __clear_task_blocked_on(struct task_struct *p, struct mutex *m)2177static inline void __clear_task_blocked_on(struct task_struct *p, struct mutex *m)
2176{2178{
2177 WARN_ON_ONCE(!m);2179 if (m) {
2178 /* Currently we serialize blocked_on under the mutex::wait_lock */2180 struct mutex *blocked_on = READ_ONCE(p->blocked_on);
2179 lockdep_assert_held_once(&m->wait_lock);2181
2180 /*2182 /* Currently we serialize blocked_on under the mutex::wait_lock */
2181 * There may be cases where we re-clear already cleared2183 lockdep_assert_held_once(&m->wait_lock);
2182 * blocked_on relationships, but make sure we are not2184 /*
2183 * clearing the relationship with a different lock.2185 * There may be cases where we re-clear already cleared
2184 */2186 * blocked_on relationships, but make sure we are not
2185 WARN_ON_ONCE(m && p->blocked_on && p->blocked_on != m);2187 * clearing the relationship with a different lock.
2186 p->blocked_on = NULL;2188 */
2189 WARN_ON_ONCE(blocked_on && blocked_on != m);
2190 }
2191 WRITE_ONCE(p->blocked_on, NULL);
2187}2192}
2188 2193
2189static inline void clear_task_blocked_on(struct task_struct *p, struct mutex *m)2194static 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
319{319{
320 if (can_do_masked_user_access())320 if (can_do_masked_user_access())
321 to = masked_user_access_begin(to);321 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)))
323 return -EFAULT;323 return -EFAULT;
324 unsafe_put_user(val, to, Efault);324 unsafe_put_user(val, to, Efault);
325 user_read_access_end();325 user_write_access_end();
326 return 0;326 return 0;
327Efault:327Efault:
328 user_read_access_end();328 user_write_access_end();
329 return -EFAULT;329 return -EFAULT;
330}330}
331 331
kernel/locking/ww_mutex.h+5−1
@@ -342,8 +342,12 @@ static bool __ww_mutex_wound(struct MUTEX *lock, · 341 unmodified lines
342 * When waking up the task to wound, be sure to clear the342 * When waking up the task to wound, be sure to clear the
343 * blocked_on pointer. Otherwise we can see circular343 * blocked_on pointer. Otherwise we can see circular
344 * blocked_on relationships that can't resolve.344 * 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.
345 */349 */
346 __clear_task_blocked_on(owner, lock);350 __clear_task_blocked_on(owner, NULL);
347 wake_q_add(wake_q, owner);351 wake_q_add(wake_q, owner);
348 }352 }
349 return true;353 return true;