.:: Hooks ::.
1. Setup
Placement in fs/inode.c
audit_inode_alloc()/audit_inode_free():
These hooks are responsible for allocating and deallocating inode audit data.
2. Management
Management of "watches" starts at the dentry level.
Placement in fs/dcache.c
Initial setup:
d_instantiate()/d_splice_alias() :
These hooks cover initial audit setup for inodes that are newly created and
for existing inodes when they are first looked up, prior to becoming
accessible via the dcache.
Update:
__d_lookup():
This hook covers updating the inode audit data if necessary upon subsequent
lookups when the inode is already accessible via dcache, both to reflect
removal of "watches" and to handle changes in state since the initial setup.
d_move():
This hook covers resetting the inode audit data and updating it accordingly
post-move.
Deletion:
dentry_iput():
This hook covers resetting the inode audit data if the dentry being
deleted is at a "watch point".
3. Generation
Any time we access a "watched" object we are auditable. These hooks are used
to notify the audit subsystem of relevant access. Placement in fs/namei.c.
Permissions:
permission()/exec_permission_lite():
Notify the audit subsystem when a "watched" object is consulted about
permissions requirements.
Creation:
vfs_link()/symlink()/create()/mkdir()/mknod():
Notify the audit subsystem when an object has successfully manifested at a
"watch point".
Deletion:
may_delete() [vfs_unlink()/rmdir()]:
Notify the audit subsystem when an object successfully leaves a "watch point".
The hook appears in may_delete() after we have determined the victim dentry
has an inode.
Note: We are unable to use may_create() in a similar fashion to may_delete()
because the inode does/should not exist for the child dentry in question yet.
Rename:
may_delete(),vfs_rename_other()/rename_dir():
Notify the audit subsystem when an object has been moved out of a "watch
point" using the may_delete() hook. Notify the audit subsystem when a object
moves in to a "watch point" using the vfs_rename_other/rename_dir() hooks.
--
PART 2
This patch was diffed against linux-2.6.11.5 and introduces the file system
hooks.
diff -Nurp linux-2.6.11.5/fs/dcache.c linux-2.6.11.5~auditfs/fs/dcache.c
--- linux-2.6.11.5/fs/dcache.c 2005-03-19 00:34:52.000000000 -0600
+++ linux-2.6.11.5~auditfs/fs/dcache.c 2005-03-31 11:31:09.000000000 -0600
@@ -32,6 +32,7 @@
#include <linux/seqlock.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
+#include <linux/audit.h>
/* #define DCACHE_DEBUG 1 */
@@ -96,6 +97,7 @@ static inline void dentry_iput(struct de
{
struct inode *inode = dentry->d_inode;
if (inode) {
+ audit_attach_watch(dentry, 1);
dentry->d_inode = NULL;
list_del_init(&dentry->d_alias);
spin_unlock(&dentry->d_lock);
@@ -798,6 +800,7 @@ void d_instantiate(struct dentry *entry,
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode;
+ audit_attach_watch(entry, 0);
spin_unlock(&dcache_lock);
security_d_instantiate(entry, inode);
}
@@ -974,6 +977,7 @@ struct dentry *d_splice_alias(struct ino
new = __d_find_alias(inode, 1);
if (new) {
BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
+ audit_attach_watch(new, 0);
spin_unlock(&dcache_lock);
security_d_instantiate(new, inode);
d_rehash(dentry);
@@ -983,6 +987,7 @@ struct dentry *d_splice_alias(struct ino
/* d_instantiate takes dcache_lock, so we do it by hand */
list_add(&dentry->d_alias, &inode->i_dentry);
dentry->d_inode = inode;
+ audit_attach_watch(dentry, 0);
spin_unlock(&dcache_lock);
security_d_instantiate(dentry, inode);
d_rehash(dentry);
@@ -1086,6 +1091,7 @@ struct dentry * __d_lookup(struct dentry
if (!d_unhashed(dentry)) {
atomic_inc(&dentry->d_count);
found = dentry;
+ audit_attach_watch(found, 0);
}
spin_unlock(&dentry->d_lock);
break;
@@ -1295,6 +1301,8 @@ void d_move(struct dentry * dentry, stru
spin_lock(&target->d_lock);
}
+ audit_attach_watch(dentry, 1);
+
/* Move the dentry to the target hash queue, if on different bucket */
if (dentry->d_flags & DCACHE_UNHASHED)
goto already_unhashed;
@@ -1328,6 +1336,7 @@ already_unhashed:
list_add(&target->d_child, &target->d_parent->d_subdirs);
}
+ audit_attach_watch(dentry, 0);
list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
spin_unlock(&target->d_lock);
spin_unlock(&dentry->d_lock);
diff -Nurp linux-2.6.11.5/fs/inode.c linux-2.6.11.5~auditfs/fs/inode.c
--- linux-2.6.11.5/fs/inode.c 2005-03-19 00:35:04.000000000 -0600
+++ linux-2.6.11.5~auditfs/fs/inode.c 2005-03-31 11:31:17.000000000 -0600
@@ -21,6 +21,7 @@
#include <linux/pagemap.h>
#include <linux/cdev.h>
#include <linux/bootmem.h>
+#include <linux/audit.h>
/*
* This is needed for the following functions:
@@ -134,9 +135,11 @@ static struct inode *alloc_inode(struct
inode->i_bdev = NULL;
inode->i_cdev = NULL;
inode->i_rdev = 0;
+ inode->i_audit = NULL;
inode->i_security = NULL;
inode->dirtied_when = 0;
- if (security_inode_alloc(inode)) {
+ if (audit_inode_alloc(inode) || security_inode_alloc(inode)) {
+ audit_inode_free(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
@@ -174,6 +177,7 @@ void destroy_inode(struct inode *inode)
{
if (inode_has_buffers(inode))
BUG();
+ audit_inode_free(inode);
security_inode_free(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
diff -Nurp linux-2.6.11.5/fs/namei.c linux-2.6.11.5~auditfs/fs/namei.c
--- linux-2.6.11.5/fs/namei.c 2005-03-19 00:34:54.000000000 -0600
+++ linux-2.6.11.5~auditfs/fs/namei.c 2005-03-31 11:31:24.000000000 -0600
@@ -214,6 +214,8 @@ int permission(struct inode *inode, int
{
int retval, submask;
+ audit_notify_watch(inode, mask);
+
if (mask & MAY_WRITE) {
umode_t mode = inode->i_mode;
@@ -347,6 +349,8 @@ static inline int exec_permission_lite(s
if (inode->i_op && inode->i_op->permission)
return -EAGAIN;
+ audit_notify_watch(inode, MAY_EXEC);
+
if (current->fsuid == inode->i_uid)
mode >>= 6;
else if (in_group_p(inode->i_gid))
@@ -1128,6 +1132,8 @@ static inline int may_delete(struct inod
BUG_ON(victim->d_parent->d_inode != dir);
+ audit_notify_watch(victim->d_inode, MAY_WRITE);
+
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
@@ -1252,6 +1258,7 @@ int vfs_create(struct inode *dir, struct
DQUOT_INIT(dir);
error = dir->i_op->create(dir, dentry, mode, nd);
if (!error) {
+ audit_notify_watch(dentry->d_inode, MAY_WRITE);
inode_dir_notify(dir, DN_CREATE);
security_inode_post_create(dir, dentry, mode);
}
@@ -1557,6 +1564,7 @@ int vfs_mknod(struct inode *dir, struct
DQUOT_INIT(dir);
error = dir->i_op->mknod(dir, dentry, mode, dev);
if (!error) {
+ audit_notify_watch(dentry->d_inode, MAY_WRITE|MAY_EXEC);
inode_dir_notify(dir, DN_CREATE);
security_inode_post_mknod(dir, dentry, mode, dev);
}
@@ -1630,6 +1638,7 @@ int vfs_mkdir(struct inode *dir, struct
DQUOT_INIT(dir);
error = dir->i_op->mkdir(dir, dentry, mode);
if (!error) {
+ audit_notify_watch(dentry->d_inode, MAY_WRITE);
inode_dir_notify(dir, DN_CREATE);
security_inode_post_mkdir(dir,dentry, mode);
}
@@ -1874,6 +1883,7 @@ int vfs_symlink(struct inode *dir, struc
DQUOT_INIT(dir);
error = dir->i_op->symlink(dir, dentry, oldname);
if (!error) {
+ audit_notify_watch(dentry->d_inode, MAY_WRITE);
inode_dir_notify(dir, DN_CREATE);
security_inode_post_symlink(dir, dentry, oldname);
}
@@ -1947,6 +1957,7 @@ int vfs_link(struct dentry *old_dentry,
error = dir->i_op->link(old_dentry, dir, new_dentry);
up(&old_dentry->d_inode->i_sem);
if (!error) {
+ audit_notify_watch(new_dentry->d_inode, MAY_WRITE);
inode_dir_notify(dir, DN_CREATE);
security_inode_post_link(old_dentry, dir, new_dentry);
}
@@ -2070,6 +2081,7 @@ int vfs_rename_dir(struct inode *old_dir
}
if (!error) {
d_move(old_dentry,new_dentry);
+ audit_notify_watch(old_dentry->d_inode, MAY_WRITE);
security_inode_post_rename(old_dir, old_dentry,
new_dir, new_dentry);
}
@@ -2098,6 +2110,7 @@ int vfs_rename_other(struct inode *old_d
/* The following d_move() should become unconditional */
if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
d_move(old_dentry, new_dentry);
+ audit_notify_watch(old_dentry->d_inode, MAY_WRITE);
security_inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
}
if (target)
-tim