Skip to content

Commit 59d0f78

Browse files
committed
vsyscall-less glibc lives in its own base image.
The Dockerfile and supporting scripts for this live in docker/glibc/. This cannot be built on Travis because it takes too long and emits too many log messages. Later patches should address reproducibility.
1 parent c1e4795 commit 59d0f78

File tree

9 files changed

+138
-125
lines changed

9 files changed

+138
-125
lines changed

docker/Dockerfile-x86_64

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
FROM centos:6.9 as build_glibc
2-
3-
COPY prep /prep
4-
RUN bash prep/rebuild-glibc-without-vsyscall.sh
5-
6-
FROM centos:6.9
1+
# See docker/glibc/
2+
FROM markrwilliams/manylinux2:centos-6.9-no-vsyscall
73
LABEL maintainer="The ManyLinux project"
84

95
ENV LC_ALL en_US.UTF-8
@@ -13,9 +9,6 @@ ENV PATH /opt/rh/devtoolset-2/root/usr/bin:$PATH
139
ENV LD_LIBRARY_PATH /opt/rh/devtoolset-2/root/usr/lib64:/opt/rh/devtoolset-2/root/usr/lib:/usr/local/lib64:/usr/local/lib
1410
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
1511

16-
COPY --from=build_glibc /root/rpmbuild/RPMS /RPMS
17-
RUN yum -y install /RPMS/x86_64/*.rpm && rm -r /RPMS
18-
1912
COPY build_scripts /build_scripts
2013
RUN bash build_scripts/build.sh && rm -r build_scripts
2114

File renamed without changes.

docker/glibc/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM centos:6.9 as centos-with-vsyscall
2+
3+
COPY ./build_scripts /build_scripts
4+
RUN bash /build_scripts/rebuild-glibc-without-vsyscall.sh
5+
6+
FROM centos:6.9
7+
LABEL maintainer="The Manylinux project"
8+
9+
COPY --from=centos-with-vsyscall /rpms /rpms
10+
11+
RUN yum -y install /rpms/* && rm -rf /rpms

docker/glibc/README.rst

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
centos-6.9-no-vsyscall
2+
======================
3+
4+
*Summary*: Because of
5+
https://mail.python.org/pipermail/wheel-builders/2016-December/000239.html,
6+
this a CentOS 6.9 Docker image that rebuilds ``glibc`` without
7+
*vsyscall* is necessary to reliably run ``manylinux2`` on 64-bit
8+
hosts. This requires building the image on a system with
9+
``vsyscall=emulate`` but allows the resulting container to run on
10+
systems with ``vsyscall=none`` or ``vsyscall=emulate``.
11+
12+
*vsyscall* is an antiquated optimization for a small number of
13+
frequently-used system calls. A vsyscall-enabled Linux kernel maps a
14+
read-only page of data and system calls into a process' memory at a
15+
fixed address. These system calls can then be invoked by
16+
dereferencing a function pointers to fixed offsets in that page,
17+
saving a relatively expensive context switch. [1]_
18+
19+
Unfortunately, because the code and its location in memory are fixed
20+
and well-known, the vsyscall mechanism has become a source of gadgets
21+
for ROP attacks (specifically, Sigreturn-Oriented Programs). [2]_
22+
Linux 3.1 introduced vsyscall emulation that prevents attackers from
23+
jumping into the middle of the system calls' code at the expense of
24+
speed, as well as the ability to disable it entirely. [3]_ [4]_ The
25+
vsyscall mechanism could not be eliminated at the time because
26+
``glibc`` versions earlier than 2.14 contained hard-coded references
27+
to the fixed memory address, specifically in ``time(2)``. [5]_ These
28+
segfault when attempting to issue a vsyscall-optimized system call
29+
against a kernel that has disabled it.
30+
31+
Linux introduced a "virtual dynamic shared object" (vDSO) that
32+
achieves the same high-speed, in-process system call mechanism via
33+
shared objects sometime before the kernel's migration to git. While
34+
old itself, vDSO 's presentation as a shared library allows it to
35+
benefit from ASLR on modern systems, making it no more amenable to ROP
36+
gadgets than any other shared library. ``glibc`` only switched over
37+
completely to vDSO as of glibc 2.25, so until recently vsyscall
38+
emulation has remained on for most kernels. [6]_ Furthermore, i686
39+
does not use vsyscall at all, so no version of ``glibc`` requires
40+
patching on that architecture.
41+
42+
At the same time, vsyscall emulation still exposed values useful to
43+
ROP attacks, so Linux 4.4 added a compilation option to disable
44+
it. [7]_ [8]_ Distributions are beginning to ship kernels configured
45+
without vsyscall, and running CentOS 5 (``glibc`` 2.5) or 6 (``glibc``
46+
2.12) Docker containers on these distributions indeed causes segfaults
47+
without ``vsyscall=emulate`` [9]_ [10]_. CentOS 6, however, is
48+
supported until 2020. It is likely that more and more distributions
49+
will ship with ``CONFIG_LEGACY_VSYSCALL_NONE``; if managed CI services
50+
like Travis make this switch, developers will be unable to build
51+
``manylinux2`` wheels with our Docker image.
52+
53+
Fortunately, vsyscall is merely an optimization, and patches that
54+
remove it can be backported to glibc 2.12 and the library recompiled.
55+
The result is this Docker image. It can be run on kernels regardless
56+
of their vsyscall configuration because executable and libraries on
57+
CentOS are dynamically linked against glibc. Libraries built on this
58+
image are unaffected because:
59+
60+
a) the kernel only maps vsyscall pages into processes;
61+
b) only glibc used the vsyscall interface directly, and it's
62+
included in manylinux2's whitelist policy.
63+
64+
Developers who build this vsyscall-less Docker image itself, however,
65+
must do so on a system with ``vsyscall=emulate``.
66+
67+
References:
68+
===========
69+
70+
.. [1] https://lwn.net/Articles/446528/
71+
.. [2] http://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf
72+
.. [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5cec93c216db77c45f7ce970d46283bcb1933884
73+
.. [4] https://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1
74+
.. [5] https://sourceware.org/git/?p=glibc.git;a=blob;f=ChangeLog;h=3a6abda7d07fdaa367c48a9274cc1c08498964dc;hb=356f8bc660a154a07b03da7c536831da5c8f74fe
75+
.. [6] https://sourceware.org/git/?p=glibc.git;a=blob;f=ChangeLog;h=6037fef737f0338a84c6fb564b3b8dc1b1221087;hb=58557c229319a3b8d2eefdb62e7df95089eabe37
76+
.. [7] https://googleprojectzero.blogspot.fr/2015/08/three-bypasses-and-fix-for-one-of.html
77+
.. [8] https://outflux.net/blog/archives/2016/09/27/security-things-in-linux-v4-4/
78+
.. [9] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=852620#20
79+
.. [10] https://github.com/CentOS/sig-cloud-instance-images/issues/62
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/sh
2+
# Prep script for x86_64 that recompiles glibc without vsyscalls.
3+
4+
# Stop at any error, show all commands
5+
set -ex
6+
7+
# Locate the prep directory
8+
MY_DIR=/$(dirname "${BASH_SOURCE[0]}")
9+
10+
# glibc versions
11+
ORIGINAL_GLIBC_VERSION=2.12-1.209
12+
PATCHED_GLIBC_VERSION=2.12-1.209.1
13+
14+
# Source RPM topdir
15+
SRPM_TOPDIR=/root/rpmbuild
16+
17+
# Source RPM download directory
18+
DOWNLOADED_SRPMS=/root/srpms
19+
20+
# Include the CentOS source RPM repository.
21+
# https://bugs.centos.org/view.php?id=1646
22+
cp $MY_DIR/CentOS-source.repo /etc/yum.repos.d/CentOS-source.repo
23+
24+
# Extract and prepare the source
25+
# https://blog.packagecloud.io/eng/2015/04/20/working-with-source-rpms/
26+
yum -y update
27+
yum -y install yum-utils rpm-build
28+
yum-builddep -y glibc
29+
mkdir $DOWNLOADED_SRPMS
30+
# The glibc RPM's contents are owned by mockbuild
31+
adduser mockbuild
32+
# yumdownloader assumes the current working directory
33+
(cd $DOWNLOADED_SRPMS && yumdownloader --source glibc)
34+
rpm -ivh $DOWNLOADED_SRPMS/glibc-$ORIGINAL_GLIBC_VERSION.el6.src.rpm
35+
# Prepare the source by applying Red Hat and CentOS patches
36+
rpmbuild -bp $SRPM_TOPDIR/SPECS/glibc.spec
37+
38+
# Copy the vsyscall removal patch into place
39+
cp $MY_DIR/remove-vsyscall.patch $SRPM_TOPDIR/SOURCES
40+
# Patch the RPM spec file so that it uses the vsyscall removal patch
41+
(cd $SRPM_TOPDIR/SPECS && patch -p2 < $MY_DIR/glibc.spec.patch)
42+
43+
# Build the RPMS
44+
rpmbuild -ba $SRPM_TOPDIR/SPECS/glibc.spec
45+
46+
mv $SRPM_TOPDIR/RPMS/* /rpms/

docker/prep/rebuild-glibc-without-vsyscall.sh

Lines changed: 0 additions & 116 deletions
This file was deleted.

0 commit comments

Comments
 (0)