lsm: infrastructure management of the dev_tun blob
authorCasey Schaufler <casey@schaufler-ca.com>
Wed, 10 Jul 2024 21:32:28 +0000 (14:32 -0700)
committerPaul Moore <paul@paul-moore.com>
Mon, 29 Jul 2024 20:54:51 +0000 (16:54 -0400)
Move management of the dev_tun security blob out of the individual
security modules and into the LSM infrastructure.  The security modules
tell the infrastructure how much space they require at initialization.
There are no longer any modules that require the dev_tun_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, selinux style fixes]
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 8cc60644f3bd0882fe881421e83826fe4843e95d..22c475f530aea58c4a737c6d9cc0179fe90d95c1 100644 (file)
@@ -353,8 +353,7 @@ LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void)
 LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void)
 LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req,
         struct flowi_common *flic)
-LSM_HOOK(int, 0, tun_dev_alloc_security, void **security)
-LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security)
+LSM_HOOK(int, 0, tun_dev_alloc_security, void *security)
 LSM_HOOK(int, 0, tun_dev_create, void)
 LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
 LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security)
index 7233bc0737be677555afd3a009f9f9c9464e203a..0ff14ff128c800f211bb83436e0fd72e455ef2ec 100644 (file)
@@ -80,6 +80,7 @@ struct lsm_blob_sizes {
        int     lbs_msg_msg;
        int     lbs_task;
        int     lbs_xattr_count; /* number of xattr slots in new_xattrs array */
+       int     lbs_tun_dev;
 };
 
 /**
index 15efcf43e168826618e543e66075baa9293909ed..137a1f7e0e8bf5fb1530da338cda636ba99ddd77 100644 (file)
@@ -232,6 +232,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
        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);
+       lsm_set_blob_size(&needed->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
        lsm_set_blob_size(&needed->lbs_xattr_count,
                          &blob_sizes.lbs_xattr_count);
 }
@@ -410,6 +411,7 @@ static void __init ordered_lsm_init(void)
        init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
        init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
        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);
 
        /*
@@ -4875,7 +4877,18 @@ EXPORT_SYMBOL(security_secmark_refcount_dec);
  */
 int security_tun_dev_alloc_security(void **security)
 {
-       return call_int_hook(tun_dev_alloc_security, security);
+       int rc;
+
+       rc = lsm_blob_alloc(security, blob_sizes.lbs_tun_dev, GFP_KERNEL);
+       if (rc)
+               return rc;
+
+       rc = call_int_hook(tun_dev_alloc_security, *security);
+       if (rc) {
+               kfree(*security);
+               *security = NULL;
+       }
+       return rc;
 }
 EXPORT_SYMBOL(security_tun_dev_alloc_security);
 
@@ -4887,7 +4900,7 @@ EXPORT_SYMBOL(security_tun_dev_alloc_security);
  */
 void security_tun_dev_free_security(void *security)
 {
-       call_void_hook(tun_dev_free_security, security);
+       kfree(security);
 }
 EXPORT_SYMBOL(security_tun_dev_free_security);
 
index 7dbf169f733fddf07e35d189c43ccee90f08511c..793cfdc4c0ef51e0c1fccf5acc4f5e49a1aa3343 100644 (file)
@@ -5578,24 +5578,14 @@ static void selinux_req_classify_flow(const struct request_sock *req,
        flic->flowic_secid = req->secid;
 }
 
-static int selinux_tun_dev_alloc_security(void **security)
+static int selinux_tun_dev_alloc_security(void *security)
 {
-       struct tun_security_struct *tunsec;
+       struct tun_security_struct *tunsec = selinux_tun_dev(security);
 
-       tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
-       if (!tunsec)
-               return -ENOMEM;
        tunsec->sid = current_sid();
-
-       *security = tunsec;
        return 0;
 }
 
-static void selinux_tun_dev_free_security(void *security)
-{
-       kfree(security);
-}
-
 static int selinux_tun_dev_create(void)
 {
        u32 sid = current_sid();
@@ -5613,7 +5603,7 @@ static int selinux_tun_dev_create(void)
 
 static int selinux_tun_dev_attach_queue(void *security)
 {
-       struct tun_security_struct *tunsec = security;
+       struct tun_security_struct *tunsec = selinux_tun_dev(security);
 
        return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
                            TUN_SOCKET__ATTACH_QUEUE, NULL);
@@ -5621,7 +5611,7 @@ static int selinux_tun_dev_attach_queue(void *security)
 
 static int selinux_tun_dev_attach(struct sock *sk, void *security)
 {
-       struct tun_security_struct *tunsec = security;
+       struct tun_security_struct *tunsec = selinux_tun_dev(security);
        struct sk_security_struct *sksec = selinux_sock(sk);
 
        /* we don't currently perform any NetLabel based labeling here and it
@@ -5639,7 +5629,7 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
 
 static int selinux_tun_dev_open(void *security)
 {
-       struct tun_security_struct *tunsec = security;
+       struct tun_security_struct *tunsec = selinux_tun_dev(security);
        u32 sid = current_sid();
        int err;
 
@@ -6978,6 +6968,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
        .lbs_sock = sizeof(struct sk_security_struct),
        .lbs_superblock = sizeof(struct superblock_security_struct),
        .lbs_xattr_count = SELINUX_INODE_INIT_XATTRS,
+       .lbs_tun_dev = sizeof(struct tun_security_struct),
 };
 
 #ifdef CONFIG_PERF_EVENTS
@@ -7289,7 +7280,6 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
        LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
        LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
-       LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
        LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
        LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
        LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
index 83b9443d6919034d7cad7a9d725108236be3a724..b7d4b1fc8feec4c979ec37b413d8682c200608c3 100644 (file)
@@ -207,4 +207,9 @@ static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
        return sock->sk_security + selinux_blob_sizes.lbs_sock;
 }
 
+static inline struct tun_security_struct *selinux_tun_dev(void *security)
+{
+       return security + selinux_blob_sizes.lbs_tun_dev;
+}
+
 #endif /* _SELINUX_OBJSEC_H_ */