From: Paul Eggert <eggert@cs.ucla.edu>
To: Philipp Stephani <phst@google.com>, Eli Zaretskii <eliz@gnu.org>,
Andreas Schwab <schwab@linux-m68k.org>
Cc: p.stephani2@gmail.com, emacs-devel@gnu.org
Subject: Re: [PATCH] Fix use of sockaddr_in
Date: Wed, 17 May 2017 13:38:41 -0700 [thread overview]
Message-ID: <034ef5c4-8bb1-264a-f1f4-46789d2d98c3@cs.ucla.edu> (raw)
In-Reply-To: <CAP-RRPuHeeb5fyd8a_A2vGwiUBhZ1R3-62E9HcAHcTszqV75XA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 989 bytes --]
On 05/15/2017 02:04 AM, Philipp Stephani wrote:
> - Maybe add verify(INT_MAX >= TYPE_MAXIMUM(in_port_t)) and
> verify(TYPE_MINIMUM(in_port_t) == 0) to make sure that we can use int
> for the port?
The code has been changed so that the port number is no longer stored in
an int so this remark is obsolete now. However, if this issue crops up
later I don't think we need to worry about it for IPv4 and IPv6 ports,
since they're always in the range 0..65535. Emacs already assumes that
'int' is at least 32 bits wide, as per POSIX.
> - Should there be a guard against the alias violation, e.g. by
> declaring sa and sa1 with __attribute__((may_alias))? Otherwise it's
> UB and the compiler might elide the switch entirely.
Yes, that is easy enough to do and would avoid some unlikely but
hard-to-catch bugs. I installed the attached. Most likely other parts of
Emacs should use may_alias too; do you happen to have any tool in your
toolbox that would find them systematically?
[-- Attachment #2: 0001-Avoid-undefined-behavior-in-struct-sockaddr.patch --]
[-- Type: text/x-patch, Size: 6297 bytes --]
From 2c70724a4d9809d34caefa0903012d8449b62a3c Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 17 May 2017 13:35:52 -0700
Subject: [PATCH] Avoid undefined behavior in struct sockaddr
Problem noted by Philipp Stephani in:
http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00391.html
* src/conf_post.h (ATTRIBUTE_MAY_ALIAS, DECLARE_POINTER_ALIAS):
New macros.
* src/process.c (conv_sockaddr_to_lisp, conv_lisp_to_sockaddr)
(connect_network_socket, network_interface_info)
(server_accept_connection): Use it when aliasing non-char objects.
---
src/conf_post.h | 14 ++++++++++++++
src/process.c | 31 +++++++++++++++++--------------
2 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/conf_post.h b/src/conf_post.h
index 1462bd1..c05c93b 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -263,6 +263,20 @@ extern int emacs_setenv_TZ (char const *);
#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
#define ATTRIBUTE_UNUSED _GL_UNUSED
+#if GNUC_PREREQ (3, 3, 0)
+# define ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
+#else
+# define ATTRIBUTE_MAY_ALIAS
+#endif
+
+/* Declare NAME to be a pointer to an object of type TYPE, initialized
+ to the address ADDR, which may be of a different type. Accesses
+ via NAME may alias with other accesses with the traditional
+ behavior, even if options like gcc -fstrict-aliasing are used. */
+
+#define DECLARE_POINTER_ALIAS(name, type, addr) \
+ type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
+
#if 3 <= __GNUC__
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
#else
diff --git a/src/process.c b/src/process.c
index 8180fea..c301739 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2476,7 +2476,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
{
case AF_INET:
{
- struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
len = sizeof (sin->sin_addr) + 1;
address = Fmake_vector (make_number (len), Qnil);
p = XVECTOR (address);
@@ -2487,8 +2487,8 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
#ifdef AF_INET6
case AF_INET6:
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
- uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr;
+ DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
+ DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
len = sizeof (sin6->sin6_addr) / 2 + 1;
address = Fmake_vector (make_number (len), Qnil);
p = XVECTOR (address);
@@ -2501,7 +2501,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
{
- struct sockaddr_un *sockun = (struct sockaddr_un *) sa;
+ DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path);
/* If the first byte is NUL, the name is a Linux abstract
socket name, and the name can contain embedded NULs. If
@@ -2612,7 +2612,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
p = XVECTOR (address);
if (family == AF_INET)
{
- struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
len = sizeof (sin->sin_addr) + 1;
hostport = XINT (p->contents[--len]);
sin->sin_port = htons (hostport);
@@ -2622,8 +2622,8 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
#ifdef AF_INET6
else if (family == AF_INET6)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
- uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+ DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
+ DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
len = sizeof (sin6->sin6_addr) / 2 + 1;
hostport = XINT (p->contents[--len]);
sin6->sin6_port = htons (hostport);
@@ -2645,7 +2645,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
#ifdef HAVE_LOCAL_SOCKETS
if (family == AF_LOCAL)
{
- struct sockaddr_un *sockun = (struct sockaddr_un *) sa;
+ DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
cp = SDATA (address);
for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
sockun->sun_path[i] = *cp++;
@@ -3436,13 +3436,15 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
== offsetof (struct sockaddr_in6, sin6_port))
&& sizeof (sa1.sin_port) == sizeof (sa6.sin6_port));
#endif
- if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
+ DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
+ if (getsockname (s, psa1, &len1) == 0)
{
Lisp_Object service = make_number (ntohs (sa1.sin_port));
contact = Fplist_put (contact, QCservice, service);
/* Save the port number so that we can stash it in
the process object later. */
- ((struct sockaddr_in *) sa)->sin_port = sa1.sin_port;
+ DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa);
+ psa->sin_port = sa1.sin_port;
}
}
#endif
@@ -3550,9 +3552,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
{
struct sockaddr_storage sa1;
socklen_t len1 = sizeof (sa1);
- if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
+ DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
+ if (getsockname (s, psa1, &len1) == 0)
contact = Fplist_put (contact, QClocal,
- conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1));
+ conv_sockaddr_to_lisp (psa1, len1));
}
#endif
}
@@ -4401,7 +4404,7 @@ network_interface_info (Lisp_Object ifname)
for (it = ifap; it != NULL; it = it->ifa_next)
{
- struct sockaddr_dl *sdl = (struct sockaddr_dl *) it->ifa_addr;
+ DECLARE_POINTER_ALIAS (sdl, struct sockaddr_dl, it->ifa_addr);
unsigned char linkaddr[6];
int n;
@@ -4722,7 +4725,7 @@ server_accept_connection (Lisp_Object server, int channel)
{
args[nargs++] = procname_format_in6;
nargs++;
- uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr;
+ DECLARE_POINTER_ALIAS (ip6, uint16_t, &saddr.in6.sin6_addr);
service = make_number (ntohs (saddr.in.sin_port));
for (int i = 0; i < 8; i++)
args[nargs++] = make_number (ip6[i]);
--
2.9.4
next prev parent reply other threads:[~2017-05-17 20:38 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-07 3:40 building/using address-sanitizer-enabled emacs? Jim Meyering
2017-05-07 19:54 ` Paul Eggert
2017-05-07 21:44 ` Jim Meyering
2017-05-08 2:36 ` Eli Zaretskii
2017-05-08 5:42 ` Paul Eggert
2017-05-08 14:39 ` Eli Zaretskii
2017-05-08 14:46 ` Paul Eggert
2017-05-08 16:04 ` Eli Zaretskii
2017-05-09 5:48 ` Jim Meyering
2017-05-09 15:18 ` Eli Zaretskii
2017-05-09 17:06 ` Jim Meyering
2017-05-09 17:45 ` Eli Zaretskii
2017-05-09 19:22 ` Paul Eggert
2017-05-09 22:49 ` Jim Meyering
2017-05-10 2:41 ` Eli Zaretskii
2017-05-16 21:49 ` Paul Eggert
2017-05-17 2:24 ` Eli Zaretskii
2017-05-17 14:46 ` Paul Eggert
2017-05-17 16:06 ` Eli Zaretskii
2017-05-17 20:05 ` Paul Eggert
2017-05-18 4:15 ` Eli Zaretskii
2017-05-09 23:15 ` Philipp Stephani
2017-05-10 2:42 ` Eli Zaretskii
2017-05-10 22:24 ` Philipp Stephani
2017-05-13 8:02 ` Eli Zaretskii
2017-05-13 15:08 ` [PATCH] Fix use of sockaddr_in Philipp Stephani
2017-05-13 16:52 ` Eli Zaretskii
2017-05-13 19:14 ` Andreas Schwab
2017-05-13 19:29 ` Eli Zaretskii
2017-05-13 20:05 ` Andreas Schwab
2017-05-14 2:32 ` Eli Zaretskii
2017-05-14 6:11 ` Andreas Schwab
2017-05-14 14:20 ` Eli Zaretskii
2017-05-15 6:15 ` Paul Eggert
2017-05-15 9:04 ` Philipp Stephani
2017-05-17 20:38 ` Paul Eggert [this message]
2017-05-27 11:35 ` Philipp Stephani
2017-05-17 15:16 ` Eli Zaretskii
2017-05-17 20:15 ` Paul Eggert
2017-05-14 10:28 ` Lars Ingebrigtsen
2017-05-14 19:06 ` Philipp Stephani
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=034ef5c4-8bb1-264a-f1f4-46789d2d98c3@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=p.stephani2@gmail.com \
--cc=phst@google.com \
--cc=schwab@linux-m68k.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.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
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).