Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Vivek Goyal <vgoyal@redhat.com>
[PM: slight tweaks to the description to make checkpatch.pl happy]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Vivek Goyal and committed by
Paul Moore
43af5de7 9b6a9ecc

+23 -8
+2
include/linux/lsm_audit.h
··· 59 59 #define LSM_AUDIT_DATA_INODE 9 60 60 #define LSM_AUDIT_DATA_DENTRY 10 61 61 #define LSM_AUDIT_DATA_IOCTL_OP 11 62 + #define LSM_AUDIT_DATA_FILE 12 62 63 union { 63 64 struct path path; 64 65 struct dentry *dentry; ··· 76 75 #endif 77 76 char *kmod_name; 78 77 struct lsm_ioctlop_audit *op; 78 + struct file *file; 79 79 } u; 80 80 /* this union contains LSM specific data */ 81 81 union {
+13
security/lsm_audit.c
··· 245 245 } 246 246 break; 247 247 } 248 + case LSM_AUDIT_DATA_FILE: { 249 + struct inode *inode; 250 + 251 + audit_log_d_path(ab, " path=", &a->u.file->f_path); 252 + 253 + inode = file_inode(a->u.file); 254 + if (inode) { 255 + audit_log_format(ab, " dev="); 256 + audit_log_untrustedstring(ab, inode->i_sb->s_id); 257 + audit_log_format(ab, " ino=%lu", inode->i_ino); 258 + } 259 + break; 260 + } 248 261 case LSM_AUDIT_DATA_IOCTL_OP: { 249 262 struct inode *inode; 250 263
+8 -8
security/selinux/hooks.c
··· 1761 1761 { 1762 1762 struct common_audit_data ad; 1763 1763 1764 - ad.type = LSM_AUDIT_DATA_PATH; 1765 - ad.u.path = file->f_path; 1764 + ad.type = LSM_AUDIT_DATA_FILE; 1765 + ad.u.file = file; 1766 1766 return inode_has_perm(cred, file_inode(file), av, &ad); 1767 1767 } 1768 1768 ··· 1784 1784 u32 sid = cred_sid(cred); 1785 1785 int rc; 1786 1786 1787 - ad.type = LSM_AUDIT_DATA_PATH; 1788 - ad.u.path = file->f_path; 1787 + ad.type = LSM_AUDIT_DATA_FILE; 1788 + ad.u.file = file; 1789 1789 1790 1790 if (sid != fsec->sid) { 1791 1791 rc = avc_has_perm(sid, fsec->sid, ··· 2365 2365 new_tsec->sid = old_tsec->sid; 2366 2366 } 2367 2367 2368 - ad.type = LSM_AUDIT_DATA_PATH; 2369 - ad.u.path = bprm->file->f_path; 2368 + ad.type = LSM_AUDIT_DATA_FILE; 2369 + ad.u.file = bprm->file; 2370 2370 2371 2371 if (new_tsec->sid == old_tsec->sid) { 2372 2372 rc = avc_has_perm(old_tsec->sid, isec->sid, ··· 3833 3833 3834 3834 /* finit_module */ 3835 3835 3836 - ad.type = LSM_AUDIT_DATA_PATH; 3837 - ad.u.path = file->f_path; 3836 + ad.type = LSM_AUDIT_DATA_FILE; 3837 + ad.u.file = file; 3838 3838 3839 3839 fsec = file->f_security; 3840 3840 if (sid != fsec->sid) {