Commit 73d3ec5a authored by Amy Griffis's avatar Amy Griffis Committed by Al Viro

[PATCH] fix missed create event for directory audit

When an object is created via a symlink into an audited directory, audit misses
the event due to not having collected the inode data for the directory.  Modify
__audit_inode_child() to copy the parent inode data if a parent wasn't found in
audit_names[].
Signed-off-by: default avatarAmy Griffis <amy.griffis@hp.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3e2efce0
...@@ -1357,7 +1357,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) ...@@ -1357,7 +1357,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT; return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir); BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino); audit_inode_child(victim->d_name.name, victim->d_inode, dir);
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error) if (error)
......
...@@ -327,7 +327,7 @@ extern void __audit_getname(const char *name); ...@@ -327,7 +327,7 @@ extern void __audit_getname(const char *name);
extern void audit_putname(const char *name); extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode(const char *name, const struct inode *inode);
extern void __audit_inode_child(const char *dname, const struct inode *inode, extern void __audit_inode_child(const char *dname, const struct inode *inode,
unsigned long pino); const struct inode *parent);
extern void __audit_inode_update(const struct inode *inode); extern void __audit_inode_update(const struct inode *inode);
static inline void audit_getname(const char *name) static inline void audit_getname(const char *name)
{ {
...@@ -340,9 +340,9 @@ static inline void audit_inode(const char *name, const struct inode *inode) { ...@@ -340,9 +340,9 @@ static inline void audit_inode(const char *name, const struct inode *inode) {
} }
static inline void audit_inode_child(const char *dname, static inline void audit_inode_child(const char *dname,
const struct inode *inode, const struct inode *inode,
unsigned long pino) { const struct inode *parent) {
if (unlikely(current->audit_context)) if (unlikely(current->audit_context))
__audit_inode_child(dname, inode, pino); __audit_inode_child(dname, inode, parent);
} }
static inline void audit_inode_update(const struct inode *inode) { static inline void audit_inode_update(const struct inode *inode) {
if (unlikely(current->audit_context)) if (unlikely(current->audit_context))
......
...@@ -67,7 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, ...@@ -67,7 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
if (source) { if (source) {
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
} }
audit_inode_child(new_name, source, new_dir->i_ino); audit_inode_child(new_name, source, new_dir);
} }
/* /*
...@@ -98,7 +98,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) ...@@ -98,7 +98,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
inode_dir_notify(inode, DN_CREATE); inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
dentry->d_inode); dentry->d_inode);
audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
} }
/* /*
...@@ -109,7 +109,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) ...@@ -109,7 +109,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
inode_dir_notify(inode, DN_CREATE); inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0,
dentry->d_name.name, dentry->d_inode); dentry->d_name.name, dentry->d_inode);
audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
} }
/* /*
......
...@@ -1251,7 +1251,7 @@ void __audit_inode(const char *name, const struct inode *inode) ...@@ -1251,7 +1251,7 @@ void __audit_inode(const char *name, const struct inode *inode)
* audit_inode_child - collect inode info for created/removed objects * audit_inode_child - collect inode info for created/removed objects
* @dname: inode's dentry name * @dname: inode's dentry name
* @inode: inode being audited * @inode: inode being audited
* @pino: inode number of dentry parent * @parent: inode of dentry parent
* *
* For syscalls that create or remove filesystem objects, audit_inode * For syscalls that create or remove filesystem objects, audit_inode
* can only collect information for the filesystem object's parent. * can only collect information for the filesystem object's parent.
...@@ -1262,7 +1262,7 @@ void __audit_inode(const char *name, const struct inode *inode) ...@@ -1262,7 +1262,7 @@ void __audit_inode(const char *name, const struct inode *inode)
* unsuccessful attempts. * unsuccessful attempts.
*/ */
void __audit_inode_child(const char *dname, const struct inode *inode, void __audit_inode_child(const char *dname, const struct inode *inode,
unsigned long pino) const struct inode *parent)
{ {
int idx; int idx;
struct audit_context *context = current->audit_context; struct audit_context *context = current->audit_context;
...@@ -1276,7 +1276,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, ...@@ -1276,7 +1276,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
if (!dname) if (!dname)
goto update_context; goto update_context;
for (idx = 0; idx < context->name_count; idx++) for (idx = 0; idx < context->name_count; idx++)
if (context->names[idx].ino == pino) { if (context->names[idx].ino == parent->i_ino) {
const char *name = context->names[idx].name; const char *name = context->names[idx].name;
if (!name) if (!name)
...@@ -1304,6 +1304,16 @@ void __audit_inode_child(const char *dname, const struct inode *inode, ...@@ -1304,6 +1304,16 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
context->names[idx].ino = (unsigned long)-1; context->names[idx].ino = (unsigned long)-1;
else else
audit_copy_inode(&context->names[idx], inode); audit_copy_inode(&context->names[idx], inode);
/* A parent was not found in audit_names, so copy the inode data for the
* provided parent. */
if (!found_name) {
idx = context->name_count++;
#if AUDIT_DEBUG
context->ino_count++;
#endif
audit_copy_inode(&context->names[idx], parent);
}
} }
/** /**
......
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