Bug 30293 - Socket API is not alias safe
Summary: Socket API is not alias safe
Status: RESOLVED DUPLICATE of bug 19622
Alias: None
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: 2.39
: P2 normal
Target Milestone: ---
Assignee: Florian Weimer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-03-30 17:41 UTC by Bastien Roucariès
Modified: 2024-06-13 07:40 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bastien Roucariès 2023-03-30 17:41:40 UTC
Hi,

POSIX was ammended about aliasing in socket API.

Glibc should implement alias safe socket API

https://austingroupbugs.net/view.php?id=1641
Comment 1 Eric Blake 2023-03-30 21:24:04 UTC
In particular, the intent of the POSIX amendment is that user code (such as this example abridged from 'man 2 bind' on Fedora 37) must compile without compiler diagnostics about an alias violation under default compiler warning levels, and must produce the intended semantics without the compiler mis-optimizing it on the grounds of undefined behavior from an alias violation:

       #include <sys/socket.h>
       #include <sys/un.h>
       #include <stdlib.h>
       #include <stdio.h>
       #include <string.h>

       #define MY_SOCK_PATH "/somepath"
       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       int
       main(int argc, char *argv[])
       {
           int sfd, cfd;
           struct sockaddr_un my_addr;

           sfd = socket(AF_UNIX, SOCK_STREAM, 0);
           if (sfd == -1)
               handle_error("socket");

           memset(&my_addr, 0, sizeof(my_addr));
           my_addr.sun_family = AF_UNIX;
           strncpy(my_addr.sun_path, MY_SOCK_PATH,
                   sizeof(my_addr.sun_path) - 1);

           if (bind(sfd, (struct sockaddr *) &my_addr,
                   sizeof(my_addr)) == -1)  // compiler must not flag this
               handle_error("bind");
           //...
       }

However, other (bad) user code, such as the following, may still trigger undefined behavior, even if the compiler is no longer able to diagnose it because of whatever was done to the structs in order to make the sockaddr.sa_family/sockaddr_un.sun_family aliasing be well-defined behavior:

    struct sockaddr too_small = { .sa_family = AF_UNIX };
    int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
    bind(sfd, &too_small, sizeof(struct sockaddr_storage)); // BAD - don't do this; the compiler can't flag this as an aliasing violation, but might be able to flag it for potential out-of-bounds referencing

Conversely, POSIX does not intend to require that the various sockaddr* types must be universal aliases (that is, sockaddr* does not have to be synonymous with void* or char*, if an implementation has a way to fine-tune how much it can alias):

    struct stat *st;
    struct sockaddr *sa = (struct sockaddr *)st; // BAD - compiler may, but not must, flag this as an obvious aliasing violation, as it is not one of the casts required by POSIX to be diagnostic-free

[If the POSIX amendment is itself inaccurate, the Austin Group welcomes comments on how to improve the wording before Issue 8 is finalized]
Comment 2 Bastien Roucariès 2023-07-21 19:28:35 UTC
Any news now that POSIX was amended ?
Comment 3 Eric Blake 2023-07-21 19:52:33 UTC
(In reply to Bastien Roucariès from comment #2)
> Any news now that POSIX was amended ?

Issue 8 is not yet finalized; but the latest POSIX wording looks like it will be this:
https://austingroupbugs.net/view.php?id=1641#c6290

with the following normative text:
    When a pointer to a sockaddr_storage structure is converted to a pointer to a sockaddr structure, or vice versa, the ss_family member of the sockaddr_storage structure shall map onto the sa_family member of the sockaddr structure. When a pointer to a sockaddr_storage structure is converted to a pointer to a protocol-specific address structure, or vice versa, the ss_family member shall map onto a member of that structure that is of type sa_family_t that identifies the protocol’s address family. When a pointer to a sockaddr structure is converted to a pointer to a protocol-specific address structure, or vice versa, the sa_family member shall map onto a member of that structure that is of type sa_family_t that identifies the protocol’s address family. Additionally, the structures shall be defined in such a way that the compiler treats an access to the stored value of the sa_family_t member of any of these structures, via an lvalue expression whose type involves any other one of these structures, as permissible, despite the more restrictive expression rules on stored value access as stated in the ISO C standard. Similarly, when a pointer to a sockaddr_storage or sockaddr structure is converted to a pointer to a protocol-specific address structure, the compiler shall treat an access (using this converted pointer) to the stored value of any member of the protocol-specific structure as permissible. The application shall ensure that the protocol-specific address structure corresponds to the family indicated by the member with type sa_family_t of that structure and the pointed-to object has sufficient memory for addressing all members of the protocol-specific structure.

and the following informative rationale text:
Note that defining the sockaddr_storage and sockaddr structures using only mechanisms defined in early editions of the ISO C standard may produce aliasing diagnostics when applications use casting between pointers to the various socket address structures. Because of the large body of existing code utilizing sockets in a way that could trigger undefined behavior due to strict aliasing rules, this standard mandates that these structures can alias each other for accessing the sa_family_t member of the structures (or other members for protocol-specific structure references), so as to preserve well-defined semantics. An implementation's header files may need to use anonymous unions, or even an implementation-specific extension, to comply with the requirements of this standard.
Comment 4 Florian Weimer 2024-06-13 07:40:54 UTC
Fixed via bug 19622.

*** This bug has been marked as a duplicate of bug 19622 ***