lsm: infrastructure management of the perf_event security blob
authorCasey Schaufler <casey@schaufler-ca.com>
Wed, 10 Jul 2024 21:32:30 +0000 (14:32 -0700)
committerPaul Moore <paul@paul-moore.com>
Mon, 29 Jul 2024 20:54:52 +0000 (16:54 -0400)
Move management of the perf_event->security blob out of the individual
security modules and into the security infrastructure. Instead of
allocating the blobs from within the modules the modules tell the
infrastructure how much space is required, and the space is allocated
there.  There are no longer any modules that require the perf_event_free()
hook.  The hook definition has been removed.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: John Johansen <john.johansen@canonical.com>
[PM: subject tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
security/security.c
security/selinux/hooks.c
security/selinux/include/objsec.h

index 4fcbc5b3f58ce36c35e73ee752f6fd613d151657..12c81be78eb947ba2cd5da50ed3f4d8aad250823 100644 (file)
@@ -439,7 +439,6 @@ LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
 #ifdef CONFIG_PERF_EVENTS
 LSM_HOOK(int, 0, perf_event_open, struct perf_event_attr *attr, int type)
 LSM_HOOK(int, 0, perf_event_alloc, struct perf_event *event)
-LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event)
 LSM_HOOK(int, 0, perf_event_read, struct perf_event *event)
 LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
 #endif /* CONFIG_PERF_EVENTS */
index b6fc6ac887238dd069e64106e9e63b18d36758ea..f1ca8082075a399157511e84cef2ec42c95c05ca 100644 (file)
@@ -79,6 +79,7 @@ struct lsm_blob_sizes {
        int     lbs_ipc;
        int     lbs_key;
        int     lbs_msg_msg;
+       int     lbs_perf_event;
        int     lbs_task;
        int     lbs_xattr_count; /* number of xattr slots in new_xattrs array */
        int     lbs_tun_dev;
index 80dc58d60aabb3f77a55429309346d32889a67cc..93ed7670fbc9fa7951a587e47e7284c8066ee250 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/xattr.h>
 #include <linux/msg.h>
 #include <linux/overflow.h>
+#include <linux/perf_event.h>
 #include <net/flow.h>
 #include <net/sock.h>
 
@@ -230,6 +231,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
        lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
        lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
        lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
+       lsm_set_blob_size(&needed->lbs_perf_event, &blob_sizes.lbs_perf_event);
        lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
        lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
        lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
@@ -412,6 +414,7 @@ static void __init ordered_lsm_init(void)
        init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
        init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
        init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
+       init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event);
        init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
        init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
        init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
@@ -5685,7 +5688,19 @@ int security_perf_event_open(struct perf_event_attr *attr, int type)
  */
 int security_perf_event_alloc(struct perf_event *event)
 {
-       return call_int_hook(perf_event_alloc, event);
+       int rc;
+
+       rc = lsm_blob_alloc(&event->security, blob_sizes.lbs_perf_event,
+                           GFP_KERNEL);
+       if (rc)
+               return rc;
+
+       rc = call_int_hook(perf_event_alloc, event);
+       if (rc) {
+               kfree(event->security);
+               event->security = NULL;
+       }
+       return rc;
 }
 
 /**
@@ -5696,7 +5711,8 @@ int security_perf_event_alloc(struct perf_event *event)
  */
 void security_perf_event_free(struct perf_event *event)
 {
-       call_void_hook(perf_event_free, event);
+       kfree(event->security);
+       event->security = NULL;
 }
 
 /**
index 675c69ebb77c3508ebcef329e9984e2b8ab88792..0939816e967120969223053e21ead9aa1e1d7691 100644 (file)
@@ -6955,6 +6955,9 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
        .lbs_ipc = sizeof(struct ipc_security_struct),
        .lbs_key = sizeof(struct key_security_struct),
        .lbs_msg_msg = sizeof(struct msg_security_struct),
+#ifdef CONFIG_PERF_EVENTS
+       .lbs_perf_event = sizeof(struct perf_event_security_struct),
+#endif
        .lbs_sock = sizeof(struct sk_security_struct),
        .lbs_superblock = sizeof(struct superblock_security_struct),
        .lbs_xattr_count = SELINUX_INODE_INIT_XATTRS,
@@ -6986,24 +6989,12 @@ 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 = selinux_perf_event(event->security);
        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;
@@ -7316,7 +7307,6 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
 
 #ifdef CONFIG_PERF_EVENTS
        LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
-       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
index ed9e37f3c9b55126643b14100b3cf9fa0e4519ce..c88cae81ee4c52e84639545f328db3b3fb3e354d 100644 (file)
@@ -217,4 +217,10 @@ static inline struct ib_security_struct *selinux_ib(void *ib_sec)
        return ib_sec + selinux_blob_sizes.lbs_ib;
 }
 
+static inline struct perf_event_security_struct *
+selinux_perf_event(void *perf_event)
+{
+       return perf_event + selinux_blob_sizes.lbs_perf_event;
+}
+
 #endif /* _SELINUX_OBJSEC_H_ */