Commit 3e2efce0 authored by Amy Griffis's avatar Amy Griffis Committed by Al Viro

[PATCH] fix faulty inode data collection for open() with O_CREAT

When the specified path is an existing file or when it is a symlink, audit
collects the wrong inode number, which causes it to miss the open() event.
Adding a second hook to the open() path fixes this.

Also add audit_copy_inode() to consolidate some code.
Signed-off-by: default avatarAmy Griffis <amy.griffis@hp.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 46f5960f
...@@ -1659,6 +1659,7 @@ int open_namei(int dfd, const char *pathname, int flag, ...@@ -1659,6 +1659,7 @@ int open_namei(int dfd, const char *pathname, int flag,
* It already exists. * It already exists.
*/ */
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
audit_inode_update(path.dentry->d_inode);
error = -EEXIST; error = -EEXIST;
if (flag & O_EXCL) if (flag & O_EXCL)
...@@ -1669,6 +1670,7 @@ int open_namei(int dfd, const char *pathname, int flag, ...@@ -1669,6 +1670,7 @@ int open_namei(int dfd, const char *pathname, int flag,
if (flag & O_NOFOLLOW) if (flag & O_NOFOLLOW)
goto exit_dput; goto exit_dput;
} }
error = -ENOENT; error = -ENOENT;
if (!path.dentry->d_inode) if (!path.dentry->d_inode)
goto exit_dput; goto exit_dput;
......
...@@ -328,6 +328,7 @@ extern void audit_putname(const char *name); ...@@ -328,6 +328,7 @@ 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); unsigned long pino);
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)
{ {
if (unlikely(current->audit_context)) if (unlikely(current->audit_context))
...@@ -343,6 +344,10 @@ static inline void audit_inode_child(const char *dname, ...@@ -343,6 +344,10 @@ static inline void audit_inode_child(const char *dname,
if (unlikely(current->audit_context)) if (unlikely(current->audit_context))
__audit_inode_child(dname, inode, pino); __audit_inode_child(dname, inode, pino);
} }
static inline void audit_inode_update(const struct inode *inode) {
if (unlikely(current->audit_context))
__audit_inode_update(inode);
}
/* Private API (for audit.c only) */ /* Private API (for audit.c only) */
extern unsigned int audit_serial(void); extern unsigned int audit_serial(void);
...@@ -414,8 +419,10 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) ...@@ -414,8 +419,10 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
#define audit_putname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i) do { ; } while (0) #define __audit_inode(n,i) do { ; } while (0)
#define __audit_inode_child(d,i,p) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0)
#define __audit_inode_update(i) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0)
#define audit_inode_update(i) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; }) #define audit_get_loginuid(c) ({ -1; })
#define audit_ipc_obj(i) ({ 0; }) #define audit_ipc_obj(i) ({ 0; })
......
...@@ -1199,14 +1199,18 @@ void audit_putname(const char *name) ...@@ -1199,14 +1199,18 @@ void audit_putname(const char *name)
#endif #endif
} }
static void audit_inode_context(int idx, const struct inode *inode) /* Copy inode data into an audit_names. */
static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
{ {
struct audit_context *context = current->audit_context; name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
selinux_get_inode_sid(inode, &context->names[idx].osid); name->mode = inode->i_mode;
name->uid = inode->i_uid;
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
selinux_get_inode_sid(inode, &name->osid);
} }
/** /**
* audit_inode - store the inode and device from a lookup * audit_inode - store the inode and device from a lookup
* @name: name being audited * @name: name being audited
...@@ -1240,13 +1244,7 @@ void __audit_inode(const char *name, const struct inode *inode) ...@@ -1240,13 +1244,7 @@ void __audit_inode(const char *name, const struct inode *inode)
++context->ino_count; ++context->ino_count;
#endif #endif
} }
context->names[idx].ino = inode->i_ino; audit_copy_inode(&context->names[idx], inode);
context->names[idx].dev = inode->i_sb->s_dev;
context->names[idx].mode = inode->i_mode;
context->names[idx].uid = inode->i_uid;
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev;
audit_inode_context(idx, inode);
} }
/** /**
...@@ -1302,16 +1300,37 @@ void __audit_inode_child(const char *dname, const struct inode *inode, ...@@ -1302,16 +1300,37 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
context->names[idx].name_len = AUDIT_NAME_FULL; context->names[idx].name_len = AUDIT_NAME_FULL;
context->names[idx].name_put = 0; /* don't call __putname() */ context->names[idx].name_put = 0; /* don't call __putname() */
if (inode) { if (!inode)
context->names[idx].ino = inode->i_ino; context->names[idx].ino = (unsigned long)-1;
context->names[idx].dev = inode->i_sb->s_dev; else
context->names[idx].mode = inode->i_mode; audit_copy_inode(&context->names[idx], inode);
context->names[idx].uid = inode->i_uid; }
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev; /**
audit_inode_context(idx, inode); * audit_inode_update - update inode info for last collected name
} else * @inode: inode being audited
context->names[idx].ino = (unsigned long)-1; *
* When open() is called on an existing object with the O_CREAT flag, the inode
* data audit initially collects is incorrect. This additional hook ensures
* audit has the inode data for the actual object to be opened.
*/
void __audit_inode_update(const struct inode *inode)
{
struct audit_context *context = current->audit_context;
int idx;
if (!context->in_syscall || !inode)
return;
if (context->name_count == 0) {
context->name_count++;
#if AUDIT_DEBUG
context->ino_count++;
#endif
}
idx = context->name_count - 1;
audit_copy_inode(&context->names[idx], inode);
} }
/** /**
......
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