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

Commit 43af5de7 authored by Vivek Goyal's avatar Vivek Goyal Committed by Paul Moore
Browse files

lsm,audit,selinux: Introduce a new audit data type LSM_AUDIT_DATA_FILE



Right now LSM_AUDIT_DATA_PATH type contains "struct path" in union "u"
of common_audit_data. This information is used to print path of file
at the same time it is also used to get to dentry and inode. And this
inode information is used to get to superblock and device and print
device information.

This does not work well for layered filesystems like overlay where dentry
contained in path is overlay dentry and not the real dentry of underlying
file system. That means inode retrieved from dentry is also overlay
inode and not the real inode.

SELinux helpers like file_path_has_perm() are doing checks on inode
retrieved from file_inode(). This returns the real inode and not the
overlay inode. That means we are doing check on real inode but for audit
purposes we are printing details of overlay inode and that can be
confusing while debugging.

Hence, introduce a new type LSM_AUDIT_DATA_FILE which carries file
information and inode retrieved is real inode using file_inode(). That
way right avc denied information is given to user.

For example, following is one example avc before the patch.

  type=AVC msg=audit(1473360868.399:214): avc:  denied  { read open } for
    pid=1765 comm="cat"
    path="/root/.../overlay/container1/merged/readfile"
    dev="overlay" ino=21443
    scontext=unconfined_u:unconfined_r:test_overlay_client_t:s0:c10,c20
    tcontext=unconfined_u:object_r:test_overlay_files_ro_t:s0
    tclass=file permissive=0

It looks as follows after the patch.

  type=AVC msg=audit(1473360017.388:282): avc:  denied  { read open } for
    pid=2530 comm="cat"
    path="/root/.../overlay/container1/merged/readfile"
    dev="dm-0" ino=2377915
    scontext=unconfined_u:unconfined_r:test_overlay_client_t:s0:c10,c20
    tcontext=unconfined_u:object_r:test_overlay_files_ro_t:s0
    tclass=file permissive=0

Notice that now dev information points to "dm-0" device instead of
"overlay" device. This makes it clear that check failed on underlying
inode and not on the overlay inode.

Signed-off-by: default avatarVivek Goyal <vgoyal@redhat.com>
[PM: slight tweaks to the description to make checkpatch.pl happy]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 9b6a9ecc
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_INODE	9
#define LSM_AUDIT_DATA_INODE	9
#define LSM_AUDIT_DATA_DENTRY	10
#define LSM_AUDIT_DATA_DENTRY	10
#define LSM_AUDIT_DATA_IOCTL_OP	11
#define LSM_AUDIT_DATA_IOCTL_OP	11
#define LSM_AUDIT_DATA_FILE	12
	union 	{
	union 	{
		struct path path;
		struct path path;
		struct dentry *dentry;
		struct dentry *dentry;
@@ -75,6 +76,7 @@ struct common_audit_data {
#endif
#endif
		char *kmod_name;
		char *kmod_name;
		struct lsm_ioctlop_audit *op;
		struct lsm_ioctlop_audit *op;
		struct file *file;
	} u;
	} u;
	/* this union contains LSM specific data */
	/* this union contains LSM specific data */
	union {
	union {
+13 −0
Original line number Original line Diff line number Diff line
@@ -245,6 +245,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
		}
		}
		break;
		break;
	}
	}
	case LSM_AUDIT_DATA_FILE: {
		struct inode *inode;

		audit_log_d_path(ab, " path=", &a->u.file->f_path);

		inode = file_inode(a->u.file);
		if (inode) {
			audit_log_format(ab, " dev=");
			audit_log_untrustedstring(ab, inode->i_sb->s_id);
			audit_log_format(ab, " ino=%lu", inode->i_ino);
		}
		break;
	}
	case LSM_AUDIT_DATA_IOCTL_OP: {
	case LSM_AUDIT_DATA_IOCTL_OP: {
		struct inode *inode;
		struct inode *inode;


+8 −8
Original line number Original line Diff line number Diff line
@@ -1761,8 +1761,8 @@ static inline int file_path_has_perm(const struct cred *cred,
{
{
	struct common_audit_data ad;
	struct common_audit_data ad;


	ad.type = LSM_AUDIT_DATA_PATH;
	ad.type = LSM_AUDIT_DATA_FILE;
	ad.u.path = file->f_path;
	ad.u.file = file;
	return inode_has_perm(cred, file_inode(file), av, &ad);
	return inode_has_perm(cred, file_inode(file), av, &ad);
}
}


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


	ad.type = LSM_AUDIT_DATA_PATH;
	ad.type = LSM_AUDIT_DATA_FILE;
	ad.u.path = file->f_path;
	ad.u.file = file;


	if (sid != fsec->sid) {
	if (sid != fsec->sid) {
		rc = avc_has_perm(sid, fsec->sid,
		rc = avc_has_perm(sid, fsec->sid,
@@ -2365,8 +2365,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
			new_tsec->sid = old_tsec->sid;
			new_tsec->sid = old_tsec->sid;
	}
	}


	ad.type = LSM_AUDIT_DATA_PATH;
	ad.type = LSM_AUDIT_DATA_FILE;
	ad.u.path = bprm->file->f_path;
	ad.u.file = bprm->file;


	if (new_tsec->sid == old_tsec->sid) {
	if (new_tsec->sid == old_tsec->sid) {
		rc = avc_has_perm(old_tsec->sid, isec->sid,
		rc = avc_has_perm(old_tsec->sid, isec->sid,
@@ -3833,8 +3833,8 @@ static int selinux_kernel_module_from_file(struct file *file)


	/* finit_module */
	/* finit_module */


	ad.type = LSM_AUDIT_DATA_PATH;
	ad.type = LSM_AUDIT_DATA_FILE;
	ad.u.path = file->f_path;
	ad.u.file = file;


	fsec = file->f_security;
	fsec = file->f_security;
	if (sid != fsec->sid) {
	if (sid != fsec->sid) {