aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2008-11-11 05:48:14 -0500
committerJames Morris <jmorris@namei.org>2008-11-11 05:48:14 -0500
commit851f7ff56d9c21272f289dd85fb3f1b6cf7a6e10 (patch)
tree42c72104230d93bf785a4cdda1e1ea5895339db0 /kernel
parentc0b004413a46a0a5744e6d2b85220fe9d2c33d48 (diff)
This patch will print cap_permitted and cap_inheritable data in the PATH
records of any file that has file capabilities set. Files which do not have fcaps set will not have different PATH records. An example audit record if you run: setcap "cap_net_admin+pie" /bin/bash /bin/bash type=SYSCALL msg=audit(1225741937.363:230): arch=c000003e syscall=59 success=yes exit=0 a0=2119230 a1=210da30 a2=20ee290 a3=8 items=2 ppid=2149 pid=2923 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="ping" exe="/bin/ping" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) type=EXECVE msg=audit(1225741937.363:230): argc=2 a0="ping" a1="www.google.com" type=CWD msg=audit(1225741937.363:230): cwd="/root" type=PATH msg=audit(1225741937.363:230): item=0 name="/bin/ping" inode=49256 dev=fd:00 mode=0104755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ping_exec_t:s0 cap_fp=0000000000002000 cap_fi=0000000000002000 cap_fe=1 cap_fver=2 type=PATH msg=audit(1225741937.363:230): item=1 name=(null) inode=507915 dev=fd:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0 Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c82
1 files changed, 77 insertions, 5 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index cf5bc2f5f9c3..de7e9bcba9ae 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -65,6 +65,7 @@
65#include <linux/highmem.h> 65#include <linux/highmem.h>
66#include <linux/syscalls.h> 66#include <linux/syscalls.h>
67#include <linux/inotify.h> 67#include <linux/inotify.h>
68#include <linux/capability.h>
68 69
69#include "audit.h" 70#include "audit.h"
70 71
@@ -84,6 +85,15 @@ int audit_n_rules;
84/* determines whether we collect data for signals sent */ 85/* determines whether we collect data for signals sent */
85int audit_signals; 86int audit_signals;
86 87
88struct audit_cap_data {
89 kernel_cap_t permitted;
90 kernel_cap_t inheritable;
91 union {
92 unsigned int fE; /* effective bit of a file capability */
93 kernel_cap_t effective; /* effective set of a process */
94 };
95};
96
87/* When fs/namei.c:getname() is called, we store the pointer in name and 97/* When fs/namei.c:getname() is called, we store the pointer in name and
88 * we don't let putname() free it (instead we free all of the saved 98 * we don't let putname() free it (instead we free all of the saved
89 * pointers at syscall exit time). 99 * pointers at syscall exit time).
@@ -100,6 +110,8 @@ struct audit_names {
100 gid_t gid; 110 gid_t gid;
101 dev_t rdev; 111 dev_t rdev;
102 u32 osid; 112 u32 osid;
113 struct audit_cap_data fcap;
114 unsigned int fcap_ver;
103}; 115};
104 116
105struct audit_aux_data { 117struct audit_aux_data {
@@ -1171,6 +1183,35 @@ static void audit_log_execve_info(struct audit_context *context,
1171 kfree(buf); 1183 kfree(buf);
1172} 1184}
1173 1185
1186static void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
1187{
1188 int i;
1189
1190 audit_log_format(ab, " %s=", prefix);
1191 CAP_FOR_EACH_U32(i) {
1192 audit_log_format(ab, "%08x", cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
1193 }
1194}
1195
1196static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
1197{
1198 kernel_cap_t *perm = &name->fcap.permitted;
1199 kernel_cap_t *inh = &name->fcap.inheritable;
1200 int log = 0;
1201
1202 if (!cap_isclear(*perm)) {
1203 audit_log_cap(ab, "cap_fp", perm);
1204 log = 1;
1205 }
1206 if (!cap_isclear(*inh)) {
1207 audit_log_cap(ab, "cap_fi", inh);
1208 log = 1;
1209 }
1210
1211 if (log)
1212 audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver);
1213}
1214
1174static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) 1215static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
1175{ 1216{
1176 int i, call_panic = 0; 1217 int i, call_panic = 0;
@@ -1421,6 +1462,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
1421 } 1462 }
1422 } 1463 }
1423 1464
1465 audit_log_fcaps(ab, n);
1466
1424 audit_log_end(ab); 1467 audit_log_end(ab);
1425 } 1468 }
1426 1469
@@ -1787,8 +1830,36 @@ static int audit_inc_name_count(struct audit_context *context,
1787 return 0; 1830 return 0;
1788} 1831}
1789 1832
1833
1834static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry)
1835{
1836 struct cpu_vfs_cap_data caps;
1837 int rc;
1838
1839 memset(&name->fcap.permitted, 0, sizeof(kernel_cap_t));
1840 memset(&name->fcap.inheritable, 0, sizeof(kernel_cap_t));
1841 name->fcap.fE = 0;
1842 name->fcap_ver = 0;
1843
1844 if (!dentry)
1845 return 0;
1846
1847 rc = get_vfs_caps_from_disk(dentry, &caps);
1848 if (rc)
1849 return rc;
1850
1851 name->fcap.permitted = caps.permitted;
1852 name->fcap.inheritable = caps.inheritable;
1853 name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
1854 name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
1855
1856 return 0;
1857}
1858
1859
1790/* Copy inode data into an audit_names. */ 1860/* Copy inode data into an audit_names. */
1791static void audit_copy_inode(struct audit_names *name, const struct inode *inode) 1861static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
1862 const struct inode *inode)
1792{ 1863{
1793 name->ino = inode->i_ino; 1864 name->ino = inode->i_ino;
1794 name->dev = inode->i_sb->s_dev; 1865 name->dev = inode->i_sb->s_dev;
@@ -1797,6 +1868,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
1797 name->gid = inode->i_gid; 1868 name->gid = inode->i_gid;
1798 name->rdev = inode->i_rdev; 1869 name->rdev = inode->i_rdev;
1799 security_inode_getsecid(inode, &name->osid); 1870 security_inode_getsecid(inode, &name->osid);
1871 audit_copy_fcaps(name, dentry);
1800} 1872}
1801 1873
1802/** 1874/**
@@ -1831,7 +1903,7 @@ void __audit_inode(const char *name, const struct dentry *dentry)
1831 context->names[idx].name = NULL; 1903 context->names[idx].name = NULL;
1832 } 1904 }
1833 handle_path(dentry); 1905 handle_path(dentry);
1834 audit_copy_inode(&context->names[idx], inode); 1906 audit_copy_inode(&context->names[idx], dentry, inode);
1835} 1907}
1836 1908
1837/** 1909/**
@@ -1892,7 +1964,7 @@ void __audit_inode_child(const char *dname, const struct dentry *dentry,
1892 if (!strcmp(dname, n->name) || 1964 if (!strcmp(dname, n->name) ||
1893 !audit_compare_dname_path(dname, n->name, &dirlen)) { 1965 !audit_compare_dname_path(dname, n->name, &dirlen)) {
1894 if (inode) 1966 if (inode)
1895 audit_copy_inode(n, inode); 1967 audit_copy_inode(n, NULL, inode);
1896 else 1968 else
1897 n->ino = (unsigned long)-1; 1969 n->ino = (unsigned long)-1;
1898 found_child = n->name; 1970 found_child = n->name;
@@ -1906,7 +1978,7 @@ add_names:
1906 return; 1978 return;
1907 idx = context->name_count - 1; 1979 idx = context->name_count - 1;
1908 context->names[idx].name = NULL; 1980 context->names[idx].name = NULL;
1909 audit_copy_inode(&context->names[idx], parent); 1981 audit_copy_inode(&context->names[idx], NULL, parent);
1910 } 1982 }
1911 1983
1912 if (!found_child) { 1984 if (!found_child) {
@@ -1927,7 +1999,7 @@ add_names:
1927 } 1999 }
1928 2000
1929 if (inode) 2001 if (inode)
1930 audit_copy_inode(&context->names[idx], inode); 2002 audit_copy_inode(&context->names[idx], NULL, inode);
1931 else 2003 else
1932 context->names[idx].ino = (unsigned long)-1; 2004 context->names[idx].ino = (unsigned long)-1;
1933 } 2005 }