public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: "Zack Weinberg" <zack@owlfolio.org>
To: "GNU libc development" <libc-alpha@sourceware.org>
Subject: Re: [PATCH] sockaddr.3type: BUGS: Document that libc should be fixed using a union
Date: Mon, 06 Feb 2023 12:21:03 -0500	[thread overview]
Message-ID: <6de0523f-623b-49ed-af84-1f8e026f6244@app.fastmail.com> (raw)
In-Reply-To: <9998a4eb-528b-b006-ebeb-d94816e62d82@gmail.com>

On Mon, Feb 6, 2023, at 9:11 AM, Alejandro Colomar via Libc-alpha wrote:
> On 2/6/23 14:38, Rich Felker wrote:
>> 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.
>
> Except that you may be using generic code that may use either of AF_UNIX, 
> AF_INET, and AF_INET6.  A web server may very well use all the three.

I have personally tripped over systems where struct sockaddr_un was _bigger_
than struct sockaddr_storage.  Also, AFAIK modern kernels (not just Linux)
do not actually impose a 108-byte (or whatever) limit on the length of
sun_path; application code can treat the structure definition as being

   struct sockaddr_un {
       sa_family_t sun_family;
       char sun_path[];  // C99 flexible array member
   };

as long as the `addrlen` parameter to whatever system call you're using
accurately reflects the size of the address object you passed in.  Kind
of the same as how you can make your own bigger fd_set to call select()
with, if you want.  Point being, even if sockaddr_storage is bigger than
the _default_ sockaddr_un, that still might not be big enough.

I'd also like to point out that none of these structures can change size
without breaking ABI compatibility.  In particular, namespace issues
aside, glibc _cannot_ make the definition of struct sockaddr be either

    struct sockaddr {
        sa_family_t sa_family;
    };

or

    struct sockaddr {
        union {
            // ...
            struct sockaddr_in6 in6;
        };
    };

because a variable declaration `struct sockaddr sa;` must allocate 16
bytes of space -- no more and no less.

> However, there are some APIs that require you to allocate an object.  For 
> example recvfrom(2).  How would you recommend using recvfrom(2)

Well, most address families have fixed-size addresses: if you called
socket(AF_INET6, SOCK_DGRAM, 0) then you know recvfrom on that socket
needs enough space for struct sockaddr_in6.  If you receive a socket
descriptor as an argument and you don't know its address family, you
can use `getsockopt(sock, SOL_SOCKET, SO_DOMAIN)` to look it up.

This won't work for AF_UNIX, though.  recvfrom() _will_ tell you if
you didn't give it enough space (by updating `addrlen` to a bigger
number than you passed in); it's not idempotent, so you can't call
it again, but you _could_ call getpeername() instead.  In principle
you could have a connectionless (SOCK_DGRAM) AF_UNIX socket and then
getpeername() wouldn't work, but does anyone actually _want_ the
peer address when serving from an AF_UNIX socket, as opposed to
the SCM_CREDENTIALS ancillary message or the SO_PEERCRED sockopt query?

zw

  reply	other threads:[~2023-02-06 17:21 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
2023-02-06 14:11         ` Alejandro Colomar
2023-02-06 17:21           ` Zack Weinberg [this message]
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=6de0523f-623b-49ed-af84-1f8e026f6244@app.fastmail.com \
    --to=zack@owlfolio.org \
    --cc=libc-alpha@sourceware.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).