From patchwork Wed Mar 15 00:25:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 9624651 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 83A5A60244 for ; Wed, 15 Mar 2017 00:27:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 70E6728173 for ; Wed, 15 Mar 2017 00:27:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6437E2851B; Wed, 15 Mar 2017 00:27:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D1BEA28173 for ; Wed, 15 Mar 2017 00:27:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750881AbdCOA1J (ORCPT ); Tue, 14 Mar 2017 20:27:09 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:34365 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750796AbdCOA1I (ORCPT ); Tue, 14 Mar 2017 20:27:08 -0400 Received: by mail-pg0-f68.google.com with SMTP id b5so244787pgg.1; Tue, 14 Mar 2017 17:27:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=tnM9j+hHPIDXFdQ2ZOGkON3X+mQ13KxG7iKrsoX1Kjg=; b=qDsdlCUYyIYOSYv2c9T1S65BMahQdyymF/VrzK71nHhYgiMXnNHhImDWbr31LdudWG JpdZ25xF+5RxUbqBIO+en5BKL2DXmVBHLPfYr3NlM9GPSA8jQshbrCRDWT+uGYU1Euin sIwSx6WjB5+5hO22XhclAfOBMePSWR/w1ZdaEQ3smedL4JyRtmB7bifRPF29GWCt675e nSShqjIW69YH2cDTFkvbTnzBE4DH2rAK21k+klH2T7Il+OogfeV+MJv/SAF2NKCugkt5 ctGSYJqP+S//vT9qKF5AnhZE7LUbpF1XUcYo8CTzmI/KZ4KN8KXwhGIlGXlICNCfaerd n6fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=tnM9j+hHPIDXFdQ2ZOGkON3X+mQ13KxG7iKrsoX1Kjg=; b=CulzADFghq718uXD+0+SULZXPididPan16uWP5WHaoCF0ahe8PY/tMAxAJApUbJ88Y LnemBWsOJoaibFuhPKJdXIIEXU5LtaMSadKWRGXVXYLQcGZsdCvxdX3rlnRlopHaPKF7 Z29CNXqJ28e2VxLUAdXKROovIxKAfR6Df+P3au23lv8d1tJpCJdQ0JbEMwAHaFWUieAj kqziUwz1ke9Hj2rcDHUMBCcmhUZxBw0QpzpzykfqBHbsAaWknPJR7sFi5rbc5yLYeC18 PWmdGy49XOw1M1nZUiRdcBGhSZDIGjZe+kDtUWaze1k7D5FBf9i0h8qhE2hoOSJhYXGD jeYg== X-Gm-Message-State: AFeK/H0xGMG9OPLDQoEYV7rsD6JGhAOThTxVE+3MkjMdSloB0cbauKfC2eZZFUSy7JS/bA== X-Received: by 10.98.84.67 with SMTP id i64mr556442pfb.44.1489537626845; Tue, 14 Mar 2017 17:27:06 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.119.30.131]) by smtp.gmail.com with ESMTPSA id i124sm218615pgd.22.2017.03.14.17.27.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 14 Mar 2017 17:27:05 -0700 (PDT) From: Eric Biggers To: fstests@vger.kernel.org Cc: linux-fscrypt@vger.kernel.org, Eric Biggers , Theodore Ts'o , Jaegeuk Kim , Richard Weinberger , Michael Halcrow Subject: [PATCH] generic: test encryption key revocation during concurrent I/O Date: Tue, 14 Mar 2017 17:25:51 -0700 Message-Id: <20170315002551.9423-1-ebiggers3@gmail.com> X-Mailer: git-send-email 2.12.0.367.g23dc2f6d3c-goog Sender: linux-fscrypt-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers Add a test which revokes a keyring key while other processes are performing I/O on an encrypted file that was "unlocked" using that key. This crashes unpatched kernels with filesystem encryption enabled, so place it in the "dangerous" group. [The patch to fix this is titled "fscrypt: remove broken support for detecting keyring key revocation" but hasn't been merged yet; we may want to wait a bit before merging this test.] Cc: Theodore Ts'o Cc: Jaegeuk Kim Cc: Richard Weinberger Cc: Michael Halcrow Signed-off-by: Eric Biggers --- common/encrypt | 8 ++++ tests/generic/500 | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/500.out | 2 + tests/generic/group | 1 + 4 files changed, 120 insertions(+) create mode 100755 tests/generic/500 create mode 100644 tests/generic/500.out diff --git a/common/encrypt b/common/encrypt index f09104d1..85f71d5b 100644 --- a/common/encrypt +++ b/common/encrypt @@ -144,3 +144,11 @@ _unlink_encryption_key() local keyid=$($KEYCTL_PROG search @s logon $FSTYP:$keydesc) $KEYCTL_PROG unlink $keyid >>$seqres.full } + +# Revoke an encryption key from the keyring, given its key descriptor. +_revoke_encryption_key() +{ + local keydesc=$1 + local keyid=$($KEYCTL_PROG search @s logon $FSTYP:$keydesc) + $KEYCTL_PROG revoke $keyid >>$seqres.full +} diff --git a/tests/generic/500 b/tests/generic/500 new file mode 100755 index 00000000..44c8e81b --- /dev/null +++ b/tests/generic/500 @@ -0,0 +1,109 @@ +#! /bin/bash +# FS QA Test generic/500 +# +# Test revoking an encryption key during concurrent I/O. Regression test for +# "fscrypt: remove broken support for detecting keyring key revocation". +# +#----------------------------------------------------------------------- +# Copyright (c) 2017 Google, Inc. All Rights Reserved. +# +# Author: Eric Biggers +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/encrypt + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here +_supported_fs ext4 f2fs +_supported_os Linux +_require_scratch_encryption +_require_xfs_io_command "set_encpolicy" +_require_command "$KEYCTL_PROG" keyctl + +_new_session_keyring +_scratch_mkfs_encrypted &>> $seqres.full +_scratch_mount + +dir=$SCRATCH_MNT/encrypted_dir +file=$dir/file + +# 4 processes, 2 MB per process +nproc=4 +slice=2 + +# Create an encrypted file and sync its data to disk. +rm -rf $dir +mkdir $dir +keydesc=$(_generate_encryption_key) +$XFS_IO_PROG -c "set_encpolicy $keydesc" $dir +$XFS_IO_PROG -f $file -c "pwrite 0 $((nproc*slice))M" -c "fsync" > /dev/null + +# Create processes to read from the encrypted file. Use fadvise to wipe the +# pagecache before each read, ensuring that each read actually does decryption. +for ((proc = 0; proc < nproc; proc++)); do + ( + range="$((proc * slice))M ${slice}M" + while [ ! -e $tmp.done ]; do + $XFS_IO_PROG $file -c "fadvise -d $range" \ + -c "pread $range" &> /dev/null + done + ) & +done + +# Wait a second for the readers to start up. +sleep 1 + +# Revoke the encryption key. +keyid=$(_revoke_encryption_key $keydesc) + +# Now try to open the file again. In buggy kernels this caused concurrent +# readers to crash with a NULL pointer dereference during decryption. +# +# Note that the fix also made filenames stop "immediately" reverting to their +# ciphertext on key revocation. Therefore, the name of the file we're opening +# here may be in either plaintext or ciphertext depending on the kernel version, +# and ciphertext names are unpredictable anyway, so just use 'find' to find it. +cat $(find $dir -type f) > /dev/null + +# Wait for readers to exit +touch $tmp.done +wait + +# success, all done +echo "Didn't crash!" +status=0 +exit diff --git a/tests/generic/500.out b/tests/generic/500.out new file mode 100644 index 00000000..b46461f3 --- /dev/null +++ b/tests/generic/500.out @@ -0,0 +1,2 @@ +QA output created by 500 +Didn't crash! diff --git a/tests/generic/group b/tests/generic/group index f0096bbc..f2c4755c 100644 --- a/tests/generic/group +++ b/tests/generic/group @@ -420,3 +420,4 @@ 415 auto clone 416 auto enospc 417 auto quick shutdown log +500 auto quick encrypt dangerous