aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2016-09-09 11:37:49 -0400
committerPaul Moore <paul@paul-moore.com>2016-09-19 13:42:38 -0400
commit43af5de74288a7cdc3684902c5259346ae67adf8 (patch)
tree40ffe7231d18197267a947500c776c520d0b548b /security
parent9b6a9ecc2d88ccdc57efc22d69436b9dd7e2eceb (diff)
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>
Diffstat (limited to 'security')
-rw-r--r--security/lsm_audit.c13
-rw-r--r--security/selinux/hooks.c16
2 files changed, 21 insertions, 8 deletions
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 9bf851884800..8bfa3147fd54 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -245,6 +245,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
245 } 245 }
246 break; 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 case LSM_AUDIT_DATA_IOCTL_OP: { 261 case LSM_AUDIT_DATA_IOCTL_OP: {
249 struct inode *inode; 262 struct inode *inode;
250 263
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e15e56081c0c..2205ea27aa0a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1761,8 +1761,8 @@ static inline int file_path_has_perm(const struct cred *cred,
1761{ 1761{
1762 struct common_audit_data ad; 1762 struct common_audit_data ad;
1763 1763
1764 ad.type = LSM_AUDIT_DATA_PATH; 1764 ad.type = LSM_AUDIT_DATA_FILE;
1765 ad.u.path = file->f_path; 1765 ad.u.file = file;
1766 return inode_has_perm(cred, file_inode(file), av, &ad); 1766 return inode_has_perm(cred, file_inode(file), av, &ad);
1767} 1767}
1768 1768
@@ -1784,8 +1784,8 @@ static int file_has_perm(const struct cred *cred,
1784 u32 sid = cred_sid(cred); 1784 u32 sid = cred_sid(cred);
1785 int rc; 1785 int rc;
1786 1786
1787 ad.type = LSM_AUDIT_DATA_PATH; 1787 ad.type = LSM_AUDIT_DATA_FILE;
1788 ad.u.path = file->f_path; 1788 ad.u.file = file;
1789 1789
1790 if (sid != fsec->sid) { 1790 if (sid != fsec->sid) {
1791 rc = avc_has_perm(sid, fsec->sid, 1791 rc = avc_has_perm(sid, fsec->sid,
@@ -2365,8 +2365,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2365 new_tsec->sid = old_tsec->sid; 2365 new_tsec->sid = old_tsec->sid;
2366 } 2366 }
2367 2367
2368 ad.type = LSM_AUDIT_DATA_PATH; 2368 ad.type = LSM_AUDIT_DATA_FILE;
2369 ad.u.path = bprm->file->f_path; 2369 ad.u.file = bprm->file;
2370 2370
2371 if (new_tsec->sid == old_tsec->sid) { 2371 if (new_tsec->sid == old_tsec->sid) {
2372 rc = avc_has_perm(old_tsec->sid, isec->sid, 2372 rc = avc_has_perm(old_tsec->sid, isec->sid,
@@ -3833,8 +3833,8 @@ static int selinux_kernel_module_from_file(struct file *file)
3833 3833
3834 /* finit_module */ 3834 /* finit_module */
3835 3835
3836 ad.type = LSM_AUDIT_DATA_PATH; 3836 ad.type = LSM_AUDIT_DATA_FILE;
3837 ad.u.path = file->f_path; 3837 ad.u.file = file;
3838 3838
3839 fsec = file->f_security; 3839 fsec = file->f_security;
3840 if (sid != fsec->sid) { 3840 if (sid != fsec->sid) {