Merge tag 'y2038-cleanups-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / security / selinux / hooks.c
index 456b5b5..116b4d6 100644 (file)
@@ -3140,6 +3140,9 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
                return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
        }
 
+       if (!selinux_state.initialized)
+               return (inode_owner_or_capable(inode) ? 0 : -EPERM);
+
        sbsec = inode->i_sb->s_security;
        if (!(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
@@ -3223,6 +3226,15 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
                return;
        }
 
+       if (!selinux_state.initialized) {
+               /* If we haven't even been initialized, then we can't validate
+                * against a policy, so leave the label as invalid. It may
+                * resolve to a valid label on the next revalidation try if
+                * we've since initialized.
+                */
+               return;
+       }
+
        rc = security_context_to_sid_force(&selinux_state, value, size,
                                           &newsid);
        if (rc) {
@@ -4619,8 +4631,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)
@@ -6791,6 +6803,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),
@@ -7026,6 +7099,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)