aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6625699f497c..57b0b49f4e6e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -234,6 +234,14 @@ static int inode_alloc_security(struct inode *inode)
234 return 0; 234 return 0;
235} 235}
236 236
237static void inode_free_rcu(struct rcu_head *head)
238{
239 struct inode_security_struct *isec;
240
241 isec = container_of(head, struct inode_security_struct, rcu);
242 kmem_cache_free(sel_inode_cache, isec);
243}
244
237static void inode_free_security(struct inode *inode) 245static void inode_free_security(struct inode *inode)
238{ 246{
239 struct inode_security_struct *isec = inode->i_security; 247 struct inode_security_struct *isec = inode->i_security;
@@ -244,8 +252,16 @@ static void inode_free_security(struct inode *inode)
244 list_del_init(&isec->list); 252 list_del_init(&isec->list);
245 spin_unlock(&sbsec->isec_lock); 253 spin_unlock(&sbsec->isec_lock);
246 254
247 inode->i_security = NULL; 255 /*
248 kmem_cache_free(sel_inode_cache, isec); 256 * The inode may still be referenced in a path walk and
257 * a call to selinux_inode_permission() can be made
258 * after inode_free_security() is called. Ideally, the VFS
259 * wouldn't do this, but fixing that is a much harder
260 * job. For now, simply free the i_security via RCU, and
261 * leave the current inode->i_security pointer intact.
262 * The inode will be freed after the RCU grace period too.
263 */
264 call_rcu(&isec->rcu, inode_free_rcu);
249} 265}
250 266
251static int file_alloc_security(struct file *file) 267static int file_alloc_security(struct file *file)