Skip to content

Commit e9493d5

Browse files
committed
Recompile glibc without vsyscall.
1 parent 93c1b75 commit e9493d5

File tree

5 files changed

+552
-0
lines changed

5 files changed

+552
-0
lines changed

docker/Dockerfile-x86_64

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ ENV PATH /opt/rh/devtoolset-2/root/usr/bin:$PATH
88
ENV LD_LIBRARY_PATH /opt/rh/devtoolset-2/root/usr/lib64:/opt/rh/devtoolset-2/root/usr/lib:/usr/local/lib64:/usr/local/lib
99
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
1010

11+
COPY prep /prep
12+
RUN bash prep/rebuild-glibc-without-vsyscall.sh && rm -r /prep
13+
1114
COPY build_scripts /build_scripts
1215
RUN bash build_scripts/build.sh && rm -r build_scripts
1316

docker/prep/CentOS-source.repo

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[base-source]
2+
name=CentOS-6.9 - Base SRPMS
3+
baseurl=http://vault.centos.org/6.9/os/Source/
4+
gpgcheck=1
5+
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
6+
priority=1
7+
enabled=1

docker/prep/glibc.spec.patch

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
2+
index 9bd07c9..eb601a4 100644
3+
--- a/SPECS/glibc.spec
4+
+++ b/SPECS/glibc.spec
5+
@@ -273,6 +273,7 @@ Patch240: glibc-rh1384281.patch
6+
Patch241: glibc-rh1338673.patch
7+
Patch242: glibc-rh1358015.patch
8+
Patch243: glibc-rh1012343.patch
9+
+Patch244: remove-vsyscall.patch
10+
11+
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
12+
Obsoletes: glibc-profile < 2.4
13+
@@ -719,6 +720,7 @@ package or when debugging this package.
14+
%patch241 -p1
15+
%patch242 -p1
16+
%patch243 -p1
17+
+%patch244 -E -p3
18+
19+
# A lot of programs still misuse memcpy when they have to use
20+
# memmove. The memcpy implementation below is not tolerant at
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/sh
2+
# Prep script for x86_64 that recompiles glibc without vsyscalls.
3+
#
4+
# tl;dr: Because of
5+
# https://mail.python.org/pipermail/wheel-builders/2016-December/000239.html,
6+
# this removes vsyscall code from glibc. This requires building the
7+
# image on a system with vsyscall=emulate but allows the resulting
8+
# container to run on systems with vsyscall=none or vsyscall=emulate.
9+
#
10+
# "vsyscall" is an antiquated optimization for a small number of
11+
# frequently-used system calls. A vsyscall-enabeld Linux kernel would
12+
# map a read-only page of data and system calls into a process' memory
13+
# at a fixed address. These system calls could be invoked by
14+
# dereferencing a function pointers to fixed offsets in that page,
15+
# saving a relatively expensive context switch. [1]
16+
#
17+
# Unfortunately, because the code and its location in memory were
18+
# fixed and well-known, the vsyscall mechanism became a source of
19+
# gadgets for ROP attacks (specifically, Sigreturn-Oriented Programs)
20+
# [2]. Linux 3.1 introduced vsyscall emulation that prevented
21+
# attackers from jumping into the middle of the system calls' code at
22+
# the expense of speed, as well as the ability to disable it entirely.
23+
# [3][4] The vsyscall mechanism could not be eliminated at the time
24+
# because glibc versions earlier than 2.14 contained hard-coded
25+
# references to the fixed memory address, specifically in time(2). [5]
26+
# These segfault when attempting to issue a vsyscall against a kernel
27+
# that has disabled vsyscalls.
28+
#
29+
# Linux introduced a "virtual dynamic shared object" (vDSO) that
30+
# achieves the same high-speed, in-process system call mechanism via
31+
# shared objects sometime before the kernel's migration to git. While
32+
# old itself, vDSO's presentation as a shared library allows it to
33+
# benefit from ASLR on modern systems, making it no more amenable to
34+
# ROP gadgets than any other shared library. glibc only switched over
35+
# completely to vDSO as of glibc 2.25, so until recently vsyscall
36+
# emulation has remained on for most kernels. [6] Furthermore, i686
37+
# does not use vsyscall at all, so it requires no patching.
38+
#
39+
# At the same time, vsyscall emulation still exposed values useful to
40+
# ROP attacks, so Linux 4.4 added a compilation option to disable
41+
# it. [7][8] Distributions are beginning to ship kernels configured
42+
# without vsyscall, and running CentOS 5 (glibc 2.5) or 6 (glibc 2.12)
43+
# Docker containers on these distributions indeed causes segfaults
44+
# without vsyscall=emulate [9][10]. CentOS 6, however, is supported
45+
# until 2020, and it's likely that more and more distributions will
46+
# ship with CONFIG_LEGACY_VSYSCALL_NONE. If managed CI services like
47+
# Travis make this switch, developers will be unable to build
48+
# manylinux2 wheels with our Docker image.
49+
#
50+
# Fortunately, vsyscall is merely an optimization, and patches that
51+
# remove it can be backported to glibc 2.12 and the library
52+
# recompiled. The result is a Docker image that can be run on kernels
53+
# regardless of their vsyscall configuration because executable and
54+
# libraries on CentOS are dynamically linked against glibc. Libraries
55+
# built on this image are unaffected because:
56+
#
57+
# a) the kernel only maps vsyscall pages into processes;
58+
# b) only glibc used the vsyscall interface directly, and it's
59+
# included in manylinux2's whitelist policy.
60+
#
61+
# Developers who build the manylinux2 Docker image itself, however,
62+
# must do so on a system with vsyscall=emulate.
63+
#
64+
# References:
65+
# [1] https://lwn.net/Articles/446528/
66+
# [2] http://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf
67+
# [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5cec93c216db77c45f7ce970d46283bcb1933884
68+
# [4] https://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1
69+
# [5] https://sourceware.org/git/?p=glibc.git;a=blob;f=ChangeLog;h=3a6abda7d07fdaa367c48a9274cc1c08498964dc;hb=356f8bc660a154a07b03da7c536831da5c8f74fe
70+
# [6] https://sourceware.org/git/?p=glibc.git;a=blob;f=ChangeLog;h=6037fef737f0338a84c6fb564b3b8dc1b1221087;hb=58557c229319a3b8d2eefdb62e7df95089eabe37
71+
# [7] https://googleprojectzero.blogspot.fr/2015/08/three-bypasses-and-fix-for-one-of.html
72+
# [8] https://outflux.net/blog/archives/2016/09/27/security-things-in-linux-v4-4/
73+
# [9] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=852620#20
74+
# [10] https://github.com/CentOS/sig-cloud-instance-images/issues/62
75+
76+
# Stop at any error, show all commands
77+
set -ex
78+
79+
# Locate the prep directory
80+
MY_DIR=/$(dirname "${BASH_SOURCE[0]}")
81+
82+
# glibc version
83+
GLIBC_VERSION=glibc-2.12-1.209
84+
85+
# Source RPM topdir
86+
SRPM_TOPDIR=/root/rpmbuild
87+
88+
# Source RPM download directory
89+
DOWNLOADED_SRPMS=/root/srpms
90+
91+
# Include the CentOS source RPM repository.
92+
# https://bugs.centos.org/view.php?id=1646
93+
cp $MY_DIR/CentOS-source.repo /etc/yum.repos.d/CentOS-source.repo
94+
95+
# Extract and prepare the source
96+
# https://blog.packagecloud.io/eng/2015/04/20/working-with-source-rpms/
97+
yum -y update
98+
yum -y install yum-utils rpm-build
99+
yum-builddep -y glibc
100+
mkdir $DOWNLOADED_SRPMS
101+
# The glibc RPM's contents are owned by mockbuild
102+
adduser mockbuild
103+
# yumdownloader assumes the current working directory
104+
(cd $DOWNLOADED_SRPMS && yumdownloader --source glibc)
105+
rpm -ivh $DOWNLOADED_SRPMS/$GLIBC_VERSION.el6.src.rpm
106+
# Prepare the source by applying Red Hat and CentOS patches
107+
rpmbuild -bp $SRPM_TOPDIR/SPECS/glibc.spec
108+
109+
# Copy the vsyscall removal patch into place
110+
cp $MY_DIR/remove-vsyscall.patch $SRPM_TOPDIR/SOURCES
111+
# Patch the RPM spec file so that it uses the vsyscall removal patch
112+
(cd $SRPM_TOPDIR/SPECS && patch -p2 < $MY_DIR/glibc.spec.patch)
113+
114+
# Build the RPMS
115+
rpmbuild -ba $SRPM_TOPDIR/SPECS/glibc.spec
116+
117+
# Install the replacement glibc
118+
rpm --install --force --nodeps $SRPM_TOPDIR/RPMS/x86_64/$GLIBC_VERSION.el6.x86_64.rpm
119+
120+
# XXX: Remove all unneeded dependencies
121+
yum -y erase yum-utils rpm-build

0 commit comments

Comments
 (0)