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

Commit f48b7399 authored by Eric Paris's avatar Eric Paris
Browse files

LSM: split LSM_AUDIT_DATA_FS into _PATH and _INODE



The lsm common audit code has wacky contortions making sure which pieces
of information are set based on if it was given a path, dentry, or
inode.  Split this into path and inode to get rid of some of the code
complexity.

Signed-off-by: default avatarEric Paris <eparis@redhat.com>
Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
parent 0dc1ba24
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
/* Auxiliary data to use in generating the audit record. */
struct common_audit_data {
	char type;
#define LSM_AUDIT_DATA_FS	1
#define LSM_AUDIT_DATA_PATH	1
#define LSM_AUDIT_DATA_NET	2
#define LSM_AUDIT_DATA_CAP	3
#define LSM_AUDIT_DATA_IPC	4
@@ -35,12 +35,11 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KEY	6
#define LSM_AUDIT_DATA_NONE	7
#define LSM_AUDIT_DATA_KMOD	8
#define LSM_AUDIT_DATA_INODE	9
	struct task_struct *tsk;
	union 	{
		struct {
		struct path path;
		struct inode *inode;
		} fs;
		struct {
			int netif;
			struct sock *sk;
+28 −22
Original line number Diff line number Diff line
@@ -210,7 +210,6 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
static void dump_common_audit_data(struct audit_buffer *ab,
				   struct common_audit_data *a)
{
	struct inode *inode = NULL;
	struct task_struct *tsk = current;

	if (a->tsk)
@@ -229,20 +228,29 @@ static void dump_common_audit_data(struct audit_buffer *ab,
	case LSM_AUDIT_DATA_CAP:
		audit_log_format(ab, " capability=%d ", a->u.cap);
		break;
	case LSM_AUDIT_DATA_FS:
		if (a->u.fs.path.dentry) {
			struct dentry *dentry = a->u.fs.path.dentry;
			if (a->u.fs.path.mnt) {
				audit_log_d_path(ab, "path=", &a->u.fs.path);
	case LSM_AUDIT_DATA_PATH: {
		struct dentry *dentry = a->u.path.dentry;
		struct inode *inode;

		if (a->u.path.mnt) {
			audit_log_d_path(ab, "path=", &a->u.path);
		} else {
			audit_log_format(ab, " name=");
			audit_log_untrustedstring(ab,
					 dentry->d_name.name);
		}
		inode = dentry->d_inode;
		} else if (a->u.fs.inode) {
		if (inode)
			audit_log_format(ab, " dev=%s ino=%lu",
					inode->i_sb->s_id,
					inode->i_ino);
		break;
	}
	case LSM_AUDIT_DATA_INODE: {
		struct dentry *dentry;
			inode = a->u.fs.inode;
		struct inode *inode;

		inode = a->u.inode;
		dentry = d_find_alias(inode);
		if (dentry) {
			audit_log_format(ab, " name=");
@@ -250,12 +258,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,
					 dentry->d_name.name);
			dput(dentry);
		}
		}
		if (inode)
			audit_log_format(ab, " dev=%s ino=%lu",
					inode->i_sb->s_id,
		audit_log_format(ab, " dev=%s ino=%lu", inode->i_sb->s_id,
				 inode->i_ino);
		break;
	}
	case LSM_AUDIT_DATA_TASK:
		tsk = a->u.tsk;
		if (tsk && tsk->pid) {
+1 −1
Original line number Diff line number Diff line
@@ -531,7 +531,7 @@ int avc_audit(u32 ssid, u32 tsid,
	 * during retry. However this is logically just as if the operation
	 * happened a little later.
	 */
	if ((a->type == LSM_AUDIT_DATA_FS) &&
	if ((a->type == LSM_AUDIT_DATA_INODE) &&
	    (flags & IPERM_FLAG_RCU))
		return -ECHILD;

+25 −25
Original line number Diff line number Diff line
@@ -1488,8 +1488,8 @@ static int inode_has_perm(const struct cred *cred,

	if (!adp) {
		adp = &ad;
		COMMON_AUDIT_DATA_INIT(&ad, FS);
		ad.u.fs.inode = inode;
		COMMON_AUDIT_DATA_INIT(&ad, INODE);
		ad.u.inode = inode;
	}

	return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
@@ -1506,9 +1506,9 @@ static inline int dentry_has_perm(const struct cred *cred,
	struct inode *inode = dentry->d_inode;
	struct common_audit_data ad;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.mnt = mnt;
	ad.u.fs.path.dentry = dentry;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.mnt = mnt;
	ad.u.path.dentry = dentry;
	return inode_has_perm(cred, inode, av, &ad, 0);
}

@@ -1530,8 +1530,8 @@ static int file_has_perm(const struct cred *cred,
	u32 sid = cred_sid(cred);
	int rc;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path = file->f_path;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path = file->f_path;

	if (sid != fsec->sid) {
		rc = avc_has_perm(sid, fsec->sid,
@@ -1569,8 +1569,8 @@ static int may_create(struct inode *dir,
	sid = tsec->sid;
	newsid = tsec->create_sid;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.dentry = dentry;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.dentry = dentry;

	rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
			  DIR__ADD_NAME | DIR__SEARCH,
@@ -1621,8 +1621,8 @@ static int may_link(struct inode *dir,
	dsec = dir->i_security;
	isec = dentry->d_inode->i_security;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.dentry = dentry;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.dentry = dentry;

	av = DIR__SEARCH;
	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1667,9 +1667,9 @@ static inline int may_rename(struct inode *old_dir,
	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
	new_dsec = new_dir->i_security;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	COMMON_AUDIT_DATA_INIT(&ad, PATH);

	ad.u.fs.path.dentry = old_dentry;
	ad.u.path.dentry = old_dentry;
	rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
			  DIR__REMOVE_NAME | DIR__SEARCH, &ad);
	if (rc)
@@ -1685,7 +1685,7 @@ static inline int may_rename(struct inode *old_dir,
			return rc;
	}

	ad.u.fs.path.dentry = new_dentry;
	ad.u.path.dentry = new_dentry;
	av = DIR__ADD_NAME | DIR__SEARCH;
	if (new_dentry->d_inode)
		av |= DIR__REMOVE_NAME;
@@ -1991,8 +1991,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
			return rc;
	}

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path = bprm->file->f_path;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path = bprm->file->f_path;

	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
		new_tsec->sid = old_tsec->sid;
@@ -2120,7 +2120,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,

	/* Revalidate access to inherited open files. */

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	COMMON_AUDIT_DATA_INIT(&ad, INODE);

	spin_lock(&files->file_lock);
	for (;;) {
@@ -2468,8 +2468,8 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
	if (flags & MS_KERNMOUNT)
		return 0;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.dentry = sb->s_root;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.dentry = sb->s_root;
	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
}

@@ -2478,8 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry)
	const struct cred *cred = current_cred();
	struct common_audit_data ad;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.dentry = dentry->d_sb->s_root;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.dentry = dentry->d_sb->s_root;
	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}

@@ -2653,8 +2653,8 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
	if (!mask)
		return 0;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.inode = inode;
	COMMON_AUDIT_DATA_INIT(&ad, INODE);
	ad.u.inode = inode;

	if (from_access)
		ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
@@ -2732,8 +2732,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
	if (!is_owner_or_cap(inode))
		return -EPERM;

	COMMON_AUDIT_DATA_INIT(&ad, FS);
	ad.u.fs.path.dentry = dentry;
	COMMON_AUDIT_DATA_INIT(&ad, PATH);
	ad.u.path.dentry = dentry;

	rc = avc_has_perm(sid, isec->sid, isec->sclass,
			  FILE__RELABELFROM, &ad);
+4 −4
Original line number Diff line number Diff line
@@ -316,22 +316,22 @@ static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
						    struct dentry *d)
{
	a->a.u.fs.path.dentry = d;
	a->a.u.path.dentry = d;
}
static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
						 struct vfsmount *m)
{
	a->a.u.fs.path.mnt = m;
	a->a.u.path.mnt = m;
}
static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
					      struct inode *i)
{
	a->a.u.fs.inode = i;
	a->a.u.inode = i;
}
static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
					     struct path p)
{
	a->a.u.fs.path = p;
	a->a.u.path = p;
}
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
					    struct sock *sk)
Loading