mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
[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: Amy Griffis <amy.griffis@hp.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
46f5960fdb
commit
3e2efce067
@ -1659,6 +1659,7 @@ do_last:
|
||||
* It already exists.
|
||||
*/
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
audit_inode_update(path.dentry->d_inode);
|
||||
|
||||
error = -EEXIST;
|
||||
if (flag & O_EXCL)
|
||||
@ -1669,6 +1670,7 @@ do_last:
|
||||
if (flag & O_NOFOLLOW)
|
||||
goto exit_dput;
|
||||
}
|
||||
|
||||
error = -ENOENT;
|
||||
if (!path.dentry->d_inode)
|
||||
goto exit_dput;
|
||||
|
@ -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_child(const char *dname, const struct inode *inode,
|
||||
unsigned long pino);
|
||||
extern void __audit_inode_update(const struct inode *inode);
|
||||
static inline void audit_getname(const char *name)
|
||||
{
|
||||
if (unlikely(current->audit_context))
|
||||
@ -343,6 +344,10 @@ static inline void audit_inode_child(const char *dname,
|
||||
if (unlikely(current->audit_context))
|
||||
__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) */
|
||||
extern unsigned int audit_serial(void);
|
||||
@ -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_inode(n,i) 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_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 audit_get_loginuid(c) ({ -1; })
|
||||
#define audit_ipc_obj(i) ({ 0; })
|
||||
|
@ -1199,14 +1199,18 @@ void audit_putname(const char *name)
|
||||
#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;
|
||||
|
||||
selinux_get_inode_sid(inode, &context->names[idx].osid);
|
||||
name->ino = inode->i_ino;
|
||||
name->dev = inode->i_sb->s_dev;
|
||||
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
|
||||
* @name: name being audited
|
||||
@ -1240,13 +1244,7 @@ void __audit_inode(const char *name, const struct inode *inode)
|
||||
++context->ino_count;
|
||||
#endif
|
||||
}
|
||||
context->names[idx].ino = inode->i_ino;
|
||||
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);
|
||||
audit_copy_inode(&context->names[idx], inode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1302,16 +1300,37 @@ update_context:
|
||||
context->names[idx].name_len = AUDIT_NAME_FULL;
|
||||
context->names[idx].name_put = 0; /* don't call __putname() */
|
||||
|
||||
if (inode) {
|
||||
context->names[idx].ino = inode->i_ino;
|
||||
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);
|
||||
} else
|
||||
context->names[idx].ino = (unsigned long)-1;
|
||||
if (!inode)
|
||||
context->names[idx].ino = (unsigned long)-1;
|
||||
else
|
||||
audit_copy_inode(&context->names[idx], inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_inode_update - update inode info for last collected name
|
||||
* @inode: inode being audited
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user