Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

CRED: Fix __task_cred()'s lockdep check and banner comment

Fix __task_cred()'s lockdep check by removing the following validation
condition:

lockdep_tasklist_lock_is_held()

as commit_creds() does not take the tasklist_lock, and nor do most of the
functions that call it, so this check is pointless and it can prevent
detection of the RCU lock not being held if the tasklist_lock is held.

Instead, add the following validation condition:

task->exit_state >= 0

to permit the access if the target task is dead and therefore unable to change
its own credentials.

Fix __task_cred()'s comment to:

(1) discard the bit that says that the caller must prevent the target task
from being deleted. That shouldn't need saying.

(2) Add a comment indicating the result of __task_cred() should not be passed
directly to get_cred(), but rather than get_task_cred() should be used
instead.

Also put a note into the documentation to enforce this point there too.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

David Howells and committed by
Linus Torvalds
8f92054e de09a977

+14 -5
+3
Documentation/credentials.txt
··· 417 417 This does all the RCU magic inside of it. The caller must call put_cred() on 418 418 the credentials so obtained when they're finished with. 419 419 420 + [*] Note: The result of __task_cred() should not be passed directly to 421 + get_cred() as this may race with commit_cred(). 422 + 420 423 There are a couple of convenience functions to access bits of another task's 421 424 credentials, hiding the RCU magic from the caller: 422 425
+10 -5
include/linux/cred.h
··· 274 274 * @task: The task to query 275 275 * 276 276 * Access the objective credentials of a task. The caller must hold the RCU 277 - * readlock. 277 + * readlock or the task must be dead and unable to change its own credentials. 278 278 * 279 - * The caller must make sure task doesn't go away, either by holding a ref on 280 - * task or by holding tasklist_lock to prevent it from being unlinked. 279 + * The result of this function should not be passed directly to get_cred(); 280 + * rather get_task_cred() should be used instead. 281 281 */ 282 - #define __task_cred(task) \ 283 - ((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_tasklist_lock_is_held()))) 282 + #define __task_cred(task) \ 283 + ({ \ 284 + const struct task_struct *__t = (task); \ 285 + rcu_dereference_check(__t->real_cred, \ 286 + rcu_read_lock_held() || \ 287 + task_is_dead(__t)); \ 288 + }) 284 289 285 290 /** 286 291 * get_current_cred - Get the current task's subjective credentials
+1
include/linux/sched.h
··· 214 214 215 215 #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) 216 216 #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) 217 + #define task_is_dead(task) ((task)->exit_state != 0) 217 218 #define task_is_stopped_or_traced(task) \ 218 219 ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) 219 220 #define task_contributes_to_load(task) \