Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[sfrench/cifs-2.6.git] / security / selinux / hooks.c
index 9625b99e677fd33cf4abc1ebcc48fb3b79fb44d8..73986c1101b96dc0f382d01e7475a4df4f3216bc 100644 (file)
@@ -4623,8 +4623,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 
                        inet_get_local_port_range(sock_net(sk), &low, &high);
 
-                       if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
-                           snum > high) {
+                       if (inet_port_requires_bind_service(sock_net(sk), snum) ||
+                           snum < low || snum > high) {
                                err = sel_netport_sid(sk->sk_protocol,
                                                      snum, &sid);
                                if (err)
@@ -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)