From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by sourceware.org (Postfix) with ESMTPS id 290123858D1E for ; Fri, 20 Jan 2023 13:41:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 290123858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-x432.google.com with SMTP id q5so241676wrv.0 for ; Fri, 20 Jan 2023 05:41:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=29UuMZbFNvAJQvZZe7CsOFMjH1IuDxTbGoCRBb8noJk=; b=FaV/FL0zfM/aV1W+bXmTP6oQ9vmBK1lk/93CVutbul57DXdM+bUnmP02Wax88REXUu DlkuoLtXeixgPmIADINo51upLGF9pF0cxAaPMNg4X5P3GS89GGCkTQx+DRdzdt+WukUx hZsV7zQn/qVtN394bfDun+MAdzcbYzntzOaFBFw5RpMI3JwCDoJuwetMocHExDf9LAZ2 +weCdYPRpC+vWNKZ7gNbWmF01jFQb3gQwFN5Bx97Ab+GPk2qwvcGNCUlCnu4ohJuVw4d miHUQS1rUG3HZFat4+6eyMhQfaRdeik2mKlryqqWz0E48H7gFJjfeERfqawHd3NqWeWX i3BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=29UuMZbFNvAJQvZZe7CsOFMjH1IuDxTbGoCRBb8noJk=; b=SCeSN1vyghLLAKPdocwisLMEagI7m9/+jwJD5wNi4lpo7oKdETs/7T8+soSN2z20AJ 96tLqkbqd6+GLfJ3QTBbyAGFaw5wZm8mQD/HfeZeqjokAaHGPR6lEgP3usrMBzI8y5AX IOwrMbAnEFLz/1TJ1lOIlpoCG5C2mSr5W/QalD55dYFpNVRo/GYPWzRTVqZ/BqRpMshX xavN8VRvnw19C93agDo9+txPQQPnnZUhINsmRNVapeRfThF4/ILEjETPrCJNpnUgtmR7 /8lPD4uZqwjeGo4I+6HnaBSLyuZW8Iryr16MEsxVxMySVcwGjBDZ+AByJdOAK5Mgi4AW xmDg== X-Gm-Message-State: AFqh2koFndC2c+WBioNLgPtEYYyhf0geZYrkwPvJGbIs0HcWrjvAnztI KBvOLWKI4EKhBS7BHQbev6Cru9DObTY= X-Google-Smtp-Source: AMrXdXupUEqDWbAhBuMtoZ0Ji1r5xJLJxZJsjMBmra/KJgiy1IagQS4sgll+5a5lNWwTsRlxRynnJg== X-Received: by 2002:adf:e947:0:b0:2be:579b:158 with SMTP id m7-20020adfe947000000b002be579b0158mr2002457wrn.39.1674222113523; Fri, 20 Jan 2023 05:41:53 -0800 (PST) Received: from asus5775.alejandro-colomar.es ([170.253.36.171]) by smtp.googlemail.com with ESMTPSA id s18-20020adfecd2000000b002bdfcd8c77csm14112625wro.101.2023.01.20.05.41.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 05:41:53 -0800 (PST) From: Alejandro Colomar X-Google-Original-From: Alejandro Colomar To: libc-alpha@sourceware.org Cc: Alejandro Colomar , linux-man@vger.kernel.org, =?UTF-8?q?Bastien=20Roucari=C3=A8s?= , Eric Blake , Zack Weinberg , Stefan Puiu , Igor Sysoev Subject: [PATCH v2] socket: Implement sockaddr_storage with an anonymous union Date: Fri, 20 Jan 2023 14:40:44 +0100 Message-Id: <20230120134043.10247-1-alx@kernel.org> X-Mailer: git-send-email 2.39.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Developer-Signature: v=1; a=openpgp-sha256; l=3417; i=alx@kernel.org; h=from:subject; bh=hFEQe++dPCjfYJneXg5K84jfa3ctoJSsSNor/f7bY8A=; b=owEBbQKS/ZANAwAKAZ6MGvu+/9syAcsmYgBjypnaFBhXmoYAsyzmL4KbiBJQKg0m3nkMYkxUZiNP VZ51XeWJAjMEAAEKAB0WIQTqOofwpOugMORd8kCejBr7vv/bMgUCY8qZ2gAKCRCejBr7vv/bMiPCEA CgtaHuHaSGUBnktWIp5b6qK74n4octdb7J6TKojrr+B95wRWNMHll57WI6UE5AVqSQuA/l5zefSvsZ j56+no3HX634mxezBBntnLVPjh9G8Op6lriF3YyJCqlfXO+cmgoGWsnAfjV8qdSX4wnFqrtKf9B3YB EnhBALsLcUJzvSXG1orfQfmQAg/kgJpSMVz53GmXbhh2pNxbvlGWhSgV0fIAltM/hlSVU/wa2ZiqEt GA1WlxuwRkzRL9Da2uCGwfO9v3mrisnSJtlsDiToHlDMXFxl0qCVi6WP2QGMP7FiVg4kqkDoe4lRrv MDtaXoRFSnjxtZMB3jmDbN3K3WSXzNPvAgbkX9/NCRgFJCOJmw0GDYaongoRL/FYazsBloOf88YflL kaf5wvsEvLb7EKuwLdDHaGvI+7LHPpAX1m7Nc900QJHrBlzwavBLqBQ1twoAs5rte536N7SXqUf+fA uYjBkO7XtIq/biw3CVD6JGTkjoUOM5KvgZK6qVol7Z4VPlVZEzHVNlajSVzO/OedK6QWDRxIxs8SgJ yA5Xyb+cFJ7legllCqDCF5jWw3sgNWARiVEqtX2UKqX9hhceae1s5GiXnbs3KgeoAE9JHcdgXHcStv B5vv35Jv+guV3uonw1pLGaGJWmJwiCGBKA6aeP5THuvO+djcrjhKjZ3iqzgQ== X-Developer-Key: i=alx@kernel.org; a=openpgp; fpr=A9348594CE31283A826FBDD8D57633D441E25BB5 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: The historical design of `sockaddr_storage` makes it impossible to use without breaking strict aliasing rules. Not only this type is unusable, but even the use of other `sockaddr_*` structures directly (when the programmer only cares about a single address family) is also incorrect, since at some point the structure will be accessed as a `sockaddr`, and that breaks strict aliasing rules too. So, the only way for a programmer to not invoke Undefined Behavior is to declare a union that includes `sockaddr` and any `sockaddr_*` structures that are of interest, which allows later accessing as either the correct structure or plain `sockaddr` for the sa_family. This patch fixes sockaddr_storage to remove UB on its uses and make it that structure that everybody should be using. It also allows removing many casts in code that needs to pass a sockaddr as a side effect. The following is an example of how this improves both existing code and new code: void foo(foo) { struct old_sockaddr_storage oss; struct new_sockaddr_storage nss; // ... (initialize oss and nss) inet_sockaddr2str(&nss.sa); // correct (and has no casts) inet_sockaddr2str((struct sockaddr *)&oss); // UB inet_sockaddr2str((struct sockaddr *)&nss); // correct } /* This function is correct, as far as the accessed object has the * type we're using. That's only possible through a `union`, since * we're accessing it with 2 different types: `sockaddr` for the * `sa_family` and then the appropriate subtype for the address * itself. */ const char * inet_sockaddr2str(const struct sockaddr *sa) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; static char buf[MAXHOSTNAMELEN]; switch (sa->sa_family) { case AF_INET: sin = (struct sockaddr_in *) sa; inet_ntop(AF_INET, &sin->sin_addr, buf, NITEMS(buf)); return buf; case AF_INET6: sin6 = (struct sockaddr_in6 *) sa; inet_ntop(AF_INET6, &sin6->sin6_addr, buf, NITEMS(buf)); return buf; default: errno = EAFNOSUPPORT; return NULL; } } While it's not necessary to do the same for `sockaddr`, it might still be interesting to so, since it will allow removing many casts in the implementation of many libc functions. Link: Link: Link: Link: Cc: Bastien Roucariès Cc: Eric Blake Cc: Zack Weinberg Cc: Stefan Puiu Cc: Igor Sysoev Signed-off-by: Alejandro Colomar --- v2: - Fix incorrect cast in commit message. bits/socket.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bits/socket.h b/bits/socket.h index aac8c49b00..c0c23b4e84 100644 --- a/bits/socket.h +++ b/bits/socket.h @@ -168,9 +168,14 @@ struct sockaddr struct sockaddr_storage { - __SOCKADDR_COMMON (ss_); /* Address family, etc. */ - char __ss_padding[_SS_PADSIZE]; - __ss_aligntype __ss_align; /* Force desired alignment. */ + union + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_un sun; + }; }; -- 2.39.0