diff mbox series

[4/6] LSM: Infrastructure management of the dev_tun blob

Message ID 20240708213957.20519-5-casey@schaufler-ca.com (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series LSM: Infrastructure blob allocation | expand

Commit Message

Casey Schaufler July 8, 2024, 9:39 p.m. UTC
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.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hook_defs.h     |  2 +-
 include/linux/lsm_hooks.h         |  1 +
 security/security.c               | 11 ++++++++++-
 security/selinux/hooks.c          | 22 ++++++----------------
 security/selinux/include/objsec.h |  6 ++++++
 5 files changed, 24 insertions(+), 18 deletions(-)

Comments

Paul Moore July 9, 2024, 10:08 p.m. UTC | #1
On Jul  8, 2024 Casey Schaufler <casey@schaufler-ca.com> wrote:
> 
> 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.
> 
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
>  include/linux/lsm_hook_defs.h     |  2 +-
>  include/linux/lsm_hooks.h         |  1 +
>  security/security.c               | 11 ++++++++++-
>  security/selinux/hooks.c          | 22 ++++++----------------
>  security/selinux/include/objsec.h |  6 ++++++
>  5 files changed, 24 insertions(+), 18 deletions(-)

...

> diff --git a/security/security.c b/security/security.c
> index 438ec6708eb3..2c9d075f5f92 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -4864,6 +4872,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);

If we removed key_free in patch 2/6, we should probably do the same
here for the same reasons.  Don't forget to mention it in the commit
description.

--
paul-moore.com
John Johansen July 9, 2024, 11:01 p.m. UTC | #2
On 7/8/24 14:39, Casey Schaufler wrote:
> 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.
> 
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

one issue below, besides Paul's point the rest of it looks good

> ---
>   include/linux/lsm_hook_defs.h     |  2 +-
>   include/linux/lsm_hooks.h         |  1 +
>   security/security.c               | 11 ++++++++++-
>   security/selinux/hooks.c          | 22 ++++++----------------
>   security/selinux/include/objsec.h |  6 ++++++
>   5 files changed, 24 insertions(+), 18 deletions(-)
> 
> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
> index 44488b1ab9a9..601e3092a7ed 100644
> --- a/include/linux/lsm_hook_defs.h
> +++ b/include/linux/lsm_hook_defs.h
> @@ -352,7 +352,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(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_create, void)
>   LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 7233bc0737be..0ff14ff128c8 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -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;
>   };
>   
>   /**
> diff --git a/security/security.c b/security/security.c
> index 438ec6708eb3..2c9d075f5f92 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -234,6 +234,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);
>   }
> @@ -412,6 +413,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);
>   
>   	/*
> @@ -4851,7 +4853,13 @@ 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;
> +
> +	return call_int_hook(tun_dev_alloc_security, *security);

we either need to free the blob here or make a change to tun_net_init.

if security_tun_dev_alloc fails it is not calling the corresponding
security_tun_dev_free_security()

>   }
>   EXPORT_SYMBOL(security_tun_dev_alloc_security);
>   
> @@ -4864,6 +4872,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);
>   
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index b3de2e941ef7..7f1d8358922a 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -5573,24 +5573,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();
> @@ -5608,7 +5598,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);
> @@ -5616,7 +5606,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
> @@ -5634,7 +5624,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;
>   
> @@ -6975,6 +6965,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
> @@ -7285,7 +7276,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),
> diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
> index 83b9443d6919..461c6985977d 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -207,4 +207,10 @@ 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_ */
Casey Schaufler July 9, 2024, 11:11 p.m. UTC | #3
On 7/9/2024 4:01 PM, John Johansen wrote:
> On 7/8/24 14:39, Casey Schaufler wrote:
>> 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.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>
> one issue below, besides Paul's point the rest of it looks good
>
>> ---
>>   include/linux/lsm_hook_defs.h     |  2 +-
>>   include/linux/lsm_hooks.h         |  1 +
>>   security/security.c               | 11 ++++++++++-
>>   security/selinux/hooks.c          | 22 ++++++----------------
>>   security/selinux/include/objsec.h |  6 ++++++
>>   5 files changed, 24 insertions(+), 18 deletions(-)
>>
>> diff --git a/include/linux/lsm_hook_defs.h
>> b/include/linux/lsm_hook_defs.h
>> index 44488b1ab9a9..601e3092a7ed 100644
>> --- a/include/linux/lsm_hook_defs.h
>> +++ b/include/linux/lsm_hook_defs.h
>> @@ -352,7 +352,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(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_create, void)
>>   LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>> index 7233bc0737be..0ff14ff128c8 100644
>> --- a/include/linux/lsm_hooks.h
>> +++ b/include/linux/lsm_hooks.h
>> @@ -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;
>>   };
>>     /**
>> diff --git a/security/security.c b/security/security.c
>> index 438ec6708eb3..2c9d075f5f92 100644
>> --- a/security/security.c
>> +++ b/security/security.c
>> @@ -234,6 +234,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);
>>   }
>> @@ -412,6 +413,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);
>>         /*
>> @@ -4851,7 +4853,13 @@ 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;
>> +
>> +    return call_int_hook(tun_dev_alloc_security, *security);
>
> we either need to free the blob here or make a change to tun_net_init.
>
> if security_tun_dev_alloc fails it is not calling the corresponding
> security_tun_dev_free_security()

Yes indeed, I missed that one. Fix in v2.

>
>>   }
>>   EXPORT_SYMBOL(security_tun_dev_alloc_security);
>>   @@ -4864,6 +4872,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);
>>   diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index b3de2e941ef7..7f1d8358922a 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -5573,24 +5573,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();
>> @@ -5608,7 +5598,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);
>> @@ -5616,7 +5606,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
>> @@ -5634,7 +5624,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;
>>   @@ -6975,6 +6965,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
>> @@ -7285,7 +7276,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),
>> diff --git a/security/selinux/include/objsec.h
>> b/security/selinux/include/objsec.h
>> index 83b9443d6919..461c6985977d 100644
>> --- a/security/selinux/include/objsec.h
>> +++ b/security/selinux/include/objsec.h
>> @@ -207,4 +207,10 @@ 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_ */
>
>
diff mbox series

Patch

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 44488b1ab9a9..601e3092a7ed 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -352,7 +352,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(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_create, void)
 LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7233bc0737be..0ff14ff128c8 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -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;
 };
 
 /**
diff --git a/security/security.c b/security/security.c
index 438ec6708eb3..2c9d075f5f92 100644
--- a/security/security.c
+++ b/security/security.c
@@ -234,6 +234,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);
 }
@@ -412,6 +413,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);
 
 	/*
@@ -4851,7 +4853,13 @@  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;
+
+	return call_int_hook(tun_dev_alloc_security, *security);
 }
 EXPORT_SYMBOL(security_tun_dev_alloc_security);
 
@@ -4864,6 +4872,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);
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b3de2e941ef7..7f1d8358922a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5573,24 +5573,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();
@@ -5608,7 +5598,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);
@@ -5616,7 +5606,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
@@ -5634,7 +5624,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;
 
@@ -6975,6 +6965,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
@@ -7285,7 +7276,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),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 83b9443d6919..461c6985977d 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -207,4 +207,10 @@  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_ */