diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 1368f8925343..5deda8e0fe96 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1006,15 +1006,39 @@ static int smack_inode_alloc_security(struct inode *inode) } /** - * smack_inode_free_security - free an inode blob + * smack_inode_free_rcu - Free inode_smack blob from cache + * @head: the rcu_head for getting inode_smack pointer + * + * Call back function called from call_rcu() to free + * the i_security blob pointer in inode + */ +static void smack_inode_free_rcu(struct rcu_head *head) +{ + struct inode_smack *issp; + + issp = container_of(head, struct inode_smack, smk_rcu); + kmem_cache_free(smack_inode_cache, issp); +} + +/** + * smack_inode_free_security - free an inode blob using call_rcu() * @inode: the inode with a blob * - * Clears the blob pointer in inode + * Clears the blob pointer in inode using RCU */ static void smack_inode_free_security(struct inode *inode) { - kmem_cache_free(smack_inode_cache, inode->i_security); - inode->i_security = NULL; + struct inode_smack *issp = inode->i_security; + + /* + * The inode may still be referenced in a path walk and + * a call to smack_inode_permission() can be made + * after smack_inode_free_security() is called. + * To avoid race condition free the i_security via RCU + * and leave the current inode->i_security pointer intact. + * The inode will be freed after the RCU grace period too. + */ + call_rcu(&issp->smk_rcu, smack_inode_free_rcu); } /** |