public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Rich Felker <dalias@libc.org>
To: Alejandro Colomar <alx.manpages@gmail.com>
Cc: "Xi Ruoyao" <xry111@xry111.site>,
	linux-man@vger.kernel.org, "Alejandro Colomar" <alx@kernel.org>,
	GCC <gcc@gcc.gnu.org>, glibc <libc-alpha@sourceware.org>,
	"Bastien Roucariès" <rouca@debian.org>,
	"Stefan Puiu" <stefan.puiu@gmail.com>,
	"Igor Sysoev" <igor@sysoev.ru>,
	"Andrew Clayton" <a.clayton@nginx.com>,
	"Richard Biener" <richard.guenther@gmail.com>,
	"Zack Weinberg" <zack@owlfolio.org>,
	"Florian Weimer" <fweimer@redhat.com>,
	"Joseph Myers" <joseph@codesourcery.com>,
	"Jakub Jelinek" <jakub@redhat.com>,
	"Eric Blake" <eblake@redhat.com>
Subject: Re: [PATCH] sockaddr.3type: BUGS: Document that libc should be fixed using a union
Date: Mon, 6 Feb 2023 08:38:50 -0500	[thread overview]
Message-ID: <20230206133850.GI3298@brightrain.aerifal.cx> (raw)
In-Reply-To: <ae73337b-7b37-9c94-e5e0-d6ebbf2c7ffb@gmail.com>

On Mon, Feb 06, 2023 at 12:55:12PM +0100, Alejandro Colomar wrote:
> Hi Xi,
> 
> On 2/6/23 07:02, Xi Ruoyao wrote:
> >On Sun, 2023-02-05 at 16:31 +0100, Alejandro Colomar via Libc-alpha wrote:
> >
> >>The only correct way to use  different  types  in  an  API  is
> >>through  a  union.
> >
> >I don't think this statement is true (in general).  Technically we can
> >write something like this:
> >
> >struct sockaddr { ... };
> >struct sockaddr_in { ... };
> >struct sockaddr_in6 { ... };
> >
> >int bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
> >{
> >     if (addrlen < sizeof(struct sockaddr) {
> >         errno = EINVAL;
> >         return -1;
> >     }
> >
> >     /* cannot use "addr->sa_family" directly: it will be an UB */
> >     sa_family_t sa_family;
> >     memcpy(&sa_family, addr, sizeof(sa_family));
> >
> >     switch (sa_family) {
> >         case AF_INET:
> >             return _do_bind_in(fd, (struct sockaddr_in *)addr, addrlen);
> >         case AF_INET6:
> >             return _do_bind_in6(fd, (struct sockaddr_in6 *)addr, addrlen);
> >         /* more cases follow here */
> >         default:
> >             errno = EINVAL;
> >             return -1;
> >         }
> >     }
> >}
> >
> >In this way we can use sockaddr_{in,in6,...} for bind() safely, as long
> >as we can distinguish the "real" type of addr using the leading byte
> >sequence (and the caller uses it carefully).
> 
> True; I hadn't thought of memcpy()ing the first member of the
> struct.  That's valid; overcomplicated but valid.
> 
> >
> >But obviously sockaddr_storage can't be distinguished here, so casting a
> >struct sockaddr_stroage * to struct sockaddr * and passing it to bind()
> >will still be wrong (unless we make sockaddr_storage an union or add
> >[[gnu::may_alias]]).
> 
> But as you say, it still leaves us with a question.  What should one
> declare for passing to the standard APIs?  It can only be a union.
> So we can either tell users to each create their own union, or we
> can make sockaddr_storage be a union.  The latter slightly violates
> POSIX due to namespaces as Rich noted, but that's a minor violation,
> and POSIX can be changed to accomodate for that.

There is absolutely not any need to declare the union for application
code calling the socket APIs. You declare whatever type you will be
using. For binding or connecting a unix socket, sockaddr_un. For IPv6,
sockaddr_in6. Etc. Then you cast the pointer to struct sockaddr * and
pass it to the function.

But normally you don't use declared-type objects for this anyway. You
use the struct sockaddr * obtained from getaddrinfo as an abstract
pointer and never dereference it at all.

> If we change sockaddr_storage to be a union, we have two benefits:
> 
> -  Old code which uses sockaddr_storage is made conforming (non-UB)
> without modifying the source.

It's not conforming. It's just no longer UB as a result of unspecified
implementation choices you'd be making.

> -  Users can inspect the structures.
> 
> If we don't, and deprecate sockaddr_storage, we should tell users to
> declare their own unions _and_ treat all these structures as black
> boxes which can only be read by memcpy()ing their contents.

No, there is no need to tell users to do any such thing. No action is
needed here except for folks to stop using sockaddr_storage.

Rich

  reply	other threads:[~2023-02-06 13:38 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-05 15:28 Alejandro Colomar
2023-02-05 15:31 ` Alejandro Colomar
2023-02-06  6:02   ` Xi Ruoyao
2023-02-06 11:20     ` Rich Felker
2023-02-06 11:55     ` Alejandro Colomar
2023-02-06 13:38       ` Rich Felker [this message]
2023-02-06 14:11         ` Alejandro Colomar
2023-02-06 17:21           ` Zack Weinberg
2023-02-06 17:48           ` Rich Felker
2023-02-05 23:43 ` Rich Felker
2023-02-05 23:59   ` Alejandro Colomar
2023-02-06  0:15     ` Rich Felker
2023-02-06 18:45 ` Eric Blake
2023-02-07  1:21   ` Alejandro Colomar
2023-03-18  7:54   ` roucaries bastien
2023-03-20 10:49     ` Alejandro Colomar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230206133850.GI3298@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=a.clayton@nginx.com \
    --cc=alx.manpages@gmail.com \
    --cc=alx@kernel.org \
    --cc=eblake@redhat.com \
    --cc=fweimer@redhat.com \
    --cc=gcc@gcc.gnu.org \
    --cc=igor@sysoev.ru \
    --cc=jakub@redhat.com \
    --cc=joseph@codesourcery.com \
    --cc=libc-alpha@sourceware.org \
    --cc=linux-man@vger.kernel.org \
    --cc=richard.guenther@gmail.com \
    --cc=rouca@debian.org \
    --cc=stefan.puiu@gmail.com \
    --cc=xry111@xry111.site \
    --cc=zack@owlfolio.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).