Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[sfrench/cifs-2.6.git] / security / selinux / hooks.c
index 753b327f48067c3be23f8b5661c30b07c99e09a3..73986c1101b96dc0f382d01e7475a4df4f3216bc 100644 (file)
@@ -6795,6 +6795,67 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
        .lbs_msg_msg = sizeof(struct msg_security_struct),
 };
 
+#ifdef CONFIG_PERF_EVENTS
+static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
+{
+       u32 requested, sid = current_sid();
+
+       if (type == PERF_SECURITY_OPEN)
+               requested = PERF_EVENT__OPEN;
+       else if (type == PERF_SECURITY_CPU)
+               requested = PERF_EVENT__CPU;
+       else if (type == PERF_SECURITY_KERNEL)
+               requested = PERF_EVENT__KERNEL;
+       else if (type == PERF_SECURITY_TRACEPOINT)
+               requested = PERF_EVENT__TRACEPOINT;
+       else
+               return -EINVAL;
+
+       return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
+                           requested, NULL);
+}
+
+static int selinux_perf_event_alloc(struct perf_event *event)
+{
+       struct perf_event_security_struct *perfsec;
+
+       perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
+       if (!perfsec)
+               return -ENOMEM;
+
+       perfsec->sid = current_sid();
+       event->security = perfsec;
+
+       return 0;
+}
+
+static void selinux_perf_event_free(struct perf_event *event)
+{
+       struct perf_event_security_struct *perfsec = event->security;
+
+       event->security = NULL;
+       kfree(perfsec);
+}
+
+static int selinux_perf_event_read(struct perf_event *event)
+{
+       struct perf_event_security_struct *perfsec = event->security;
+       u32 sid = current_sid();
+
+       return avc_has_perm(&selinux_state, sid, perfsec->sid,
+                           SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
+}
+
+static int selinux_perf_event_write(struct perf_event *event)
+{
+       struct perf_event_security_struct *perfsec = event->security;
+       u32 sid = current_sid();
+
+       return avc_has_perm(&selinux_state, sid, perfsec->sid,
+                           SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
+}
+#endif
+
 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
        LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
@@ -7030,6 +7091,14 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
        LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
 #endif
+
+#ifdef CONFIG_PERF_EVENTS
+       LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
+       LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
+       LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
+       LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
+       LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
+#endif
 };
 
 static __init int selinux_init(void)