Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Oct 2022 13:48:27 +0300
From:      Andriy Gapon <avg@FreeBSD.org>
To:        "net@FreeBSD.org" <net@FreeBSD.org>, FreeBSD Current <current@FreeBSD.org>
Subject:   UDP port re-use [Was: in_pcbbind_setup: wrong condition regarding INP_REUSEPORT ?]
Message-ID:  <be1e64bf-458a-76a0-4b9b-4b2d9e8addc1@FreeBSD.org>
In-Reply-To: <9037ac3d-8d8e-2d7d-cbdb-996a53613aca@FreeBSD.org>
References:  <ef09313c-14f4-01bc-b9c8-043f1c0ee830@FreeBSD.org> <896ee089-27ad-c98f-6bf9-4b05caf778fd@freebsd.org> <9037ac3d-8d8e-2d7d-cbdb-996a53613aca@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Do we have test cases or a document that can be a definitive guide to UDP port 
re-use on FreeBSD?
Including effects of INP_REUSEADDR, INP_REUSEPORT and INP_REUSEPORT_LB socket 
options, socket addresses, socket credentials?
I can find some descriptions on the internet, but they do not seem to be 
complete.  The effect of addresses is under-described and I do not see any 
mention of credentials (UIDs).

Is there a way to tell if some behavior is correct or not?
Is it all in heads of people and in the change history?

On 04/10/2022 14:46, Andriy Gapon wrote:
> On 04/10/2022 14:37, Sean Bruno wrote:
>>
>>
>> On 10/3/22 04:14, Andriy Gapon wrote:
>>>
>>> I must admit that the condition in question is fairly long and non-trivial 
>>> and I cannot decipher it, but these two lines look wrong to me:
>>>
>>>                                       (t->inp_flags2 & INP_REUSEPORT) ||
>>>                                       (t->inp_flags2 & INP_REUSEPORT_LB) == 
>>> 0) &&
>>>
>>> I'd expect that the check would be symmetric with respect to INP_REUSEPORT 
>>> and INP_REUSEPORT_LB.
>>> The problem seems to come from 1a43cff92a20d / r334719 / D11003.
>>>
>>
>> I think you are pointing at this absurd conditional?
>>
>> https://cgit.freebsd.org/src/tree/sys/netinet/in_pcb.c#n1049
>>
>> Besides the twisted logic, what problem are you trying to solve?
> 
> Yes, that conditional.
> I pointed out the part of it that does not make sense to me.
> 
> Also, in my tests SO_REUSEPORT does not actually allow to share a port.
> Test scenario:
> - create a UDP socket
> - setsockopt(SO_REUSEPORT)
> - bind the socket to a port and wild card address
> - success
> - now repeat the previous steps with the same port *under a different user id*
> - bind fails
> 
> I wonder if the following would be a correct change.
> 
> diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
> index d9247f50d32b..f5e6e3932a96 100644
> --- a/sys/netinet/in_pcb.c
> +++ b/sys/netinet/in_pcb.c
> @@ -1003,6 +1003,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, 
> in_addr_t *laddrp,
>       /*
>        * XXX
>        * This entire block sorely needs a rewrite.
> +     * And a good comment describing the rationale behind the conditions.
>        */
>                   if (t &&
>                       ((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
> @@ -1011,8 +1012,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, 
> in_addr_t *laddrp,
>                        ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
>                       (ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
>                        ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
> -                     (t->inp_flags2 & INP_REUSEPORT) ||
> -                     (t->inp_flags2 & INP_REUSEPORT_LB) == 0) &&
> +                     (t->inp_flags2 & (INP_REUSEPORT | INP_REUSEPORT_LB)) == 0) &&
>                       (inp->inp_cred->cr_uid !=
>                        t->inp_cred->cr_uid))
>                       return (EADDRINUSE);
> 

-- 
Andriy Gapon




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?be1e64bf-458a-76a0-4b9b-4b2d9e8addc1>