All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
@ 2024-12-12 10:20 Mikhail Ivanov
  2024-12-12 17:50 ` Mickaël Salaün
  2025-01-07 20:13 ` Stephen Smalley
  0 siblings, 2 replies; 11+ messages in thread
From: Mikhail Ivanov @ 2024-12-12 10:20 UTC (permalink / raw)
  To: paul
  Cc: mic, selinux, stephen.smalley.work, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

selinux_socket_bind() is called without holding the socket lock.

Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].

[1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
---
 security/selinux/hooks.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5e5f3398f39d..b7adff2cf5f6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 	if (err)
 		goto out;
 
+	/* IPV6_ADDRFORM can change sk->sk_family under us. */
+	family = READ_ONCE(sk->sk_family);
+
 	/* If PF_INET or PF_INET6, check name_bind permission for the port. */
-	family = sk->sk_family;
 	if (family == PF_INET || family == PF_INET6) {
 		char *addrp;
 		struct common_audit_data ad;

base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-12 10:20 [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind() Mikhail Ivanov
@ 2024-12-12 17:50 ` Mickaël Salaün
  2024-12-13 10:57   ` Mikhail Ivanov
  2025-01-07 20:13 ` Stephen Smalley
  1 sibling, 1 reply; 11+ messages in thread
From: Mickaël Salaün @ 2024-12-12 17:50 UTC (permalink / raw)
  To: Mikhail Ivanov
  Cc: paul, selinux, stephen.smalley.work, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

This looks good be there are other places using sk->sk_family that
should also be fixed.

On Thu, Dec 12, 2024 at 06:20:00PM +0800, Mikhail Ivanov wrote:
> selinux_socket_bind() is called without holding the socket lock.
> 
> Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
> of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].
> 
> [1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
> ---
>  security/selinux/hooks.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 5e5f3398f39d..b7adff2cf5f6 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>  	if (err)
>  		goto out;
>  
> +	/* IPV6_ADDRFORM can change sk->sk_family under us. */
> +	family = READ_ONCE(sk->sk_family);
> +
>  	/* If PF_INET or PF_INET6, check name_bind permission for the port. */
> -	family = sk->sk_family;
>  	if (family == PF_INET || family == PF_INET6) {
>  		char *addrp;
>  		struct common_audit_data ad;
> 
> base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
> -- 
> 2.34.1
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-12 17:50 ` Mickaël Salaün
@ 2024-12-13 10:57   ` Mikhail Ivanov
  2024-12-13 15:46     ` Stephen Smalley
  0 siblings, 1 reply; 11+ messages in thread
From: Mikhail Ivanov @ 2024-12-13 10:57 UTC (permalink / raw)
  To: Mickaël Salaün
  Cc: paul, selinux, stephen.smalley.work, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> This looks good be there are other places using sk->sk_family that
> should also be fixed.

Thanks for checking this!

For selinux this should be enough, I haven't found any other places
where sk->sk_family could be read from an IPv6 socket without locking.

I also would like to prepare such fix for other LSMs (apparmor, smack,
tomoyo) (in separate patches).

> 
> On Thu, Dec 12, 2024 at 06:20:00PM +0800, Mikhail Ivanov wrote:
>> selinux_socket_bind() is called without holding the socket lock.
>>
>> Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
>> of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].
>>
>> [1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/
>>
>> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
>> Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
>> ---
>>   security/selinux/hooks.c | 4 +++-
>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index 5e5f3398f39d..b7adff2cf5f6 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>>   	if (err)
>>   		goto out;
>>   
>> +	/* IPV6_ADDRFORM can change sk->sk_family under us. */
>> +	family = READ_ONCE(sk->sk_family);
>> +
>>   	/* If PF_INET or PF_INET6, check name_bind permission for the port. */
>> -	family = sk->sk_family;
>>   	if (family == PF_INET || family == PF_INET6) {
>>   		char *addrp;
>>   		struct common_audit_data ad;
>>
>> base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
>> -- 
>> 2.34.1
>>
>>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-13 10:57   ` Mikhail Ivanov
@ 2024-12-13 15:46     ` Stephen Smalley
  2024-12-13 16:40       ` Mikhail Ivanov
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen Smalley @ 2024-12-13 15:46 UTC (permalink / raw)
  To: Mikhail Ivanov
  Cc: Mickaël Salaün, paul, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
<ivanov.mikhail1@huawei-partners.com> wrote:
>
> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> > This looks good be there are other places using sk->sk_family that
> > should also be fixed.
>
> Thanks for checking this!
>
> For selinux this should be enough, I haven't found any other places
> where sk->sk_family could be read from an IPv6 socket without locking.
>
> I also would like to prepare such fix for other LSMs (apparmor, smack,
> tomoyo) (in separate patches).

I'm wondering about the implications for SELinux beyond just
sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
triple to a security class at socket creation time via
socket_type_to_security_class() and caches the security class in the
inode_security_struct and sk_security_struct for later use.

>
> >
> > On Thu, Dec 12, 2024 at 06:20:00PM +0800, Mikhail Ivanov wrote:
> >> selinux_socket_bind() is called without holding the socket lock.
> >>
> >> Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
> >> of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].
> >>
> >> [1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/
> >>
> >> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> >> Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
> >> ---
> >>   security/selinux/hooks.c | 4 +++-
> >>   1 file changed, 3 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >> index 5e5f3398f39d..b7adff2cf5f6 100644
> >> --- a/security/selinux/hooks.c
> >> +++ b/security/selinux/hooks.c
> >> @@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
> >>      if (err)
> >>              goto out;
> >>
> >> +    /* IPV6_ADDRFORM can change sk->sk_family under us. */
> >> +    family = READ_ONCE(sk->sk_family);
> >> +
> >>      /* If PF_INET or PF_INET6, check name_bind permission for the port. */
> >> -    family = sk->sk_family;
> >>      if (family == PF_INET || family == PF_INET6) {
> >>              char *addrp;
> >>              struct common_audit_data ad;
> >>
> >> base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
> >> --
> >> 2.34.1
> >>
> >>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-13 15:46     ` Stephen Smalley
@ 2024-12-13 16:40       ` Mikhail Ivanov
  2024-12-13 19:12         ` Stephen Smalley
  2024-12-13 20:09         ` Paul Moore
  0 siblings, 2 replies; 11+ messages in thread
From: Mikhail Ivanov @ 2024-12-13 16:40 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Mickaël Salaün, paul, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On 12/13/2024 6:46 PM, Stephen Smalley wrote:
> On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
> <ivanov.mikhail1@huawei-partners.com> wrote:
>>
>> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
>>> This looks good be there are other places using sk->sk_family that
>>> should also be fixed.
>>
>> Thanks for checking this!
>>
>> For selinux this should be enough, I haven't found any other places
>> where sk->sk_family could be read from an IPv6 socket without locking.
>>
>> I also would like to prepare such fix for other LSMs (apparmor, smack,
>> tomoyo) (in separate patches).
> 
> I'm wondering about the implications for SELinux beyond just
> sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
> triple to a security class at socket creation time via
> socket_type_to_security_class() and caches the security class in the
> inode_security_struct and sk_security_struct for later use.

IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
security class. AFAICS there is no other places that can be affected by
the IPV6_ADDFORM transformation.

> 
>>
>>>
>>> On Thu, Dec 12, 2024 at 06:20:00PM +0800, Mikhail Ivanov wrote:
>>>> selinux_socket_bind() is called without holding the socket lock.
>>>>
>>>> Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
>>>> of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].
>>>>
>>>> [1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/
>>>>
>>>> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
>>>> Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
>>>> ---
>>>>    security/selinux/hooks.c | 4 +++-
>>>>    1 file changed, 3 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>> index 5e5f3398f39d..b7adff2cf5f6 100644
>>>> --- a/security/selinux/hooks.c
>>>> +++ b/security/selinux/hooks.c
>>>> @@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>>>>       if (err)
>>>>               goto out;
>>>>
>>>> +    /* IPV6_ADDRFORM can change sk->sk_family under us. */
>>>> +    family = READ_ONCE(sk->sk_family);
>>>> +
>>>>       /* If PF_INET or PF_INET6, check name_bind permission for the port. */
>>>> -    family = sk->sk_family;
>>>>       if (family == PF_INET || family == PF_INET6) {
>>>>               char *addrp;
>>>>               struct common_audit_data ad;
>>>>
>>>> base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
>>>> --
>>>> 2.34.1
>>>>
>>>>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-13 16:40       ` Mikhail Ivanov
@ 2024-12-13 19:12         ` Stephen Smalley
  2024-12-13 20:09         ` Paul Moore
  1 sibling, 0 replies; 11+ messages in thread
From: Stephen Smalley @ 2024-12-13 19:12 UTC (permalink / raw)
  To: Mikhail Ivanov
  Cc: Mickaël Salaün, paul, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On Fri, Dec 13, 2024 at 11:40 AM Mikhail Ivanov
<ivanov.mikhail1@huawei-partners.com> wrote:
>
> On 12/13/2024 6:46 PM, Stephen Smalley wrote:
> > On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
> > <ivanov.mikhail1@huawei-partners.com> wrote:
> >>
> >> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> >>> This looks good be there are other places using sk->sk_family that
> >>> should also be fixed.
> >>
> >> Thanks for checking this!
> >>
> >> For selinux this should be enough, I haven't found any other places
> >> where sk->sk_family could be read from an IPv6 socket without locking.
> >>
> >> I also would like to prepare such fix for other LSMs (apparmor, smack,
> >> tomoyo) (in separate patches).
> >
> > I'm wondering about the implications for SELinux beyond just
> > sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
> > triple to a security class at socket creation time via
> > socket_type_to_security_class() and caches the security class in the
> > inode_security_struct and sk_security_struct for later use.
>
> IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
> security class. AFAICS there is no other places that can be affected by
> the IPV6_ADDFORM transformation.

Great, thank you for checking!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-13 16:40       ` Mikhail Ivanov
  2024-12-13 19:12         ` Stephen Smalley
@ 2024-12-13 20:09         ` Paul Moore
  2025-01-07 20:16           ` Stephen Smalley
  1 sibling, 1 reply; 11+ messages in thread
From: Paul Moore @ 2024-12-13 20:09 UTC (permalink / raw)
  To: Mikhail Ivanov
  Cc: Stephen Smalley, Mickaël Salaün, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On Fri, Dec 13, 2024 at 11:40 AM Mikhail Ivanov
<ivanov.mikhail1@huawei-partners.com> wrote:
> On 12/13/2024 6:46 PM, Stephen Smalley wrote:
> > On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
> > <ivanov.mikhail1@huawei-partners.com> wrote:
> >>
> >> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> >>> This looks good be there are other places using sk->sk_family that
> >>> should also be fixed.
> >>
> >> Thanks for checking this!
> >>
> >> For selinux this should be enough, I haven't found any other places
> >> where sk->sk_family could be read from an IPv6 socket without locking.
> >>
> >> I also would like to prepare such fix for other LSMs (apparmor, smack,
> >> tomoyo) (in separate patches).
> >
> > I'm wondering about the implications for SELinux beyond just
> > sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
> > triple to a security class at socket creation time via
> > socket_type_to_security_class() and caches the security class in the
> > inode_security_struct and sk_security_struct for later use.
>
> IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
> security class. AFAICS there is no other places that can be affected by
> the IPV6_ADDFORM transformation.

Yes, thankfully we don't really encode the IP address family in any of
the SELinux object classes so that shouldn't be an issue.  I also
don't think we have to worry about the per-packet labeling protocols
as it's too late in the communication to change the socket's
associated packet labeling, it's either working or it isn't; we should
handle the mapped IPv4 address already.

I am a little concerned about bind being the only place where we have
to worry about accessing sk_family while the socket isn't locked.  As
an example, I'm a little concerned about the netfilter code paths; I
haven't chased them down, but my guess is that the associated
socket/sock isn't locked in those cases (in the relevant output and
postroute cases, forward should be a non-issue).

How bad is the performance impact of READ_ONCE()?  In other words, how
stupid would it be to simply do all of our sock->sk_family lookups
using READ_ONCE()?

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-12 10:20 [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind() Mikhail Ivanov
  2024-12-12 17:50 ` Mickaël Salaün
@ 2025-01-07 20:13 ` Stephen Smalley
  1 sibling, 0 replies; 11+ messages in thread
From: Stephen Smalley @ 2025-01-07 20:13 UTC (permalink / raw)
  To: Mikhail Ivanov
  Cc: paul, mic, selinux, omosnace, linux-security-module, netdev,
	yusongping, artem.kuzin, konstantin.meskhidze

On Thu, Dec 12, 2024 at 5:20 AM Mikhail Ivanov
<ivanov.mikhail1@huawei-partners.com> wrote:
>
> selinux_socket_bind() is called without holding the socket lock.
>
> Use READ_ONCE() to safely read sk->sk_family for IPv6 socket in case
> of lockless transformation to IPv4 socket via IPV6_ADDRFORM [1].
>
> [1] https://lore.kernel.org/all/20240202095404.183274-1-edumazet@google.com/
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

> ---
>  security/selinux/hooks.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 5e5f3398f39d..b7adff2cf5f6 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4715,8 +4715,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>         if (err)
>                 goto out;
>
> +       /* IPV6_ADDRFORM can change sk->sk_family under us. */
> +       family = READ_ONCE(sk->sk_family);
> +
>         /* If PF_INET or PF_INET6, check name_bind permission for the port. */
> -       family = sk->sk_family;
>         if (family == PF_INET || family == PF_INET6) {
>                 char *addrp;
>                 struct common_audit_data ad;
>
> base-commit: 034294fbfdf0ded4f931f9503d2ca5bbf8b9aebd
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2024-12-13 20:09         ` Paul Moore
@ 2025-01-07 20:16           ` Stephen Smalley
  2025-01-07 21:00             ` Paul Moore
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen Smalley @ 2025-01-07 20:16 UTC (permalink / raw)
  To: Paul Moore
  Cc: Mikhail Ivanov, Mickaël Salaün, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On Fri, Dec 13, 2024 at 3:09 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Fri, Dec 13, 2024 at 11:40 AM Mikhail Ivanov
> <ivanov.mikhail1@huawei-partners.com> wrote:
> > On 12/13/2024 6:46 PM, Stephen Smalley wrote:
> > > On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
> > > <ivanov.mikhail1@huawei-partners.com> wrote:
> > >>
> > >> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> > >>> This looks good be there are other places using sk->sk_family that
> > >>> should also be fixed.
> > >>
> > >> Thanks for checking this!
> > >>
> > >> For selinux this should be enough, I haven't found any other places
> > >> where sk->sk_family could be read from an IPv6 socket without locking.
> > >>
> > >> I also would like to prepare such fix for other LSMs (apparmor, smack,
> > >> tomoyo) (in separate patches).
> > >
> > > I'm wondering about the implications for SELinux beyond just
> > > sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
> > > triple to a security class at socket creation time via
> > > socket_type_to_security_class() and caches the security class in the
> > > inode_security_struct and sk_security_struct for later use.
> >
> > IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
> > security class. AFAICS there is no other places that can be affected by
> > the IPV6_ADDFORM transformation.
>
> Yes, thankfully we don't really encode the IP address family in any of
> the SELinux object classes so that shouldn't be an issue.  I also
> don't think we have to worry about the per-packet labeling protocols
> as it's too late in the communication to change the socket's
> associated packet labeling, it's either working or it isn't; we should
> handle the mapped IPv4 address already.
>
> I am a little concerned about bind being the only place where we have
> to worry about accessing sk_family while the socket isn't locked.  As
> an example, I'm a little concerned about the netfilter code paths; I
> haven't chased them down, but my guess is that the associated
> socket/sock isn't locked in those cases (in the relevant output and
> postroute cases, forward should be a non-issue).
>
> How bad is the performance impact of READ_ONCE()?  In other words, how
> stupid would it be to simply do all of our sock->sk_family lookups
> using READ_ONCE()?

I could be wrong, but I don't think there is any overhead except on Dec Alpha.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2025-01-07 20:16           ` Stephen Smalley
@ 2025-01-07 21:00             ` Paul Moore
  2025-01-09 16:28               ` Mikhail Ivanov
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Moore @ 2025-01-07 21:00 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Mikhail Ivanov, Mickaël Salaün, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On Tue, Jan 7, 2025 at 3:16 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Fri, Dec 13, 2024 at 3:09 PM Paul Moore <paul@paul-moore.com> wrote:
> > On Fri, Dec 13, 2024 at 11:40 AM Mikhail Ivanov
> > <ivanov.mikhail1@huawei-partners.com> wrote:
> > > On 12/13/2024 6:46 PM, Stephen Smalley wrote:
> > > > On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
> > > > <ivanov.mikhail1@huawei-partners.com> wrote:
> > > >>
> > > >> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
> > > >>> This looks good be there are other places using sk->sk_family that
> > > >>> should also be fixed.
> > > >>
> > > >> Thanks for checking this!
> > > >>
> > > >> For selinux this should be enough, I haven't found any other places
> > > >> where sk->sk_family could be read from an IPv6 socket without locking.
> > > >>
> > > >> I also would like to prepare such fix for other LSMs (apparmor, smack,
> > > >> tomoyo) (in separate patches).
> > > >
> > > > I'm wondering about the implications for SELinux beyond just
> > > > sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
> > > > triple to a security class at socket creation time via
> > > > socket_type_to_security_class() and caches the security class in the
> > > > inode_security_struct and sk_security_struct for later use.
> > >
> > > IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
> > > security class. AFAICS there is no other places that can be affected by
> > > the IPV6_ADDFORM transformation.
> >
> > Yes, thankfully we don't really encode the IP address family in any of
> > the SELinux object classes so that shouldn't be an issue.  I also
> > don't think we have to worry about the per-packet labeling protocols
> > as it's too late in the communication to change the socket's
> > associated packet labeling, it's either working or it isn't; we should
> > handle the mapped IPv4 address already.
> >
> > I am a little concerned about bind being the only place where we have
> > to worry about accessing sk_family while the socket isn't locked.  As
> > an example, I'm a little concerned about the netfilter code paths; I
> > haven't chased them down, but my guess is that the associated
> > socket/sock isn't locked in those cases (in the relevant output and
> > postroute cases, forward should be a non-issue).

We still need an answer on this.

> > How bad is the performance impact of READ_ONCE()?  In other words, how
> > stupid would it be to simply do all of our sock->sk_family lookups
> > using READ_ONCE()?
>
> I could be wrong, but I don't think there is any overhead except on Dec Alpha.

Then perhaps the right answer is to use it everywhere.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind()
  2025-01-07 21:00             ` Paul Moore
@ 2025-01-09 16:28               ` Mikhail Ivanov
  0 siblings, 0 replies; 11+ messages in thread
From: Mikhail Ivanov @ 2025-01-09 16:28 UTC (permalink / raw)
  To: Paul Moore, Stephen Smalley
  Cc: Mickaël Salaün, selinux, omosnace,
	linux-security-module, netdev, yusongping, artem.kuzin,
	konstantin.meskhidze

On 1/8/2025 12:00 AM, Paul Moore wrote:
> On Tue, Jan 7, 2025 at 3:16 PM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
>> On Fri, Dec 13, 2024 at 3:09 PM Paul Moore <paul@paul-moore.com> wrote:
>>> On Fri, Dec 13, 2024 at 11:40 AM Mikhail Ivanov
>>> <ivanov.mikhail1@huawei-partners.com> wrote:
>>>> On 12/13/2024 6:46 PM, Stephen Smalley wrote:
>>>>> On Fri, Dec 13, 2024 at 5:57 AM Mikhail Ivanov
>>>>> <ivanov.mikhail1@huawei-partners.com> wrote:
>>>>>>
>>>>>> On 12/12/2024 8:50 PM, Mickaël Salaün wrote:
>>>>>>> This looks good be there are other places using sk->sk_family that
>>>>>>> should also be fixed.
>>>>>>
>>>>>> Thanks for checking this!
>>>>>>
>>>>>> For selinux this should be enough, I haven't found any other places
>>>>>> where sk->sk_family could be read from an IPv6 socket without locking.
>>>>>>
>>>>>> I also would like to prepare such fix for other LSMs (apparmor, smack,
>>>>>> tomoyo) (in separate patches).
>>>>>
>>>>> I'm wondering about the implications for SELinux beyond just
>>>>> sk->sk_family access, e.g. SELinux maps the (family, type, protocol)
>>>>> triple to a security class at socket creation time via
>>>>> socket_type_to_security_class() and caches the security class in the
>>>>> inode_security_struct and sk_security_struct for later use.
>>>>
>>>> IPv6 and IPv4 TCP sockets are mapped to the same SECCLASS_TCP_SOCKET
>>>> security class. AFAICS there is no other places that can be affected by
>>>> the IPV6_ADDFORM transformation.
>>>
>>> Yes, thankfully we don't really encode the IP address family in any of
>>> the SELinux object classes so that shouldn't be an issue.  I also
>>> don't think we have to worry about the per-packet labeling protocols
>>> as it's too late in the communication to change the socket's
>>> associated packet labeling, it's either working or it isn't; we should
>>> handle the mapped IPv4 address already.
>>>
>>> I am a little concerned about bind being the only place where we have
>>> to worry about accessing sk_family while the socket isn't locked.  As
>>> an example, I'm a little concerned about the netfilter code paths; I
>>> haven't chased them down, but my guess is that the associated
>>> socket/sock isn't locked in those cases (in the relevant output and
>>> postroute cases, forward should be a non-issue).
> 
> We still need an answer on this.

Sorry for the late reply,
I found out that security_sock_rcv_skb() can also be called without
locking the IPv6 socket (this can be easily verified by manual testing).

Netfilter hooks seems to be ok, family value is taken from the
nf_hook_state structure, so there is no access to sk->sk_family.

SCTP and MPTCP hooks should not be considered, because IPV6_ADDRFORM is
only available for TCP, UDP and UDPLITE protocols.

There are 2 more functions that access sk_family:
* security_sock_graft() - socket is locked by inet_accept(),
* security_inet_conn_established() - socket is locked by connect(2) or
   in BH context (Cf. tcp_v6_rcv).

> 
>>> How bad is the performance impact of READ_ONCE()?  In other words, how
>>> stupid would it be to simply do all of our sock->sk_family lookups
>>> using READ_ONCE()?
>>
>> I could be wrong, but I don't think there is any overhead except on Dec Alpha.
> 
> Then perhaps the right answer is to use it everywhere.
> 

Indeed, using READ_ONCE() in the considered hooks should not lead to
any overhead. I wonder if it would be better not to touch the SCTP
and MPTCP hooks anyway. Adding READ_ONCE() in selinux_sock_graft() is
fine if you think it's better this way.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-01-09 16:28 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-12 10:20 [PATCH] selinux: Read sk->sk_family once in selinux_socket_bind() Mikhail Ivanov
2024-12-12 17:50 ` Mickaël Salaün
2024-12-13 10:57   ` Mikhail Ivanov
2024-12-13 15:46     ` Stephen Smalley
2024-12-13 16:40       ` Mikhail Ivanov
2024-12-13 19:12         ` Stephen Smalley
2024-12-13 20:09         ` Paul Moore
2025-01-07 20:16           ` Stephen Smalley
2025-01-07 21:00             ` Paul Moore
2025-01-09 16:28               ` Mikhail Ivanov
2025-01-07 20:13 ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.