diff mbox series

[v2,1/2] selinux: add tracepoint on denials

Message ID 20200813144914.737306-1-tweek@google.com (mailing list archive)
State Superseded
Headers show
Series [v2,1/2] selinux: add tracepoint on denials | expand

Commit Message

Thiébaud Weksteen Aug. 13, 2020, 2:48 p.m. UTC
The audit data currently captures which process and which target
is responsible for a denial. There is no data on where exactly in the
process that call occurred. Debugging can be made easier by being able to
reconstruct the unified kernel and userland stack traces [1]. Add a
tracepoint on the SELinux denials which can then be used by userland
(i.e. perf).

Although this patch could manually be added by each OS developer to
trouble shoot a denial, adding it to the kernel streamlines the
developers workflow.

It is possible to use perf for monitoring the event:
  # perf record -e avc:selinux_audited -g -a
  ^C
  # perf report -g
  [...]
      6.40%     6.40%  audited=800000 tclass=4
               |
                  __libc_start_main
                  |
                  |--4.60%--__GI___ioctl
                  |          entry_SYSCALL_64
                  |          do_syscall_64
                  |          __x64_sys_ioctl
                  |          ksys_ioctl
                  |          binder_ioctl
                  |          binder_set_nice
                  |          can_nice
                  |          capable
                  |          security_capable
                  |          cred_has_capability.isra.0
                  |          slow_avc_audit
                  |          common_lsm_audit
                  |          avc_audit_post_callback
                  |          avc_audit_post_callback
                  |

It is also possible to use the ftrace interface:
  # echo 1 > /sys/kernel/debug/tracing/events/avc/selinux_audited/enable
  # cat /sys/kernel/debug/tracing/trace
  tracer: nop
  entries-in-buffer/entries-written: 1/1   #P:8
  [...]
  dmesg-3624  [001] 13072.325358: selinux_denied: audited=800000 tclass=4

[1] https://source.android.com/devices/tech/debug/native_stack_dump

Signed-off-by: Thiébaud Weksteen <tweek@google.com>
Suggested-by: Joel Fernandes <joelaf@google.com>
Reviewed-by: Peter Enderborg <peter.enderborg@sony.com>
---
v2 changes:
- update changelog to include usage examples

 MAINTAINERS                |  1 +
 include/trace/events/avc.h | 37 +++++++++++++++++++++++++++++++++++++
 security/selinux/avc.c     |  5 +++++
 3 files changed, 43 insertions(+)
 create mode 100644 include/trace/events/avc.h

Comments

Stephen Smalley Aug. 13, 2020, 3:41 p.m. UTC | #1
On 8/13/20 10:48 AM, Thiébaud Weksteen wrote:

> The audit data currently captures which process and which target
> is responsible for a denial. There is no data on where exactly in the
> process that call occurred. Debugging can be made easier by being able to
> reconstruct the unified kernel and userland stack traces [1]. Add a
> tracepoint on the SELinux denials which can then be used by userland
> (i.e. perf).
>
> Although this patch could manually be added by each OS developer to
> trouble shoot a denial, adding it to the kernel streamlines the
> developers workflow.
>
> It is possible to use perf for monitoring the event:
>    # perf record -e avc:selinux_audited -g -a
>    ^C
>    # perf report -g
>    [...]
>        6.40%     6.40%  audited=800000 tclass=4
>                 |
>                    __libc_start_main
>                    |
>                    |--4.60%--__GI___ioctl
>                    |          entry_SYSCALL_64
>                    |          do_syscall_64
>                    |          __x64_sys_ioctl
>                    |          ksys_ioctl
>                    |          binder_ioctl
>                    |          binder_set_nice
>                    |          can_nice
>                    |          capable
>                    |          security_capable
>                    |          cred_has_capability.isra.0
>                    |          slow_avc_audit
>                    |          common_lsm_audit
>                    |          avc_audit_post_callback
>                    |          avc_audit_post_callback
>                    |
>
> It is also possible to use the ftrace interface:
>    # echo 1 > /sys/kernel/debug/tracing/events/avc/selinux_audited/enable
>    # cat /sys/kernel/debug/tracing/trace
>    tracer: nop
>    entries-in-buffer/entries-written: 1/1   #P:8
>    [...]
>    dmesg-3624  [001] 13072.325358: selinux_denied: audited=800000 tclass=4

An explanation here of how one might go about decoding audited and 
tclass would be helpful to users (even better would be a script to do it 
for them).  Again, I know how to do that but not everyone using 
perf/ftrace will.
Thiébaud Weksteen Aug. 14, 2020, 1:05 p.m. UTC | #2
On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> An explanation here of how one might go about decoding audited and
> tclass would be helpful to users (even better would be a script to do it
> for them).  Again, I know how to do that but not everyone using
> perf/ftrace will.

What about something along those lines:

The tclass value can be mapped to a class by searching
security/selinux/flask.h. The audited value is a bit field of the
permissions described in security/selinux/av_permissions.h for the
corresponding class.
Stephen Smalley Aug. 14, 2020, 4:51 p.m. UTC | #3
On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:
>
> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
> >
> > An explanation here of how one might go about decoding audited and
> > tclass would be helpful to users (even better would be a script to do it
> > for them).  Again, I know how to do that but not everyone using
> > perf/ftrace will.
>
> What about something along those lines:
>
> The tclass value can be mapped to a class by searching
> security/selinux/flask.h. The audited value is a bit field of the
> permissions described in security/selinux/av_permissions.h for the
> corresponding class.

Sure, I guess that works.  Would be nice if we just included the class
and permission name(s) in the event itself but I guess you viewed that
as too heavyweight?
Peter Enderborg Aug. 14, 2020, 5:07 p.m. UTC | #4
On 8/14/20 6:51 PM, Stephen Smalley wrote:
> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:
>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
>> <stephen.smalley.work@gmail.com> wrote:
>>> An explanation here of how one might go about decoding audited and
>>> tclass would be helpful to users (even better would be a script to do it
>>> for them).  Again, I know how to do that but not everyone using
>>> perf/ftrace will.
>> What about something along those lines:
>>
>> The tclass value can be mapped to a class by searching
>> security/selinux/flask.h. The audited value is a bit field of the
>> permissions described in security/selinux/av_permissions.h for the
>> corresponding class.
> Sure, I guess that works.  Would be nice if we just included the class
> and permission name(s) in the event itself but I guess you viewed that
> as too heavyweight?

The class name is added in part 2. Im not sure how a proper format for permission
would look like in trace terms. It is a list, right?
Stephen Smalley Aug. 14, 2020, 5:08 p.m. UTC | #5
On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
<peter.enderborg@sony.com> wrote:
>
> On 8/14/20 6:51 PM, Stephen Smalley wrote:
> > On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:
> >> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
> >> <stephen.smalley.work@gmail.com> wrote:
> >>> An explanation here of how one might go about decoding audited and
> >>> tclass would be helpful to users (even better would be a script to do it
> >>> for them).  Again, I know how to do that but not everyone using
> >>> perf/ftrace will.
> >> What about something along those lines:
> >>
> >> The tclass value can be mapped to a class by searching
> >> security/selinux/flask.h. The audited value is a bit field of the
> >> permissions described in security/selinux/av_permissions.h for the
> >> corresponding class.
> > Sure, I guess that works.  Would be nice if we just included the class
> > and permission name(s) in the event itself but I guess you viewed that
> > as too heavyweight?
>
> The class name is added in part 2. Im not sure how a proper format for permission
> would look like in trace terms. It is a list, right?

Yes.  See avc_audit_pre_callback() for example code to log the permission names.
Peter Enderborg Aug. 14, 2020, 5:22 p.m. UTC | #6
On 8/14/20 7:08 PM, Stephen Smalley wrote:
> On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
> <peter.enderborg@sony.com> wrote:
>> On 8/14/20 6:51 PM, Stephen Smalley wrote:
>>> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:
>>>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
>>>> <stephen.smalley.work@gmail.com> wrote:
>>>>> An explanation here of how one might go about decoding audited and
>>>>> tclass would be helpful to users (even better would be a script to do it
>>>>> for them).  Again, I know how to do that but not everyone using
>>>>> perf/ftrace will.
>>>> What about something along those lines:
>>>>
>>>> The tclass value can be mapped to a class by searching
>>>> security/selinux/flask.h. The audited value is a bit field of the
>>>> permissions described in security/selinux/av_permissions.h for the
>>>> corresponding class.
>>> Sure, I guess that works.  Would be nice if we just included the class
>>> and permission name(s) in the event itself but I guess you viewed that
>>> as too heavyweight?
>> The class name is added in part 2. Im not sure how a proper format for permission
>> would look like in trace terms. It is a list, right?
> Yes.  See avc_audit_pre_callback() for example code to log the permission names.

I wrote about that on some of the previous sets. The problem is that trace format is quite fixed. So it is lists are not
that easy to handle if you want to filter in them. You can have a trace event for each of them. You can also add
additional trace event "selinux_audied_permission" for each permission. With that you can filter out tclass or permissions.

But the basic thing we would like at the moment is a event that we can debug in user space.
Steven Rostedt Aug. 14, 2020, 5:46 p.m. UTC | #7
On Fri, 14 Aug 2020 19:22:13 +0200
peter enderborg <peter.enderborg@sony.com> wrote:

> On 8/14/20 7:08 PM, Stephen Smalley wrote:
> > On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
> > <peter.enderborg@sony.com> wrote:  
> >> On 8/14/20 6:51 PM, Stephen Smalley wrote:  
> >>> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:  
> >>>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
> >>>> <stephen.smalley.work@gmail.com> wrote:  
> >>>>> An explanation here of how one might go about decoding audited and
> >>>>> tclass would be helpful to users (even better would be a script to do it
> >>>>> for them).  Again, I know how to do that but not everyone using
> >>>>> perf/ftrace will.  
> >>>> What about something along those lines:
> >>>>
> >>>> The tclass value can be mapped to a class by searching
> >>>> security/selinux/flask.h. The audited value is a bit field of the
> >>>> permissions described in security/selinux/av_permissions.h for the
> >>>> corresponding class.  
> >>> Sure, I guess that works.  Would be nice if we just included the class
> >>> and permission name(s) in the event itself but I guess you viewed that
> >>> as too heavyweight?  
> >> The class name is added in part 2. Im not sure how a proper format for permission
> >> would look like in trace terms. It is a list, right?  
> > Yes.  See avc_audit_pre_callback() for example code to log the permission names.  
> 
> I wrote about that on some of the previous sets. The problem is that trace format is quite fixed. So it is lists are not
> that easy to handle if you want to filter in them. You can have a trace event for each of them. You can also add
> additional trace event "selinux_audied_permission" for each permission. With that you can filter out tclass or permissions.
> 
> But the basic thing we would like at the moment is a event that we can debug in user space.

We have a trace_seq p helper, that lets you create strings in
TP_printk(). I should document this more. Thus you can do:

extern const char *audit_perm_to_name(struct trace_seq *p, u16 class, u32 audited);
#define __perm_to_name(p, class, audited) audit_perm_to_name(p, class, audited)

	TP_printk("tclass=%u audited=%x (%s)",
		__entry->tclass,
		__entry->audited,
		__perm_to_name(__entry->tclass, __entry->audited))


const char *audit_perm_to_name(struct trace_seq *p, u16 tclass, u32 av)
{
	const char *ret = trace_seq_buffer_ptr(p);
	int i, perm;

	( some check for tclass integrity here)

	perms = secclass_map[tclass-1].perms;

	i = 0;
	perm = 1;
	while (i < (sizeof(av) * 8)) {
		if ((perm & av) && perms[i]) {
			trace_seq_printf(p, " %s", perms[i]);
			av &= ~perm;
		}
		i++;
		perm <<= 1;
	}

	return ret;
}

Note, this wont work for perf and trace-cmd as it wouldn't know how to
parse it, but if the tclass perms are stable, you could create a plugin
to libtraceevent that can do the above as well.

-- Steve
Peter Enderborg Aug. 14, 2020, 6:06 p.m. UTC | #8
On 8/14/20 7:46 PM, Steven Rostedt wrote:
> On Fri, 14 Aug 2020 19:22:13 +0200
> peter enderborg <peter.enderborg@sony.com> wrote:
>
>> On 8/14/20 7:08 PM, Stephen Smalley wrote:
>>> On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
>>> <peter.enderborg@sony.com> wrote:  
>>>> On 8/14/20 6:51 PM, Stephen Smalley wrote:  
>>>>> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:  
>>>>>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
>>>>>> <stephen.smalley.work@gmail.com> wrote:  
>>>>>>> An explanation here of how one might go about decoding audited and
>>>>>>> tclass would be helpful to users (even better would be a script to do it
>>>>>>> for them).  Again, I know how to do that but not everyone using
>>>>>>> perf/ftrace will.  
>>>>>> What about something along those lines:
>>>>>>
>>>>>> The tclass value can be mapped to a class by searching
>>>>>> security/selinux/flask.h. The audited value is a bit field of the
>>>>>> permissions described in security/selinux/av_permissions.h for the
>>>>>> corresponding class.  
>>>>> Sure, I guess that works.  Would be nice if we just included the class
>>>>> and permission name(s) in the event itself but I guess you viewed that
>>>>> as too heavyweight?  
>>>> The class name is added in part 2. Im not sure how a proper format for permission
>>>> would look like in trace terms. It is a list, right?  
>>> Yes.  See avc_audit_pre_callback() for example code to log the permission names.  
>> I wrote about that on some of the previous sets. The problem is that trace format is quite fixed. So it is lists are not
>> that easy to handle if you want to filter in them. You can have a trace event for each of them. You can also add
>> additional trace event "selinux_audied_permission" for each permission. With that you can filter out tclass or permissions.
>>
>> But the basic thing we would like at the moment is a event that we can debug in user space.
> We have a trace_seq p helper, that lets you create strings in
> TP_printk(). I should document this more. Thus you can do:
>
> extern const char *audit_perm_to_name(struct trace_seq *p, u16 class, u32 audited);
> #define __perm_to_name(p, class, audited) audit_perm_to_name(p, class, audited)
>
> 	TP_printk("tclass=%u audited=%x (%s)",
> 		__entry->tclass,
> 		__entry->audited,
> 		__perm_to_name(__entry->tclass, __entry->audited))
>
>
> const char *audit_perm_to_name(struct trace_seq *p, u16 tclass, u32 av)
> {
> 	const char *ret = trace_seq_buffer_ptr(p);
> 	int i, perm;
>
> 	( some check for tclass integrity here)
>
> 	perms = secclass_map[tclass-1].perms;
>
> 	i = 0;
> 	perm = 1;
> 	while (i < (sizeof(av) * 8)) {
> 		if ((perm & av) && perms[i]) {
> 			trace_seq_printf(p, " %s", perms[i]);
> 			av &= ~perm;
> 		}
> 		i++;
> 		perm <<= 1;
> 	}
>
> 	return ret;
> }
>
> Note, this wont work for perf and trace-cmd as it wouldn't know how to
> parse it, but if the tclass perms are stable, you could create a plugin
> to libtraceevent that can do the above as well.
>
> -- Steve

Im find with that, but then you  can not do filtering? I would be pretty neat with a filter saying tclass=file permission=write.
Steven Rostedt Aug. 14, 2020, 6:30 p.m. UTC | #9
On Fri, 14 Aug 2020 20:06:34 +0200
peter enderborg <peter.enderborg@sony.com> wrote:

> Im find with that, but then you  can not do filtering? I would be
> pretty neat with a filter saying tclass=file permission=write.
> 

Well, if the mapping is stable, you could do:

	(tclass == 6) && (audited & 0x4)

-- Steve
Peter Enderborg Aug. 14, 2020, 6:50 p.m. UTC | #10
On 8/14/20 8:30 PM, Steven Rostedt wrote:
> On Fri, 14 Aug 2020 20:06:34 +0200
> peter enderborg <peter.enderborg@sony.com> wrote:
>
>> Im find with that, but then you  can not do filtering? I would be
>> pretty neat with a filter saying tclass=file permission=write.
>>
> Well, if the mapping is stable, you could do:
>
> 	(tclass == 6) && (audited & 0x4)

It does not happen to exist a hook for translate strings to numeric values when inserting filter?


> -- Steve
Steven Rostedt Aug. 14, 2020, 6:56 p.m. UTC | #11
On Fri, 14 Aug 2020 20:50:47 +0200
peter enderborg <peter.enderborg@sony.com> wrote:

> On 8/14/20 8:30 PM, Steven Rostedt wrote:
> > On Fri, 14 Aug 2020 20:06:34 +0200
> > peter enderborg <peter.enderborg@sony.com> wrote:
> >  
> >> Im find with that, but then you  can not do filtering? I would be
> >> pretty neat with a filter saying tclass=file permission=write.
> >>  
> > Well, if the mapping is stable, you could do:
> >
> > 	(tclass == 6) && (audited & 0x4)  
> 
> It does not happen to exist a hook for translate strings to numeric values when inserting filter?
> 

How would you imagine such a hook existing?

Something that would be specific to each trace event class, where you
can register at boot up a mapping of names to values? Or a function
that would translate it?

-- Steve
Peter Enderborg Aug. 15, 2020, 7:17 a.m. UTC | #12
On 8/14/20 7:46 PM, Steven Rostedt wrote:
> On Fri, 14 Aug 2020 19:22:13 +0200
> peter enderborg <peter.enderborg@sony.com> wrote:
>
>> On 8/14/20 7:08 PM, Stephen Smalley wrote:
>>> On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
>>> <peter.enderborg@sony.com> wrote:  
>>>> On 8/14/20 6:51 PM, Stephen Smalley wrote:  
>>>>> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:  
>>>>>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
>>>>>> <stephen.smalley.work@gmail.com> wrote:  
>>>>>>> An explanation here of how one might go about decoding audited and
>>>>>>> tclass would be helpful to users (even better would be a script to do it
>>>>>>> for them).  Again, I know how to do that but not everyone using
>>>>>>> perf/ftrace will.  
>>>>>> What about something along those lines:
>>>>>>
>>>>>> The tclass value can be mapped to a class by searching
>>>>>> security/selinux/flask.h. The audited value is a bit field of the
>>>>>> permissions described in security/selinux/av_permissions.h for the
>>>>>> corresponding class.  
>>>>> Sure, I guess that works.  Would be nice if we just included the class
>>>>> and permission name(s) in the event itself but I guess you viewed that
>>>>> as too heavyweight?  
>>>> The class name is added in part 2. Im not sure how a proper format for permission
>>>> would look like in trace terms. It is a list, right?  
>>> Yes.  See avc_audit_pre_callback() for example code to log the permission names.  
>> I wrote about that on some of the previous sets. The problem is that trace format is quite fixed. So it is lists are not
>> that easy to handle if you want to filter in them. You can have a trace event for each of them. You can also add
>> additional trace event "selinux_audied_permission" for each permission. With that you can filter out tclass or permissions.
>>
>> But the basic thing we would like at the moment is a event that we can debug in user space.
> We have a trace_seq p helper, that lets you create strings in
> TP_printk(). I should document this more. Thus you can do:
>
> extern const char *audit_perm_to_name(struct trace_seq *p, u16 class, u32 audited);
> #define __perm_to_name(p, class, audited) audit_perm_to_name(p, class, audited)
>
> 	TP_printk("tclass=%u audited=%x (%s)",
> 		__entry->tclass,
> 		__entry->audited,
> 		__perm_to_name(__entry->tclass, __entry->audited))
>
>
> const char *audit_perm_to_name(struct trace_seq *p, u16 tclass, u32 av)
> {
> 	const char *ret = trace_seq_buffer_ptr(p);
> 	int i, perm;
>
> 	( some check for tclass integrity here)
>
> 	perms = secclass_map[tclass-1].perms;
>
> 	i = 0;
> 	perm = 1;
> 	while (i < (sizeof(av) * 8)) {
> 		if ((perm & av) && perms[i]) {
> 			trace_seq_printf(p, " %s", perms[i]);
> 			av &= ~perm;
> 		}
> 		i++;
> 		perm <<= 1;
> 	}
>
> 	return ret;
> }
>
> Note, this wont work for perf and trace-cmd as it wouldn't know how to
> parse it, but if the tclass perms are stable, you could create a plugin
> to libtraceevent that can do the above as well.
>
> -- Steve

That works fine. I will do this as third patch in our patch-set.  But I think we also should export the permission-map
somewhere. I don’t think there is any good place for it in tracefs. So selinuxfs or debugfs might do? And I think it is
more useful to print what is denied than what is audited but that does not match the trace event name.
Peter Enderborg Aug. 15, 2020, 8:45 a.m. UTC | #13
On 8/14/20 7:46 PM, Steven Rostedt wrote:
> On Fri, 14 Aug 2020 19:22:13 +0200
> peter enderborg <peter.enderborg@sony.com> wrote:
>
>> On 8/14/20 7:08 PM, Stephen Smalley wrote:
>>> On Fri, Aug 14, 2020 at 1:07 PM peter enderborg
>>> <peter.enderborg@sony.com> wrote:  
>>>> On 8/14/20 6:51 PM, Stephen Smalley wrote:  
>>>>> On Fri, Aug 14, 2020 at 9:05 AM Thiébaud Weksteen <tweek@google.com> wrote:  
>>>>>> On Thu, Aug 13, 2020 at 5:41 PM Stephen Smalley
>>>>>> <stephen.smalley.work@gmail.com> wrote:  
>>>>>>> An explanation here of how one might go about decoding audited and
>>>>>>> tclass would be helpful to users (even better would be a script to do it
>>>>>>> for them).  Again, I know how to do that but not everyone using
>>>>>>> perf/ftrace will.  
>>>>>> What about something along those lines:
>>>>>>
>>>>>> The tclass value can be mapped to a class by searching
>>>>>> security/selinux/flask.h. The audited value is a bit field of the
>>>>>> permissions described in security/selinux/av_permissions.h for the
>>>>>> corresponding class.  
>>>>> Sure, I guess that works.  Would be nice if we just included the class
>>>>> and permission name(s) in the event itself but I guess you viewed that
>>>>> as too heavyweight?  
>>>> The class name is added in part 2. Im not sure how a proper format for permission
>>>> would look like in trace terms. It is a list, right?  
>>> Yes.  See avc_audit_pre_callback() for example code to log the permission names.  
>> I wrote about that on some of the previous sets. The problem is that trace format is quite fixed. So it is lists are not
>> that easy to handle if you want to filter in them. You can have a trace event for each of them. You can also add
>> additional trace event "selinux_audied_permission" for each permission. With that you can filter out tclass or permissions.
>>
>> But the basic thing we would like at the moment is a event that we can debug in user space.
> We have a trace_seq p helper, that lets you create strings in
> TP_printk(). I should document this more. Thus you can do:
>
> extern const char *audit_perm_to_name(struct trace_seq *p, u16 class, u32 audited);
> #define __perm_to_name(p, class, audited) audit_perm_to_name(p, class, audited)
>
> 	TP_printk("tclass=%u audited=%x (%s)",
> 		__entry->tclass,
> 		__entry->audited,
> 		__perm_to_name(__entry->tclass, __entry->audited))
>
>
> const char *audit_perm_to_name(struct trace_seq *p, u16 tclass, u32 av)
> {
> 	const char *ret = trace_seq_buffer_ptr(p);
> 	int i, perm;
>
> 	( some check for tclass integrity here)
>
> 	perms = secclass_map[tclass-1].perms;
>
> 	i = 0;
> 	perm = 1;
> 	while (i < (sizeof(av) * 8)) {
> 		if ((perm & av) && perms[i]) {
> 			trace_seq_printf(p, " %s", perms[i]);
> 			av &= ~perm;
> 		}
> 		i++;
> 		perm <<= 1;
> 	}
>
> 	return ret;
> }
>
> Note, this wont work for perf and trace-cmd as it wouldn't know how to
> parse it, but if the tclass perms are stable, you could create a plugin
> to libtraceevent that can do the above as well.
>
> -- Steve

Something like:

    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;

And you get information about denied too.
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index c8e8232c65da..0efaea0e144c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15426,6 +15426,7 @@  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
 F:	Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
 F:	Documentation/ABI/obsolete/sysfs-selinux-disable
 F:	Documentation/admin-guide/LSM/SELinux.rst
+F:	include/trace/events/avc.h
 F:	include/uapi/linux/selinux_netlink.h
 F:	scripts/selinux/
 F:	security/selinux/
diff --git a/include/trace/events/avc.h b/include/trace/events/avc.h
new file mode 100644
index 000000000000..07c058a9bbcd
--- /dev/null
+++ b/include/trace/events/avc.h
@@ -0,0 +1,37 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Author: Thiébaud Weksteen <tweek@google.com>
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM avc
+
+#if !defined(_TRACE_SELINUX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SELINUX_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(selinux_audited,
+
+	TP_PROTO(struct selinux_audit_data *sad),
+
+	TP_ARGS(sad),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, tclass)
+		__field(unsigned int, audited)
+	),
+
+	TP_fast_assign(
+		__entry->tclass = sad->tclass;
+		__entry->audited = sad->audited;
+	),
+
+	TP_printk("tclass=%u audited=%x",
+		__entry->tclass,
+		__entry->audited)
+);
+
+#endif
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index d18cb32a242a..b0a0af778b70 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -31,6 +31,9 @@ 
 #include "avc_ss.h"
 #include "classmap.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/avc.h>
+
 #define AVC_CACHE_SLOTS			512
 #define AVC_DEF_CACHE_THRESHOLD		512
 #define AVC_CACHE_RECLAIM		16
@@ -706,6 +709,8 @@  static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
 	u32 scontext_len;
 	int rc;
 
+	trace_selinux_audited(sad);
+
 	rc = security_sid_to_context(sad->state, sad->ssid, &scontext,
 				     &scontext_len);
 	if (rc)