diff mbox series

[v3,3/3] selinux: add permission names to trace event

Message ID 20200817170729.2605279-4-tweek@google.com (mailing list archive)
State Superseded
Delegated to: Paul Moore
Headers show
Series selinux: add detailed tracepoint on audited events | expand

Commit Message

Thiébaud Weksteen Aug. 17, 2020, 5:07 p.m. UTC
From: Peter Enderborg <peter.enderborg@sony.com>

In the print out add permissions, it will look like:
    <...>-1042  [007] ....   201.965142: selinux_audited:
    requested=0x4000000 denied=0x4000000 audited=0x4000000
    result=-13
    scontext=system_u:system_r:cupsd_t:s0-s0:c0.c1023
    tcontext=system_u:object_r:bin_t:s0
    tclass=file permissions={ !entrypoint }

This patch is adding the "permissions={ !entrypoint }".
The permissions preceded by "!" have been denied and the permissions
without have been accepted.

Note that permission filtering is done on the audited, denied or
requested attributes.

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Reviewed-by: Thiébaud Weksteen <tweek@google.com>
Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
---
 include/trace/events/avc.h | 11 +++++++++--
 security/selinux/avc.c     | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

Comments

Stephen Smalley Aug. 17, 2020, 8:13 p.m. UTC | #1
On 8/17/20 1:07 PM, Thiébaud Weksteen wrote:

> From: Peter Enderborg <peter.enderborg@sony.com>
>
> In the print out add permissions, it will look like:
>      <...>-1042  [007] ....   201.965142: selinux_audited:
>      requested=0x4000000 denied=0x4000000 audited=0x4000000
>      result=-13
>      scontext=system_u:system_r:cupsd_t:s0-s0:c0.c1023
>      tcontext=system_u:object_r:bin_t:s0
>      tclass=file permissions={ !entrypoint }
>
> This patch is adding the "permissions={ !entrypoint }".
> The permissions preceded by "!" have been denied and the permissions
> without have been accepted.
>
> Note that permission filtering is done on the audited, denied or
> requested attributes.
>
> Suggested-by: Steven Rostedt <rostedt@goodmis.org>
> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> Reviewed-by: Thiébaud Weksteen <tweek@google.com>
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---

Does this require a corresponding patch to userspace?  Otherwise, I get 
the following:

libtraceevent: No such file or directory
   [avc:selinux_audited] function avc_trace_perm_to_name not defined
Stephen Smalley Aug. 17, 2020, 8:16 p.m. UTC | #2
On 8/17/20 1:07 PM, Thiébaud Weksteen wrote:

> From: Peter Enderborg <peter.enderborg@sony.com>
>
> In the print out add permissions, it will look like:
>      <...>-1042  [007] ....   201.965142: selinux_audited:
>      requested=0x4000000 denied=0x4000000 audited=0x4000000
>      result=-13
>      scontext=system_u:system_r:cupsd_t:s0-s0:c0.c1023
>      tcontext=system_u:object_r:bin_t:s0
>      tclass=file permissions={ !entrypoint }
>
> This patch is adding the "permissions={ !entrypoint }".
> The permissions preceded by "!" have been denied and the permissions
> without have been accepted.
>
> Note that permission filtering is done on the audited, denied or
> requested attributes.
>
> Suggested-by: Steven Rostedt <rostedt@goodmis.org>
> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> Reviewed-by: Thiébaud Weksteen <tweek@google.com>
> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> ---
>   include/trace/events/avc.h | 11 +++++++++--
>   security/selinux/avc.c     | 36 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 45 insertions(+), 2 deletions(-)
>
> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> index 7de5cc5169af..d585b68c2a50 100644
> --- a/security/selinux/avc.c
> +++ b/security/selinux/avc.c
> @@ -695,6 +695,7 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
>   	audit_log_format(ab, " } for ");
>   }
>   
> +
>   /**
>    * avc_audit_post_callback - SELinux specific information
>    * will be called by generic audit code

Also, drop the spurious whitespace change above.
Steven Rostedt Aug. 17, 2020, 8:29 p.m. UTC | #3
On Mon, 17 Aug 2020 16:13:29 -0400
Stephen Smalley <stephen.smalley.work@gmail.com> wrote:

> Does this require a corresponding patch to userspace?  Otherwise, I get 
> the following:
> 
> libtraceevent: No such file or directory
>    [avc:selinux_audited] function avc_trace_perm_to_name not defined

Yes, we need to add a plugin to libtraceevent that will add that
function.

I could possibly write one up real quick.

-- Steve
Peter Enderborg Aug. 18, 2020, 8:11 a.m. UTC | #4
On 8/17/20 10:16 PM, Stephen Smalley wrote:
> On 8/17/20 1:07 PM, Thiébaud Weksteen wrote:
>
>> From: Peter Enderborg <peter.enderborg@sony.com>
>>
>> In the print out add permissions, it will look like:
>>      <...>-1042  [007] ....   201.965142: selinux_audited:
>>      requested=0x4000000 denied=0x4000000 audited=0x4000000
>>      result=-13
>>      scontext=system_u:system_r:cupsd_t:s0-s0:c0.c1023
>>      tcontext=system_u:object_r:bin_t:s0
>>      tclass=file permissions={ !entrypoint }
>>
>> This patch is adding the "permissions={ !entrypoint }".
>> The permissions preceded by "!" have been denied and the permissions
>> without have been accepted.
>>
>> Note that permission filtering is done on the audited, denied or
>> requested attributes.
>>
>> Suggested-by: Steven Rostedt <rostedt@goodmis.org>
>> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
>> Reviewed-by: Thiébaud Weksteen <tweek@google.com>
>> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
>> ---
>>   include/trace/events/avc.h | 11 +++++++++--
>>   security/selinux/avc.c     | 36 ++++++++++++++++++++++++++++++++++++
>>   2 files changed, 45 insertions(+), 2 deletions(-)
>>
>> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
>> index 7de5cc5169af..d585b68c2a50 100644
>> --- a/security/selinux/avc.c
>> +++ b/security/selinux/avc.c
>> @@ -695,6 +695,7 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
>>       audit_log_format(ab, " } for ");
>>   }
>>   +
>>   /**
>>    * avc_audit_post_callback - SELinux specific information
>>    * will be called by generic audit code
>
> Also, drop the spurious whitespace change above.
>
>
Is there any other things we need to fix? A part 1&2 now OK?
Stephen Smalley Aug. 18, 2020, 12:13 p.m. UTC | #5
On Tue, Aug 18, 2020 at 4:11 AM peter enderborg
<peter.enderborg@sony.com> wrote:
>
> On 8/17/20 10:16 PM, Stephen Smalley wrote:
> > On 8/17/20 1:07 PM, Thiébaud Weksteen wrote:
> >
> >> From: Peter Enderborg <peter.enderborg@sony.com>
> >>
> >> In the print out add permissions, it will look like:
> >>      <...>-1042  [007] ....   201.965142: selinux_audited:
> >>      requested=0x4000000 denied=0x4000000 audited=0x4000000
> >>      result=-13
> >>      scontext=system_u:system_r:cupsd_t:s0-s0:c0.c1023
> >>      tcontext=system_u:object_r:bin_t:s0
> >>      tclass=file permissions={ !entrypoint }
> >>
> >> This patch is adding the "permissions={ !entrypoint }".
> >> The permissions preceded by "!" have been denied and the permissions
> >> without have been accepted.
> >>
> >> Note that permission filtering is done on the audited, denied or
> >> requested attributes.
> >>
> >> Suggested-by: Steven Rostedt <rostedt@goodmis.org>
> >> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> >> Reviewed-by: Thiébaud Weksteen <tweek@google.com>
> >> Signed-off-by: Peter Enderborg <peter.enderborg@sony.com>
> >> ---
> >>   include/trace/events/avc.h | 11 +++++++++--
> >>   security/selinux/avc.c     | 36 ++++++++++++++++++++++++++++++++++++
> >>   2 files changed, 45 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> >> index 7de5cc5169af..d585b68c2a50 100644
> >> --- a/security/selinux/avc.c
> >> +++ b/security/selinux/avc.c
> >> @@ -695,6 +695,7 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
> >>       audit_log_format(ab, " } for ");
> >>   }
> >>   +
> >>   /**
> >>    * avc_audit_post_callback - SELinux specific information
> >>    * will be called by generic audit code
> >
> > Also, drop the spurious whitespace change above.
> >
> >
> Is there any other things we need to fix? A part 1&2 now OK?

They looked ok to me, but Paul should review them.
Steven Rostedt Aug. 18, 2020, 4:09 p.m. UTC | #6
On Mon, 17 Aug 2020 16:29:33 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Mon, 17 Aug 2020 16:13:29 -0400
> Stephen Smalley <stephen.smalley.work@gmail.com> wrote:
> 
> > Does this require a corresponding patch to userspace?  Otherwise, I get 
> > the following:
> > 
> > libtraceevent: No such file or directory
> >    [avc:selinux_audited] function avc_trace_perm_to_name not defined  
> 
> Yes, we need to add a plugin to libtraceevent that will add that
> function.
> 
> I could possibly write one up real quick.

Something like this (this is patched on top of trace-cmd, but will work
for tools/lib/traceevent too).

With CONFIG_TRACE_EVENT_INJECT enabled (to test events), I did the following:

 # echo 'utclass=1 audited=1 denied=0' > /sys/kernel/tracing/events/avc/selinux_audited/inject
 # trace-cmd extract
 # trace-cmd report
cpus=8
           <...>-1685  [005]  1607.612032: selinux_audited:      requested=0x0 denied=0x0 audited=0x1 result=0 scontext= tcontext= tclass= permissions={ compute_av }

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

---
diff --git a/lib/traceevent/plugins/Makefile b/lib/traceevent/plugins/Makefile
index 21e933af..13cbcb92 100644
--- a/lib/traceevent/plugins/Makefile
+++ b/lib/traceevent/plugins/Makefile
@@ -16,6 +16,7 @@ PLUGIN_OBJS += plugin_scsi.o
 PLUGIN_OBJS += plugin_cfg80211.o
 PLUGIN_OBJS += plugin_blk.o
 PLUGIN_OBJS += plugin_tlb.o
+PLUGIN_OBJS += plugin_avc.o
 
 PLUGIN_OBJS := $(PLUGIN_OBJS:%.o=$(bdir)/%.o)
 PLUGIN_BUILD := $(PLUGIN_OBJS:$(bdir)/%.o=$(bdir)/%.so)
diff --git a/lib/traceevent/plugins/plugin_avc.c b/lib/traceevent/plugins/plugin_avc.c
new file mode 100644
index 00000000..76af23b9
--- /dev/null
+++ b/lib/traceevent/plugins/plugin_avc.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+#include "event-parse.h"
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+typedef unsigned short u16;
+
+/* Class/perm mapping support */
+struct security_class_mapping {
+	const char *name;
+	const char *perms[sizeof(unsigned) * 8 + 1];
+};
+
+#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \
+    "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append", "map"
+
+#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
+    "rename", "execute", "quotaon", "mounton", "audit_access", \
+	"open", "execmod", "watch", "watch_mount", "watch_sb", \
+	"watch_with_perm", "watch_reads"
+
+#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
+    "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom",  \
+    "sendto", "name_bind"
+
+#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
+	    "write", "associate", "unix_read", "unix_write"
+
+#define COMMON_CAP_PERMS  "chown", "dac_override", "dac_read_search", \
+	    "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", \
+	    "linux_immutable", "net_bind_service", "net_broadcast", \
+	    "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", \
+	    "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", \
+	    "sys_boot", "sys_nice", "sys_resource", "sys_time", \
+	    "sys_tty_config", "mknod", "lease", "audit_write", \
+	    "audit_control", "setfcap"
+
+#define COMMON_CAP2_PERMS  "mac_override", "mac_admin", "syslog", \
+		"wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf"
+
+/*
+ * Note: The name for any socket class should be suffixed by "socket",
+ *	 and doesn't contain more than one substr of "socket".
+ */
+struct security_class_mapping secclass_map[] = {
+	{ "security",
+	  { "compute_av", "compute_create", "compute_member",
+	    "check_context", "load_policy", "compute_relabel",
+	    "compute_user", "setenforce", "setbool", "setsecparam",
+	    "setcheckreqprot", "read_policy", "validate_trans", NULL } },
+	{ "process",
+	  { "fork", "transition", "sigchld", "sigkill",
+	    "sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
+	    "getsession", "getpgid", "setpgid", "getcap", "setcap", "share",
+	    "getattr", "setexec", "setfscreate", "noatsecure", "siginh",
+	    "setrlimit", "rlimitinh", "dyntransition", "setcurrent",
+	    "execmem", "execstack", "execheap", "setkeycreate",
+	    "setsockcreate", "getrlimit", NULL } },
+	{ "process2",
+	  { "nnp_transition", "nosuid_transition", NULL } },
+	{ "system",
+	  { "ipc_info", "syslog_read", "syslog_mod",
+	    "syslog_console", "module_request", "module_load", NULL } },
+	{ "capability",
+	  { COMMON_CAP_PERMS, NULL } },
+	{ "filesystem",
+	  { "mount", "remount", "unmount", "getattr",
+	    "relabelfrom", "relabelto", "associate", "quotamod",
+	    "quotaget", "watch", NULL } },
+	{ "file",
+	  { COMMON_FILE_PERMS,
+	    "execute_no_trans", "entrypoint", NULL } },
+	{ "dir",
+	  { COMMON_FILE_PERMS, "add_name", "remove_name",
+	    "reparent", "search", "rmdir", NULL } },
+	{ "fd", { "use", NULL } },
+	{ "lnk_file",
+	  { COMMON_FILE_PERMS, NULL } },
+	{ "chr_file",
+	  { COMMON_FILE_PERMS, NULL } },
+	{ "blk_file",
+	  { COMMON_FILE_PERMS, NULL } },
+	{ "sock_file",
+	  { COMMON_FILE_PERMS, NULL } },
+	{ "fifo_file",
+	  { COMMON_FILE_PERMS, NULL } },
+	{ "socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "tcp_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", "name_connect",
+	    NULL } },
+	{ "udp_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", NULL } },
+	{ "rawip_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", NULL } },
+	{ "node",
+	  { "recvfrom", "sendto", NULL } },
+	{ "netif",
+	  { "ingress", "egress", NULL } },
+	{ "netlink_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "packet_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "key_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "unix_stream_socket",
+	  { COMMON_SOCK_PERMS, "connectto", NULL } },
+	{ "unix_dgram_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "sem",
+	  { COMMON_IPC_PERMS, NULL } },
+	{ "msg", { "send", "receive", NULL } },
+	{ "msgq",
+	  { COMMON_IPC_PERMS, "enqueue", NULL } },
+	{ "shm",
+	  { COMMON_IPC_PERMS, "lock", NULL } },
+	{ "ipc",
+	  { COMMON_IPC_PERMS, NULL } },
+	{ "netlink_route_socket",
+	  { COMMON_SOCK_PERMS,
+	    "nlmsg_read", "nlmsg_write", NULL } },
+	{ "netlink_tcpdiag_socket",
+	  { COMMON_SOCK_PERMS,
+	    "nlmsg_read", "nlmsg_write", NULL } },
+	{ "netlink_nflog_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_xfrm_socket",
+	  { COMMON_SOCK_PERMS,
+	    "nlmsg_read", "nlmsg_write", NULL } },
+	{ "netlink_selinux_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_iscsi_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_audit_socket",
+	  { COMMON_SOCK_PERMS,
+	    "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv",
+	    "nlmsg_tty_audit", NULL } },
+	{ "netlink_fib_lookup_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_connector_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_netfilter_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_dnrt_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "association",
+	  { "sendto", "recvfrom", "setcontext", "polmatch", NULL } },
+	{ "netlink_kobject_uevent_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_generic_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_scsitransport_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_rdma_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netlink_crypto_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "appletalk_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "packet",
+	  { "send", "recv", "relabelto", "forward_in", "forward_out", NULL } },
+	{ "key",
+	  { "view", "read", "write", "search", "link", "setattr", "create",
+	    NULL } },
+	{ "dccp_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", "name_connect", NULL } },
+	{ "memprotect", { "mmap_zero", NULL } },
+	{ "peer", { "recv", NULL } },
+	{ "capability2",
+	  { COMMON_CAP2_PERMS, NULL } },
+	{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
+	{ "tun_socket",
+	  { COMMON_SOCK_PERMS, "attach_queue", NULL } },
+	{ "binder", { "impersonate", "call", "set_context_mgr", "transfer",
+		      NULL } },
+	{ "cap_userns",
+	  { COMMON_CAP_PERMS, NULL } },
+	{ "cap2_userns",
+	  { COMMON_CAP2_PERMS, NULL } },
+	{ "sctp_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", "name_connect", "association", NULL } },
+	{ "icmp_socket",
+	  { COMMON_SOCK_PERMS,
+	    "node_bind", NULL } },
+	{ "ax25_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "ipx_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "netrom_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "atmpvc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "x25_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "rose_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "decnet_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "atmsvc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "rds_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "irda_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "pppox_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "llc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "can_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "tipc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "bluetooth_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "iucv_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "rxrpc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "isdn_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "phonet_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "ieee802154_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "caif_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "alg_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "nfc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "vsock_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "kcm_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "qipcrtr_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "smc_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "infiniband_pkey",
+	  { "access", NULL } },
+	{ "infiniband_endport",
+	  { "manage_subnet", NULL } },
+	{ "bpf",
+	  {"map_create", "map_read", "map_write", "prog_load", "prog_run"} },
+	{ "xdp_socket",
+	  { COMMON_SOCK_PERMS, NULL } },
+	{ "perf_event",
+	  {"open", "cpu", "kernel", "tracepoint", "read", "write"} },
+	{ "lockdown",
+	  { "integrity", "confidentiality", NULL } },
+	{ NULL }
+  };
+
+
+static unsigned long long
+avc_trace_perm_to_name(struct trace_seq *p, unsigned long long *args)
+{
+	u16 tclass = args[1];
+	int av = args[2];
+	int avdenied = args[3];
+	int i, perm;
+	const char **perms;
+
+	if (!tclass || tclass >= ARRAY_SIZE(secclass_map))
+		return 0;
+
+	perms = secclass_map[tclass-1].perms;
+
+	i = 0;
+	perm = 1;
+	while (i < (sizeof(av) * 8)) {
+		if ((perm & av)  && perms[i]) {
+			if (!(perm & avdenied))
+				trace_seq_printf(p, " %s", perms[i]);
+			else
+				trace_seq_printf(p, " !%s", perms[i]);
+			av &= ~perm;
+		}
+		i++;
+		perm <<= 1;
+	}
+
+	return 0;
+}
+
+int TEP_PLUGIN_LOADER(struct tep_handle *tep)
+{
+	tep_register_print_function(tep,
+				    avc_trace_perm_to_name,
+				    TEP_FUNC_ARG_STRING,
+				    "avc_trace_perm_to_name",
+				    TEP_FUNC_ARG_PTR,
+				    TEP_FUNC_ARG_INT,
+				    TEP_FUNC_ARG_INT,
+				    TEP_FUNC_ARG_INT,
+				    TEP_FUNC_ARG_VOID);
+
+	return 0;
+}
+
+void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
+{
+	tep_unregister_print_function(tep, avc_trace_perm_to_name,
+				    "avc_trace_perm_to_name");
+}
Stephen Smalley Aug. 19, 2020, 1:11 p.m. UTC | #7
On 8/18/20 12:09 PM, Steven Rostedt wrote:

> On Mon, 17 Aug 2020 16:29:33 -0400
> Steven Rostedt <rostedt@goodmis.org> wrote:
>
>> On Mon, 17 Aug 2020 16:13:29 -0400
>> Stephen Smalley <stephen.smalley.work@gmail.com> wrote:
>>
>>> Does this require a corresponding patch to userspace?  Otherwise, I get
>>> the following:
>>>
>>> libtraceevent: No such file or directory
>>>     [avc:selinux_audited] function avc_trace_perm_to_name not defined
>> Yes, we need to add a plugin to libtraceevent that will add that
>> function.
>>
>> I could possibly write one up real quick.
> Something like this (this is patched on top of trace-cmd, but will work
> for tools/lib/traceevent too).
>
> With CONFIG_TRACE_EVENT_INJECT enabled (to test events), I did the following:
>
>   # echo 'utclass=1 audited=1 denied=0' > /sys/kernel/tracing/events/avc/selinux_audited/inject
>   # trace-cmd extract
>   # trace-cmd report
> cpus=8
>             <...>-1685  [005]  1607.612032: selinux_audited:      requested=0x0 denied=0x0 audited=0x1 result=0 scontext= tcontext= tclass= permissions={ compute_av }
>
> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
>
> ---
> diff --git a/lib/traceevent/plugins/Makefile b/lib/traceevent/plugins/Makefile
> index 21e933af..13cbcb92 100644
> --- a/lib/traceevent/plugins/Makefile
> +++ b/lib/traceevent/plugins/Makefile
> @@ -16,6 +16,7 @@ PLUGIN_OBJS += plugin_scsi.o
>   PLUGIN_OBJS += plugin_cfg80211.o
>   PLUGIN_OBJS += plugin_blk.o
>   PLUGIN_OBJS += plugin_tlb.o
> +PLUGIN_OBJS += plugin_avc.o
>   
>   PLUGIN_OBJS := $(PLUGIN_OBJS:%.o=$(bdir)/%.o)
>   PLUGIN_BUILD := $(PLUGIN_OBJS:$(bdir)/%.o=$(bdir)/%.so)
> diff --git a/lib/traceevent/plugins/plugin_avc.c b/lib/traceevent/plugins/plugin_avc.c
> new file mode 100644
> index 00000000..76af23b9
> --- /dev/null
> +++ b/lib/traceevent/plugins/plugin_avc.c
> @@ -0,0 +1,312 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <stdio.h>
> +#include <string.h>
> +#include "event-parse.h"
> +
> +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> +
> +typedef unsigned short u16;
> +
> +/* Class/perm mapping support */
> +struct security_class_mapping {
> +	const char *name;
> +	const char *perms[sizeof(unsigned) * 8 + 1];
> +};
> +
> +#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \
> +    "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append", "map"
> +
> +#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
> +    "rename", "execute", "quotaon", "mounton", "audit_access", \
> +	"open", "execmod", "watch", "watch_mount", "watch_sb", \
> +	"watch_with_perm", "watch_reads"
> +
> +#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
> +    "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom",  \
> +    "sendto", "name_bind"
> +
> +#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
> +	    "write", "associate", "unix_read", "unix_write"
> +
> +#define COMMON_CAP_PERMS  "chown", "dac_override", "dac_read_search", \
> +	    "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", \
> +	    "linux_immutable", "net_bind_service", "net_broadcast", \
> +	    "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", \
> +	    "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", \
> +	    "sys_boot", "sys_nice", "sys_resource", "sys_time", \
> +	    "sys_tty_config", "mknod", "lease", "audit_write", \
> +	    "audit_control", "setfcap"
> +
> +#define COMMON_CAP2_PERMS  "mac_override", "mac_admin", "syslog", \
> +		"wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf"
> +
> +/*
> + * Note: The name for any socket class should be suffixed by "socket",
> + *	 and doesn't contain more than one substr of "socket".
> + */
> +struct security_class_mapping secclass_map[] = {
> +	{ "security",
> +	  { "compute_av", "compute_create", "compute_member",
> +	    "check_context", "load_policy", "compute_relabel",
> +	    "compute_user", "setenforce", "setbool", "setsecparam",
> +	    "setcheckreqprot", "read_policy", "validate_trans", NULL } },
>
So we'll need to update this plugin whenever we modify 
security/selinux/include/classmap.h to keep them in sync.  Is that a 
concern?  I don't suppose the plugin could directly include classmap.h?  
I guess we'd have to export it as a public header. It isn't considered 
to be part of the kernel API/ABI and can change anytime (but in practice 
changes are not that frequent, and usually just additive in nature).
Paul Moore Aug. 21, 2020, 2:22 a.m. UTC | #8
On Tue, Aug 18, 2020 at 8:14 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Tue, Aug 18, 2020 at 4:11 AM peter enderborg <peter.enderborg@sony.com> wrote:

...

> > Is there any other things we need to fix? A part 1&2 now OK?
>
> They looked ok to me, but Paul should review them.

Patches 1 and 2 look fine to me with the small nits that Stephen
pointed out corrected.  I'm glad to see the information in string form
now, I think that will be a big help for people making use of this.

Unfortunately, I'm a little concerned about patch 3 for the reason
Stephen already mentioned.  While changes to the class mapping are
infrequent, they do happen, and I'm not very excited about adding it
to the userspace kAPI via a header.  Considering that the tracing
tools are going to be running on the same system that is being
inspected, perhaps the tracing tools could inspect
/sys/fs/selinux/class at runtime to query the permission mappings?
Stephen, is there a libselinux API which does this already?
Steven Rostedt Aug. 21, 2020, 2:31 a.m. UTC | #9
On Wed, 19 Aug 2020 09:11:08 -0400
Stephen Smalley <stephen.smalley.work@gmail.com> wrote:

> So we'll need to update this plugin whenever we modify 
> security/selinux/include/classmap.h to keep them in sync.  Is that a 
> concern?  I don't suppose the plugin could directly include classmap.h?  
> I guess we'd have to export it as a public header. It isn't considered 
> to be part of the kernel API/ABI and can change anytime (but in practice 
> changes are not that frequent, and usually just additive in nature).

Yes, it would require some stability between userspace and the plugin.
If the value indexes don't change then that would work fine. If you add
new ones, that too should be OK, just have a way to state "unknown" in
the plugin.

-- Steve
Peter Enderborg Aug. 21, 2020, 5:53 a.m. UTC | #10
On 8/21/20 4:22 AM, Paul Moore wrote:
> On Tue, Aug 18, 2020 at 8:14 AM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
>> On Tue, Aug 18, 2020 at 4:11 AM peter enderborg <peter.enderborg@sony.com> wrote:
> ...
>
>>> Is there any other things we need to fix? A part 1&2 now OK?
>> They looked ok to me, but Paul should review them.
> Patches 1 and 2 look fine to me with the small nits that Stephen
> pointed out corrected.  I'm glad to see the information in string form
> now, I think that will be a big help for people making use of this.
>
> Unfortunately, I'm a little concerned about patch 3 for the reason
> Stephen already mentioned.  While changes to the class mapping are
> infrequent, they do happen, and I'm not very excited about adding it
> to the userspace kAPI via a header.  Considering that the tracing
> tools are going to be running on the same system that is being
> inspected, perhaps the tracing tools could inspect
> /sys/fs/selinux/class at runtime to query the permission mappings?
> Stephen, is there a libselinux API which does this already?
>
One way to use this trace is to write directly to a memory buffer over a time
period. In the case for Android and I guess in many other embedded cases too
they are moved to be some other machine to be analysed so having them
locked to where it was running also have problems.

So what is the problem we see with the plugin, that we have perms names
that are "unknown" ?
Stephen Smalley Aug. 21, 2020, 12:14 p.m. UTC | #11
On Thu, Aug 20, 2020 at 10:22 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Tue, Aug 18, 2020 at 8:14 AM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
> > On Tue, Aug 18, 2020 at 4:11 AM peter enderborg <peter.enderborg@sony.com> wrote:
>
> ...
>
> > > Is there any other things we need to fix? A part 1&2 now OK?
> >
> > They looked ok to me, but Paul should review them.
>
> Patches 1 and 2 look fine to me with the small nits that Stephen
> pointed out corrected.  I'm glad to see the information in string form
> now, I think that will be a big help for people making use of this.
>
> Unfortunately, I'm a little concerned about patch 3 for the reason
> Stephen already mentioned.  While changes to the class mapping are
> infrequent, they do happen, and I'm not very excited about adding it
> to the userspace kAPI via a header.  Considering that the tracing
> tools are going to be running on the same system that is being
> inspected, perhaps the tracing tools could inspect
> /sys/fs/selinux/class at runtime to query the permission mappings?
> Stephen, is there a libselinux API which does this already?

There is a libselinux API but both it and the /sys/fs/selinux/class
tree is exposing the policy values for classes/permissions, not the
kernel-private indices.  The dynamic class/perm mapping support
introduced a layer of indirection between them.  The tracepoint is in
the avc and therefore dealing with the kernel-private values, not the
policy values.  The mapping occurs on entry/exit of the security
server functions. So there is no way for userspace to read the kernel
class/perm values.  We'd just need to keep them in sync manually.  And
one is allowed to insert new classes or permissions before existing
ones, thereby changing the values of existing ones, or even to remove
them.
Stephen Smalley Aug. 21, 2020, 12:29 p.m. UTC | #12
On Thu, Aug 20, 2020 at 10:31 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 19 Aug 2020 09:11:08 -0400
> Stephen Smalley <stephen.smalley.work@gmail.com> wrote:
>
> > So we'll need to update this plugin whenever we modify
> > security/selinux/include/classmap.h to keep them in sync.  Is that a
> > concern?  I don't suppose the plugin could directly include classmap.h?
> > I guess we'd have to export it as a public header. It isn't considered
> > to be part of the kernel API/ABI and can change anytime (but in practice
> > changes are not that frequent, and usually just additive in nature).
>
> Yes, it would require some stability between userspace and the plugin.
> If the value indexes don't change then that would work fine. If you add
> new ones, that too should be OK, just have a way to state "unknown" in
> the plugin.

Since we introduced the dynamic class/perm mapping support, it has
been possible for the values of existing classes/permissions to
change, and that has happened at time, e.g. when we added watch
permissions to the common file perms, that shifted the values of the
class file perms like entrypoint, when we added the process2 class
right after the process class, it shifted the values of all the
subsequent classes in the classmap.h.  So you can't rely on those
values remaining stable across kernel versions.
Paul Moore Aug. 21, 2020, 1:10 p.m. UTC | #13
On Fri, Aug 21, 2020 at 8:15 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Thu, Aug 20, 2020 at 10:22 PM Paul Moore <paul@paul-moore.com> wrote:
> >
> > On Tue, Aug 18, 2020 at 8:14 AM Stephen Smalley
> > <stephen.smalley.work@gmail.com> wrote:
> > > On Tue, Aug 18, 2020 at 4:11 AM peter enderborg <peter.enderborg@sony.com> wrote:
> >
> > ...
> >
> > > > Is there any other things we need to fix? A part 1&2 now OK?
> > >
> > > They looked ok to me, but Paul should review them.
> >
> > Patches 1 and 2 look fine to me with the small nits that Stephen
> > pointed out corrected.  I'm glad to see the information in string form
> > now, I think that will be a big help for people making use of this.
> >
> > Unfortunately, I'm a little concerned about patch 3 for the reason
> > Stephen already mentioned.  While changes to the class mapping are
> > infrequent, they do happen, and I'm not very excited about adding it
> > to the userspace kAPI via a header.  Considering that the tracing
> > tools are going to be running on the same system that is being
> > inspected, perhaps the tracing tools could inspect
> > /sys/fs/selinux/class at runtime to query the permission mappings?
> > Stephen, is there a libselinux API which does this already?
>
> There is a libselinux API but both it and the /sys/fs/selinux/class
> tree is exposing the policy values for classes/permissions, not the
> kernel-private indices.  The dynamic class/perm mapping support
> introduced a layer of indirection between them.  The tracepoint is in
> the avc and therefore dealing with the kernel-private values, not the
> policy values.  The mapping occurs on entry/exit of the security
> server functions. So there is no way for userspace to read the kernel
> class/perm values.  We'd just need to keep them in sync manually.  And
> one is allowed to insert new classes or permissions before existing
> ones, thereby changing the values of existing ones, or even to remove
> them.

Ah, okay, thanks.  Can you tell I've never really had to look very
closely at that code ;)
Paul Moore Aug. 21, 2020, 1:19 p.m. UTC | #14
On Fri, Aug 21, 2020 at 8:29 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Thu, Aug 20, 2020 at 10:31 PM Steven Rostedt <rostedt@goodmis.org> wrote:
> > On Wed, 19 Aug 2020 09:11:08 -0400
> > Stephen Smalley <stephen.smalley.work@gmail.com> wrote:
> >
> > > So we'll need to update this plugin whenever we modify
> > > security/selinux/include/classmap.h to keep them in sync.  Is that a
> > > concern?  I don't suppose the plugin could directly include classmap.h?
> > > I guess we'd have to export it as a public header. It isn't considered
> > > to be part of the kernel API/ABI and can change anytime (but in practice
> > > changes are not that frequent, and usually just additive in nature).
> >
> > Yes, it would require some stability between userspace and the plugin.
> > If the value indexes don't change then that would work fine. If you add
> > new ones, that too should be OK, just have a way to state "unknown" in
> > the plugin.
>
> Since we introduced the dynamic class/perm mapping support, it has
> been possible for the values of existing classes/permissions to
> change, and that has happened at time, e.g. when we added watch
> permissions to the common file perms, that shifted the values of the
> class file perms like entrypoint, when we added the process2 class
> right after the process class, it shifted the values of all the
> subsequent classes in the classmap.h.  So you can't rely on those
> values remaining stable across kernel versions.

I think it is becoming increasingly clear that generating the
permission set string in userspace isn't really workable without
breaking the dynamic class/permission mapping to some degree.
Unfortunately I don't see these perf changes as a big enough "win" to
offset the loss of the dynamic mapping loss.

I'm okay with merging patches 1/3 and 2/3 wth the changes Stephen
suggested, but I think we will need to leave patch 3/3 out of this for
now.
Peter Enderborg Aug. 21, 2020, 1:39 p.m. UTC | #15
On 8/21/20 3:19 PM, Paul Moore wrote:
> On Fri, Aug 21, 2020 at 8:29 AM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
>> On Thu, Aug 20, 2020 at 10:31 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>>> On Wed, 19 Aug 2020 09:11:08 -0400
>>> Stephen Smalley <stephen.smalley.work@gmail.com> wrote:
>>>
>>>> So we'll need to update this plugin whenever we modify
>>>> security/selinux/include/classmap.h to keep them in sync.  Is that a
>>>> concern?  I don't suppose the plugin could directly include classmap.h?
>>>> I guess we'd have to export it as a public header. It isn't considered
>>>> to be part of the kernel API/ABI and can change anytime (but in practice
>>>> changes are not that frequent, and usually just additive in nature).
>>> Yes, it would require some stability between userspace and the plugin.
>>> If the value indexes don't change then that would work fine. If you add
>>> new ones, that too should be OK, just have a way to state "unknown" in
>>> the plugin.
>> Since we introduced the dynamic class/perm mapping support, it has
>> been possible for the values of existing classes/permissions to
>> change, and that has happened at time, e.g. when we added watch
>> permissions to the common file perms, that shifted the values of the
>> class file perms like entrypoint, when we added the process2 class
>> right after the process class, it shifted the values of all the
>> subsequent classes in the classmap.h.  So you can't rely on those
>> values remaining stable across kernel versions.
> I think it is becoming increasingly clear that generating the
> permission set string in userspace isn't really workable without
> breaking the dynamic class/permission mapping to some degree.
> Unfortunately I don't see these perf changes as a big enough "win" to
> offset the loss of the dynamic mapping loss.
>
> I'm okay with merging patches 1/3 and 2/3 wth the changes Stephen
> suggested, but I think we will need to leave patch 3/3 out of this for
> now.
>
Ok.
Paul Moore Aug. 21, 2020, 1:46 p.m. UTC | #16
On Fri, Aug 21, 2020 at 9:21 AM Thiébaud Weksteen <tweek@google.com> wrote:
>>
>> I'm okay with merging patches 1/3 and 2/3 wth the changes Stephen
>> suggested, but I think we will need to leave patch 3/3 out of this for
>> now.
>
> That works for me.

Can you respin patches 1 and two with those changes and repost?  I try
to refrain from making non-merge-fuzz changes when merging patches.
Peter Enderborg Aug. 24, 2020, 1:22 p.m. UTC | #17
This is other solution. I dont think needs any plugin support. It will generate one
event for eatch denial and there is possible to filter on permission.
.
diff mbox series

Patch

diff --git a/include/trace/events/avc.h b/include/trace/events/avc.h
index b55fda2e0773..94bca8bef8d2 100644
--- a/include/trace/events/avc.h
+++ b/include/trace/events/avc.h
@@ -10,6 +10,10 @@ 
 #define _TRACE_SELINUX_H
 
 #include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+extern const char *avc_trace_perm_to_name(struct trace_seq *p, u16 class, u32 audited, u32 denied);
+#define __perm_to_name(class, audited, denied) avc_trace_perm_to_name(p, class, audited, denied)
 
 TRACE_EVENT(selinux_audited,
 
@@ -29,6 +33,7 @@  TRACE_EVENT(selinux_audited,
 		__string(scontext, scontext)
 		__string(tcontext, tcontext)
 		__string(tclass, tclass)
+		__field(u16, utclass)
 	),
 
 	TP_fast_assign(
@@ -36,14 +41,16 @@  TRACE_EVENT(selinux_audited,
 		__entry->denied		= sad->denied;
 		__entry->audited	= sad->audited;
 		__entry->result		= sad->result;
+		__entry->utclass	= sad->tclass;
 		__assign_str(tcontext, tcontext);
 		__assign_str(scontext, scontext);
 		__assign_str(tclass, tclass);
 	),
 
-	TP_printk("requested=0x%x denied=0x%x audited=0x%x result=%d scontext=%s tcontext=%s tclass=%s",
+	TP_printk("requested=0x%x denied=0x%x audited=0x%x result=%d scontext=%s tcontext=%s tclass=%s permissions={%s }",
 		__entry->requested, __entry->denied, __entry->audited, __entry->result,
-		__get_str(scontext), __get_str(tcontext), __get_str(tclass)
+		__get_str(scontext), __get_str(tcontext), __get_str(tclass),
+		__perm_to_name(__entry->utclass, __entry->audited, __entry->denied)
 	)
 );
 
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 7de5cc5169af..d585b68c2a50 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -695,6 +695,7 @@  static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
 	audit_log_format(ab, " } for ");
 }
 
+
 /**
  * avc_audit_post_callback - SELinux specific information
  * will be called by generic audit code
@@ -991,6 +992,41 @@  int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
 	return rc;
 }
 
+/**
+ * avc_trace_perm_to_name - SELinux help function for trace
+ * @p pointer to output storage
+ * @tclass tclass for the event
+ * @av access vector
+ * @avdenied denied permissions in av format
+ */
+const char *avc_trace_perm_to_name(struct trace_seq *p, u16 tclass, u32 av, u32 avdenied)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+	int i, perm;
+	const char **perms;
+
+	if (WARN_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map)))
+		return NULL;
+
+	perms = secclass_map[tclass-1].perms;
+
+	i = 0;
+	perm = 1;
+	while (i < (sizeof(av) * 8)) {
+		if ((perm & av)  && perms[i]) {
+			if (!(perm & avdenied))
+				trace_seq_printf(p, " %s", perms[i]);
+			else
+				trace_seq_printf(p, " !%s", perms[i]);
+			av &= ~perm;
+		}
+		i++;
+		perm <<= 1;
+	}
+
+	return ret;
+}
+
 /*
  * Slow-path helper function for avc_has_perm_noaudit,
  * when the avc_node lookup fails. We get called with