From patchwork Wed Dec 14 20:39:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxim Cournoyer X-Patchwork-Id: 45305 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id CA29127BBE9; Wed, 14 Dec 2022 20:40:46 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id DC59D27BBEB for ; Wed, 14 Dec 2022 20:40:40 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p5YY7-0000R4-Q0; Wed, 14 Dec 2022 15:40:19 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p5YXr-0000IV-MK for guix-patches@gnu.org; Wed, 14 Dec 2022 15:40:04 -0500 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1p5YXq-0003vB-6D for guix-patches@gnu.org; Wed, 14 Dec 2022 15:40:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1p5YXp-0001q8-P9 for guix-patches@gnu.org; Wed, 14 Dec 2022 15:40:01 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#60076] [PATCH RFC] Revert "gnu: glibc: Remove old versions." Resent-From: Maxim Cournoyer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Wed, 14 Dec 2022 20:40:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 60076 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 60076@debbugs.gnu.org Cc: marius@gnu.org, Maxim Cournoyer , contact@carldong.me X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.16710503787053 (code B ref -1); Wed, 14 Dec 2022 20:40:01 +0000 Received: (at submit) by debbugs.gnu.org; 14 Dec 2022 20:39:38 +0000 Received: from localhost ([127.0.0.1]:41779 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p5YXS-0001ph-3C for submit@debbugs.gnu.org; Wed, 14 Dec 2022 15:39:38 -0500 Received: from lists.gnu.org ([209.51.188.17]:46564) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p5YXP-0001pX-PM for submit@debbugs.gnu.org; Wed, 14 Dec 2022 15:39:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p5YXP-0008QF-5h for guix-patches@gnu.org; Wed, 14 Dec 2022 15:39:35 -0500 Received: from mail-yb1-xb32.google.com ([2607:f8b0:4864:20::b32]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1p5YXH-0003Zr-Qm; Wed, 14 Dec 2022 15:39:33 -0500 Received: by mail-yb1-xb32.google.com with SMTP id o127so1205500yba.5; Wed, 14 Dec 2022 12:39:25 -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=Y5/xUHTaveU9pxuAOB9kLk9ojcQYJr1Jd6YqYlwBnWk=; b=SqkTsSIG4y/xS1JTA2kP7LieTmsnT2U3PYZ2/ZgIls/qVGPxGzIoiR5YPr74YBMV96 wKPXGbD13icLjB55TDjEAQLCUMKW9KBuAdVrpw6qCwG93o5iiX8bKjL+37GtqTrEO/3r X0cqucKKoVIwvrtgUGNZ2QQ4pJDZbdZ3VIB3VWc3WJP8PrDai8mr9xz8xolvGW3SpOoX 5guo8vEf0OHBEB+Rq8L2yQUTwz+T82kg30j2X2CPzH4smf0XA5NMCXTZpeVWhU6antCl hFIGDpZFyO0xJEHa2Qd+A9qAxsZjF7eCBchuyo2U8Gax+je7k7+NMGNKqP2bu0lHZTWP aiWQ== 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=Y5/xUHTaveU9pxuAOB9kLk9ojcQYJr1Jd6YqYlwBnWk=; b=p8IZw+HhqsxxIWXftXGvXmaFQ04uSCckzUD+O/mUUN3mb7o2Q9pvLbVEA4xtmlwiof KKhRaSy6igUvW6snf+pPH7I69FL8KIjUWPnxoCDcgrzhS51GLZs8mWwbqSkpk+AYT1Tf WK7viMlP5VhE9b2dC7EPmeaCELjisADVGpeCQevE7EzLo9jpEQCOGkCyHpZ7TLUcmj7B udK6okMybdCGXog6ITQJwIB0r884NVbMgE5ThTLeWV6HHuxd7kmIxViBRYoRuIQ7yW2p iH5D/30jr0hr7ey6/EeUm1cLMI6EGRb85EffB3F4xfyPaO7VnRIVbDqVSAaT2uZQ5O1E wQqQ== X-Gm-Message-State: ANoB5pn4zQIViJtd5fanJSdJHGc/hQaJKuA3w3n0dv9e3wYgh7kkBZUt tcBTZw6ZfBEg3hEk35RhjdxsabGZZfpchw== X-Google-Smtp-Source: AA0mqf6KK4RLWIzcCpLvvf+JtSC1pYz088VqdBE6Os1cz38E/XLU/fRTu3Zrr6VYg/DvLAtBKdASeA== X-Received: by 2002:a25:8b85:0:b0:6d3:224d:49e4 with SMTP id j5-20020a258b85000000b006d3224d49e4mr19696696ybl.56.1671050360897; Wed, 14 Dec 2022 12:39:20 -0800 (PST) Received: from localhost.localdomain ([2607:fad8:4:3::1006]) by smtp.gmail.com with ESMTPSA id x10-20020a05620a258a00b006fefa5f7fc9sm10625093qko.134.2022.12.14.12.39.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Dec 2022 12:39:20 -0800 (PST) From: Maxim Cournoyer Date: Wed, 14 Dec 2022 15:39:12 -0500 Message-Id: <20221214203912.14694-1-maxim.cournoyer@gmail.com> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::b32; envelope-from=maxim.cournoyer@gmail.com; helo=mail-yb1-xb32.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches This reinstates glibc 2.22 through 2.28, by reverting commit ebd1ba713cbefc9ad5dac609255e1344a328e360 ("gnu: glibc: Remove old versions."), adding two patches removed in d2bb4847b96e51b71126778bb16daa7674a6690c ("gnu: Remove leftover patch files."), and partially reverting 1feca4be5296d7f0c0e2269ccb612cadded6573b ("gnu: glibc: Remove versions 2.27 and 2.28."). Rationale: Keeping older glibc versions around is useful when experimenting with 'package-with-c-toolchain'. * gnu/local.mk (dist_patch_DATA): Register any missing patches now re-instated and sort. --- gnu/local.mk | 32 +- gnu/packages/base.scm | 87 ++- .../patches/glibc-2.27-git-fixes.patch | 702 ++++++++++++++++++ .../glibc-2.27-supported-locales.patch | 33 + .../patches/glibc-2.28-git-fixes.patch | 248 +++++++ .../glibc-2.28-supported-locales.patch | 33 + .../patches/glibc-CVE-2015-5180.patch | 311 ++++++++ .../patches/glibc-CVE-2015-7547.patch | 590 +++++++++++++++ .../patches/glibc-CVE-2016-3075.patch | 43 ++ .../patches/glibc-CVE-2016-3706.patch | 188 +++++ .../patches/glibc-CVE-2016-4429.patch | 58 ++ .../patches/glibc-CVE-2017-1000366-pt1.patch | 36 + .../patches/glibc-CVE-2017-1000366-pt2.patch | 124 ++++ .../patches/glibc-CVE-2017-1000366-pt3.patch | 206 +++++ .../patches/glibc-CVE-2018-11236.patch | 149 ++++ .../patches/glibc-CVE-2018-11237.patch | 55 ++ .../patches/glibc-cvs-common-symbols.patch | 58 ++ .../patches/glibc-hurd-magic-pid.patch | 190 +++++ gnu/packages/patches/glibc-o-largefile.patch | 25 + .../glibc-vectorized-strcspn-guards.patch | 23 + 20 files changed, 3183 insertions(+), 8 deletions(-) create mode 100644 gnu/packages/patches/glibc-2.27-git-fixes.patch create mode 100644 gnu/packages/patches/glibc-2.27-supported-locales.patch create mode 100644 gnu/packages/patches/glibc-2.28-git-fixes.patch create mode 100644 gnu/packages/patches/glibc-2.28-supported-locales.patch create mode 100644 gnu/packages/patches/glibc-CVE-2015-5180.patch create mode 100644 gnu/packages/patches/glibc-CVE-2015-7547.patch create mode 100644 gnu/packages/patches/glibc-CVE-2016-3075.patch create mode 100644 gnu/packages/patches/glibc-CVE-2016-3706.patch create mode 100644 gnu/packages/patches/glibc-CVE-2016-4429.patch create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch create mode 100644 gnu/packages/patches/glibc-CVE-2018-11236.patch create mode 100644 gnu/packages/patches/glibc-CVE-2018-11237.patch create mode 100644 gnu/packages/patches/glibc-cvs-common-symbols.patch create mode 100644 gnu/packages/patches/glibc-hurd-magic-pid.patch create mode 100644 gnu/packages/patches/glibc-o-largefile.patch create mode 100644 gnu/packages/patches/glibc-vectorized-strcspn-guards.patch base-commit: c6f81ff7a6a527b5a14189a2c359b981ddba43bc prerequisite-patch-id: 77c51f63cfaba6cafe4e7125f50077d6dc5ca24a prerequisite-patch-id: 776778c03bce9b7ad3ab94a120f42b764c00fcae prerequisite-patch-id: 4910d08bdc27384d76030b6ac491ad2c2ed0957f prerequisite-patch-id: 2de8762a6381a93682d0fe4c893962b9803362b0 prerequisite-patch-id: b9b6f21a2db3f7a5ef82bb11ed23f69749cc6b3d prerequisite-patch-id: fd4074fb4cf068ccac3122c19138f098a610542a prerequisite-patch-id: 2b8e69760af1f7bfb66c1edb44471653b6b229d1 prerequisite-patch-id: 51cecbabc04c69d4338addaece536c42a075660f prerequisite-patch-id: 2c67bfd85b343a65440e6c63451e5417129dea6f prerequisite-patch-id: 7c7e8e7affe4a115423836e82a0930db2b25ae59 prerequisite-patch-id: 53f792328e96bc30e638d953317e730535d89d42 diff --git a/gnu/local.mk b/gnu/local.mk index aae6e23e12..51415eddf0 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1201,36 +1201,54 @@ dist_patch_DATA = \ %D%/packages/patches/glib-networking-gnutls-binding.patch \ %D%/packages/patches/glib-networking-32-bit-time.patch \ %D%/packages/patches/glib-skip-failing-test.patch \ + %D%/packages/patches/glibc-2.27-git-fixes.patch \ + %D%/packages/patches/glibc-2.27-supported-locales.patch \ + %D%/packages/patches/glibc-2.28-git-fixes.patch \ + %D%/packages/patches/glibc-2.28-supported-locales.patch \ + %D%/packages/patches/glibc-2.29-git-updates.patch \ + %D%/packages/patches/glibc-2.29-supported-locales.patch \ + %D%/packages/patches/glibc-2.31-hurd-clock_gettime_monotonic.patch \ + %D%/packages/patches/glibc-CVE-2015-5180.patch \ + %D%/packages/patches/glibc-CVE-2015-7547.patch \ + %D%/packages/patches/glibc-CVE-2016-3075.patch \ + %D%/packages/patches/glibc-CVE-2016-3706.patch \ + %D%/packages/patches/glibc-CVE-2016-4429.patch \ + %D%/packages/patches/glibc-CVE-2017-1000366-pt1.patch \ + %D%/packages/patches/glibc-CVE-2017-1000366-pt2.patch \ + %D%/packages/patches/glibc-CVE-2017-1000366-pt3.patch \ + %D%/packages/patches/glibc-CVE-2018-11236.patch \ + %D%/packages/patches/glibc-CVE-2018-11237.patch \ + %D%/packages/patches/glibc-CVE-2019-19126.patch \ %D%/packages/patches/glibc-CVE-2019-7309.patch \ %D%/packages/patches/glibc-CVE-2019-9169.patch \ - %D%/packages/patches/glibc-CVE-2019-19126.patch \ %D%/packages/patches/glibc-allow-kernel-2.6.32.patch \ %D%/packages/patches/glibc-boot-2.16.0.patch \ %D%/packages/patches/glibc-boot-2.2.5.patch \ - %D%/packages/patches/glibc-bootstrap-system-2.2.5.patch \ %D%/packages/patches/glibc-bootstrap-system-2.16.0.patch \ + %D%/packages/patches/glibc-bootstrap-system-2.2.5.patch \ %D%/packages/patches/glibc-bootstrap-system.patch \ %D%/packages/patches/glibc-cross-objcopy.patch \ %D%/packages/patches/glibc-cross-objdump.patch \ + %D%/packages/patches/glibc-cvs-common-symbols.patch \ %D%/packages/patches/glibc-dl-cache.patch \ %D%/packages/patches/glibc-hidden-visibility-ldconfig.patch \ %D%/packages/patches/glibc-hurd-clock_gettime_monotonic.patch \ - %D%/packages/patches/glibc-2.31-hurd-clock_gettime_monotonic.patch \ %D%/packages/patches/glibc-hurd-clock_t_centiseconds.patch \ %D%/packages/patches/glibc-hurd-gettyent.patch \ %D%/packages/patches/glibc-hurd-mach-print.patch \ + %D%/packages/patches/glibc-hurd-magic-pid.patch \ %D%/packages/patches/glibc-hurd-signal-sa-siginfo.patch \ %D%/packages/patches/glibc-ldd-powerpc.patch \ %D%/packages/patches/glibc-ldd-x86_64.patch \ - %D%/packages/patches/glibc-locales.patch \ %D%/packages/patches/glibc-locales-2.28.patch \ + %D%/packages/patches/glibc-locales.patch \ + %D%/packages/patches/glibc-o-largefile.patch \ %D%/packages/patches/glibc-reinstate-prlimit64-fallback.patch \ %D%/packages/patches/glibc-skip-c++.patch \ - %D%/packages/patches/glibc-versioned-locpath.patch \ - %D%/packages/patches/glibc-2.29-git-updates.patch \ - %D%/packages/patches/glibc-2.29-supported-locales.patch \ %D%/packages/patches/glibc-static-nss.patch \ %D%/packages/patches/glibc-supported-locales.patch \ + %D%/packages/patches/glibc-vectorized-strcspn-guards.patch \ + %D%/packages/patches/glibc-versioned-locpath.patch \ %D%/packages/patches/gmp-arm-asm-nothumb.patch \ %D%/packages/patches/gmp-faulty-test.patch \ %D%/packages/patches/gnash-fix-giflib-version.patch \ diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm index b8b0ea241f..ef1b4f135c 100644 --- a/gnu/packages/base.scm +++ b/gnu/packages/base.scm @@ -985,7 +985,8 @@ (define-public glibc-for-fhs (origin-patches (package-source glibc))))))))) ;; Below are old libc versions, which we use mostly to build locale data in -;; the old format (which the new libc cannot cope with.) +;; the old format (which the new libc cannot cope with.). Older versions are +;; kept around for the convenience of users of '--with-c-toolchain'. (define-public glibc-2.32 (package (inherit glibc) @@ -1126,6 +1127,90 @@ (define-public glibc-2.29 "glibc-reinstate-prlimit64-fallback.patch" "glibc-2.29-supported-locales.patch")))))) +(define-public glibc-2.28 + (package + (inherit glibc-2.29) + (version "2.28") + (source (origin + (inherit (package-source glibc)) + (uri (string-append "mirror://gnu/glibc/glibc-" version ".tar.xz")) + (sha256 + (base32 + "10iha5ynvdj5m62vgpgqbq4cwvc2yhyl2w9yyyjgfxmdmx8h145i")) + (patches (search-patches "glibc-ldd-x86_64.patch" + "glibc-2.28-git-fixes.patch" + "glibc-hidden-visibility-ldconfig.patch" + "glibc-versioned-locpath.patch" + "glibc-allow-kernel-2.6.32.patch" + "glibc-reinstate-prlimit64-fallback.patch" + "glibc-hurd-magic-pid.patch" + "glibc-2.28-supported-locales.patch")))))) + +(define-public glibc-2.27 + (package + (inherit glibc-2.28) + (version "2.27") + (source (origin + (inherit (package-source glibc)) + (uri (string-append "mirror://gnu/glibc/glibc-" version ".tar.xz")) + (sha256 + (base32 + "0wpwq7gsm7sd6ysidv0z575ckqdg13cr2njyfgrbgh4f65adwwji")) + (patches (search-patches "glibc-ldd-x86_64.patch" + "glibc-2.27-git-fixes.patch" + "glibc-hidden-visibility-ldconfig.patch" + "glibc-versioned-locpath.patch" + "glibc-allow-kernel-2.6.32.patch" + "glibc-reinstate-prlimit64-fallback.patch" + "glibc-2.27-supported-locales.patch" + "glibc-CVE-2018-11236.patch" + "glibc-CVE-2018-11237.patch")))) + (properties `((lint-hidden-cve . ("CVE-2017-18269")))))) ; glibc-2.27-git-fixes + +(define-public glibc-2.26 + (package + (inherit glibc-2.27) + ;; This version number corresponds to the output of `git describe` and the + ;; archive can be generated by checking out the commit ID and running: + ;; git archive --prefix=$(git describe)/ HEAD | xz > $(git describe).tar.xz + ;; See for why this was necessary. + (version "2.26.105-g0890d5379c") + (source (origin + (inherit (package-source glibc)) + (uri (string-append "https://alpha.gnu.org/gnu/guix/mirror/" + "glibc-" (version-major+minor version) "-" + (caddr (string-split version #\.)) ".tar.xz")) + (sha256 + (base32 + "1jck0c1i248sn02rvsfjykk77qncma34bjq89dyy2irwm50d7s3g")) + (patches (search-patches "glibc-ldd-x86_64.patch" + "glibc-versioned-locpath.patch" + "glibc-allow-kernel-2.6.32.patch")))) + (native-inputs + ;; This fails with a build error in if_index.c when using GCC 8. Use an + ;; older compiler. + (modify-inputs (package-native-inputs glibc-2.27) + (replace "gcc" gcc-7))))) + +(define-public glibc-2.25 + (package + (inherit glibc-2.26) + (version "2.25") + (source (origin + (inherit (package-source glibc)) + (uri (string-append "mirror://gnu/glibc/glibc-" + version ".tar.xz")) + (sha256 + (base32 + "1813dzkgw6v8q8q1m4v96yfis7vjqc9pslqib6j9mrwh6fxxjyq6")) + (patches (search-patches "glibc-ldd-x86_64.patch" + "glibc-versioned-locpath.patch" + "glibc-vectorized-strcspn-guards.patch" + "glibc-CVE-2017-1000366-pt1.patch" + "glibc-CVE-2017-1000366-pt2.patch" + "glibc-CVE-2017-1000366-pt3.patch" + "glibc-cvs-common-symbols.patch")))))) + (define-public (make-gcc-libc base-gcc libc) "Return a GCC that targets LIBC." (package (inherit base-gcc) diff --git a/gnu/packages/patches/glibc-2.27-git-fixes.patch b/gnu/packages/patches/glibc-2.27-git-fixes.patch new file mode 100644 index 0000000000..4ed67c7c25 --- /dev/null +++ b/gnu/packages/patches/glibc-2.27-git-fixes.patch @@ -0,0 +1,702 @@ +These commits are cherry-picked from the "release/2.27/master" branch. + +https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.27/master + +Currently, we have the following (with NEWS and ChangeLog entries omitted). + +56170e064e2b21ce204f0817733e92f1730541ea +516fa6080481a1433c173320b1c1432868e1e38a +f36553bf6a4f69070f99badbdab5802b43e6e211 +7c6304182b9f422b782ace1cdd3efbde056aec36 +78a90c2f74a2012dd3eff302189e47ff6779a757 +1e52d8e65a58c49a48549053a1b89c06240e0c6c +55ad82e45c313454de657931898e974a7a036cad + +From 56170e064e2b21ce204f0817733e92f1730541ea Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Wed, 7 Feb 2018 13:53:10 +0100 +Subject: [PATCH] Linux: use reserved name __key in pkey_get [BZ #22797] + +_key is not reserved name and we should avoid using that. It seems that +it was simple typo when pkey_* was implemented. + +(cherry picked from commit 388ff7bd0d57d7061fdd39a2f26f65687e8058da) + +diff --git a/sysdeps/unix/sysv/linux/bits/mman-shared.h b/sysdeps/unix/sysv/linux/bits/mman-shared.h +index 7715e680ca..d15ba95c9d 100644 +--- a/sysdeps/unix/sysv/linux/bits/mman-shared.h ++++ b/sysdeps/unix/sysv/linux/bits/mman-shared.h +@@ -61,7 +61,7 @@ int pkey_set (int __key, unsigned int __access_rights) __THROW; + + /* Return the access rights for the current thread for KEY, which must + have been allocated using pkey_alloc. */ +-int pkey_get (int _key) __THROW; ++int pkey_get (int __key) __THROW; + + /* Free an allocated protection key, which must have been allocated + using pkey_alloc. */ + +From 516fa6080481a1433c173320b1c1432868e1e38a Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Fri, 29 Dec 2017 23:19:32 +0000 +Subject: [PATCH] linux/aarch64: sync sys/ptrace.h with Linux 4.15 [BZ #22433] + +Remove compat-specific constants that were never exported by kernel +headers under these names. Before linux commit v3.7-rc1~16^2~1 they +were exported with COMPAT_ prefix, and since that commit they are not +exported at all. + +* sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h (__ptrace_request): +Remove arm-specific PTRACE_GET_THREAD_AREA, PTRACE_GETHBPREGS, +and PTRACE_SETHBPREGS. + +(cherry picked from commit 2fd4bbaa1446f1be700e10c526cf585a796c4991) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h +index 4be45b95ff..444edbb702 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h +@@ -78,18 +78,10 @@ enum __ptrace_request + PTRACE_DETACH = 17, + #define PT_DETACH PTRACE_DETACH + +- PTRACE_GET_THREAD_AREA = 22, +- + /* Continue and stop at the next entry to or return from syscall. */ + PTRACE_SYSCALL = 24, + #define PT_SYSCALL PTRACE_SYSCALL + +- /* Get all hardware breakpoint registers. */ +- PTRACE_GETHBPREGS = 29, +- +- /* Set all hardware breakpoint registers. */ +- PTRACE_SETHBPREGS = 30, +- + /* Set ptrace filter options. */ + PTRACE_SETOPTIONS = 0x4200, + #define PT_SETOPTIONS PTRACE_SETOPTIONS + +From f36553bf6a4f69070f99badbdab5802b43e6e211 Mon Sep 17 00:00:00 2001 +From: Mike FABIAN +Date: Mon, 19 Feb 2018 21:59:30 +0100 +Subject: [PATCH] =?UTF-8?q?Add=20missing=20=E2=80=9Creorder-end=E2=80=9D?= + =?UTF-8?q?=20in=20LC=5FCOLLATE=20of=20et=5FEE=20[BZ=20#22517]?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + [BZ #22517] + * localedata/locales/et_EE (LC_COLLATE): add missing “reorder-end” + +(cherry picked from commit 7ec5f9465e732e668d0dc94ac078ba68056d6d0a) + +diff --git a/localedata/locales/et_EE b/localedata/locales/et_EE +index 9cb55b568f..bab7493c98 100644 +--- a/localedata/locales/et_EE ++++ b/localedata/locales/et_EE +@@ -103,6 +103,8 @@ reorder-after + ;;;IGNORE % ü + ;;;IGNORE % Ü + ++reorder-end ++ + END LC_COLLATE + + LC_CTYPE + +From 7c6304182b9f422b782ace1cdd3efbde056aec36 Mon Sep 17 00:00:00 2001 +From: DJ Delorie +Date: Thu, 1 Mar 2018 23:20:45 -0500 +Subject: [PATCH] [BZ #22342] Fix netgroup cache keys. + +Unlike other nscd caches, the netgroup cache contains two types of +records - those for "iterate through a netgroup" (i.e. setnetgrent()) +and those for "is this user in this netgroup" (i.e. innetgr()), +i.e. full and partial records. The timeout code assumes these records +have the same key for the group name, so that the collection of records +that is "this netgroup" can be expired as a unit. + +However, the keys are not the same, as the in-netgroup key is generated +by nscd rather than being passed to it from elsewhere, and is generated +without the trailing NUL. All other keys have the trailing NUL, and as +noted in the linked BZ, debug statements confirm that two keys for the +same netgroup are added to the cache with two different lengths. + +The result of this is that as records in the cache expire, the purge +code only cleans out one of the two types of entries, resulting in +stale, possibly incorrect, and possibly inconsistent cache data. + +The patch simply includes the existing NUL in the computation for the +key length ('key' points to the char after the NUL, and 'group' to the +first char of the group, so 'key-group' includes the first char to the +NUL, inclusive). + + [BZ #22342] + * nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in + key value. + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 1c81d55fc4b07b51adf68558ba74ce975153e580) + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index b832c9315f..2f187b208c 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -480,7 +480,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + { + const char *group = key; + key = (char *) rawmemchr (key, '\0') + 1; +- size_t group_len = key - group - 1; ++ size_t group_len = key - group; + const char *host = *key++ ? key : NULL; + if (host != NULL) + key = (char *) rawmemchr (key, '\0') + 1; + +From 78a90c2f74a2012dd3eff302189e47ff6779a757 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Fri, 2 Mar 2018 23:07:14 +0100 +Subject: [PATCH] Fix multiple definitions of __nss_*_database (bug 22918) + +(cherry picked from commit eaf6753f8aac33a36deb98c1031d1bad7b593d2d) + +diff --git a/nscd/gai.c b/nscd/gai.c +index d081747797..576fd0045b 100644 +--- a/nscd/gai.c ++++ b/nscd/gai.c +@@ -45,3 +45,6 @@ + #ifdef HAVE_LIBIDN + # include + #endif ++ ++/* Some variables normally defined in libc. */ ++service_user *__nss_hosts_database attribute_hidden; +diff --git a/nss/nsswitch.c b/nss/nsswitch.c +index d5e655974f..b0f0c11a3e 100644 +--- a/nss/nsswitch.c ++++ b/nss/nsswitch.c +@@ -62,7 +62,7 @@ static service_library *nss_new_service (name_database *database, + + /* Declare external database variables. */ + #define DEFINE_DATABASE(name) \ +- extern service_user *__nss_##name##_database attribute_hidden; \ ++ service_user *__nss_##name##_database attribute_hidden; \ + weak_extern (__nss_##name##_database) + #include "databases.def" + #undef DEFINE_DATABASE +diff --git a/nss/nsswitch.h b/nss/nsswitch.h +index eccb535ef5..63573b9ebc 100644 +--- a/nss/nsswitch.h ++++ b/nss/nsswitch.h +@@ -226,10 +226,10 @@ libc_hidden_proto (__nss_hostname_digits_dots) + #define MAX_NR_ADDRS 48 + + /* Prototypes for __nss_*_lookup2 functions. */ +-#define DEFINE_DATABASE(arg) \ +- service_user *__nss_##arg##_database attribute_hidden; \ +- int __nss_##arg##_lookup2 (service_user **, const char *, \ +- const char *, void **); \ ++#define DEFINE_DATABASE(arg) \ ++ extern service_user *__nss_##arg##_database attribute_hidden; \ ++ int __nss_##arg##_lookup2 (service_user **, const char *, \ ++ const char *, void **); \ + libc_hidden_proto (__nss_##arg##_lookup2) + #include "databases.def" + #undef DEFINE_DATABASE +diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c +index f509534ca9..8c64ac59ff 100644 +--- a/posix/tst-rfc3484-2.c ++++ b/posix/tst-rfc3484-2.c +@@ -58,6 +58,7 @@ _res_hconf_init (void) + #undef USE_NSCD + #include "../sysdeps/posix/getaddrinfo.c" + ++service_user *__nss_hosts_database attribute_hidden; + + /* This is the beginning of the real test code. The above defines + (among other things) the function rfc3484_sort. */ +diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c +index ae44087a10..1c61aaf844 100644 +--- a/posix/tst-rfc3484-3.c ++++ b/posix/tst-rfc3484-3.c +@@ -58,6 +58,7 @@ _res_hconf_init (void) + #undef USE_NSCD + #include "../sysdeps/posix/getaddrinfo.c" + ++service_user *__nss_hosts_database attribute_hidden; + + /* This is the beginning of the real test code. The above defines + (among other things) the function rfc3484_sort. */ +diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c +index 7f191abbbc..8f45848e44 100644 +--- a/posix/tst-rfc3484.c ++++ b/posix/tst-rfc3484.c +@@ -58,6 +58,7 @@ _res_hconf_init (void) + #undef USE_NSCD + #include "../sysdeps/posix/getaddrinfo.c" + ++service_user *__nss_hosts_database attribute_hidden; + + /* This is the beginning of the real test code. The above defines + (among other things) the function rfc3484_sort. */ + +From 1e52d8e65a58c49a48549053a1b89c06240e0c6c Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 17 Nov 2017 16:04:29 -0200 +Subject: [PATCH] i386: Fix i386 sigaction sa_restorer initialization + (BZ#21269) + +This patch fixes the i386 sa_restorer field initialization for sigaction +syscall for kernel with vDSO. As described in bug report, i386 Linux +(and compat on x86_64) interprets SA_RESTORER clear with nonzero +sa_restorer as a request for stack switching if the SS segment is 'funny'. +This means that anything that tries to mix glibc's signal handling with +segmentation (for instance through modify_ldt syscall) is randomly broken +depending on what values lands in sa_restorer. + +The testcase added is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, +more specifically in do_multicpu_tests function. The main changes are: + + - C11 atomics instead of plain access. + + - Remove x86_64 support which simplifies the syscall handling and fallbacks. + + - Replicate only the test required to trigger the issue. + +Checked on i686-linux-gnu. + + [BZ #21269] + * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269. + * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear + sa_restorer for vDSO case. + * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file. + +(cherry picked from commit 68448be208ee06e76665918b37b0a57e3e00c8b4) + +diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile +index 4080b8c966..da716e2c1b 100644 +--- a/sysdeps/unix/sysv/linux/i386/Makefile ++++ b/sysdeps/unix/sysv/linux/i386/Makefile +@@ -3,6 +3,9 @@ default-abi := 32 + + ifeq ($(subdir),misc) + sysdep_routines += ioperm iopl vm86 ++ ++tests += tst-bz21269 ++$(objpfx)tst-bz21269: $(shared-thread-library) + endif + + ifeq ($(subdir),elf) +diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c +index a5eb9e0d3e..177ff60ee6 100644 +--- a/sysdeps/unix/sysv/linux/i386/sigaction.c ++++ b/sysdeps/unix/sysv/linux/i386/sigaction.c +@@ -42,7 +42,6 @@ extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; + #endif + extern void restore (void) asm ("__restore") attribute_hidden; + +- + /* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ + int +@@ -65,6 +64,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) + kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) + ? &restore_rt : &restore); + } ++ else ++ kact.sa_restorer = NULL; + } + + /* XXX The size argument hopefully will have to be changed to the +diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +new file mode 100644 +index 0000000000..353e36507d +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +@@ -0,0 +1,233 @@ ++/* Test for i386 sigaction sa_restorer handling (BZ#21269) ++ Copyright (C) 2017 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 ++ . */ ++ ++/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, ++ more specifically in do_multicpu_tests function. The main changes ++ are: ++ ++ - C11 atomics instead of plain access. ++ - Remove x86_64 support which simplifies the syscall handling ++ and fallbacks. ++ - Replicate only the test required to trigger the issue for the ++ BZ#21269. */ ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++static int ++xset_thread_area (struct user_desc *u_info) ++{ ++ long ret = syscall (SYS_set_thread_area, u_info); ++ TEST_VERIFY_EXIT (ret == 0); ++ return ret; ++} ++ ++static void ++xmodify_ldt (int func, const void *ptr, unsigned long bytecount) ++{ ++ TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0); ++} ++ ++static int ++futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2, ++ int val3) ++{ ++ return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); ++} ++ ++static void ++xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags) ++{ ++ struct sigaction sa = { 0 }; ++ sa.sa_sigaction = handler; ++ sa.sa_flags = SA_SIGINFO | flags; ++ TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0); ++ TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0); ++} ++ ++static jmp_buf jmpbuf; ++ ++static void ++sigsegv_handler (int sig, siginfo_t *info, void *ctx_void) ++{ ++ siglongjmp (jmpbuf, 1); ++} ++ ++/* Points to an array of 1024 ints, each holding its own index. */ ++static const unsigned int *counter_page; ++static struct user_desc *low_user_desc; ++static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry. */ ++static int gdt_entry_num; ++ ++static void ++setup_counter_page (void) ++{ ++ long page_size = sysconf (_SC_PAGE_SIZE); ++ TEST_VERIFY_EXIT (page_size > 0); ++ unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); ++ for (int i = 0; i < (page_size / sizeof (unsigned int)); i++) ++ page[i] = i; ++ counter_page = page; ++} ++ ++static void ++setup_low_user_desc (void) ++{ ++ low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc), ++ PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); ++ ++ low_user_desc->entry_number = -1; ++ low_user_desc->base_addr = (unsigned long) &counter_page[1]; ++ low_user_desc->limit = 0xffff; ++ low_user_desc->seg_32bit = 1; ++ low_user_desc->contents = 0; ++ low_user_desc->read_exec_only = 0; ++ low_user_desc->limit_in_pages = 1; ++ low_user_desc->seg_not_present = 0; ++ low_user_desc->useable = 0; ++ ++ xset_thread_area (low_user_desc); ++ ++ low_user_desc_clear = low_user_desc + 1; ++ low_user_desc_clear->entry_number = gdt_entry_num; ++ low_user_desc_clear->read_exec_only = 1; ++ low_user_desc_clear->seg_not_present = 1; ++} ++ ++/* Possible values of futex: ++ 0: thread is idle. ++ 1: thread armed. ++ 2: thread should clear LDT entry 0. ++ 3: thread should exit. */ ++static atomic_uint ftx; ++ ++static void * ++threadproc (void *ctx) ++{ ++ while (1) ++ { ++ futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); ++ while (atomic_load (&ftx) != 2) ++ { ++ if (atomic_load (&ftx) >= 3) ++ return NULL; ++ } ++ ++ /* clear LDT entry 0. */ ++ const struct user_desc desc = { 0 }; ++ xmodify_ldt (1, &desc, sizeof (desc)); ++ ++ /* If ftx == 2, set it to zero, If ftx == 100, quit. */ ++ if (atomic_fetch_add (&ftx, -2) != 2) ++ return NULL; ++ } ++} ++ ++ ++/* As described in testcase, for historical reasons x86_32 Linux (and compat ++ on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a ++ request for stack switching if the SS segment is 'funny' (this is default ++ scenario for vDSO system). This means that anything that tries to mix ++ signal handling with segmentation should explicit clear the sa_restorer. ++ ++ This testcase check if sigaction in fact does it by changing the local ++ descriptor table (LDT) through the modify_ldt syscall and triggering ++ a synchronous segfault on iret fault by trying to install an invalid ++ segment. With a correct zeroed sa_restorer it should not trigger an ++ 'real' SEGSEGV and allows the siglongjmp in signal handler. */ ++ ++static int ++do_test (void) ++{ ++ setup_counter_page (); ++ setup_low_user_desc (); ++ ++ pthread_t thread; ++ unsigned short orig_ss; ++ ++ xsethandler (SIGSEGV, sigsegv_handler, 0); ++ /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ ++ xsethandler (SIGILL, sigsegv_handler, 0); ++ ++ thread = xpthread_create (0, threadproc, 0); ++ ++ asm volatile ("mov %%ss, %0" : "=rm" (orig_ss)); ++ ++ for (int i = 0; i < 5; i++) ++ { ++ if (sigsetjmp (jmpbuf, 1) != 0) ++ continue; ++ ++ /* Make sure the thread is ready after the last test. */ ++ while (atomic_load (&ftx) != 0) ++ ; ++ ++ struct user_desc desc = { ++ .entry_number = 0, ++ .base_addr = 0, ++ .limit = 0xffff, ++ .seg_32bit = 1, ++ .contents = 0, ++ .read_exec_only = 0, ++ .limit_in_pages = 1, ++ .seg_not_present = 0, ++ .useable = 0 ++ }; ++ ++ xmodify_ldt (0x11, &desc, sizeof (desc)); ++ ++ /* Arm the thread. */ ++ ftx = 1; ++ futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); ++ ++ asm volatile ("mov %0, %%ss" : : "r" (0x7)); ++ ++ /* Fire up thread modify_ldt call. */ ++ atomic_store (&ftx, 2); ++ ++ while (atomic_load (&ftx) != 0) ++ ; ++ ++ /* On success, modify_ldt will segfault us synchronously and we will ++ escape via siglongjmp. */ ++ support_record_failure (); ++ } ++ ++ atomic_store (&ftx, 100); ++ futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); ++ ++ xpthread_join (thread); ++ ++ return 0; ++} ++ ++#include + +From 55ad82e45c313454de657931898e974a7a036cad Mon Sep 17 00:00:00 2001 +From: Andrew Senkevich +Date: Fri, 23 Mar 2018 16:19:45 +0100 +Subject: [PATCH] Fix i386 memmove issue (bug 22644). + + [BZ #22644] + * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed + branch conditions. + * string/test-memmove.c (do_test2): New testcase. + +(cherry picked from commit cd66c0e584c6d692bc8347b5e72723d02b8a8ada) + +diff --git a/string/test-memmove.c b/string/test-memmove.c +index edc7a4c3bf..64e3651ba4 100644 +--- a/string/test-memmove.c ++++ b/string/test-memmove.c +@@ -24,6 +24,7 @@ + # define TEST_NAME "memmove" + #endif + #include "test-string.h" ++#include + + char *simple_memmove (char *, const char *, size_t); + +@@ -245,6 +246,60 @@ do_random_tests (void) + } + } + ++static void ++do_test2 (void) ++{ ++ size_t size = 0x20000000; ++ uint32_t * large_buf; ++ ++ large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON, -1, 0); ++ ++ if (large_buf == MAP_FAILED) ++ error (EXIT_UNSUPPORTED, errno, "Large mmap failed"); ++ ++ if ((uintptr_t) large_buf > 0x80000000 - 128 ++ || 0x80000000 - (uintptr_t) large_buf > 0x20000000) ++ { ++ error (0, 0, "Large mmap allocated improperly"); ++ ret = EXIT_UNSUPPORTED; ++ munmap ((void *) large_buf, size); ++ return; ++ } ++ ++ size_t bytes_move = 0x80000000 - (uintptr_t) large_buf; ++ size_t arr_size = bytes_move / sizeof (uint32_t); ++ size_t i; ++ ++ FOR_EACH_IMPL (impl, 0) ++ { ++ for (i = 0; i < arr_size; i++) ++ large_buf[i] = (uint32_t) i; ++ ++ uint32_t * dst = &large_buf[33]; ++ ++#ifdef TEST_BCOPY ++ CALL (impl, (char *) large_buf, (char *) dst, bytes_move); ++#else ++ CALL (impl, (char *) dst, (char *) large_buf, bytes_move); ++#endif ++ ++ for (i = 0; i < arr_size; i++) ++ { ++ if (dst[i] != (uint32_t) i) ++ { ++ error (0, 0, ++ "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", ++ impl->name, dst, large_buf, i); ++ ret = 1; ++ break; ++ } ++ } ++ } ++ ++ munmap ((void *) large_buf, size); ++} ++ + int + test_main (void) + { +@@ -284,6 +339,9 @@ test_main (void) + } + + do_random_tests (); ++ ++ do_test2 (); ++ + return ret; + } + +diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +index 9c3bbe7e17..9aa17de99c 100644 +--- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S ++++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +@@ -72,7 +72,7 @@ ENTRY (MEMCPY) + cmp %edx, %eax + + # ifdef USE_AS_MEMMOVE +- jg L(check_forward) ++ ja L(check_forward) + + L(mm_len_0_or_more_backward): + /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128] +@@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward): + jbe L(mm_len_0_16_bytes_backward) + + cmpl $32, %ecx +- jg L(mm_len_32_or_more_backward) ++ ja L(mm_len_32_or_more_backward) + + /* Copy [0..32] and return. */ + movdqu (%eax), %xmm0 +@@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward): + + L(mm_len_32_or_more_backward): + cmpl $64, %ecx +- jg L(mm_len_64_or_more_backward) ++ ja L(mm_len_64_or_more_backward) + + /* Copy [0..64] and return. */ + movdqu (%eax), %xmm0 +@@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward): + + L(mm_len_64_or_more_backward): + cmpl $128, %ecx +- jg L(mm_len_128_or_more_backward) ++ ja L(mm_len_128_or_more_backward) + + /* Copy [0..128] and return. */ + movdqu (%eax), %xmm0 +@@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward): + add %ecx, %eax + cmp %edx, %eax + movl SRC(%esp), %eax +- jle L(forward) ++ jbe L(forward) + PUSH (%esi) + PUSH (%edi) + PUSH (%ebx) +@@ -269,7 +269,7 @@ L(check_forward): + add %edx, %ecx + cmp %eax, %ecx + movl LEN(%esp), %ecx +- jle L(forward) ++ jbe L(forward) + + /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128] + separately. */ diff --git a/gnu/packages/patches/glibc-2.27-supported-locales.patch b/gnu/packages/patches/glibc-2.27-supported-locales.patch new file mode 100644 index 0000000000..2888052bb8 --- /dev/null +++ b/gnu/packages/patches/glibc-2.27-supported-locales.patch @@ -0,0 +1,33 @@ +This patch is taken from debian's glibc package (generate-supported.mk). +It install the localedata/SUPPORTED file of the glibc. This file lists +all the supported locales of the glibc. + +diff --git a/localedata/Makefile.old b/localedata/Makefile +index 34877c0..a61d9b9 100644 +--- a/localedata/Makefile.old ++++ b/localedata/Makefile +@@ -91,7 +91,8 @@ endif + # Files to install. + install-others := $(addprefix $(inst_i18ndir)/, \ + $(addsuffix .gz, $(charmaps)) \ +- $(locales)) ++ $(locales)) \ ++ $(inst_i18ndir)/SUPPORTED + + tests: $(objdir)/iconvdata/gconv-modules + +@@ -195,6 +196,14 @@ endif + + include SUPPORTED + ++$(inst_i18ndir)/SUPPORTED: SUPPORTED $(+force) ++ for locale in $(SUPPORTED-LOCALES); do \ ++ [ $$locale = true ] && continue; \ ++ echo $$locale | sed 's,/, ,' >> LOCALES; \ ++ done ++ $(make-target-directory) ++ $(INSTALL_DATA) LOCALES $@ ++ + INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES)) + + # Sometimes the whole collection of locale files should be installed. diff --git a/gnu/packages/patches/glibc-2.28-git-fixes.patch b/gnu/packages/patches/glibc-2.28-git-fixes.patch new file mode 100644 index 0000000000..7e370ef0b1 --- /dev/null +++ b/gnu/packages/patches/glibc-2.28-git-fixes.patch @@ -0,0 +1,248 @@ +This file contains fixes from the "release/2.28/master" branch: +https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.28/master + +Currently we have these commits (sans tests and ChangeLog updates): +7f11842e7483da7aa9fa3031be122021978ef600 +726e1554ce4db5e35af41cb0110c54c5e1232054 +4b25485f03158959cff45379eecc1d73c7dcdd11 +d05b05d1570ba3ae354a2f5a3cfeefb373b09979 +bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0 +2f498f3d140ab5152bd784df2be7af7d9c5e63ed + +diff --git a/htl/Versions b/htl/Versions +index 6a63a1b8a1..c5a616da10 100644 +--- a/htl/Versions ++++ b/htl/Versions +@@ -150,6 +150,8 @@ libpthread { + __cthread_keycreate; + __cthread_getspecific; + __cthread_setspecific; ++ __pthread_getspecific; ++ __pthread_setspecific; + __pthread_getattr_np; + __pthread_attr_getstack; + } + +diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c +index a0227a67f6..64ddf9551a 100644 +--- a/sysdeps/htl/pt-getspecific.c ++++ b/sysdeps/htl/pt-getspecific.c +@@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key) + return self->thread_specifics[key]; + } + strong_alias (__pthread_getspecific, pthread_getspecific); ++hidden_def (__pthread_getspecific) +diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c +index a46a12f157..02aff417ef 100644 +--- a/sysdeps/htl/pt-setspecific.c ++++ b/sysdeps/htl/pt-setspecific.c +@@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value) + return 0; + } + strong_alias (__pthread_setspecific, pthread_setspecific); ++hidden_def (__pthread_setspecific) +diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h +index 132ac1718e..71c2fcd9c6 100644 +--- a/sysdeps/htl/pthreadP.h ++++ b/sysdeps/htl/pthreadP.h +@@ -68,6 +68,8 @@ struct __pthread_cancelation_handler **___pthread_get_cleanup_stack (void) attri + + #if IS_IN (libpthread) + hidden_proto (__pthread_key_create) ++hidden_proto (__pthread_getspecific) ++hidden_proto (__pthread_setspecific) + hidden_proto (_pthread_mutex_init) + #endif + +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c +index 3bde0cf4f0..bc140b5a7f 100644 +--- a/sysdeps/unix/sysv/linux/getdents64.c ++++ b/sysdeps/unix/sysv/linux/getdents64.c +@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents) + # include + + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +-# include ++# include ++# include + +-/* kernel definition of as of 3.2. */ +-struct compat_linux_dirent ++static ssize_t ++handle_overflow (int fd, __off64_t offset, ssize_t count) + { +- /* Both d_ino and d_off are compat_ulong_t which are defined in all +- architectures as 'u32'. */ +- uint32_t d_ino; +- uint32_t d_off; +- unsigned short d_reclen; +- char d_name[1]; +-}; ++ /* If this is the first entry in the buffer, we can report the ++ error. */ ++ if (count == 0) ++ { ++ __set_errno (EOVERFLOW); ++ return -1; ++ } ++ ++ /* Otherwise, seek to the overflowing entry, so that the next call ++ will report the error, and return the data read so far.. */ ++ if (__lseek64 (fd, offset, SEEK_SET) != 0) ++ return -1; ++ return count; ++} + + ssize_t + __old_getdents64 (int fd, char *buf, size_t nbytes) + { +- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes); ++ /* We do not move the individual directory entries. This is only ++ possible if the target type (struct __old_dirent64) is smaller ++ than the source type. */ ++ _Static_assert (offsetof (struct __old_dirent64, d_name) ++ <= offsetof (struct dirent64, d_name), ++ "__old_dirent64 is larger than dirent64"); ++ _Static_assert (__alignof__ (struct __old_dirent64) ++ <= __alignof__ (struct dirent64), ++ "alignment of __old_dirent64 is larger than dirent64"); + +- /* The kernel added the d_type value after the name. Change this now. */ +- if (retval != -1) ++ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); ++ if (retval > 0) + { +- union +- { +- struct compat_linux_dirent k; +- struct dirent u; +- } *kbuf = (void *) buf; +- +- while ((char *) kbuf < buf + retval) ++ char *p = buf; ++ char *end = buf + retval; ++ while (p < end) + { +- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); +- memmove (kbuf->u.d_name, kbuf->k.d_name, +- strlen (kbuf->k.d_name) + 1); +- kbuf->u.d_type = d_type; ++ struct dirent64 *source = (struct dirent64 *) p; ++ ++ /* Copy out the fixed-size data. */ ++ __ino_t ino = source->d_ino; ++ __off64_t offset = source->d_off; ++ unsigned int reclen = source->d_reclen; ++ unsigned char type = source->d_type; ++ ++ /* Check for ino_t overflow. */ ++ if (__glibc_unlikely (ino != source->d_ino)) ++ return handle_overflow (fd, offset, p - buf); ++ ++ /* Convert to the target layout. Use a separate struct and ++ memcpy to side-step aliasing issues. */ ++ struct __old_dirent64 result; ++ result.d_ino = ino; ++ result.d_off = offset; ++ result.d_reclen = reclen; ++ result.d_type = type; ++ ++ /* Write the fixed-sized part of the result to the ++ buffer. */ ++ size_t result_name_offset = offsetof (struct __old_dirent64, d_name); ++ memcpy (p, &result, result_name_offset); ++ ++ /* Adjust the position of the name if necessary. Copy ++ everything until the end of the record, including the ++ terminating NUL byte. */ ++ if (result_name_offset != offsetof (struct dirent64, d_name)) ++ memmove (p + result_name_offset, source->d_name, ++ reclen - offsetof (struct dirent64, d_name)); + +- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); ++ p += reclen; + } + } + return retval; + +diff --git a/misc/error.c b/misc/error.c +index b4e8b6c938..03378e2f2a 100644 +--- a/misc/error.c ++++ b/misc/error.c +@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...) + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name, + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); + +diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c +index 265a02434d..7293b795b6 100644 +--- a/nscd/nscd_conf.c ++++ b/nscd/nscd_conf.c +@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + if (!arg1) + error (0, 0, _("Must specify user name for server-user option")); + else +- server_user = xstrdup (arg1); ++ { ++ free ((char *) server_user); ++ server_user = xstrdup (arg1); ++ } + } + else if (strcmp (entry, "stat-user") == 0) + { +@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + error (0, 0, _("Must specify user name for stat-user option")); + else + { ++ free ((char *) stat_user); + stat_user = xstrdup (arg1); + + struct passwd *pw = getpwnam (stat_user); + +diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +index cfd34b66b9..35b0bfc5d2 100644 +--- a/nss/nss_files/files-alias.c ++++ b/nss/nss_files/files-alias.c +@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + { + while (! feof_unlocked (listfile)) + { ++ if (room_left < 2) ++ { ++ free (old_line); ++ fclose (listfile); ++ goto no_more_room; ++ } ++ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, + listfile); +@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + if (first_unused[room_left - 1] != '\xff') + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + +@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + + __alignof__ (char *))) + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + room_left -= ((first_unused - cp) + diff --git a/gnu/packages/patches/glibc-2.28-supported-locales.patch b/gnu/packages/patches/glibc-2.28-supported-locales.patch new file mode 100644 index 0000000000..2888052bb8 --- /dev/null +++ b/gnu/packages/patches/glibc-2.28-supported-locales.patch @@ -0,0 +1,33 @@ +This patch is taken from debian's glibc package (generate-supported.mk). +It install the localedata/SUPPORTED file of the glibc. This file lists +all the supported locales of the glibc. + +diff --git a/localedata/Makefile.old b/localedata/Makefile +index 34877c0..a61d9b9 100644 +--- a/localedata/Makefile.old ++++ b/localedata/Makefile +@@ -91,7 +91,8 @@ endif + # Files to install. + install-others := $(addprefix $(inst_i18ndir)/, \ + $(addsuffix .gz, $(charmaps)) \ +- $(locales)) ++ $(locales)) \ ++ $(inst_i18ndir)/SUPPORTED + + tests: $(objdir)/iconvdata/gconv-modules + +@@ -195,6 +196,14 @@ endif + + include SUPPORTED + ++$(inst_i18ndir)/SUPPORTED: SUPPORTED $(+force) ++ for locale in $(SUPPORTED-LOCALES); do \ ++ [ $$locale = true ] && continue; \ ++ echo $$locale | sed 's,/, ,' >> LOCALES; \ ++ done ++ $(make-target-directory) ++ $(INSTALL_DATA) LOCALES $@ ++ + INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES)) + + # Sometimes the whole collection of locale files should be installed. diff --git a/gnu/packages/patches/glibc-CVE-2015-5180.patch b/gnu/packages/patches/glibc-CVE-2015-5180.patch new file mode 100644 index 0000000000..92e3740fc1 --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2015-5180.patch @@ -0,0 +1,311 @@ +From b3b37f1a5559a7620e31c8053ed1b44f798f2b6d Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Sat, 31 Dec 2016 20:22:09 +0100 +Subject: [PATCH] CVE-2015-5180: resolv: Fix crash with internal QTYPE [BZ + #18784] + +Also rename T_UNSPEC because an upcoming public header file +update will use that name. + +(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5) +--- + ChangeLog | 14 ++++ + NEWS | 6 ++ + include/arpa/nameser_compat.h | 6 +- + resolv/Makefile | 5 ++ + resolv/nss_dns/dns-host.c | 2 +- + resolv/res_mkquery.c | 4 + + resolv/res_query.c | 6 +- + resolv/tst-resolv-qtypes.c | 185 ++++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 221 insertions(+), 7 deletions(-) + create mode 100644 resolv/tst-resolv-qtypes.c + +diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h +index 2e735ed..7c0deed 100644 +--- a/include/arpa/nameser_compat.h ++++ b/include/arpa/nameser_compat.h +@@ -1,8 +1,8 @@ + #ifndef _ARPA_NAMESER_COMPAT_ + #include + +-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e., +- T_A and T_AAAA). */ +-#define T_UNSPEC 62321 ++/* The number is outside the 16-bit RR type range and is used ++ internally by the implementation. */ ++#define T_QUERY_A_AND_AAAA 439963904 + + #endif +diff --git a/resolv/Makefile b/resolv/Makefile +index 8be41d3..a4c86b9 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes) + extra-libs += libanl + routines += gai_sigqueue + tests += tst-res_hconf_reorder ++ ++# This test sends millions of packets and is rather slow. ++xtests += tst-resolv-qtypes + endif + extra-libs-others = $(extra-libs) + libresolv-routines := gethnamaddr res_comp res_debug \ +@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace + $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 5f9e357..d16fa4b 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -323,7 +323,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + + int olderr = errno; + enum nss_status status; +- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, ++ int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); + if (n >= 0) +diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c +index 12f9730..d80b531 100644 +--- a/resolv/res_mkquery.c ++++ b/resolv/res_mkquery.c +@@ -103,6 +103,10 @@ res_nmkquery(res_state statp, + int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + ++ if (class < 0 || class > 65535 ++ || type < 0 || type > 65535) ++ return -1; ++ + #ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", +diff --git a/resolv/res_query.c b/resolv/res_query.c +index 944d1a9..07dc6f6 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp, + int n, use_malloc = 0; + u_int oflags = statp->_flags; + +- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE; ++ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; + u_char *buf = alloca (bufsize); + u_char *query1 = buf; + int nquery1 = -1; +@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp, + printf(";; res_query(%s, %d, %d)\n", name, class, type); + #endif + +- if (type == T_UNSPEC) ++ if (type == T_QUERY_A_AND_AAAA) + { + n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL, + query1, bufsize); +@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp, + if (__builtin_expect (n <= 0, 0) && !use_malloc) { + /* Retry just in case res_nmkquery failed because of too + short buffer. Shouldn't happen. */ +- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET; ++ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET; + buf = malloc (bufsize); + if (buf != NULL) { + query1 = buf; +diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c +new file mode 100644 +index 0000000..b3e60c6 +--- /dev/null ++++ b/resolv/tst-resolv-qtypes.c +@@ -0,0 +1,185 @@ ++/* Exercise low-level query functions with different QTYPEs. ++ 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; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* If ture, the response function will send the actual response packet ++ over TCP instead of UDP. */ ++static volatile bool force_tcp; ++ ++/* Send back a fake resource record matching the QTYPE. */ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ if (force_tcp && ctx->tcp) ++ { ++ resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 }); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ return; ++ } ++ ++ resolv_response_init (b, (struct resolv_response_flags) { }); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ resolv_response_section (b, ns_s_an); ++ resolv_response_open_record (b, qname, qclass, qtype, 0); ++ resolv_response_add_data (b, &qtype, sizeof (qtype)); ++ resolv_response_close_record (b); ++} ++ ++static const const char *domain = "www.example.com"; ++ ++static int ++wrap_res_query (int type, unsigned char *answer, int answer_length) ++{ ++ return res_query (domain, C_IN, type, answer, answer_length); ++} ++ ++static int ++wrap_res_search (int type, unsigned char *answer, int answer_length) ++{ ++ return res_query (domain, C_IN, type, answer, answer_length); ++} ++ ++static int ++wrap_res_querydomain (int type, unsigned char *answer, int answer_length) ++{ ++ return res_querydomain ("www", "example.com", C_IN, type, ++ answer, answer_length); ++} ++ ++static int ++wrap_res_send (int type, unsigned char *answer, int answer_length) ++{ ++ unsigned char buf[512]; ++ int ret = res_mkquery (QUERY, domain, C_IN, type, ++ (const unsigned char *) "", 0, NULL, ++ buf, sizeof (buf)); ++ if (type < 0 || type >= 65536) ++ { ++ /* res_mkquery fails for out-of-range record types. */ ++ TEST_VERIFY_EXIT (ret == -1); ++ return -1; ++ } ++ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */ ++ return res_send (buf, ret, answer, answer_length); ++} ++ ++static int ++wrap_res_nquery (int type, unsigned char *answer, int answer_length) ++{ ++ return res_nquery (&_res, domain, C_IN, type, answer, answer_length); ++} ++ ++static int ++wrap_res_nsearch (int type, unsigned char *answer, int answer_length) ++{ ++ return res_nquery (&_res, domain, C_IN, type, answer, answer_length); ++} ++ ++static int ++wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length) ++{ ++ return res_nquerydomain (&_res, "www", "example.com", C_IN, type, ++ answer, answer_length); ++} ++ ++static int ++wrap_res_nsend (int type, unsigned char *answer, int answer_length) ++{ ++ unsigned char buf[512]; ++ int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type, ++ (const unsigned char *) "", 0, NULL, ++ buf, sizeof (buf)); ++ if (type < 0 || type >= 65536) ++ { ++ /* res_mkquery fails for out-of-range record types. */ ++ TEST_VERIFY_EXIT (ret == -1); ++ return -1; ++ } ++ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */ ++ return res_nsend (&_res, buf, ret, answer, answer_length); ++} ++ ++static void ++test_function (const char *fname, ++ int (*func) (int type, ++ unsigned char *answer, int answer_length)) ++{ ++ unsigned char buf[512]; ++ for (int tcp = 0; tcp < 2; ++tcp) ++ { ++ force_tcp = tcp; ++ for (unsigned int type = 1; type <= 65535; ++type) ++ { ++ if (test_verbose) ++ printf ("info: sending QTYPE %d with %s (tcp=%d)\n", ++ type, fname, tcp); ++ int ret = func (type, buf, sizeof (buf)); ++ if (ret != 47) ++ FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d", ++ fname,tcp, type, ret); ++ /* One question, one answer record. */ ++ TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0); ++ /* Question section. */ ++ static const char qname[] = "\3www\7example\3com"; ++ size_t qname_length = sizeof (qname); ++ TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0); ++ /* RDATA part of answer. */ ++ uint16_t type16 = type; ++ TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0); ++ } ++ } ++ ++ TEST_VERIFY (func (-1, buf, sizeof (buf) == -1)); ++ TEST_VERIFY (func (65536, buf, sizeof (buf) == -1)); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_redirect_config config = ++ { ++ .response_callback = response, ++ }; ++ struct resolv_test *obj = resolv_test_start (config); ++ ++ test_function ("res_query", &wrap_res_query); ++ test_function ("res_search", &wrap_res_search); ++ test_function ("res_querydomain", &wrap_res_querydomain); ++ test_function ("res_send", &wrap_res_send); ++ ++ test_function ("res_nquery", &wrap_res_nquery); ++ test_function ("res_nsearch", &wrap_res_nsearch); ++ test_function ("res_nquerydomain", &wrap_res_nquerydomain); ++ test_function ("res_nsend", &wrap_res_nsend); ++ ++ resolv_test_end (obj); ++ return 0; ++} ++ ++#define TIMEOUT 300 ++#include +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2015-7547.patch b/gnu/packages/patches/glibc-CVE-2015-7547.patch new file mode 100644 index 0000000000..12abeb76d4 --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2015-7547.patch @@ -0,0 +1,590 @@ +From b995d95a5943785be3ab862b2d3276f3b4a22481 Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell +Date: Tue, 16 Feb 2016 21:26:37 -0500 +Subject: [PATCH] CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug + 18665). + +* A stack-based buffer overflow was found in libresolv when invoked from + libnss_dns, allowing specially crafted DNS responses to seize control + of execution flow in the DNS client. The buffer overflow occurs in + the functions send_dg (send datagram) and send_vc (send TCP) for the + NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC + family. The use of AF_UNSPEC triggers the low-level resolver code to + send out two parallel queries for A and AAAA. A mismanagement of the + buffers used for those queries could result in the response of a query + writing beyond the alloca allocated buffer created by + _nss_dns_gethostbyname4_r. Buffer management is simplified to remove + the overflow. Thanks to the Google Security Team and Red Hat for + reporting the security impact of this issue, and Robert Holiday of + Ciena for reporting the related bug 18665. (CVE-2015-7547) + +See also: +https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html +https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html + +(cherry picked from commit e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca) +--- + ChangeLog | 15 +++ + NEWS | 14 +++ + resolv/nss_dns/dns-host.c | 111 ++++++++++++++++++- + resolv/res_query.c | 3 + + resolv/res_send.c | 264 ++++++++++++++++++++++++++++++++++------------ + 5 files changed, 338 insertions(+), 69 deletions(-) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 357ac04..a0fe9a8 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + int h_namelen = 0; + + if (ancount == 0) +- return NSS_STATUS_NOTFOUND; ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { +@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ +- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; ++ if (canon != NULL) ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } ++ ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; + } + + +@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + + enum nss_status status = NSS_STATUS_NOTFOUND; + ++ /* Combining the NSS status of two distinct queries requires some ++ compromise and attention to symmetry (A or AAAA queries can be ++ returned in any order). What follows is a breakdown of how this ++ code is expected to work and why. We discuss only SUCCESS, ++ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns ++ that apply (though RETURN and MERGE exist). We make a distinction ++ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). ++ A recoverable TRYAGAIN is almost always due to buffer size issues ++ and returns ERANGE in errno and the caller is expected to retry ++ with a larger buffer. ++ ++ Lastly, you may be tempted to make significant changes to the ++ conditions in this code to bring about symmetry between responses. ++ Please don't change anything without due consideration for ++ expected application behaviour. Some of the synthesized responses ++ aren't very well thought out and sometimes appear to imply that ++ IPv4 responses are always answer 1, and IPv6 responses are always ++ answer 2, but that's not true (see the implementation of send_dg ++ and send_vc to see response can arrive in any order, particularly ++ for UDP). However, we expect it holds roughly enough of the time ++ that this code works, but certainly needs to be fixed to make this ++ a more robust implementation. ++ ++ ---------------------------------------------- ++ | Answer 1 Status / | Synthesized | Reason | ++ | Answer 2 Status | Status | | ++ |--------------------------------------------| ++ | SUCCESS/SUCCESS | SUCCESS | [1] | ++ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | ++ | SUCCESS/TRYAGAIN' | SUCCESS | [1] | ++ | SUCCESS/NOTFOUND | SUCCESS | [1] | ++ | SUCCESS/UNAVAIL | SUCCESS | [1] | ++ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | ++ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | ++ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | ++ | TRYAGAIN'/SUCCESS | SUCCESS | [3] | ++ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | ++ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | ++ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | ++ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | ++ | NOTFOUND/SUCCESS | SUCCESS | [3] | ++ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | ++ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | ++ | NOTFOUND/NOTFOUND | NOTFOUND | [3] | ++ | NOTFOUND/UNAVAIL | UNAVAIL | [3] | ++ | UNAVAIL/SUCCESS | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | ++ | UNAVAIL/NOTFOUND | UNAVAIL | [4] | ++ | UNAVAIL/UNAVAIL | UNAVAIL | [4] | ++ ---------------------------------------------- ++ ++ [1] If the first response is a success we return success. ++ This ignores the state of the second answer and in fact ++ incorrectly sets errno and h_errno to that of the second ++ answer. However because the response is a success we ignore ++ *errnop and *h_errnop (though that means you touched errno on ++ success). We are being conservative here and returning the ++ likely IPv4 response in the first answer as a success. ++ ++ [2] If the first response is a recoverable TRYAGAIN we return ++ that instead of looking at the second response. The ++ expectation here is that we have failed to get an IPv4 response ++ and should retry both queries. ++ ++ [3] If the first response was not a SUCCESS and the second ++ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, ++ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the ++ result from the second response, otherwise the first responses ++ status is used. Again we have some odd side-effects when the ++ second response is NOTFOUND because we overwrite *errnop and ++ *h_errnop that means that a first answer of NOTFOUND might see ++ its *errnop and *h_errnop values altered. Whether it matters ++ in practice that a first response NOTFOUND has the wrong ++ *errnop and *h_errnop is undecided. ++ ++ [4] If the first response is UNAVAIL we return that instead of ++ looking at the second response. The expectation here is that ++ it will have failed similarly e.g. configuration failure. ++ ++ [5] Testing this code is complicated by the fact that truncated ++ second response buffers might be returned as SUCCESS if the ++ first answer is a SUCCESS. To fix this we add symmetry to ++ TRYAGAIN with the second response. If the second response ++ is a recoverable error we now return TRYAGIN even if the first ++ response was SUCCESS. */ ++ + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND + || (status == NSS_STATUS_TRYAGAIN + /* We want to look at the second answer in case of an +@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; ++ /* Do not return a truncated second response (unless it was ++ unavoidable e.g. unrecoverable TRYAGAIN). */ ++ if (status == NSS_STATUS_SUCCESS ++ && (status2 == NSS_STATUS_TRYAGAIN ++ && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) ++ status = NSS_STATUS_TRYAGAIN; + } + + return status; +diff --git a/resolv/res_query.c b/resolv/res_query.c +index 4a9b3b3..95470a9 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + } +@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + +@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + if (saved_herrno != -1) +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 5e53cc2..6511bb1 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1,3 +1,20 @@ ++/* 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; if not, see ++ . */ ++ + /* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. +@@ -363,6 +380,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, + #ifdef USE_HOOKS + if (__glibc_unlikely (statp->qhook || statp->rhook)) { + if (anssiz < MAXPACKET && ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *buf = malloc (MAXPACKET); + if (buf == NULL) + return (-1); +@@ -638,6 +657,77 @@ get_nsaddr (res_state statp, int n) + return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; + } + ++/* The send_vc function is responsible for sending a DNS query over TCP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and ++ IPv6 queries at the same serially on the same socket. ++ ++ Please note that for TCP there is no way to disable sending both ++ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP ++ and sends the queries serially and waits for the result after each ++ sent query. This implemetnation should be corrected to honour these ++ options. ++ ++ Please also note that for TCP we send both queries over the same ++ socket one after another. This technically violates best practice ++ since the server is allowed to read the first query, respond, and ++ then close the socket (to service another client). If the server ++ does this, then the remaining second query in the socket data buffer ++ will cause the server to send the client an RST which will arrive ++ asynchronously and the client's OS will likely tear down the socket ++ receive buffer resulting in a potentially short read and lost ++ response data. This will force the client to retry the query again, ++ and this process may repeat until all servers and connection resets ++ are exhausted and then the query will fail. It's not known if this ++ happens with any frequency in real DNS server implementations. This ++ implementation should be corrected to use two sockets by default for ++ parallel queries. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ serially on the same socket. ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header field TC will bet set to 1, indicating a truncated ++ message and the rest of the socket data will be read and discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -647,11 +737,7 @@ send_vc(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; +- // XXX REMOVE +- // int anssiz = *anssizp; +- HEADER *anhp = (HEADER *) ans; ++ HEADER *anhp = (HEADER *) *ansp; + struct sockaddr *nsap = get_nsaddr (statp, ns); + int truncating, connreset, n; + /* On some architectures compiler might emit a warning indicating +@@ -743,6 +829,8 @@ send_vc(res_state statp, + * Receive length & response + */ + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: +@@ -779,40 +867,14 @@ send_vc(res_state statp, + u_char **thisansp; + int *thisresplenp; + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if __GNUC_PREREQ (4, 7) +- DIAG_PUSH_NEEDS_COMMENT; +- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); +-#endif +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +-#if __GNUC_PREREQ (4, 7) +- DIAG_POP_NEEDS_COMMENT; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; +@@ -820,10 +882,14 @@ send_vc(res_state statp, + anhp = (HEADER *) *thisansp; + + *thisresplenp = rlen; +- if (rlen > *thisanssizp) { +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- if (__glibc_likely (anscp != NULL)) { ++ /* Is the answer buffer too small? */ ++ if (*thisanssizp < rlen) { ++ /* If the current buffer is not the the static ++ user-supplied buffer then we can reallocate ++ it. */ ++ if (thisansp != NULL && thisansp != ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp == NULL) { + *terrno = ENOMEM; +@@ -835,6 +901,9 @@ send_vc(res_state statp, + if (thisansp == ansp2) + *ansp2_malloced = 1; + anhp = (HEADER *) newp; ++ /* A uint16_t can't be larger than MAXPACKET ++ thus it's safe to allocate MAXPACKET but ++ read RLEN bytes instead. */ + len = rlen; + } else { + Dprint(statp->options & RES_DEBUG, +@@ -997,6 +1066,66 @@ reopen (res_state statp, int *terrno, int ns) + return 1; + } + ++/* The send_dg function is responsible for sending a DNS query over UDP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries ++ along with the ability to send the query in parallel for both stacks ++ (default) or serially (RES_SINGLKUP). It also supports serial lookup ++ with a close and reopen of the socket used to talk to the server ++ (RES_SNGLKUPREOP) to work around broken name servers. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header field TC will bet set to 1, indicating a truncated ++ message, while the rest of the UDP packet is discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If an answer is truncated because of UDP datagram DNS limits then ++ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to ++ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 ++ if any progress was made reading a response from the nameserver and ++ is used by the caller to distinguish between ECONNREFUSED and ++ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -1006,8 +1135,6 @@ send_dg(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; + struct timespec now, timeout, finish; + struct pollfd pfd[1]; + int ptimeout; +@@ -1040,6 +1167,8 @@ send_dg(res_state statp, + int need_recompute = 0; + int nwritten = 0; + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; +@@ -1203,55 +1332,56 @@ send_dg(res_state statp, + int *thisresplenp; + + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + + if (*thisanssizp < MAXPACKET +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- && anscp ++ /* If the current buffer is not the the static ++ user-supplied buffer then we can reallocate ++ it. */ ++ && (thisansp != NULL && thisansp != ansp) + #ifdef FIONREAD ++ /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 + || *thisanssizp < *thisresplenp) + #endif + ) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp != NULL) { +- *anssizp = MAXPACKET; +- *thisansp = ans = newp; ++ *thisanssizp = MAXPACKET; ++ *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; + } + } ++ /* We could end up with truncation if anscp was NULL ++ (not allowed to change caller's buffer) and the ++ response buffer size is too small. This isn't a ++ reliable way to detect truncation because the ioctl ++ may be an inaccurate report of the UDP message size. ++ Therefore we use this only to issue debug output. ++ To do truncation accurately with UDP we need ++ MSG_TRUNC which is only available on Linux. We ++ can abstract out the Linux-specific feature in the ++ future to detect truncation. */ ++ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { ++ Dprint(statp->options & RES_DEBUG, ++ (stdout, ";; response may be truncated (UDP)\n") ++ ); ++ } ++ + HEADER *anhp = (HEADER *) *thisansp; + socklen_t fromlen = sizeof(struct sockaddr_in6); + assert (sizeof(from) <= fromlen); +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2016-3075.patch b/gnu/packages/patches/glibc-CVE-2016-3075.patch new file mode 100644 index 0000000000..d16722806e --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2016-3075.patch @@ -0,0 +1,43 @@ +From 146b58d11fddbef15b888906e3be4f33900c416f Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 29 Mar 2016 12:57:56 +0200 +Subject: [PATCH] CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ + #19879] + +The defensive copy is not needed because the name may not alias the +output buffer. + +(cherry picked from commit 317b199b4aff8cfa27f2302ab404d2bb5032b9a4) +(cherry picked from commit 883dceebc8f11921a9890211a4e202e5be17562f) +--- + ChangeLog | 7 +++++++ + NEWS | 10 ++++++++-- + resolv/nss_dns/dns-network.c | 5 +---- + 3 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c +index 2eb2f67..8f301a7 100644 +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, + } net_buffer; + querybuf *orig_net_buffer; + int anslen; +- char *qbuf; + enum nss_status status; + + if (__res_maybe_init (&_res, 0) == -1) + return NSS_STATUS_UNAVAIL; + +- qbuf = strdupa (name); +- + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + +- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, ++ anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2016-3706.patch b/gnu/packages/patches/glibc-CVE-2016-3706.patch new file mode 100644 index 0000000000..617242df24 --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2016-3706.patch @@ -0,0 +1,188 @@ +From 1a8a7c12950a0026a3c406a7cb1608f96aa1460e Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 29 Apr 2016 10:35:34 +0200 +Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent + conversion [BZ #20010] + +When converting a struct hostent response to struct gaih_addrtuple, the +gethosts macro (which is called from gaih_inet) used alloca, without +malloc fallback for large responses. This commit changes this code to +use calloc unconditionally. + +This commit also consolidated a second hostent-to-gaih_addrtuple +conversion loop (in gaih_inet) to use the new conversion function. + +(cherry picked from commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9) +--- + ChangeLog | 10 ++++ + sysdeps/posix/getaddrinfo.c | 130 +++++++++++++++++++++++--------------------- + 2 files changed, 79 insertions(+), 61 deletions(-) + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 1ef3f20..fed2d3b 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + return 0; + } + ++/* Convert struct hostent to a list of struct gaih_addrtuple objects. ++ h_name is not copied, and the struct hostent object must not be ++ deallocated prematurely. *RESULT must be NULL or a pointer to an ++ object allocated using malloc, which is freed. */ ++static bool ++convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, ++ int family, ++ struct hostent *h, ++ struct gaih_addrtuple **result) ++{ ++ free (*result); ++ *result = NULL; ++ ++ /* Count the number of addresses in h->h_addr_list. */ ++ size_t count = 0; ++ for (char **p = h->h_addr_list; *p != NULL; ++p) ++ ++count; ++ ++ /* Report no data if no addresses are available, or if the incoming ++ address size is larger than what we can store. */ ++ if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr)) ++ return true; ++ ++ struct gaih_addrtuple *array = calloc (count, sizeof (*array)); ++ if (array == NULL) ++ return false; ++ ++ for (size_t i = 0; i < count; ++i) ++ { ++ if (family == AF_INET && req->ai_family == AF_INET6) ++ { ++ /* Perform address mapping. */ ++ array[i].family = AF_INET6; ++ memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t)); ++ array[i].addr[2] = htonl (0xffff); ++ } ++ else ++ { ++ array[i].family = family; ++ memcpy (array[i].addr, h->h_addr_list[i], h->h_length); ++ } ++ array[i].next = array + i + 1; ++ } ++ array[0].name = h->h_name; ++ array[count - 1].next = NULL; ++ ++ *result = array; ++ return true; ++} ++ + #define gethosts(_family, _type) \ + { \ +- int i; \ + int herrno; \ + struct hostent th; \ + struct hostent *h; \ +@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + } \ + else if (h != NULL) \ + { \ +- for (i = 0; h->h_addr_list[i]; i++) \ ++ /* Make sure that addrmem can be freed. */ \ ++ if (!malloc_addrmem) \ ++ addrmem = NULL; \ ++ if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \ + { \ +- if (*pat == NULL) \ +- { \ +- *pat = __alloca (sizeof (struct gaih_addrtuple)); \ +- (*pat)->scopeid = 0; \ +- } \ +- uint32_t *addr = (*pat)->addr; \ +- (*pat)->next = NULL; \ +- (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \ +- if (_family == AF_INET && req->ai_family == AF_INET6) \ +- { \ +- (*pat)->family = AF_INET6; \ +- addr[3] = *(uint32_t *) h->h_addr_list[i]; \ +- addr[2] = htonl (0xffff); \ +- addr[1] = 0; \ +- addr[0] = 0; \ +- } \ +- else \ +- { \ +- (*pat)->family = _family; \ +- memcpy (addr, h->h_addr_list[i], sizeof(_type)); \ +- } \ +- pat = &((*pat)->next); \ ++ _res.options |= old_res_options & RES_USE_INET6; \ ++ result = -EAI_SYSTEM; \ ++ goto free_and_return; \ + } \ ++ *pat = addrmem; \ ++ /* The conversion uses malloc unconditionally. */ \ ++ malloc_addrmem = true; \ + \ + if (localcanon != NULL && canon == NULL) \ + canon = strdupa (localcanon); \ + \ +- if (_family == AF_INET6 && i > 0) \ ++ if (_family == AF_INET6 && *pat != NULL) \ + got_ipv6 = true; \ + } \ + } +@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service, + { + if (h != NULL) + { +- int i; +- /* We found data, count the number of addresses. */ +- for (i = 0; h->h_addr_list[i]; ++i) +- ; +- if (i > 0 && *pat != NULL) +- --i; +- +- if (__libc_use_alloca (alloca_used +- + i * sizeof (struct gaih_addrtuple))) +- addrmem = alloca_account (i * sizeof (struct gaih_addrtuple), +- alloca_used); +- else +- { +- addrmem = malloc (i +- * sizeof (struct gaih_addrtuple)); +- if (addrmem == NULL) +- { +- result = -EAI_MEMORY; +- goto free_and_return; +- } +- malloc_addrmem = true; +- } +- +- /* Now convert it into the list. */ +- struct gaih_addrtuple *addrfree = addrmem; +- for (i = 0; h->h_addr_list[i]; ++i) ++ /* We found data, convert it. */ ++ if (!convert_hostent_to_gaih_addrtuple ++ (req, AF_INET, h, &addrmem)) + { +- if (*pat == NULL) +- { +- *pat = addrfree++; +- (*pat)->scopeid = 0; +- } +- (*pat)->next = NULL; +- (*pat)->family = AF_INET; +- memcpy ((*pat)->addr, h->h_addr_list[i], +- h->h_length); +- pat = &((*pat)->next); ++ result = -EAI_MEMORY; ++ goto free_and_return; + } ++ *pat = addrmem; ++ /* The conversion uses malloc unconditionally. */ ++ malloc_addrmem = true; + } + } + else +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2016-4429.patch b/gnu/packages/patches/glibc-CVE-2016-4429.patch new file mode 100644 index 0000000000..5eebd10543 --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2016-4429.patch @@ -0,0 +1,58 @@ +From bdce95930e1d9a7d013d1ba78740243491262879 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 23 May 2016 20:18:34 +0200 +Subject: [PATCH] CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ + #20112] + +The call is technically in a loop, and under certain circumstances +(which are quite difficult to reproduce in a test case), alloca +can be invoked repeatedly during a single call to clntudp_call. +As a result, the available stack space can be exhausted (even +though individual alloca sizes are bounded implicitly by what +can fit into a UDP packet, as a side effect of the earlier +successful send operation). + +(cherry picked from commit bc779a1a5b3035133024b21e2f339fe4219fb11c) +--- + ChangeLog | 7 +++++++ + NEWS | 4 ++++ + sunrpc/clnt_udp.c | 10 +++++++++- + 3 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c +index a6cf5f1..4d9acb1 100644 +--- a/sunrpc/clnt_udp.c ++++ b/sunrpc/clnt_udp.c +@@ -388,9 +388,15 @@ send_again: + struct sock_extended_err *e; + struct sockaddr_in err_addr; + struct iovec iov; +- char *cbuf = (char *) alloca (outlen + 256); ++ char *cbuf = malloc (outlen + 256); + int ret; + ++ if (cbuf == NULL) ++ { ++ cu->cu_error.re_errno = errno; ++ return (cu->cu_error.re_status = RPC_CANTRECV); ++ } ++ + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; +@@ -415,10 +421,12 @@ send_again: + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { ++ free (cbuf); + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } ++ free (cbuf); + } + #endif + do +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch b/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch new file mode 100644 index 0000000000..71e80968be --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch @@ -0,0 +1,36 @@ +From f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 19 Jun 2017 17:09:55 +0200 +Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1 + programs [BZ #21624] + +LD_LIBRARY_PATH can only be used to reorder system search paths, which +is not useful functionality. + +This makes an exploitable unbounded alloca in _dl_init_paths unreachable +for AT_SECURE=1 programs. + +patch from: +https://sourceware.org/git/?p=glibc.git;a=commit;h=f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d +--- + ChangeLog | 7 +++++++ + elf/rtld.c | 3 ++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 2446a87..2269dbe 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2422,7 +2422,8 @@ process_envvars (enum mode *modep) + + case 12: + /* The library search path. */ +- if (memcmp (envline, "LIBRARY_PATH", 12) == 0) ++ if (!__libc_enable_secure ++ && memcmp (envline, "LIBRARY_PATH", 12) == 0) + { + library_path = &envline[13]; + break; +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch b/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch new file mode 100644 index 0000000000..4b859c4bfd --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch @@ -0,0 +1,124 @@ +From 6d0ba622891bed9d8394eef1935add53003b12e8 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 19 Jun 2017 22:31:04 +0200 +Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements + +patch from: +https://sourceware.org/git/?p=glibc.git;a=patch;h=6d0ba622891bed9d8394eef1935add53003b12e8 + +--- + ChangeLog | 7 ++++++ + elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ + 2 files changed, 73 insertions(+), 16 deletions(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 2269dbe..86ae20c 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local + strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) + #endif + ++/* Length limits for names and paths, to protect the dynamic linker, ++ particularly when __libc_enable_secure is active. */ ++#ifdef NAME_MAX ++# define SECURE_NAME_LIMIT NAME_MAX ++#else ++# define SECURE_NAME_LIMIT 255 ++#endif ++#ifdef PATH_MAX ++# define SECURE_PATH_LIMIT PATH_MAX ++#else ++# define SECURE_PATH_LIMIT 1024 ++#endif ++ ++/* Check that AT_SECURE=0, or that the passed name does not contain ++ directories and is not overly long. Reject empty names ++ unconditionally. */ ++static bool ++dso_name_valid_for_suid (const char *p) ++{ ++ if (__glibc_unlikely (__libc_enable_secure)) ++ { ++ /* Ignore pathnames with directories for AT_SECURE=1 ++ programs, and also skip overlong names. */ ++ size_t len = strlen (p); ++ if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL) ++ return false; ++ } ++ return *p != '\0'; ++} + + /* List of auditing DSOs. */ + static struct audit_list +@@ -718,6 +747,42 @@ static const char *preloadlist attribute_relro; + /* Nonzero if information about versions has to be printed. */ + static int version_info attribute_relro; + ++/* The LD_PRELOAD environment variable gives list of libraries ++ separated by white space or colons that are loaded before the ++ executable's dependencies and prepended to the global scope list. ++ (If the binary is running setuid all elements containing a '/' are ++ ignored since it is insecure.) Return the number of preloads ++ performed. */ ++unsigned int ++handle_ld_preload (const char *preloadlist, struct link_map *main_map) ++{ ++ unsigned int npreloads = 0; ++ const char *p = preloadlist; ++ char fname[SECURE_PATH_LIMIT]; ++ ++ while (*p != '\0') ++ { ++ /* Split preload list at space/colon. */ ++ size_t len = strcspn (p, " :"); ++ if (len > 0 && len < sizeof (fname)) ++ { ++ memcpy (fname, p, len); ++ fname[len] = '\0'; ++ } ++ else ++ fname[0] = '\0'; ++ ++ /* Skip over the substring and the following delimiter. */ ++ p += len; ++ if (*p != '\0') ++ ++p; ++ ++ if (dso_name_valid_for_suid (fname)) ++ npreloads += do_preload (fname, main_map, "LD_PRELOAD"); ++ } ++ return npreloads; ++} ++ + static void + dl_main (const ElfW(Phdr) *phdr, + ElfW(Word) phnum, +@@ -1464,23 +1529,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + + if (__glibc_unlikely (preloadlist != NULL)) + { +- /* The LD_PRELOAD environment variable gives list of libraries +- separated by white space or colons that are loaded before the +- executable's dependencies and prepended to the global scope +- list. If the binary is running setuid all elements +- containing a '/' are ignored since it is insecure. */ +- char *list = strdupa (preloadlist); +- char *p; +- + HP_TIMING_NOW (start); +- +- /* Prevent optimizing strsep. Speed is not important here. */ +- while ((p = (strsep) (&list, " :")) != NULL) +- if (p[0] != '\0' +- && (__builtin_expect (! __libc_enable_secure, 1) +- || strchr (p, '/') == NULL)) +- npreloads += do_preload (p, main_map, "LD_PRELOAD"); +- ++ npreloads += handle_ld_preload (preloadlist, main_map); + HP_TIMING_NOW (stop); + HP_TIMING_DIFF (diff, start, stop); + HP_TIMING_ACCUM_NT (load_time, diff); +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch b/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch new file mode 100644 index 0000000000..3d8f6d2bf8 --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch @@ -0,0 +1,206 @@ +From 81b82fb966ffbd94353f793ad17116c6088dedd9 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 19 Jun 2017 22:32:12 +0200 +Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements + +Also only process the last LD_AUDIT entry. + +patch from: +https://sourceware.org/git/?p=glibc.git;a=commit;h=81b82fb966ffbd94353f793ad17116c6088dedd9 + +--- + ChangeLog | 11 +++++++ + elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 106 insertions(+), 15 deletions(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 86ae20c..65647fb 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p) + return *p != '\0'; + } + +-/* List of auditing DSOs. */ ++/* LD_AUDIT variable contents. Must be processed before the ++ audit_list below. */ ++const char *audit_list_string; ++ ++/* Cyclic list of auditing DSOs. audit_list->next is the first ++ element. */ + static struct audit_list + { + const char *name; + struct audit_list *next; + } *audit_list; + ++/* Iterator for audit_list_string followed by audit_list. */ ++struct audit_list_iter ++{ ++ /* Tail of audit_list_string still needing processing, or NULL. */ ++ const char *audit_list_tail; ++ ++ /* The list element returned in the previous iteration. NULL before ++ the first element. */ ++ struct audit_list *previous; ++ ++ /* Scratch buffer for returning a name which is part of ++ audit_list_string. */ ++ char fname[SECURE_NAME_LIMIT]; ++}; ++ ++/* Initialize an audit list iterator. */ ++static void ++audit_list_iter_init (struct audit_list_iter *iter) ++{ ++ iter->audit_list_tail = audit_list_string; ++ iter->previous = NULL; ++} ++ ++/* Iterate through both audit_list_string and audit_list. */ ++static const char * ++audit_list_iter_next (struct audit_list_iter *iter) ++{ ++ if (iter->audit_list_tail != NULL) ++ { ++ /* First iterate over audit_list_string. */ ++ while (*iter->audit_list_tail != '\0') ++ { ++ /* Split audit list at colon. */ ++ size_t len = strcspn (iter->audit_list_tail, ":"); ++ if (len > 0 && len < sizeof (iter->fname)) ++ { ++ memcpy (iter->fname, iter->audit_list_tail, len); ++ iter->fname[len] = '\0'; ++ } ++ else ++ /* Do not return this name to the caller. */ ++ iter->fname[0] = '\0'; ++ ++ /* Skip over the substring and the following delimiter. */ ++ iter->audit_list_tail += len; ++ if (*iter->audit_list_tail == ':') ++ ++iter->audit_list_tail; ++ ++ /* If the name is valid, return it. */ ++ if (dso_name_valid_for_suid (iter->fname)) ++ return iter->fname; ++ /* Otherwise, wrap around and try the next name. */ ++ } ++ /* Fall through to the procesing of audit_list. */ ++ } ++ ++ if (iter->previous == NULL) ++ { ++ if (audit_list == NULL) ++ /* No pre-parsed audit list. */ ++ return NULL; ++ /* Start of audit list. The first list element is at ++ audit_list->next (cyclic list). */ ++ iter->previous = audit_list->next; ++ return iter->previous->name; ++ } ++ if (iter->previous == audit_list) ++ /* Cyclic list wrap-around. */ ++ return NULL; ++ iter->previous = iter->previous->next; ++ return iter->previous->name; ++} ++ + #ifndef HAVE_INLINED_SYSCALLS + /* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This +@@ -1305,11 +1383,13 @@ of this helper program; chances are you did not intend to run this program.\n\ + GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); + + /* If we have auditing DSOs to load, do it now. */ +- if (__glibc_unlikely (audit_list != NULL)) ++ bool need_security_init = true; ++ if (__glibc_unlikely (audit_list != NULL) ++ || __glibc_unlikely (audit_list_string != NULL)) + { +- /* Iterate over all entries in the list. The order is important. */ + struct audit_ifaces *last_audit = NULL; +- struct audit_list *al = audit_list->next; ++ struct audit_list_iter al_iter; ++ audit_list_iter_init (&al_iter); + + /* Since we start using the auditing DSOs right away we need to + initialize the data structures now. */ +@@ -1320,9 +1400,14 @@ of this helper program; chances are you did not intend to run this program.\n\ + use different values (especially the pointer guard) and will + fail later on. */ + security_init (); ++ need_security_init = false; + +- do ++ while (true) + { ++ const char *name = audit_list_iter_next (&al_iter); ++ if (name == NULL) ++ break; ++ + int tls_idx = GL(dl_tls_max_dtv_idx); + + /* Now it is time to determine the layout of the static TLS +@@ -1331,7 +1416,7 @@ of this helper program; chances are you did not intend to run this program.\n\ + no DF_STATIC_TLS bit is set. The reason is that we know + glibc will use the static model. */ + struct dlmopen_args dlmargs; +- dlmargs.fname = al->name; ++ dlmargs.fname = name; + dlmargs.map = NULL; + + const char *objname; +@@ -1344,7 +1429,7 @@ of this helper program; chances are you did not intend to run this program.\n\ + not_loaded: + _dl_error_printf ("\ + ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", +- al->name, err_str); ++ name, err_str); + if (malloced) + free ((char *) err_str); + } +@@ -1448,10 +1533,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + goto not_loaded; + } + } +- +- al = al->next; + } +- while (al != audit_list->next); + + /* If we have any auditing modules, announce that we already + have two objects loaded. */ +@@ -1715,7 +1797,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + if (tcbp == NULL) + tcbp = init_tls (); + +- if (__glibc_likely (audit_list == NULL)) ++ if (__glibc_likely (need_security_init)) + /* Initialize security features. But only if we have not done it + earlier. */ + security_init (); +@@ -2346,9 +2428,7 @@ process_dl_audit (char *str) + char *p; + + while ((p = (strsep) (&str, ":")) != NULL) +- if (p[0] != '\0' +- && (__builtin_expect (! __libc_enable_secure, 1) +- || strchr (p, '/') == NULL)) ++ if (dso_name_valid_for_suid (p)) + { + /* This is using the local malloc, not the system malloc. The + memory can never be freed. */ +@@ -2412,7 +2492,7 @@ process_envvars (enum mode *modep) + break; + } + if (memcmp (envline, "AUDIT", 5) == 0) +- process_dl_audit (&envline[6]); ++ audit_list_string = &envline[6]; + break; + + case 7: +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2018-11236.patch b/gnu/packages/patches/glibc-CVE-2018-11236.patch new file mode 100644 index 0000000000..4f8a72943c --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2018-11236.patch @@ -0,0 +1,149 @@ +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=5460617d1567657621107d895ee2dd83bc1f88f2 +with ChangeLog removed + +From 5460617d1567657621107d895ee2dd83bc1f88f2 Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Tue, 8 May 2018 18:12:41 -0700 +Subject: [PATCH] Fix BZ 22786: integer addition overflow may cause stack + buffer overflow when realpath() input length is close to SSIZE_MAX. + +2018-05-09 Paul Pluzhnikov + + [BZ #22786] + * stdlib/canonicalize.c (__realpath): Fix overflow in path length + computation. + * stdlib/Makefile (test-bz22786): New test. + * stdlib/test-bz22786.c: New test. +--- + ChangeLog | 8 +++++ + stdlib/Makefile | 2 +- + stdlib/canonicalize.c | 2 +- + stdlib/test-bz22786.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 100 insertions(+), 2 deletions(-) + create mode 100644 stdlib/test-bz22786.c + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index af1643c..1ddb1f9 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -84,7 +84,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + tst-cxa_atexit tst-on_exit test-atexit-race \ + test-at_quick_exit-race test-cxa_atexit-race \ + test-on_exit-race test-dlclose-exit-race \ +- tst-makecontext-align ++ tst-makecontext-align test-bz22786 + + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete +diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c +index 4135f3f..390fb43 100644 +--- a/stdlib/canonicalize.c ++++ b/stdlib/canonicalize.c +@@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved) + extra_buf = __alloca (path_max); + + len = strlen (end); +- if ((long int) (n + len) >= path_max) ++ if (path_max - n <= len) + { + __set_errno (ENAMETOOLONG); + goto error; +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +new file mode 100644 +index 0000000..e7837f9 +--- /dev/null ++++ b/stdlib/test-bz22786.c +@@ -0,0 +1,90 @@ ++/* Bug 22786: test for buffer overflow in realpath. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* This file must be run from within a directory called "stdlib". */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ const char dir[] = "bz22786"; ++ const char lnk[] = "bz22786/symlink"; ++ ++ rmdir (dir); ++ if (mkdir (dir, 0755) != 0 && errno != EEXIST) ++ { ++ printf ("mkdir %s: %m\n", dir); ++ return EXIT_FAILURE; ++ } ++ if (symlink (".", lnk) != 0 && errno != EEXIST) ++ { ++ printf ("symlink (%s, %s): %m\n", dir, lnk); ++ return EXIT_FAILURE; ++ } ++ ++ const size_t path_len = (size_t) INT_MAX + 1; ++ ++ DIAG_PUSH_NEEDS_COMMENT; ++#if __GNUC_PREREQ (7, 0) ++ /* GCC 7 warns about too-large allocations; here we need such ++ allocation to succeed for the test to work. */ ++ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); ++#endif ++ char *path = malloc (path_len); ++ DIAG_POP_NEEDS_COMMENT; ++ ++ if (path == NULL) ++ { ++ printf ("malloc (%zu): %m\n", path_len); ++ return EXIT_UNSUPPORTED; ++ } ++ ++ /* Construct very long path = "bz22786/symlink/aaaa....." */ ++ char *p = mempcpy (path, lnk, sizeof (lnk) - 1); ++ *(p++) = '/'; ++ memset (p, 'a', path_len - (path - p) - 2); ++ p[path_len - (path - p) - 1] = '\0'; ++ ++ /* This call crashes before the fix for bz22786 on 32-bit platforms. */ ++ p = realpath (path, NULL); ++ ++ if (p != NULL || errno != ENAMETOOLONG) ++ { ++ printf ("realpath: %s (%m)", p); ++ return EXIT_FAILURE; ++ } ++ ++ /* Cleanup. */ ++ unlink (lnk); ++ rmdir (dir); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test ++#include +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-CVE-2018-11237.patch b/gnu/packages/patches/glibc-CVE-2018-11237.patch new file mode 100644 index 0000000000..8a7c604ecd --- /dev/null +++ b/gnu/packages/patches/glibc-CVE-2018-11237.patch @@ -0,0 +1,55 @@ +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=9aaaab7c6e4176e61c59b0a63c6ba906d875dc0e +with the ChangeLog removed + +From 9aaaab7c6e4176e61c59b0a63c6ba906d875dc0e Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Tue, 22 May 2018 10:37:59 +0200 +Subject: [PATCH] Don't write beyond destination in + __mempcpy_avx512_no_vzeroupper (bug 23196) + +When compiled as mempcpy, the return value is the end of the destination +buffer, thus it cannot be used to refer to the start of it. +--- + ChangeLog | 9 +++++++++ + string/test-mempcpy.c | 1 + + sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S | 5 +++-- + 3 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c +index c08fba8..d98ecdd 100644 +--- a/string/test-mempcpy.c ++++ b/string/test-mempcpy.c +@@ -18,6 +18,7 @@ + . */ + + #define MEMCPY_RESULT(dst, len) (dst) + (len) ++#define MIN_PAGE_SIZE 131072 + #define TEST_MAIN + #define TEST_NAME "mempcpy" + #include "test-string.h" +diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S +index 23c0f7a..effc3ac 100644 +--- a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S ++++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S +@@ -336,6 +336,7 @@ L(preloop_large): + vmovups (%rsi), %zmm4 + vmovups 0x40(%rsi), %zmm5 + ++ mov %rdi, %r11 + /* Align destination for access with non-temporal stores in the loop. */ + mov %rdi, %r8 + and $-0x80, %rdi +@@ -366,8 +367,8 @@ L(gobble_256bytes_nt_loop): + cmp $256, %rdx + ja L(gobble_256bytes_nt_loop) + sfence +- vmovups %zmm4, (%rax) +- vmovups %zmm5, 0x40(%rax) ++ vmovups %zmm4, (%r11) ++ vmovups %zmm5, 0x40(%r11) + jmp L(check) + + L(preloop_large_bkw): +-- +2.9.3 + diff --git a/gnu/packages/patches/glibc-cvs-common-symbols.patch b/gnu/packages/patches/glibc-cvs-common-symbols.patch new file mode 100644 index 0000000000..7764c99fa6 --- /dev/null +++ b/gnu/packages/patches/glibc-cvs-common-symbols.patch @@ -0,0 +1,58 @@ +commit 388b4f1a02f3a801965028bbfcd48d905638b797 +Author: H.J. Lu +Date: Fri Jun 23 14:38:46 2017 -0700 + + Avoid .symver on common symbols [BZ #21666] + + The .symver directive on common symbol just creates a new common symbol, + not an alias and the newer assembler with the bug fix for + + https://sourceware.org/bugzilla/show_bug.cgi?id=21661 + + will issue an error. Before the fix, we got + + $ readelf -sW libc.so | grep "loc[12s]" + 5109: 00000000003a0608 8 OBJECT LOCAL DEFAULT 36 loc1 + 5188: 00000000003a0610 8 OBJECT LOCAL DEFAULT 36 loc2 + 5455: 00000000003a0618 8 OBJECT LOCAL DEFAULT 36 locs + 6575: 00000000003a05f0 8 OBJECT GLOBAL DEFAULT 36 locs@GLIBC_2.2.5 + 7156: 00000000003a05f8 8 OBJECT GLOBAL DEFAULT 36 loc1@GLIBC_2.2.5 + 7312: 00000000003a0600 8 OBJECT GLOBAL DEFAULT 36 loc2@GLIBC_2.2.5 + + in libc.so. The versioned loc1, loc2 and locs have the wrong addresses. + After the fix, we got + + $ readelf -sW libc.so | grep "loc[12s]" + 6570: 000000000039e3b8 8 OBJECT GLOBAL DEFAULT 34 locs@GLIBC_2.2.5 + 7151: 000000000039e3c8 8 OBJECT GLOBAL DEFAULT 34 loc1@GLIBC_2.2.5 + 7307: 000000000039e3c0 8 OBJECT GLOBAL DEFAULT 34 loc2@GLIBC_2.2.5 + + [BZ #21666] + * misc/regexp.c (loc1): Add __attribute__ ((nocommon)); + (loc2): Likewise. + (locs): Likewise. + +diff --git a/misc/regexp.c b/misc/regexp.c +index 19d76c0c37..eaea7c3b89 100644 +--- a/misc/regexp.c ++++ b/misc/regexp.c +@@ -29,14 +29,15 @@ + + #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23) + +-/* Define the variables used for the interface. */ +-char *loc1; +-char *loc2; ++/* Define the variables used for the interface. Avoid .symver on common ++ symbol, which just creates a new common symbol, not an alias. */ ++char *loc1 __attribute__ ((nocommon)); ++char *loc2 __attribute__ ((nocommon)); + compat_symbol (libc, loc1, loc1, GLIBC_2_0); + compat_symbol (libc, loc2, loc2, GLIBC_2_0); + + /* Although we do not support the use we define this variable as well. */ +-char *locs; ++char *locs __attribute__ ((nocommon)); + compat_symbol (libc, locs, locs, GLIBC_2_0); + + diff --git a/gnu/packages/patches/glibc-hurd-magic-pid.patch b/gnu/packages/patches/glibc-hurd-magic-pid.patch new file mode 100644 index 0000000000..a6849f7d35 --- /dev/null +++ b/gnu/packages/patches/glibc-hurd-magic-pid.patch @@ -0,0 +1,190 @@ +This patch implements "magic" lookup for "pid/…", as used when looking up +/proc/self. + +The patch comes from the 't/magic-pid' branch +at . It squashes +commit 392e52286a302ca6157fbd221295e64ab6b6d8ba (by Justus Winter) +and commit 392e52286a302ca6157fbd221295e64ab6b6d8ba (a subsequent fix by +Samuel Thibault). + +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Subject: [PATCH] hurd: Handle `pid' magical lookup retry + + * hurd/lookup-retry.c: Handle `pid' magical lookup + retry. + +diff --git a/hurd/lookup-retry.c b/hurd/lookup-retry.c +index aee2ba8f93..6ed8de1653 100644 +--- a/hurd/lookup-retry.c ++++ b/hurd/lookup-retry.c +@@ -25,6 +25,7 @@ + #include + #include <_itoa.h> + #include ++#include + + /* Translate the error from dir_lookup into the error the user sees. */ + static inline error_t +@@ -59,6 +60,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + error_t err; + char *file_name; + int nloops; ++ file_t lastdir = MACH_PORT_NULL; + + error_t lookup_op (file_t startdir) + { +@@ -107,14 +109,15 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + { + case FS_RETRY_REAUTH: + if (err = reauthenticate (*result)) +- return err; ++ goto out; + /* Fall through. */ + + case FS_RETRY_NORMAL: + if (nloops++ >= __eloop_threshold ()) + { + __mach_port_deallocate (__mach_task_self (), *result); +- return ELOOP; ++ err = ELOOP; ++ goto out; + } + + /* An empty RETRYNAME indicates we have the final port. */ +@@ -174,7 +177,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + + if (err) + __mach_port_deallocate (__mach_task_self (), *result); +- return err; ++ goto out; + } + + startdir = *result; +@@ -189,7 +192,10 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + if (*result != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), *result); + if (nloops++ >= __eloop_threshold ()) +- return ELOOP; ++ { ++ err = ELOOP; ++ goto out; ++ } + file_name = &retryname[1]; + break; + +@@ -208,7 +214,8 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + (*end != '/' && *end != '\0')) + { + errno = save; +- return ENOENT; ++ err = ENOENT; ++ goto out; + } + if (! get_dtable_port) + err = EGRATUITOUS; +@@ -226,9 +233,12 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + } + errno = save; + if (err) +- return err; ++ goto out; + if (*end == '\0') +- return 0; ++ { ++ err = 0; ++ goto out; ++ } + else + { + /* Do a normal retry on the remaining components. */ +@@ -255,9 +265,12 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO, + (integer_t *) &hostinfo, + &hostinfocnt)) +- return err; ++ goto out; + if (hostinfocnt != HOST_BASIC_INFO_COUNT) +- return EGRATUITOUS; ++ { ++ err = EGRATUITOUS; ++ goto out; ++ } + p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0); + *--p = '/'; + p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0); +@@ -293,10 +306,11 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + } + + case '\0': +- return opentty (result); ++ err = opentty (result); ++ goto out; + case '/': + if (err = opentty (&startdir)) +- return err; ++ goto out; + strcpy (retryname, &retryname[4]); + break; + default: +@@ -306,14 +320,48 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + goto bad_magic; + break; + ++ case 'p': ++ if (retryname[1] == 'i' && retryname[2] == 'd' && ++ (retryname[3] == '/' || retryname[3] == 0)) ++ { ++ char *p, buf[1024]; /* XXX */ ++ size_t len; ++ p = _itoa (__getpid (), &buf[sizeof buf], 10, 0); ++ len = &buf[sizeof buf] - p; ++ memcpy (buf, p, len); ++ strcpy (buf + len, &retryname[3]); ++ strcpy (retryname, buf); ++ ++ /* Do a normal retry on the remaining components. */ ++ __mach_port_mod_refs (__mach_task_self (), lastdir, ++ MACH_PORT_RIGHT_SEND, 1); ++ startdir = lastdir; ++ file_name = retryname; ++ } ++ else ++ goto bad_magic; ++ break; ++ + default: + bad_magic: +- return EGRATUITOUS; ++ err = EGRATUITOUS; ++ goto out; + } + break; + + default: +- return EGRATUITOUS; ++ err = EGRATUITOUS; ++ goto out; ++ } ++ ++ if (MACH_PORT_VALID (*result) && *result != lastdir) ++ { ++ if (MACH_PORT_VALID (lastdir)) ++ __mach_port_deallocate (__mach_task_self (), lastdir); ++ ++ lastdir = *result; ++ __mach_port_mod_refs (__mach_task_self (), lastdir, ++ MACH_PORT_RIGHT_SEND, 1); + } + + if (startdir != MACH_PORT_NULL) +@@ -326,6 +374,10 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) + err = (*use_init_port) (dirport, &lookup_op); + } while (! err); + ++out: ++ if (MACH_PORT_VALID (lastdir)) ++ __mach_port_deallocate (__mach_task_self (), lastdir); ++ + return err; + } + weak_alias (__hurd_file_name_lookup_retry, hurd_file_name_lookup_retry) diff --git a/gnu/packages/patches/glibc-o-largefile.patch b/gnu/packages/patches/glibc-o-largefile.patch new file mode 100644 index 0000000000..2b0ae8c8bb --- /dev/null +++ b/gnu/packages/patches/glibc-o-largefile.patch @@ -0,0 +1,25 @@ +This fixes +whereby, on 32-bit platforms, libc 2.22 would fail to pass O_LARGEFILE +to 'openat'. This was caught by 'tests/sparse03.at' in the tar +test suite. + +commit eb32b0d40308166c4d8f6330cc2958cb1e545075 +Author: Andreas Schwab +Date: Mon Aug 10 14:12:47 2015 +0200 + + Readd O_LARGEFILE flag for openat64 (bug 18781) + +--- a/sysdeps/unix/sysv/linux/openat.c ++++ b/sysdeps/unix/sysv/linux/openat.c +@@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...) + va_end (arg); + } + ++ /* We have to add the O_LARGEFILE flag for openat64. */ ++#ifdef MORE_OFLAGS ++ oflag |= MORE_OFLAGS; ++#endif ++ + return SYSCALL_CANCEL (openat, fd, file, oflag, mode); + } + libc_hidden_def (__OPENAT) diff --git a/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch b/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch new file mode 100644 index 0000000000..3d6c7749d4 --- /dev/null +++ b/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch @@ -0,0 +1,23 @@ +Copied from Debian. + +2017-06-14 Florian Weimer + + * sysdeps/i386/i686/multiarch/strcspn-c.c: Add IS_IN (libc) guard. + * sysdeps/i386/i686/multiarch/varshift.c: Likewise. + +--- a/sysdeps/i386/i686/multiarch/strcspn-c.c ++++ b/sysdeps/i386/i686/multiarch/strcspn-c.c +@@ -1,2 +1,4 @@ +-#define __strcspn_sse2 __strcspn_ia32 +-#include ++#if IS_IN (libc) ++# define __strcspn_sse2 __strcspn_ia32 ++# include ++#endif +--- a/sysdeps/i386/i686/multiarch/varshift.c ++++ b/sysdeps/i386/i686/multiarch/varshift.c +@@ -1 +1,3 @@ +-#include ++#if IS_IN (libc) ++# include ++#endif