On Wed, 2005-05-25 at 14:46 +0100, David Woodhouse wrote:
Why is audit_notify_watch() in auditfs.c? Can it ever do anything
useful if !CONFIG_AUDITFILESYSTEM?
Hm, because it needs visibility to the audit_context. Could possibly be
split into two functions though, along the following lines...
As an added bonus, this should prevent it oopsing if a task doesn't have
an audit context but touches a watched inode.
Are we really supposed to be using GFP_KERNEL in audit_notify_watch()
(now in audit_attach_wdata()) ? We're never checking the return value
from audit_notify_watch() either.
--- linux-2.6.9/include/linux/audit.h~ 2005-05-25 14:30:18.000000000 +0100
+++ linux-2.6.9/include/linux/audit.h 2005-05-25 15:05:00.000000000 +0100
@@ -277,7 +277,6 @@ extern int audit_socketcall(int nargs, u
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
-extern int audit_notify_watch(struct inode *inode, int mask);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -294,7 +293,6 @@ extern int audit_notify_watch(struct ino
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
-#define audit_notify_watch(i,m) ({ 0; })
#endif
#ifdef CONFIG_AUDITFILESYSTEM
@@ -308,6 +306,9 @@ extern void audit_update_watch(struct de
extern void audit_wentry_put(struct audit_wentry *wentry);
extern void audit_dentry_unpin(struct dentry *dentry);
extern struct audit_wentry *audit_wentry_get(struct audit_wentry *wentry);
+extern int audit_notify_watch(struct inode *inode, int mask);
+extern int auditfs_attach_wdata(struct inode *inode, struct audit_wentry *wentry,
+ int mask);
#else
#define audit_filesystem_init() ({ 0; })
#define audit_list_watches(p,s) ({ -EOPNOTSUPP; })
@@ -317,6 +318,7 @@ extern struct audit_wentry *audit_wentry
#define audit_update_watch(d,r) do { ; } while (0)
#define audit_wentry_put(w) do { ; } while(0)
#define audit_wentry_get(w) ({ 0; })
+#define audit_notify_watch(i,m) ({ 0; })
#endif
#ifdef CONFIG_AUDIT
--- linux-2.6.9/kernel/auditfs.c~ 2005-05-25 14:30:18.000000000 +0100
+++ linux-2.6.9/kernel/auditfs.c 2005-05-25 15:06:49.000000000 +0100
@@ -35,6 +35,8 @@
#include <asm/uaccess.h>
+#define inode_audit_data(inode) ((inode)->i_audit)
+
extern int audit_enabled;
static kmem_cache_t *audit_watch_cache;
@@ -409,7 +411,7 @@ static inline int audit_insert_watch(str
watch->filterkey,
watch->perms,
nd.dentry->d_inode->i_sb->s_dev,
- nd.dentry->d_inode->i_audit);
+ inode_audit_data(nd.dentry->d_inode));
if (ret < 0)
goto audit_insert_watch_release;
@@ -444,7 +446,7 @@ static inline int audit_remove_watch(str
if (nd.last_type != LAST_NORM || !nd.last.name)
goto audit_remove_watch_release;
- data = nd.dentry->d_inode->i_audit;
+ data = inode_audit_data(nd.dentry->d_inode);
write_lock(&data->lock);
wentry = audit_wentry_fetch(nd.last.name, data);
@@ -508,8 +510,8 @@ void audit_update_watch(struct dentry *d
if (!dentry->d_parent || !dentry->d_parent->d_inode)
return;
- data = dentry->d_inode->i_audit;
- parent = dentry->d_parent->d_inode->i_audit;
+ data = inode_audit_data(dentry->d_inode);
+ parent = inode_audit_data(dentry->d_parent->d_inode);
wentry = audit_wentry_fetch_lock(dentry->d_name.name, parent);
@@ -657,8 +659,8 @@ audit_receive_watch_exit:
int audit_inode_alloc(struct inode *inode)
{
if (inode) {
- inode->i_audit = audit_data_alloc();
- if (!inode->i_audit)
+ inode_audit_data(inode) = audit_data_alloc();
+ if (!inode_audit_data(inode))
return ENOMEM;
}
@@ -668,7 +670,7 @@ int audit_inode_alloc(struct inode *inod
void audit_inode_free(struct inode *inode)
{
if (inode)
- audit_data_free(inode->i_audit);
+ audit_data_free(inode_audit_data(inode));
}
/*
* When we delete a dentry we check to see whether or not we're being
@@ -682,10 +684,12 @@ void audit_dentry_unpin(struct dentry *d
struct audit_inode_data *parent;
struct audit_wentry *wentry;
- parent = dentry->d_parent->d_inode->i_audit;
+ parent = inode_audit_data(dentry->d_parent->d_inode);
wentry = audit_wentry_fetch_lock(dentry->d_name.name, parent);
if (wentry) {
- audit_unpin(dentry->d_inode->i_audit->wentry);
+ struct audit_inode_data *data = inode_audit_data(dentry->d_inode);
+
+ audit_unpin(data->wentry);
audit_wentry_put(wentry);
}
}
@@ -716,3 +720,43 @@ audit_filesystem_init_fail:
audit_filesystem_init_exit:
return ret;
}
+
+
+int audit_notify_watch(struct inode *inode, int mask)
+{
+ int ret = 0;
+ struct audit_inode_data *data;
+ struct audit_wentry *wentry = NULL;
+
+ if (likely(!audit_enabled))
+ return 0;
+
+ if (!inode)
+ return 0;
+
+ data = inode_audit_data(inode);
+ if (!data)
+ return 0;
+
+ /*
+ * Won't be able to drop i_audit->wentry reference
+ * before we obtain our own reference
+ */
+ read_lock(&data->lock);
+ wentry = audit_wentry_get(data->wentry);
+ read_unlock(&data->lock);
+ if (!wentry)
+ return 0;
+
+ if (mask && (wentry->w_watch->perms &&
!(wentry->w_watch->perms&mask)))
+ goto audit_notify_watch_fail;
+
+ ret = auditfs_attach_wdata(inode, wentry, mask);
+ if (!ret)
+ return 0;
+
+ audit_notify_watch_fail:
+ audit_wentry_put(wentry);
+
+ return ret;
+}
--- linux-2.6.9/kernel/auditsc.c~ 2005-05-25 14:30:18.000000000 +0100
+++ linux-2.6.9/kernel/auditsc.c 2005-05-25 15:06:25.000000000 +0100
@@ -1180,41 +1180,19 @@ void audit_signal_info(int sig, struct t
}
}
-
-int audit_notify_watch(struct inode *inode, int mask)
+#ifdef CONFIG_AUDITFILESYSTEM
+/* This has to be here instead of in auditfs.c, because it needs to
+ see the audit context */
+int auditfs_attach_wdata(struct inode *inode, struct audit_wentry *wentry,
+ int mask)
{
- int ret = 0;
struct audit_context *context = current->audit_context;
struct audit_aux_data_watched *ax;
- struct audit_wentry *wentry = NULL;
- if (likely(!audit_enabled))
- goto audit_notify_watch_exit;
-
- if (!inode || !inode->i_audit)
- goto audit_notify_watch_exit;
-
- /*
- * Won't be able to drop i_audit->wentry reference
- * before we obtain our own reference
- */
- read_lock(&inode->i_audit->lock);
- wentry = audit_wentry_get(inode->i_audit->wentry);
- if (!wentry) {
- read_unlock(&inode->i_audit->lock);
- goto audit_notify_watch_exit;
- }
- read_unlock(&inode->i_audit->lock);
-
- if (mask && (wentry->w_watch->perms &&
!(wentry->w_watch->perms&mask)))
- goto audit_notify_watch_fail;
-
- ret = -ENOMEM;
ax = kmalloc(sizeof(*ax), GFP_KERNEL);
if (!ax)
- goto audit_notify_watch_fail;
+ return -ENOMEM;
- ret = 0;
if (context->in_syscall && !context->auditable)
context->auditable = 1;
@@ -1230,10 +1208,6 @@ int audit_notify_watch(struct inode *ino
ax->link.next = context->aux;
context->aux = (void *)ax;
- goto audit_notify_watch_exit;
-
-audit_notify_watch_fail:
- audit_wentry_put(wentry);
-audit_notify_watch_exit:
- return ret;
+ return 0;
}
+#endif /* CONFIG_AUDITFILESYSTEM */
--
dwmw2