Locking in AppArmor
===================

Lock hierarchy:

	aa_interface_lock
	  profile_list_lock
	    aa_profile->lock
	      task_lock()


Which lock protects what?

	/-----------------------+-------------------------------\
	| Variable		| Lock				|
	>-----------------------+-------------------------------<
	| profile_list		| profile_list_lock		|
	+-----------------------+-------------------------------+
	| aa_profile		| (reference count)		|
	+-----------------------+-------------------------------+
	| aa_profile->		| aa_profile->lock		|
	|   isstale,		|				|
	|   task_contexts	|				|
	+-----------------------+-------------------------------+
	| task_struct->security	| read: RCU			|
	|			| write: task_lock()		|
	+-----------------------+-------------------------------+
	| aa_profile->sub	| handle on the profile (list	|
	|			| is never modified)		|
	\-----------------------+-------------------------------/

(Obviously, the list_heads embedded in data structures are always
protected with the lock that also protects the list.)

When moving a task context from one profile to another, we grab both
profile locks with lock_both_profiles(). This ensures that both locks
are always taken in the same order, and so we won't deadlock.

Since task_struct->security is RCU protected the aa_task_struct it
references is only guarenteed to exist for the rcu cycle.  Where
aa_task_context->profile is needed in blocking operations the
profile's reference count is incremented and the profile reference
is used.

Profiles on profile_list are never stale: when a profile becomes stale,
it is removed from profile_list at the same time (under profile_list_lock
and aa_profile->lock).

The aa_interface_lock is taken whenever user-space modifies the profile
list, and can sleep. This ensures that profile loading/replacement/removal
won't race with itself. We release the profile_list_lock as soon as
possible to avoid stalling exec during profile loading/replacement/removal.

AppArmor uses lock subtyping to avoid false positives from lockdep.  The
profile lock is often taken nested, but it is guaranteed to be in a lock
safe order and not the same lock when done, so it is safe.

A third lock type (aa_lock_task_release) is given to the profile lock
when it is taken in soft irq context during task release (aa_release).
This is to avoid a false positive between the task lock and the profile
lock.  In task context the profile lock wraps the task lock with irqs
off, but the kernel takes the task lock with irqs enabled.  This won't
result in a deadlock because for a deadlock to occur the kernel must
take dead task A's lock (irqs on), the rcu callback hook freeing
dead task A must be run and AppArmor must be changing the profile on
dead task A.  The kernel should not be taking a dead task's task_lock
at the same time the task is being freed by task rcu cleanup other wise
the task would not be out of its quiescent period.
