From patchwork Wed Sep 16 23:45:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 40416 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B442A386F028; Wed, 16 Sep 2020 23:45:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B442A386F028 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1600299911; bh=Hs3o0SOBHptZ+eGPDbxubqwyZ0TE3EAdSh/ST+UwYYY=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=kgxm+A1BpQ3FPwtV1FdWuGMBsky5mRvKNIViSf9VhB1ry05pl2N0Eog76mmQVPro+ 7OY2or/h2wiNC7Cc2jHdvC/82rTqx5Bm+GvwZZxqDf5hVr8K+ZEnoyqpMgqMLaABmO tAWAIXwgu95SklGwKNPcYbPhA6+1102yCSgEFfR4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x1043.google.com (mail-pj1-x1043.google.com [IPv6:2607:f8b0:4864:20::1043]) by sourceware.org (Postfix) with ESMTPS id 7E3B83857039 for ; Wed, 16 Sep 2020 23:45:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7E3B83857039 Received: by mail-pj1-x1043.google.com with SMTP id o16so287843pjr.2 for ; Wed, 16 Sep 2020 16:45:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=Hs3o0SOBHptZ+eGPDbxubqwyZ0TE3EAdSh/ST+UwYYY=; b=cYA2VI5cu9XAVXSF6EGEZrcUexJg0FQki3kisaLbwXwiQBRVqZE7RSyZl486+cuQBl RuRJf13HK+OChIBIbHs0ik5FuwRFRLcBryQmk1vzn+Fwke6j2I6UeEYIkQRAMUGuXX9i rzvSBdAJGTvaRowBJc0TngTiq8p9hAnxqsNRbRVGJNTry1J4HhfZvQ5/al47ebVcoGNH C8taqX1yU3y+b3OTz+Au6kDIPhGUlLIXq+YG6ceCbt+hWMvTRf8LhrWuGpo0QJIbQMvd 8d+Qet5a8EAD5XPk9TiSfj4mHt4g6KPdk4o9ibmLZ1oWqs/+dgtGN/ocGIcXT6neplyQ h1Hg== X-Gm-Message-State: AOAM531DsL3Itpx0iqDYNIXUAYPCR2U/WpQRfMQ03gsIa2TYHLXuy7H9 +LCr6UjF6L4aMt1oq2qcSVachDsx6+U= X-Google-Smtp-Source: ABdhPJyYkycDI2s2JpfUUkZ6be/VWuzpk3ZAJ386X/f8Bj8IIoG7sD5ESG3t0JF+DmgYXjb8f5hQsA== X-Received: by 2002:a17:902:ac82:b029:d1:e5fa:79e1 with SMTP id h2-20020a170902ac82b02900d1e5fa79e1mr8510611plr.68.1600299907192; Wed, 16 Sep 2020 16:45:07 -0700 (PDT) Received: from gnu-cfl-2.localdomain (c-69-181-90-243.hsd1.ca.comcast.net. [69.181.90.243]) by smtp.gmail.com with ESMTPSA id 138sm19094354pfu.180.2020.09.16.16.45.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Sep 2020 16:45:06 -0700 (PDT) Received: from gnu-cfl-2.localdomain (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 3F83B1A015E for ; Wed, 16 Sep 2020 16:45:04 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH] x86/CET: Update vfork to prevent child return Date: Wed, 16 Sep 2020 16:45:03 -0700 Message-Id: <20200916234503.3553822-1-hjl.tools@gmail.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Child of vfork should either call _exit or one of the exec family of functions. But normally there is nothing to prevent child of vfork from returning to caller of vfork's caller. With shadow stack enabled, we can introduce mismatched shadow stack in child of vfork. When the child returns from the function in which vfork was called, mismatched shadow stack will trigger SIGSEGV. --- sysdeps/unix/sysv/linux/i386/vfork.S | 6 +++ sysdeps/unix/sysv/linux/x86/Makefile | 5 ++ sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c | 54 +++++++++++++++++++ sysdeps/unix/sysv/linux/x86_64/vfork.S | 6 +++ 4 files changed, 71 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S index ceb41db0bd..e54fdb7e4c 100644 --- a/sysdeps/unix/sysv/linux/i386/vfork.S +++ b/sysdeps/unix/sysv/linux/i386/vfork.S @@ -91,6 +91,12 @@ ENTRY (__vfork) /* Normal return if shadow stack isn't in use. */ je L(no_shstk) + testl %eax, %eax + jnz 2f + /* NB: Jump back to caller directly with mismatched shadow stack + to prevent child return. */ + jmp *%ecx +2: /* Pop return address from shadow stack and jump back to caller directly. */ movl $1, %edx diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile index 920edd8948..f3fae85c1e 100644 --- a/sysdeps/unix/sysv/linux/x86/Makefile +++ b/sysdeps/unix/sysv/linux/x86/Makefile @@ -47,6 +47,11 @@ $(objpfx)tst-cet-property-2.out: $(objpfx)tst-cet-property-2 \ $(evaluate-test) endif +ifeq ($(subdir),posix) +tests += tst-cet-vfork-1 +CFLAGS-tst-cet-vfork-1.c += -mshstk +endif + ifeq ($(subdir),stdlib) tests += tst-cet-setcontext-1 CFLAGS-tst-cet-setcontext-1.c += -mshstk diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c new file mode 100644 index 0000000000..9ca148e857 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c @@ -0,0 +1,54 @@ +/* Verify that child of vfork can't return with shadow stack. + Copyright (C) 2020 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 + +__attribute__ ((noclone, noinline)) +static pid_t +do_test_1 (void) +{ + pid_t pid; + + pid = vfork (); + if (pid == 0) + { + /* Child return should trigger SIGSEGV. */ + return 0; + } + _exit (EXIT_SUCCESS); + + return pid; +} + +static int +do_test (void) +{ + /* NB: This test should trigger SIGSEGV with shadow stack enabled. */ + if (_get_ssp () == 0) + return EXIT_UNSUPPORTED; + return do_test_1 () ? EXIT_SUCCESS : EXIT_FAILURE; +} + +#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV) +#include diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S index 776d2fc610..5dd5cb714c 100644 --- a/sysdeps/unix/sysv/linux/x86_64/vfork.S +++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -71,6 +71,12 @@ ENTRY (__vfork) /* Normal return if shadow stack isn't in use. */ je L(no_shstk) + testl %eax, %eax + jnz 2f + /* NB: Jump back to caller directly with mismatched shadow stack + to prevent child return. */ + jmp *%rdi +2: /* Pop return address from shadow stack and jump back to caller directly. */ movl $1, %esi