Commit 4f152a7e authored by Stephen D. Smalley's avatar Stephen D. Smalley Committed by Linus Torvalds

[PATCH] Replace inode_post_lookup hook with d_instantiate hook

This patch removes the security_inode_post_lookup hook entirely and
adds a security_d_instantiate hook call to the d_instantiate function
and the d_splice_alias function.  The inode_post_lookup hook was
subject to races since the inode is already accessible through the
dcache before it is called, didn't handle filesystems that directly
populate the dcache, and wasn't always called in the desired context
(e.g. for pipe, shmem, and devpts inodes).  The d_instantiate hook
enables initialization of the inode security information.  This hook
is used by SELinux and by DTE to setup the inode security state, and
eliminated the need for the inode_precondition function in SELinux.
parent 8c3468ed
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/security.h>
#define DCACHE_PARANOIA 1 #define DCACHE_PARANOIA 1
/* #define DCACHE_DEBUG 1 */ /* #define DCACHE_DEBUG 1 */
...@@ -699,6 +700,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) ...@@ -699,6 +700,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
void d_instantiate(struct dentry *entry, struct inode * inode) void d_instantiate(struct dentry *entry, struct inode * inode)
{ {
if (!list_empty(&entry->d_alias)) BUG(); if (!list_empty(&entry->d_alias)) BUG();
security_d_instantiate(entry, inode);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
if (inode) if (inode)
list_add(&entry->d_alias, &inode->i_dentry); list_add(&entry->d_alias, &inode->i_dentry);
...@@ -825,6 +827,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) ...@@ -825,6 +827,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
struct dentry *new = NULL; struct dentry *new = NULL;
if (inode && S_ISDIR(inode->i_mode)) { if (inode && S_ISDIR(inode->i_mode)) {
security_d_instantiate(dentry, inode);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
if (!list_empty(&inode->i_dentry)) { if (!list_empty(&inode->i_dentry)) {
new = list_entry(inode->i_dentry.next, struct dentry, d_alias); new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
......
...@@ -372,10 +372,8 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i ...@@ -372,10 +372,8 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i
result = dir->i_op->lookup(dir, dentry); result = dir->i_op->lookup(dir, dentry);
if (result) if (result)
dput(dentry); dput(dentry);
else { else
result = dentry; result = dentry;
security_inode_post_lookup(dir, result);
}
} }
up(&dir->i_sem); up(&dir->i_sem);
return result; return result;
...@@ -916,10 +914,9 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ...@@ -916,10 +914,9 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
if (!new) if (!new)
goto out; goto out;
dentry = inode->i_op->lookup(inode, new); dentry = inode->i_op->lookup(inode, new);
if (!dentry) { if (!dentry)
dentry = new; dentry = new;
security_inode_post_lookup(inode, dentry); else
} else
dput(new); dput(new);
} }
out: out:
......
...@@ -339,10 +339,6 @@ struct swap_info_struct; ...@@ -339,10 +339,6 @@ struct swap_info_struct;
* @mnt is the vfsmount where the dentry was looked up * @mnt is the vfsmount where the dentry was looked up
* @dentry contains the dentry structure for the file. * @dentry contains the dentry structure for the file.
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @inode_post_lookup:
* Set the security attributes for a file after it has been looked up.
* @inode contains the inode structure for parent directory.
* @d contains the dentry structure for the file.
* @inode_delete: * @inode_delete:
* @inode contains the inode structure for deleted inode. * @inode contains the inode structure for deleted inode.
* This hook is called when a deleted inode is released (i.e. an inode * This hook is called when a deleted inode is released (i.e. an inode
...@@ -868,7 +864,6 @@ struct security_operations { ...@@ -868,7 +864,6 @@ struct security_operations {
int (*inode_permission_lite) (struct inode *inode, int mask); int (*inode_permission_lite) (struct inode *inode, int mask);
int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_post_lookup) (struct inode *inode, struct dentry *d);
void (*inode_delete) (struct inode *inode); void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, char *name, void *value, int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
size_t size, int flags); size_t size, int flags);
...@@ -953,6 +948,8 @@ struct security_operations { ...@@ -953,6 +948,8 @@ struct security_operations {
struct security_operations *ops); struct security_operations *ops);
int (*unregister_security) (const char *name, int (*unregister_security) (const char *name,
struct security_operations *ops); struct security_operations *ops);
void (*d_instantiate) (struct dentry * dentry, struct inode * inode);
}; };
/* global variables */ /* global variables */
...@@ -1246,12 +1243,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt, ...@@ -1246,12 +1243,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt,
return security_ops->inode_getattr (mnt, dentry); return security_ops->inode_getattr (mnt, dentry);
} }
static inline void security_inode_post_lookup (struct inode *inode,
struct dentry *dentry)
{
security_ops->inode_post_lookup (inode, dentry);
}
static inline void security_inode_delete (struct inode *inode) static inline void security_inode_delete (struct inode *inode)
{ {
security_ops->inode_delete (inode); security_ops->inode_delete (inode);
...@@ -1549,6 +1540,11 @@ static inline int security_sem_semop (struct sem_array * sma, ...@@ -1549,6 +1540,11 @@ static inline int security_sem_semop (struct sem_array * sma,
return security_ops->sem_semop(sma, sops, nsops, alter); return security_ops->sem_semop(sma, sops, nsops, alter);
} }
static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
{
security_ops->d_instantiate (dentry, inode);
}
/* prototypes */ /* prototypes */
extern int security_scaffolding_startup (void); extern int security_scaffolding_startup (void);
extern int register_security (struct security_operations *ops); extern int register_security (struct security_operations *ops);
...@@ -1828,10 +1824,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt, ...@@ -1828,10 +1824,6 @@ static inline int security_inode_getattr (struct vfsmount *mnt,
return 0; return 0;
} }
static inline void security_inode_post_lookup (struct inode *inode,
struct dentry *dentry)
{ }
static inline void security_inode_delete (struct inode *inode) static inline void security_inode_delete (struct inode *inode)
{ } { }
...@@ -2115,6 +2107,9 @@ static inline int security_sem_semop (struct sem_array * sma, ...@@ -2115,6 +2107,9 @@ static inline int security_sem_semop (struct sem_array * sma,
return 0; return 0;
} }
static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
{ }
#endif /* CONFIG_SECURITY */ #endif /* CONFIG_SECURITY */
#endif /* ! __LINUX_SECURITY_H */ #endif /* ! __LINUX_SECURITY_H */
......
...@@ -311,11 +311,6 @@ static int dummy_inode_getattr (struct vfsmount *mnt, struct dentry *dentry) ...@@ -311,11 +311,6 @@ static int dummy_inode_getattr (struct vfsmount *mnt, struct dentry *dentry)
return 0; return 0;
} }
static void dummy_inode_post_lookup (struct inode *ino, struct dentry *d)
{
return;
}
static void dummy_inode_delete (struct inode *ino) static void dummy_inode_delete (struct inode *ino)
{ {
return; return;
...@@ -612,6 +607,12 @@ static int dummy_unregister_security (const char *name, struct security_operatio ...@@ -612,6 +607,12 @@ static int dummy_unregister_security (const char *name, struct security_operatio
return -EINVAL; return -EINVAL;
} }
static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
{
return;
}
struct security_operations dummy_security_ops; struct security_operations dummy_security_ops;
#define set_to_dummy_if_null(ops, function) \ #define set_to_dummy_if_null(ops, function) \
...@@ -674,7 +675,6 @@ void security_fixup_ops (struct security_operations *ops) ...@@ -674,7 +675,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_permission_lite); set_to_dummy_if_null(ops, inode_permission_lite);
set_to_dummy_if_null(ops, inode_setattr); set_to_dummy_if_null(ops, inode_setattr);
set_to_dummy_if_null(ops, inode_getattr); set_to_dummy_if_null(ops, inode_getattr);
set_to_dummy_if_null(ops, inode_post_lookup);
set_to_dummy_if_null(ops, inode_delete); set_to_dummy_if_null(ops, inode_delete);
set_to_dummy_if_null(ops, inode_setxattr); set_to_dummy_if_null(ops, inode_setxattr);
set_to_dummy_if_null(ops, inode_getxattr); set_to_dummy_if_null(ops, inode_getxattr);
...@@ -731,5 +731,6 @@ void security_fixup_ops (struct security_operations *ops) ...@@ -731,5 +731,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sem_semop); set_to_dummy_if_null(ops, sem_semop);
set_to_dummy_if_null(ops, register_security); set_to_dummy_if_null(ops, register_security);
set_to_dummy_if_null(ops, unregister_security); set_to_dummy_if_null(ops, unregister_security);
set_to_dummy_if_null(ops, d_instantiate);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment