LSM: separate LSM_AUDIT_DATA_DENTRY from LSM_AUDIT_DATA_PATH

This patch separates and audit message that only contains a dentry from
one that contains a full path.  This allows us to make it harder to
misuse the interfaces or for the interfaces to be implemented wrong.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index bbaceab..88e78de 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -36,9 +36,11 @@
 #define LSM_AUDIT_DATA_NONE	7
 #define LSM_AUDIT_DATA_KMOD	8
 #define LSM_AUDIT_DATA_INODE	9
+#define LSM_AUDIT_DATA_DENTRY	10
 	struct task_struct *tsk;
 	union 	{
 		struct path path;
+		struct dentry *dentry;
 		struct inode *inode;
 		struct {
 			int netif;
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 2e84605..893af8a 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -229,17 +229,24 @@
 		audit_log_format(ab, " capability=%d ", a->u.cap);
 		break;
 	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;
+		audit_log_d_path(ab, "path=", &a->u.path);
+
+		inode = a->u.path.dentry->d_inode;
+		if (inode)
+			audit_log_format(ab, " dev=%s ino=%lu",
+					inode->i_sb->s_id,
+					inode->i_ino);
+		break;
+	}
+	case LSM_AUDIT_DATA_DENTRY: {
+		struct inode *inode;
+
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
+
+		inode = a->u.dentry->d_inode;
 		if (inode)
 			audit_log_format(ab, " dev=%s ino=%lu",
 					inode->i_sb->s_id,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad664d3..9e8078a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1569,8 +1569,8 @@
 	sid = tsec->sid;
 	newsid = tsec->create_sid;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
-	ad.u.path.dentry = dentry;
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+	ad.u.dentry = dentry;
 
 	rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
 			  DIR__ADD_NAME | DIR__SEARCH,
@@ -1621,8 +1621,8 @@
 	dsec = dir->i_security;
 	isec = dentry->d_inode->i_security;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
-	ad.u.path.dentry = dentry;
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+	ad.u.dentry = dentry;
 
 	av = DIR__SEARCH;
 	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1667,9 +1667,9 @@
 	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
 	new_dsec = new_dir->i_security;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
 
-	ad.u.path.dentry = old_dentry;
+	ad.u.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 @@
 			return rc;
 	}
 
-	ad.u.path.dentry = new_dentry;
+	ad.u.dentry = new_dentry;
 	av = DIR__ADD_NAME | DIR__SEARCH;
 	if (new_dentry->d_inode)
 		av |= DIR__REMOVE_NAME;
@@ -2468,8 +2468,8 @@
 	if (flags & MS_KERNMOUNT)
 		return 0;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
-	ad.u.path.dentry = sb->s_root;
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+	ad.u.dentry = sb->s_root;
 	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
 }
 
@@ -2478,8 +2478,8 @@
 	const struct cred *cred = current_cred();
 	struct common_audit_data ad;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
-	ad.u.path.dentry = dentry->d_sb->s_root;
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+	ad.u.dentry = dentry->d_sb->s_root;
 	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
@@ -2732,8 +2732,8 @@
 	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
-	COMMON_AUDIT_DATA_INIT(&ad, PATH);
-	ad.u.path.dentry = dentry;
+	COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+	ad.u.dentry = dentry;
 
 	rc = avc_has_perm(sid, isec->sid, isec->sclass,
 			  FILE__RELABELFROM, &ad);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index a16925c..2b6c6a5 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -316,12 +316,7 @@
 static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
 						    struct 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.path.mnt = m;
+	a->a.u.dentry = d;
 }
 static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
 					      struct inode *i)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index eeb393f..a3bdd13 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -383,7 +383,7 @@
 	int rc;
 	struct smk_audit_info ad;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
@@ -425,10 +425,13 @@
 {
 	struct superblock_smack *sbp;
 	struct smk_audit_info ad;
+	struct path path;
+
+	path.dentry = mnt->mnt_root;
+	path.mnt = mnt;
 
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
-	smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root);
-	smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
+	smk_ad_setfield_u_fs_path(&ad, path);
 
 	sbp = mnt->mnt_sb->s_security;
 	return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
@@ -563,7 +566,7 @@
 	struct smk_audit_info ad;
 	int rc;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
 
 	isp = smk_of_inode(old_dentry->d_inode);
@@ -592,7 +595,7 @@
 	struct smk_audit_info ad;
 	int rc;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	/*
@@ -623,7 +626,7 @@
 	struct smk_audit_info ad;
 	int rc;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	/*
@@ -663,7 +666,7 @@
 	char *isp;
 	struct smk_audit_info ad;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
 
 	isp = smk_of_inode(old_dentry->d_inode);
@@ -720,7 +723,7 @@
 	 */
 	if (iattr->ia_valid & ATTR_FORCE)
 		return 0;
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
@@ -736,10 +739,13 @@
 static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 {
 	struct smk_audit_info ad;
+	struct path path;
+
+	path.dentry = dentry;
+	path.mnt = mnt;
 
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
-	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-	smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
+	smk_ad_setfield_u_fs_path(&ad, path);
 	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
 }
 
@@ -784,7 +790,7 @@
 	} else
 		rc = cap_inode_setxattr(dentry, name, value, size, flags);
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	if (rc == 0)
@@ -845,7 +851,7 @@
 {
 	struct smk_audit_info ad;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
 	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
@@ -877,7 +883,7 @@
 	} else
 		rc = cap_inode_removexattr(dentry, name);
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 	if (rc == 0)
 		rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
@@ -1070,7 +1076,7 @@
 {
 	struct smk_audit_info ad;
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
 	smk_ad_setfield_u_fs_path_dentry(&ad, file->f_path.dentry);
 	return smk_curacc(file->f_security, MAY_WRITE, &ad);
 }