Hello,
This is the patch I just tested using the audit.39 SRPM on an Opteron.
Everything appears to be in order. We're going to have the performance
team here run the audit code including auditfs on a PPC 15-way with hopes
of flushing memory errors/corruption, deadlock, etc and to also get some
performance [impact] numbers as a nice "to-have".
Hopefully the patch applies cleanly to audit.39 (I just forwarded it to
myself and stripped the quotations :-))
-tim
diff -Nurp linux-2.6.9/fs/dcache.c /var/log/kernel-2.6.9/linux-2.6.9/fs/dcache.c
--- linux-2.6.9/fs/dcache.c 2005-05-18 15:50:17.182181000 -0500
+++ /var/log/kernel-2.6.9/linux-2.6.9/fs/dcache.c 2005-05-17 16:29:47.000000000
-0500
@@ -1109,14 +1109,14 @@ out:
void d_delete(struct dentry * dentry)
{
+ audit_dentry_unpin(dentry);
+
/*
* Are we the only user?
*/
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
- audit_dentry_unpin(dentry);
-
if (atomic_read(&dentry->d_count) == 1) {
dentry_iput(dentry);
return;
diff -Nurp linux-2.6.9/fs/namei.c /var/log/kernel-2.6.9/linux-2.6.9/fs/namei.c
--- linux-2.6.9/fs/namei.c 2005-05-18 15:50:17.184180696 -0500
+++ /var/log/kernel-2.6.9/linux-2.6.9/fs/namei.c 2005-05-18 15:26:11.000000000
-0500
@@ -163,8 +163,6 @@ int vfs_permission(struct inode * inode,
{
umode_t mode = inode->i_mode;
- audit_notify_watch(inode, mask);
-
if (mask & MAY_WRITE) {
/*
* Nobody gets write access to a read-only fs.
@@ -217,6 +215,8 @@ int permission(struct inode * inode,int
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
+
+ audit_notify_watch(inode, mask);
if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, submask, nd);
diff -Nurp linux-2.6.9/kernel/auditfs.c
/var/log/kernel-2.6.9/linux-2.6.9/kernel/auditfs.c
--- linux-2.6.9/kernel/auditfs.c 2005-05-18 15:50:17.186180392 -0500
+++ /var/log/kernel-2.6.9/linux-2.6.9/kernel/auditfs.c 2005-05-18 16:57:43.760007664
-0500
@@ -41,9 +41,14 @@ static kmem_cache_t *audit_watch_cache;
static kmem_cache_t *audit_wentry_cache;
/* Read-heavy list */
-HLIST_HEAD(audit_master_watchlist);
-static spinlock_t audit_master_watchlist_lock = SPIN_LOCK_UNLOCKED;
+HLIST_HEAD(master_watchlist);
+static spinlock_t master_watchlist_lock = SPIN_LOCK_UNLOCKED;
+struct audit_skb_list {
+ struct hlist_node list;
+ void *memblk;
+ size_t size;
+};
/* Private Interface */
@@ -65,7 +70,7 @@ static inline void audit_pin(struct audi
}
static inline struct audit_wentry *audit_wentry_fetch(const char *name,
- struct audit_inode_data *data)
+ struct audit_inode_data *data)
{
struct audit_wentry *wentry, *ret = NULL;
struct hlist_node *pos;
@@ -166,7 +171,7 @@ static inline void *audit_to_transport(s
struct watch_transport t;
void *memblk;
- memblk = kmalloc(size, GFP_KERNEL);
+ memblk = kmalloc(size, GFP_ATOMIC);
if (!memblk)
goto audit_to_transport_exit;
@@ -300,9 +305,9 @@ static inline int audit_create_wentry(co
write_lock(&data->lock);
hlist_add_head(&new->w_node, &data->watchlist);
- spin_lock(&audit_master_watchlist_lock);
- hlist_add_head_rcu(&new->w_master, &audit_master_watchlist);
- spin_unlock(&audit_master_watchlist_lock);
+ spin_lock(&master_watchlist_lock);
+ hlist_add_head_rcu(&new->w_master, &master_watchlist);
+ spin_unlock(&master_watchlist_lock);
write_unlock(&data->lock);
audit_create_wentry_exit:
@@ -338,10 +343,10 @@ static inline void audit_destroy_wentry(
if (wentry) {
hlist_del_init(&wentry->w_node);
audit_wentry_put(wentry);
- spin_lock(&audit_master_watchlist_lock);
+ spin_lock(&master_watchlist_lock);
hlist_del_rcu(&wentry->w_master);
call_rcu(&wentry->w_rcu, audit_wentry_rcu_put);
- spin_unlock(&audit_master_watchlist_lock);
+ spin_unlock(&master_watchlist_lock);
}
}
@@ -531,27 +536,33 @@ void audit_update_watch(struct dentry *d
audit_wentry_put(wentry);
}
-int audit_send_watch(int pid, int seq, struct audit_watch *watch)
+/* Convert a watch to a audit_skb_list */
+struct audit_skb_list *audit_to_skb(struct audit_watch *watch)
{
- int ret;
size_t size;
void *memblk;
-
+ struct audit_skb_list *entry;
+
/* We must include space for both "\0" */
size = sizeof(struct watch_transport) + strlen(watch->path) +
- strlen(watch->filterkey) + 2;
-
- ret = -ENOMEM;
+ strlen(watch->filterkey) + 2;
+
+ entry = ERR_PTR(-ENOMEM);
memblk = audit_to_transport(watch, size);
if (!memblk)
- goto audit_send_watch_exit;
+ goto audit_queue_watch_exit;
- ret = 0;
- audit_send_reply(pid, seq, AUDIT_WATCH_LIST, 0, 1, memblk, size);
- kfree(memblk);
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry) {
+ entry = ERR_PTR(-ENOMEM);
+ goto audit_queue_watch_exit;
+ }
+
+ entry->memblk = memblk;
+ entry->size = size;
-audit_send_watch_exit:
- return ret;
+audit_queue_watch_exit:
+ return entry;
}
/*
@@ -568,19 +579,40 @@ audit_send_watch_exit:
int audit_list_watches(int pid, int seq)
{
int ret = 0;
+ struct hlist_head skb_list;
+ struct hlist_node *tmp, *pos;
+ struct audit_skb_list *entry;
struct audit_wentry *wentry;
- struct hlist_node *pos;
+
+ INIT_HLIST_HEAD(&skb_list);
rcu_read_lock();
- hlist_for_each_entry_rcu(wentry, pos, &audit_master_watchlist, w_master) {
- ret = audit_send_watch(pid, seq, wentry->w_watch);
- if (ret < 0)
- break;
+ hlist_for_each_entry_rcu(wentry, pos, &master_watchlist, w_master) {
+ entry = audit_to_skb(wentry->w_watch);
+ if (IS_ERR(entry)) {
+ ret = PTR_ERR(entry);
+ goto audit_list_watches_fail;
+ }
+ hlist_add_head(&entry->list, &skb_list);
}
rcu_read_unlock();
- audit_send_reply(pid, seq, AUDIT_WATCH_LIST, 1, 1, NULL, 0);
+ hlist_for_each_entry_safe(entry, pos, tmp, &skb_list, list) {
+ audit_send_reply(pid, seq, AUDIT_WATCH_LIST, 0, 1,
+ entry->memblk, entry->size);
+ kfree(entry->memblk);
+ kfree(entry);
+ }
+ audit_send_reply(pid, seq, AUDIT_WATCH_LIST, 1, 1, NULL, 0);
+ goto audit_list_watches_exit;
+
+audit_list_watches_fail:
+ hlist_for_each_entry_safe(entry, pos, tmp, &skb_list, list) {
+ kfree(entry->memblk);
+ kfree(entry);
+ }
+audit_list_watches_exit:
return ret;
}