Skip to content

Commit 0a9ee9c

Browse files
committed
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()
2 parents 99bade3 + 21924af commit 0a9ee9c

File tree

3 files changed

+25
-16
lines changed

3 files changed

+25
-16
lines changed

include/linux/sched.h

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,8 @@ static inline struct mutex *__get_task_blocked_on(struct task_struct *p)
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)
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)
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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,13 +319,13 @@ static __always_inline int futex_put_value(u32 val, u32 __user *to)
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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,12 @@ static bool __ww_mutex_wound(struct MUTEX *lock,
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;

0 commit comments

Comments
 (0)