• David Howells's avatar
    CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials · de09a977
    David Howells authored
    It's possible for get_task_cred() as it currently stands to 'corrupt' a set of
    credentials by incrementing their usage count after their replacement by the
    task being accessed.
    
    What happens is that get_task_cred() can race with commit_creds():
    
    	TASK_1			TASK_2			RCU_CLEANER
    	-->get_task_cred(TASK_2)
    	rcu_read_lock()
    	__cred = __task_cred(TASK_2)
    				-->commit_creds()
    				old_cred = TASK_2->real_cred
    				TASK_2->real_cred = ...
    				put_cred(old_cred)
    				  call_rcu(old_cred)
    		[__cred->usage == 0]
    	get_cred(__cred)
    		[__cred->usage == 1]
    	rcu_read_unlock()
    							-->put_cred_rcu()
    							[__cred->usage == 1]
    							panic()
    
    However, since a tasks credentials are generally not changed very often, we can
    reasonably make use of a loop involving reading the creds pointer and using
    atomic_inc_not_zero() to attempt to increment it if it hasn't already hit zero.
    
    If successful, we can safely return the credentials in the knowledge that...
    de09a977
cred.c 21.7 KB