All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
@ 2011-04-20 22:00 Andi Kleen
  2011-04-20 22:51 ` Casey Schaufler
  0 siblings, 1 reply; 8+ messages in thread
From: Andi Kleen @ 2011-04-20 22:00 UTC (permalink / raw)
  To: jmorris; +Cc: linux-security-module, linux-kernel, Andi Kleen

From: Andi Kleen <ak@linux.intel.com>

smk_access_entry does a RCU list walk for a list shared with other
threads. It relies on the caller doing rcu_read_lock().
One caller forgot to do to this, which could lead to races
on preemptible kernels.

Move the rcu_read_lock() into smk_access_entry instead.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 security/smack/smack_access.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 7b0d3b3..43b20f3 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -92,6 +92,7 @@ int smk_access_entry(char *subject_label, char *object_label,
 	int may = -ENOENT;
 	struct smack_rule *srp;
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(srp, rule_list, list) {
 		if (srp->smk_subject == subject_label ||
 		    strcmp(srp->smk_subject, subject_label) == 0) {
@@ -102,6 +103,7 @@ int smk_access_entry(char *subject_label, char *object_label,
 			}
 		}
 	}
+	rcu_read_unlock();
 
 	return may;
 }
@@ -184,9 +186,7 @@ int smk_access_flags(char *subject_label, char *object_label, int request,
 	 * good. A negative response from smk_access_entry()
 	 * indicates there is no entry for this pair.
 	 */
-	rcu_read_lock();
 	may = smk_access_entry(subject_label, object_label, &smack_rule_list);
-	rcu_read_unlock();
 
 	if (may > 0 && (request & may) == request)
 		goto out_audit;
-- 
1.7.4.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-20 22:00 [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk Andi Kleen
@ 2011-04-20 22:51 ` Casey Schaufler
  2011-04-20 23:18   ` Andi Kleen
  0 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2011-04-20 22:51 UTC (permalink / raw)
  To: Andi Kleen; +Cc: jmorris, linux-security-module, linux-kernel, Andi Kleen

On 4/20/2011 3:00 PM, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> smk_access_entry does a RCU list walk for a list shared with other
> threads. It relies on the caller doing rcu_read_lock().
> One caller forgot to do to this, which could lead to races
> on preemptible kernels.
>
> Move the rcu_read_lock() into smk_access_entry instead.

Nacked-by: Casey Schaufler <casey@schaufler-ca.com>

The lock was moved out of smk_access_entry in support of the
processing done in the smack_mmap_file() hook. Where do you see
a potential race, and which caller "forgot" to do the lock?

Thank you.

> Signed-off-by: Andi Kleen <ak@linux.intel.com>
> ---
>  security/smack/smack_access.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
> index 7b0d3b3..43b20f3 100644
> --- a/security/smack/smack_access.c
> +++ b/security/smack/smack_access.c
> @@ -92,6 +92,7 @@ int smk_access_entry(char *subject_label, char *object_label,
>  	int may = -ENOENT;
>  	struct smack_rule *srp;
>  
> +	rcu_read_lock();
>  	list_for_each_entry_rcu(srp, rule_list, list) {
>  		if (srp->smk_subject == subject_label ||
>  		    strcmp(srp->smk_subject, subject_label) == 0) {
> @@ -102,6 +103,7 @@ int smk_access_entry(char *subject_label, char *object_label,
>  			}
>  		}
>  	}
> +	rcu_read_unlock();
>  
>  	return may;
>  }
> @@ -184,9 +186,7 @@ int smk_access_flags(char *subject_label, char *object_label, int request,
>  	 * good. A negative response from smk_access_entry()
>  	 * indicates there is no entry for this pair.
>  	 */
> -	rcu_read_lock();
>  	may = smk_access_entry(subject_label, object_label, &smack_rule_list);
> -	rcu_read_unlock();
>  
>  	if (may > 0 && (request & may) == request)
>  		goto out_audit;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-20 22:51 ` Casey Schaufler
@ 2011-04-20 23:18   ` Andi Kleen
  2011-04-20 23:43     ` Casey Schaufler
  0 siblings, 1 reply; 8+ messages in thread
From: Andi Kleen @ 2011-04-20 23:18 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: Andi Kleen, jmorris, linux-security-module, linux-kernel

On Wed, Apr 20, 2011 at 03:51:41PM -0700, Casey Schaufler wrote:
> On 4/20/2011 3:00 PM, Andi Kleen wrote:
> > From: Andi Kleen <ak@linux.intel.com>
> >
> > smk_access_entry does a RCU list walk for a list shared with other
> > threads. It relies on the caller doing rcu_read_lock().
> > One caller forgot to do to this, which could lead to races
> > on preemptible kernels.
> >
> > Move the rcu_read_lock() into smk_access_entry instead.
> 
> Nacked-by: Casey Schaufler <casey@schaufler-ca.com>
> 
> The lock was moved out of smk_access_entry in support of the
> processing done in the smack_mmap_file() hook. Where do you see
> a potential race, and which caller "forgot" to do the lock?

There are two callers and only one takes it.
The one that doesn't take it is smk_curacc.

I checked the callers of that and there is no rcu_read_lock() in those

As far as I understand the cred which holds this list is shared
between threads and other threads can modify it. Which means 
it needs RCU read lock protection.

-Andi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-20 23:18   ` Andi Kleen
@ 2011-04-20 23:43     ` Casey Schaufler
  2011-04-21  0:08       ` Andi Kleen
  0 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2011-04-20 23:43 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andi Kleen, jmorris, linux-security-module, linux-kernel,
	Casey Schaufler

On 4/20/2011 4:18 PM, Andi Kleen wrote:
> On Wed, Apr 20, 2011 at 03:51:41PM -0700, Casey Schaufler wrote:
>> On 4/20/2011 3:00 PM, Andi Kleen wrote:
>>> From: Andi Kleen <ak@linux.intel.com>
>>>
>>> smk_access_entry does a RCU list walk for a list shared with other
>>> threads. It relies on the caller doing rcu_read_lock().
>>> One caller forgot to do to this, which could lead to races
>>> on preemptible kernels.
>>>
>>> Move the rcu_read_lock() into smk_access_entry instead.
>> Nacked-by: Casey Schaufler <casey@schaufler-ca.com>
>>
>> The lock was moved out of smk_access_entry in support of the
>> processing done in the smack_mmap_file() hook. Where do you see
>> a potential race, and which caller "forgot" to do the lock?
> There are two callers and only one takes it.

There are two callers in smack_access.c.
There are four more in smack_lsm.c

> The one that doesn't take it is smk_curacc.

The call in smk_curacc() is using the task local list, not the system list.

> I checked the callers of that and there is no rcu_read_lock() in those
>
> As far as I understand the cred which holds this list is shared
> between threads and other threads can modify it. Which means 
> it needs RCU read lock protection.

The global list, yes. The task specific list, no. Modifying the local
list is like any other modification of the cred structure and requires
the cred be copied.

Moving the lock into smk_access_entry() would introduce a potential
deadlock in smack_mmap_file. There is a bit of convolution in the
mmap hook that requires looking at the list in a way that does not
allow the locking to be embedded where it used to be.

> -Andi
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-20 23:43     ` Casey Schaufler
@ 2011-04-21  0:08       ` Andi Kleen
  2011-04-21  0:47         ` Casey Schaufler
  0 siblings, 1 reply; 8+ messages in thread
From: Andi Kleen @ 2011-04-21  0:08 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Andi Kleen, Andi Kleen, jmorris, linux-security-module, linux-kernel

> The global list, yes. The task specific list, no. Modifying the local
> list is like any other modification of the cred structure and requires
> the cred be copied.

But you still need to free it eventually right? And that freeing will
need RCU on the reader.

> 
> Moving the lock into smk_access_entry() would introduce a potential
> deadlock in smack_mmap_file. There is a bit of convolution in the
> mmap hook that requires looking at the list in a way that does not
> allow the locking to be embedded where it used to be.

rcu_read_lock() is just a per task counter and nests fine and never deadlocks.

-Andi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-21  0:08       ` Andi Kleen
@ 2011-04-21  0:47         ` Casey Schaufler
  2011-04-21 15:58           ` Andi Kleen
  0 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2011-04-21  0:47 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andi Kleen, jmorris, linux-security-module, linux-kernel,
	Casey Schaufler

On 4/20/2011 5:08 PM, Andi Kleen wrote:
>> The global list, yes. The task specific list, no. Modifying the local
>> list is like any other modification of the cred structure and requires
>> the cred be copied.
> But you still need to free it eventually right? And that freeing will
> need RCU on the reader.

Entries are never freed from the global list. Someone is working
on a patch to do that, but is running into - wait for it - locking
issues.

Entries on the local lists are only freed when the task exits.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-21  0:47         ` Casey Schaufler
@ 2011-04-21 15:58           ` Andi Kleen
  2011-04-22  3:55             ` Casey Schaufler
  0 siblings, 1 reply; 8+ messages in thread
From: Andi Kleen @ 2011-04-21 15:58 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Andi Kleen, Andi Kleen, jmorris, linux-security-module, linux-kernel

On Wed, Apr 20, 2011 at 05:47:40PM -0700, Casey Schaufler wrote:
> On 4/20/2011 5:08 PM, Andi Kleen wrote:
> >> The global list, yes. The task specific list, no. Modifying the local
> >> list is like any other modification of the cred structure and requires
> >> the cred be copied.
> > But you still need to free it eventually right? And that freeing will
> > need RCU on the reader.
> 
> Entries are never freed from the global list. Someone is working
> on a patch to do that, but is running into - wait for it - locking
> issues.

Then why do you use rcu_read_lock() at all? 

You can drop all the rcu_read_lock()s and probably the other *_rcu 
list accesses then. And my patch is indeed not needed. 

> Entries on the local lists are only freed when the task exits.

You mean the last user of the cred?

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk.
  2011-04-21 15:58           ` Andi Kleen
@ 2011-04-22  3:55             ` Casey Schaufler
  0 siblings, 0 replies; 8+ messages in thread
From: Casey Schaufler @ 2011-04-22  3:55 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Andi Kleen, jmorris, linux-security-module, linux-kernel

On 4/21/2011 8:58 AM, Andi Kleen wrote:
> On Wed, Apr 20, 2011 at 05:47:40PM -0700, Casey Schaufler wrote:
>> On 4/20/2011 5:08 PM, Andi Kleen wrote:
>>>> The global list, yes. The task specific list, no. Modifying the local
>>>> list is like any other modification of the cred structure and requires
>>>> the cred be copied.
>>> But you still need to free it eventually right? And that freeing will
>>> need RCU on the reader.
>> Entries are never freed from the global list. Someone is working
>> on a patch to do that, but is running into - wait for it - locking
>> issues.
> Then why do you use rcu_read_lock() at all? 

Because the entries can be modified in place.

> You can drop all the rcu_read_lock()s and probably the other *_rcu 
> list accesses then. And my patch is indeed not needed. 
>
>> Entries on the local lists are only freed when the task exits.
> You mean the last user of the cred?

Yes.

> -Andi
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-04-22  3:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-20 22:00 [PATCH] SMACK: Add missing rcu_read_lock/unlock for process capability walk Andi Kleen
2011-04-20 22:51 ` Casey Schaufler
2011-04-20 23:18   ` Andi Kleen
2011-04-20 23:43     ` Casey Schaufler
2011-04-21  0:08       ` Andi Kleen
2011-04-21  0:47         ` Casey Schaufler
2011-04-21 15:58           ` Andi Kleen
2011-04-22  3:55             ` Casey Schaufler

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.