Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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,
		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;
+7 −0
Original line number Original line Diff line number Diff line
@@ -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,
	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)
#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; })
+41 −22
Original line number Original line Diff line number Diff line
@@ -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)
		++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,
	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].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;
		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);
}
}


/**
/**