From patchwork Mon Jan 22 16:24:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Crequy X-Patchwork-Id: 10178849 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 9BF10601D5 for ; Mon, 22 Jan 2018 16:25:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8EFA027DCD for ; Mon, 22 Jan 2018 16:25:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8369527F94; Mon, 22 Jan 2018 16:25:43 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable 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 0755D27F93 for ; Mon, 22 Jan 2018 16:25:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751112AbeAVQZl (ORCPT ); Mon, 22 Jan 2018 11:25:41 -0500 Received: from mail-wm0-f65.google.com ([74.125.82.65]:36445 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751086AbeAVQZk (ORCPT ); Mon, 22 Jan 2018 11:25:40 -0500 Received: by mail-wm0-f65.google.com with SMTP id f3so18004951wmc.1; Mon, 22 Jan 2018 08:25:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=5O/1YDQ8Q2ZnFXPb6w/CruJiVtk4CbAm3uT8P852LDw=; b=W6EhZACIYbnAqZKwgQjzwp3/FOL9kgJXQCo8xpZX7yXenA4M49HLBtyAWsQ+QLE6oX 6FsIhkQ9oGyiZsrhPMoIYXoBr7OkyPTFbyOS83jFZrloY6tMPp6U+SfdthhqOwvqBmOV Y64kH9HARrtGx1EpIq1lpKjT6zdoTjSxwyzYdVBTRIKJZGIw6wFIyX8yXHSbOc2ei4iE S/Yrq/h9rQ8MvyFec41wC0mQ45JNn8Fh4yNdoPHNZY7GXXpn6Lx7ILs2ULN9LluJiXoh rjLV+s7wzu+JBevWNOP4uIp+zB0FjlwsVrCwx8VqPC67ceGSm2yCNSolq7m/bDJqMp8K RUlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=5O/1YDQ8Q2ZnFXPb6w/CruJiVtk4CbAm3uT8P852LDw=; b=S8acu4tL9CqzSD1N6ltJhTOAlG3YGTcpCpCMOb/g5beYC3l/G6wBVzaGM1140Nay80 prMfUvSD+3UTspI1ZHRuip9oYOU8Kpd+ufKpsHXjvFPm+1hCAPukqKrx0FCY3cU32R4G zKGom4l3UP3069SNxPqrT5pFaqjq/tjIqXxwXKLVCX5eyO1XRFZdYABb/IhJFFv0Bztf 7FfEUUpoNEGfqMVaw6OxH45G5ak8yb/GqxStm06QIf74XkJKCUDa/E0q+XNklYW4PRq1 HqB3q5PWC9zuU8f6B8nSjIUmE17X+6r3nmyjd7W1ujC8rwpHixzQJAUBcJNNeVCMmW/S 7RqA== X-Gm-Message-State: AKwxytd8szONd1hSjQObB0ktrp9NKdEdLtlnKtI7EXaJgFnZ1B2AH0fO 04to5GLjLhBN7teibZC6i0E= X-Google-Smtp-Source: AH8x22646diHDaEF/rMj7Hm/sHb3T3Ll4XsIxAV3nycIBn5/YUjDZgIZ7CdHsmAWYGSglfniqxaREg== X-Received: by 10.80.134.132 with SMTP id r4mr14594239eda.250.1516638338511; Mon, 22 Jan 2018 08:25:38 -0800 (PST) Received: from localhost.localdomain ([178.19.216.175]) by smtp.gmail.com with ESMTPSA id g21sm11920844edg.88.2018.01.22.08.25.37 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 22 Jan 2018 08:25:37 -0800 (PST) From: Alban Crequy X-Google-Original-From: Alban Crequy To: alban@kinvolk.io Cc: dongsu@kinvolk.io, iago@kinvolk.io, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fsdevel@vger.kernel.org, miklos@szeredi.hu, viro@zeniv.linux.org.uk, zohar@linux.vnet.ibm.com, dmitry.kasatkin@gmail.com, james.l.morris@oracle.com, serge@hallyn.com, seth.forshee@canonical.com, hch@infradead.org Subject: [RFC PATCH v3 2/2] ima: force re-appraisal on filesystems with FS_IMA_NO_CACHE Date: Mon, 22 Jan 2018 17:24:52 +0100 Message-Id: <20180122162452.8756-3-alban@kinvolk.io> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180122162452.8756-1-alban@kinvolk.io> References: <20180122162452.8756-1-alban@kinvolk.io> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Alban Crequy This patch forces files to be re-measured, re-appraised and re-audited on file systems with the feature flag FS_IMA_NO_CACHE. In that way, cached integrity results won't be used. How to test this: The test I did was using a patched version of the memfs FUSE driver [1][2] and two very simple "hello-world" programs [4] (prog1 prints "hello world: 1" and prog2 prints "hello world: 2"). I copy prog1 and prog2 in the fuse-memfs mount point, execute them and check the sha1 hash in "/sys/kernel/security/ima/ascii_runtime_measurements". My patch on the memfs FUSE driver added a backdoor command to serve prog1 when the kernel asks for prog2 or vice-versa. In this way, I can exec prog1 and get it to print "hello world: 2" without ever replacing the file via the VFS, so the kernel is not aware of the change. The test was done using the branch "alban/fuse-flag-ima-nocache-v3" [3]. Step by step test procedure: 1. Mount the memfs FUSE using [2]: rm -f /tmp/memfs-switch* ; memfs -L DEBUG /mnt/memfs 2. Copy prog1 and prog2 using [4] cp prog1 /mnt/memfs/prog1 cp prog2 /mnt/memfs/prog2 3. Lookup the files and let the FUSE driver to keep the handles open: dd if=/mnt/memfs/prog1 bs=1 | (read -n 1 x ; sleep 3600 ) & dd if=/mnt/memfs/prog2 bs=1 | (read -n 1 x ; sleep 3600 ) & 4. Check the 2 programs work correctly: $ /mnt/memfs/prog1 hello world: 1 $ /mnt/memfs/prog2 hello world: 2 5. Check the measurements for prog1 and prog2: $ sudo cat /sys/kernel/security/ima/ascii_runtime_measurements \ | grep /mnt/memfs/prog 10 [...] ima-ng sha1:ac14c9268cd2[...] /mnt/memfs/prog1 10 [...] ima-ng sha1:799cb5d1e06d[...] /mnt/memfs/prog2 6. Use the backdoor command in my patched memfs to redirect file operations on file handle 3 to file handle 2: rm -f /tmp/memfs-switch* ; touch /tmp/memfs-switch-3-2 7. Check how the FUSE driver serves different content for the files: $ /mnt/memfs/prog1 hello world: 2 $ /mnt/memfs/prog2 hello world: 2 8. Check the measurements: sudo cat /sys/kernel/security/ima/ascii_runtime_measurements \ | grep /mnt/memfs/prog Without the patch, there are no new measurements, despite the FUSE driver having served different executables. With the patch, I can see additional measurements for prog1 and prog2 with the hashes reversed when the FUSE driver served the alternative content. [1] https://github.com/bbengfort/memfs [2] https://github.com/kinvolk/memfs/commits/alban/switch-files [3] https://github.com/kinvolk/linux/commits/alban/fuse-flag-ima-nocache-v3 [4] https://github.com/kinvolk/fuse-userns-patches/commit/cf1f5750cab0 Cc: linux-kernel@vger.kernel.org Cc: linux-integrity@vger.kernel.org Cc: linux-security-module@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: Miklos Szeredi Cc: Alexander Viro Cc: Mimi Zohar Cc: Dmitry Kasatkin Cc: James Morris Cc: "Serge E. Hallyn" Cc: Seth Forshee Cc: Christoph Hellwig Tested-by: Dongsu Park Signed-off-by: Alban Crequy Acked-by: Seth Forshee Acked-by: Serge Hallyn --- security/integrity/ima/ima_main.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 6d78cb26784d..8870a7bbe9b9 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "ima.h" @@ -228,9 +229,28 @@ static int process_measurement(struct file *file, char *buf, loff_t size, IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | IMA_ACTION_FLAGS); - if (test_and_clear_bit(IMA_CHANGE_XATTR, &iint->atomic_flags)) - /* reset all flags if ima_inode_setxattr was called */ + /* + * Reset the measure, appraise and audit cached flags either if: + * - ima_inode_setxattr was called, or + * - based on filesystem feature flag + * forcing the file to be re-evaluated. + */ + if (test_and_clear_bit(IMA_CHANGE_XATTR, &iint->atomic_flags)) { iint->flags &= ~IMA_DONE_MASK; + } else if (inode->i_sb->s_type->fs_flags & FS_IMA_NO_CACHE) { + if (action & IMA_MEASURE) { + iint->measured_pcrs = 0; + iint->flags &= + ~(IMA_COLLECTED | IMA_MEASURE | IMA_MEASURED); + } + if (action & IMA_APPRAISE) + iint->flags &= + ~(IMA_COLLECTED | IMA_APPRAISE | IMA_APPRAISED | + IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK); + if (action & IMA_AUDIT) + iint->flags &= + ~(IMA_COLLECTED | IMA_AUDIT | IMA_AUDITED); + } /* Determine if already appraised/measured based on bitmask * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,