From 9b47092236c6cca449a1ae242ab5608e2df7fca7 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 2 Jun 2016 12:54:47 +0200 Subject: [PATCH] Resolves: #1337291 struct sockaddr_storage GCC 6 enablement --- glibc-rh1337291.patch | 324 ++++++++++++++++++++++++++++++++++++++++++ glibc.spec | 3 + 2 files changed, 327 insertions(+) create mode 100644 glibc-rh1337291.patch diff --git a/glibc-rh1337291.patch b/glibc-rh1337291.patch new file mode 100644 index 0000000..bc0f74d --- /dev/null +++ b/glibc-rh1337291.patch @@ -0,0 +1,324 @@ +commit f2225475118c8804b1b31731bdfb3f76eb179e6d +Author: Florian Weimer +Date: Mon May 23 19:43:09 2016 +0200 + + Make padding in struct sockaddr_storage explicit [BZ #20111] + + This avoids aliasing issues with GCC 6 in -fno-strict-aliasing + mode. (With implicit padding, not all data is copied.) + + This change makes it explicit that struct sockaddr_storage is + only 126 bytes large on m68k (unlike elsewhere, where we end up + with the requested 128 bytes). The new test case makes sure that + this does not happen on other architectures. + + (cherry picked from commit 3375cfafa7961c6ae0e509c31c3b3cef9ad1f03d) + +diff --git a/bits/sockaddr.h b/bits/sockaddr.h +index e91f837..0af58c9 100644 +--- a/bits/sockaddr.h ++++ b/bits/sockaddr.h +@@ -36,4 +36,7 @@ typedef unsigned short int sa_family_t; + + #define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) + ++/* Size of struct sockaddr_storage. */ ++#define _SS_SIZE 128 ++ + #endif /* bits/sockaddr.h */ +diff --git a/bits/socket.h b/bits/socket.h +index ab9f242..a22fd56 100644 +--- a/bits/socket.h ++++ b/bits/socket.h +@@ -152,20 +152,20 @@ struct sockaddr + + + /* Structure large enough to hold any socket address (with the historical +- exception of AF_UNIX). We reserve 128 bytes. */ ++ exception of AF_UNIX). */ + #if ULONG_MAX > 0xffffffff + # define __ss_aligntype __uint64_t + #else + # define __ss_aligntype __uint32_t + #endif +-#define _SS_SIZE 128 +-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) ++#define _SS_PADSIZE \ ++ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype)) + + struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ +- __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; ++ __ss_aligntype __ss_align; /* Force desired alignment. */ + }; + + +diff --git a/inet/Makefile b/inet/Makefile +index 0e7a3c3..2207b93 100644 +--- a/inet/Makefile ++++ b/inet/Makefile +@@ -50,7 +50,7 @@ aux := check_pf check_native ifreq + + tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ + tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ +- tst-getni1 tst-getni2 tst-inet6_rth tst-checks ++ tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr + + include ../Rules + +@@ -84,6 +84,8 @@ CFLAGS-either_hton.c = -fexceptions + CFLAGS-getnetgrent.c = -fexceptions + CFLAGS-getnetgrent_r.c = -fexceptions + ++CFLAGS-tst-sockaddr.c = -fno-strict-aliasing ++ + endif + + ifeq ($(build-static-nss),yes) +diff --git a/inet/tst-sockaddr.c b/inet/tst-sockaddr.c +new file mode 100644 +index 0000000..fe0307b +--- /dev/null ++++ b/inet/tst-sockaddr.c +@@ -0,0 +1,125 @@ ++/* Tests for socket address type definitions. ++ Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* This is a copy of the previous definition of struct ++ sockaddr_storage. It is not equal to the old value of _SS_SIZE ++ (128) on all architectures. We must stay compatible with the old ++ definition. */ ++ ++#define OLD_REFERENCE_SIZE 128 ++#define OLD_PADSIZE (OLD_REFERENCE_SIZE - (2 * sizeof (__ss_aligntype))) ++struct sockaddr_storage_old ++ { ++ __SOCKADDR_COMMON (old_); ++ __ss_aligntype old_align; ++ char old_padding[OLD_PADSIZE]; ++ }; ++ ++static bool errors; ++ ++static void ++check (bool ok, const char *message) ++{ ++ if (!ok) ++ { ++ printf ("error: failed check: %s\n", message); ++ errors = true; ++ } ++} ++ ++static int ++do_test (void) ++{ ++ check (OLD_REFERENCE_SIZE >= _SS_SIZE, ++ "old target size is not smaller than actual size"); ++ check (sizeof (struct sockaddr_storage_old) ++ == sizeof (struct sockaddr_storage), ++ "old and new sizes match"); ++ check (__alignof (struct sockaddr_storage_old) ++ == __alignof (struct sockaddr_storage), ++ "old and new alignment matches"); ++ check (offsetof (struct sockaddr_storage_old, old_family) ++ == offsetof (struct sockaddr_storage, ss_family), ++ "old and new family offsets match"); ++ check (sizeof (struct sockaddr_storage) == _SS_SIZE, ++ "struct sockaddr_storage size"); ++ ++ /* Check for lack of holes in the struct definition. */ ++ check (offsetof (struct sockaddr_storage, __ss_padding) ++ == __SOCKADDR_COMMON_SIZE, ++ "implicit padding before explicit padding"); ++ check (offsetof (struct sockaddr_storage, __ss_align) ++ == __SOCKADDR_COMMON_SIZE ++ + sizeof (((struct sockaddr_storage) {}).__ss_padding), ++ "implicit padding before explicit padding"); ++ ++ /* Check for POSIX compatibility requirements between struct ++ sockaddr_storage and struct sockaddr_un. */ ++ check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_un), ++ "sockaddr_storage is at least as large as sockaddr_un"); ++ check (__alignof (struct sockaddr_storage) ++ >= __alignof (struct sockaddr_un), ++ "sockaddr_storage is at least as aligned as sockaddr_un"); ++ check (offsetof (struct sockaddr_storage, ss_family) ++ == offsetof (struct sockaddr_un, sun_family), ++ "family offsets match"); ++ ++ /* Check that the compiler preserves bit patterns in aggregate ++ copies. Based on . */ ++ check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_in), ++ "sockaddr_storage is at least as large as sockaddr_in"); ++ { ++ struct sockaddr_storage addr; ++ memset (&addr, 0, sizeof (addr)); ++ { ++ struct sockaddr_in *sinp = (struct sockaddr_in *)&addr; ++ sinp->sin_family = AF_INET; ++ sinp->sin_addr.s_addr = htonl (INADDR_LOOPBACK); ++ sinp->sin_port = htons (80); ++ } ++ struct sockaddr_storage copy; ++ copy = addr; ++ ++ struct sockaddr_storage *p = malloc (sizeof (*p)); ++ if (p == NULL) ++ { ++ printf ("error: malloc: %m\n"); ++ return 1; ++ } ++ *p = copy; ++ const struct sockaddr_in *sinp = (const struct sockaddr_in *)p; ++ check (sinp->sin_family == AF_INET, "sin_family"); ++ check (sinp->sin_addr.s_addr == htonl (INADDR_LOOPBACK), "sin_addr"); ++ check (sinp->sin_port == htons (80), "sin_port"); ++ free (p); ++ } ++ ++ return errors; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff --git a/sysdeps/mach/hurd/bits/socket.h b/sysdeps/mach/hurd/bits/socket.h +index 02c5dac..257e438 100644 +--- a/sysdeps/mach/hurd/bits/socket.h ++++ b/sysdeps/mach/hurd/bits/socket.h +@@ -156,20 +156,20 @@ struct sockaddr + + + /* Structure large enough to hold any socket address (with the historical +- exception of AF_UNIX). We reserve 128 bytes. */ ++ exception of AF_UNIX). */ + #if ULONG_MAX > 0xffffffff + # define __ss_aligntype __uint64_t + #else + # define __ss_aligntype __uint32_t + #endif +-#define _SS_SIZE 128 +-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) ++#define _SS_PADSIZE \ ++ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype)) + + struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ +- __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; ++ __ss_aligntype __ss_align; /* Force desired alignment. */ + }; + + +diff --git a/sysdeps/unix/bsd/bits/sockaddr.h b/sysdeps/unix/bsd/bits/sockaddr.h +index aa12768..f5900f9 100644 +--- a/sysdeps/unix/bsd/bits/sockaddr.h ++++ b/sysdeps/unix/bsd/bits/sockaddr.h +@@ -39,4 +39,7 @@ typedef unsigned char sa_family_t; + + #define _HAVE_SA_LEN 1 /* We have the sa_len field. */ + ++/* Size of struct sockaddr_storage. */ ++#define _SS_SIZE 128 ++ + #endif /* bits/sockaddr.h */ +diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h +index 0581c79..50bfbc3 100644 +--- a/sysdeps/unix/sysv/linux/bits/socket.h ++++ b/sysdeps/unix/sysv/linux/bits/socket.h +@@ -158,16 +158,16 @@ struct sockaddr + + + /* Structure large enough to hold any socket address (with the historical +- exception of AF_UNIX). We reserve 128 bytes. */ ++ exception of AF_UNIX). */ + #define __ss_aligntype unsigned long int +-#define _SS_SIZE 128 +-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) ++#define _SS_PADSIZE \ ++ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype)) + + struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ +- __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; ++ __ss_aligntype __ss_align; /* Force desired alignment. */ + }; + + +diff --git a/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h +new file mode 100644 +index 0000000..5721f99 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h +@@ -0,0 +1,42 @@ ++/* Definition of struct sockaddr_* members and sizes, Linux/m68k version. ++ Copyright (C) 1995-2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* ++ * Never include this file directly; use instead. ++ */ ++ ++#ifndef _BITS_SOCKADDR_H ++#define _BITS_SOCKADDR_H 1 ++ ++ ++/* POSIX.1g specifies this type name for the `sa_family' member. */ ++typedef unsigned short int sa_family_t; ++ ++/* This macro is used to declare the initial common members ++ of the data types used for socket addresses, `struct sockaddr', ++ `struct sockaddr_in', `struct sockaddr_un', etc. */ ++ ++#define __SOCKADDR_COMMON(sa_prefix) \ ++ sa_family_t sa_prefix##family ++ ++#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) ++ ++/* Size of struct sockaddr_storage. */ ++#define _SS_SIZE 126 ++ ++#endif /* bits/sockaddr.h */ diff --git a/glibc.spec b/glibc.spec index bc46a28..80c2bc3 100644 --- a/glibc.spec +++ b/glibc.spec @@ -269,6 +269,7 @@ Patch1048: glibc-rh1204521.patch Patch1049: glibc-rh1282011.patch Patch1050: glibc-rh1337140.patch Patch1051: glibc-rh1326903.patch +Patch1052: glibc-rh1337291.patch ############################################################################## # @@ -737,6 +738,7 @@ microbenchmark tests on the system. %patch1049 -p1 %patch1050 -p1 %patch1051 -p1 +%patch1052 -p1 %patch0059 -p1 ############################################################################## @@ -1960,6 +1962,7 @@ rm -f *.filelist* * Thu Jun 2 2016 Florian Weimer - 2.22-17 - CVE-2016-4429: stack overflow in Sun RPC clntudp_call (#1337140) - Fix fork redirection in libpthread (#1326903) +- struct sockaddr_storage GCC 6 enablement (#1337291) * Wed May 11 2016 Florian Weimer - 2.22-16 - Back out dlsym (RTLD_NEXT)/dlerror change (#1333945)