From patchwork Sat Apr 20 00:15:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prakhar Srivastava X-Patchwork-Id: 10909875 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C5DDF14DB for ; Sat, 20 Apr 2019 00:15:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE19128CBB for ; Sat, 20 Apr 2019 00:15:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E96328CD7; Sat, 20 Apr 2019 00:15:52 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 E833A28CBB for ; Sat, 20 Apr 2019 00:15:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725859AbfDTAPv (ORCPT ); Fri, 19 Apr 2019 20:15:51 -0400 Received: from mail-pl1-f195.google.com ([209.85.214.195]:36466 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725858AbfDTAPu (ORCPT ); Fri, 19 Apr 2019 20:15:50 -0400 Received: by mail-pl1-f195.google.com with SMTP id ck15so3231255plb.3; Fri, 19 Apr 2019 17:15:50 -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=WvABMMiydtEeyibegfEfLEBkYjxrs2E70YFNAbmjJWA=; b=SYbYmOix/0fDgJ+jIEtXGlSk/S6Iecnq23aqKgohyCHBnrnWnGsxbzrNO/ZmWWpW3v 5RKHLbf6gXnk0MVse0Yse4fGMotXuE3z3QPPLjuXYUrnJgosGiGyrUPzwZeFFApn4eEX ft4nQ7xdDe0dO8cA7wxhQ1pzfSSPRSPe89mOwo7ApCCwud/DQCnNzq61BVJa3dxfeSvz b9a/bWeBOHy0kzHUStdtcQB0N4ld510TLHkOu+Z1C/G/8evVkIXaEcLSQKUllQDXqj3f xe6JuKDdeeryznq3Kt1AVQxI2C0J4sTgj0qNOPviPNARhysIhN8DMS7lLcQqGG3i+hrE MKAg== 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=WvABMMiydtEeyibegfEfLEBkYjxrs2E70YFNAbmjJWA=; b=hYCwrvFwvWgAVEorYtC0TMJK6rQj2Y7ANqH6bibZat66ASruB3c5F07PgAThVqFiX9 fgzXnZ5wO8ONTk9+BQivuEDJWj33vt/z/vnFI0adzjlv7ciGUOWU3opdn5/I6LTEmvKG Ow44nfibDU57yp+iCu8vqZlLsNfrlYqscX4VNhkC5F+6Pr/8kNLYOLKeUeL/zh/RurNB BjDGISKtHZsVSogEbfTH/WSye3LN+2z5eP/J19VOMTcSWjtKwfgMKkGB54rYgHxhvkpo tvSHoVhhSv3vE3LcJUgtehCNNW/N4cZ94MldJfX6uGTQBZQQrONvZcAC2MrTpEk7cUJy tGhA== X-Gm-Message-State: APjAAAU3zSvVcA3sQz67mWLTdYCLQZkDSxAKwqOm+/NQFcv5+SJHwx8z PyEeFWQX9eeFKlQCPHf64hO9k0H8aTc= X-Google-Smtp-Source: APXvYqyo+o72spNAex9YybsclXDofwBaPYXwVpYYqF434YbuKtAYU1Wf47s61RwT5bLcwkg1nT8Bcg== X-Received: by 2002:a17:902:31c3:: with SMTP id x61mr6596398plb.143.1555719349744; Fri, 19 Apr 2019 17:15:49 -0700 (PDT) Received: from prsriva-linux.corp.microsoft.com ([2001:4898:80e8:2:5828:72bc:96ef:ce7c]) by smtp.gmail.com with ESMTPSA id a3sm8339902pfn.182.2019.04.19.17.15.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Apr 2019 17:15:48 -0700 (PDT) From: Prakhar Srivastava X-Google-Original-From: Prakhar Srivastava To: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, ebiederm@xmission.com, vgoyal@redhat.com, Prakhar Srivastava , Prakhar Srivastava Subject: [PATCH v2 1/3 RFC] added ima hook for buffer, being enabled as a policy Date: Fri, 19 Apr 2019 17:15:41 -0700 Message-Id: <20190420001543.6760-1-prsriva02@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Prakhar Srivastava Signed-off-by: Prakhar Srivastava --- Currently for soft reboot(kexec_file_load) the kernel file and signature is measured by IMA. The cmdline args used to load the kernel is not measured. The boot aggregate that gets calculated will have no change since the EFI loader has not been triggered. Adding the kexec cmdline args measure and kernel version will add some attestable criteria. This adds a new ima hook ima_buffer_check and a policy entry BUFFER_CHECK. This enables buffer has measurements into ima log Documentation/ABI/testing/ima_policy | 1 + include/linux/ima.h | 13 +++- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_main.c | 95 ++++++++++++++++++++++++++++ security/integrity/ima/ima_policy.c | 14 +++- 5 files changed, 122 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index bb0f9a135e21..676088c7ab26 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -28,6 +28,7 @@ Description: base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] + [BUFFER_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value diff --git a/include/linux/ima.h b/include/linux/ima.h index 7f6952f8d6aa..733d0cb9dedc 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -14,6 +14,12 @@ #include struct linux_binprm; +enum __buffer_id { + KERNEL_VERSION, + KEXEC_CMDLINE, + MAX_BUFFER_ID = KEXEC_CMDLINE +} buffer_id; + #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask, int opened); @@ -23,7 +29,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); extern void ima_post_path_mknod(struct dentry *dentry); - +extern void ima_buffer_check(const void *buff, int size, enum buffer_id id); #ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); #endif @@ -65,6 +71,11 @@ static inline void ima_post_path_mknod(struct dentry *dentry) return; } +static inline void ima_buffer_check(const void *buff, int size, + enum buffer_id id) +{ + return; +} #endif /* CONFIG_IMA */ #ifndef CONFIG_IMA_KEXEC diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b563fbd4d122..b71f2f6f7421 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -181,6 +181,7 @@ enum ima_hooks { FIRMWARE_CHECK, KEXEC_KERNEL_CHECK, KEXEC_INITRAMFS_CHECK, + BUFFER_CHECK, POLICY_CHECK, MAX_CHECK }; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2aebb7984437..6408cadaadbb 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -155,6 +155,84 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } +/* + * process_buffer_measurement - Measure the buffer passed to ima log. + * (Instead of using the file hash the buffer hash is used). + * @buff - The buffer that needs to be added to the log + * @size - size of buffer(in bytes) + * @id - buffer id, this is differentiator for the various buffers + * that can be measured. + * + * The buffer passed is added to the ima logs. + * If the sig template is used, then the sig field contains the buffer. + * + * On success return 0. + * On error cases surface errors from ima calls. + */ +static int process_buffer_measurement(const void *buff, int size, + enum buffer_id id) +{ + int ret = -EINVAL; + struct ima_template_entry *entry = NULL; + struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; + struct ima_event_data event_data = {iint, NULL, NULL, + NULL, 0, NULL}; + struct { + struct ima_digest_data hdr; + char digest[IMA_MAX_DIGEST_SIZE]; + } hash; + char *name = NULL; + int violation = 0; + int pcr = CONFIG_IMA_MEASURE_PCR_IDX; + + if (!buff || size == 0) + goto err_out; + + if (ima_get_action(NULL, 0, BUFFER_CHECK, &pcr) != IMA_MEASURE) + goto err_out; + + switch (buffer_id) { + case KERNEL_VERSION: + name = "Kernel-version"; + break; + case KEXEC_CMDLINE: + name = "Kexec-cmdline"; + break; + default: + goto err_out; + } + + memset(iint, 0, sizeof(*iint)); + memset(&hash, 0, sizeof(hash)); + + event_data.filename = name; + + iint->ima_hash = &hash.hdr; + iint->ima_hash->algo = ima_hash_algo; + iint->ima_hash->length = hash_digest_size[ima_hash_algo]; + + ret = ima_calc_buffer_hash(buff, size, iint->ima_hash); + if (ret < 0) + goto err_out; + + ret = ima_alloc_init_template(&event_data, &entry); + if (ret < 0) + goto err_out; + + ret = ima_store_template(entry, violation, NULL, + buff, pcr); + if (ret < 0) { + ima_free_template_entry(entry); + goto err_out; + } + + return 0; + +err_out: + pr_err("Error in adding buffer measure: %d\n", ret); + return ret; +} + static int process_measurement(struct file *file, char *buf, loff_t size, int mask, enum ima_hooks func, int opened) { @@ -370,6 +448,23 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) return 0; } +/** + * ima_buffer_check - based on policy, collect & store buffer measurement + * @buf: pointer to buffer + * @size: size of buffer + * @buffer_id: caller identifier + * + * Buffers can only be measured, not appraised. The buffer identifier + * is used as the measurement list entry name (eg. boot_cmdline). + */ +void ima_buffer_check(const void *buf, int size, enum buffer_id id) +{ + if (buf && size != 0) + process_buffer_measurement(buf, size, id); + + return; +} + static int read_idmap[READING_MAX_ID] = { [READING_FIRMWARE] = FIRMWARE_CHECK, [READING_MODULE] = MODULE_CHECK, diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 3ab1067db624..cefe1a188f31 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -231,6 +231,12 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, const struct cred *cred = current_cred(); int i; + // Incase of BUFFER_CHECK, Inode is NULL + if (!inode) { + if ((rule->flags & IMA_FUNC) && (rule->func == func)) + return true; + return false; + } if ((rule->flags & IMA_FUNC) && (rule->func != func && func != POST_SETATTR)) return false; @@ -665,6 +671,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK") == 0) entry->func = KEXEC_INITRAMFS_CHECK; + else if (strcmp(args[0].from, "BUFFER_CHECK") == 0) + entry->func = BUFFER_CHECK; else if (strcmp(args[0].from, "POLICY_CHECK") == 0) entry->func = POLICY_CHECK; else @@ -944,7 +952,7 @@ enum { func_file = 0, func_mmap, func_bprm, func_module, func_firmware, func_post, func_kexec_kernel, func_kexec_initramfs, - func_policy + func_buffer, func_policy }; static char *func_tokens[] = { @@ -956,6 +964,7 @@ static char *func_tokens[] = { "POST_SETATTR", "KEXEC_KERNEL_CHECK", "KEXEC_INITRAMFS_CHECK", + "BUFFER_CHECK", "POLICY_CHECK" }; @@ -1027,6 +1036,9 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func) case KEXEC_INITRAMFS_CHECK: seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs)); break; + case BUFFER_CHECK: + seq_printf(m, pt(Opt_func), ft(func_buffer)); + break; case POLICY_CHECK: seq_printf(m, pt(Opt_func), ft(func_policy)); break; From patchwork Sat Apr 20 00:15:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prakhar Srivastava X-Patchwork-Id: 10909879 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0858613B5 for ; Sat, 20 Apr 2019 00:16:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB21428CBB for ; Sat, 20 Apr 2019 00:16:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DFB0D28E14; Sat, 20 Apr 2019 00:16:02 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 C419228CBB for ; Sat, 20 Apr 2019 00:16:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727357AbfDTAPw (ORCPT ); Fri, 19 Apr 2019 20:15:52 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:41281 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725858AbfDTAPv (ORCPT ); Fri, 19 Apr 2019 20:15:51 -0400 Received: by mail-pf1-f194.google.com with SMTP id 188so3153626pfd.8; Fri, 19 Apr 2019 17:15:51 -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:in-reply-to:references; bh=eMFDUMGPg9svBemR3kNl+I7JDj7h3EAZp1KY9ojzIcE=; b=SCdyD0t8NDNzdihEGSsf3RbYesAe2cvCjKRDzLZ6UW1K5RtzF79MbDe2MLUIy8cb6l E8yyJ8jdY+UVOXHUZ2hpgKspfXuh9pYIhU3SAeC0y4JoPsUzZsQZtK7DksLqgX027LTm JUSSvDs63zk+d2Ckb804pXjs7NKaCYg6bwUyrJu0og1VtBd7iM9cRUY+iSDzDpXx91wh H9oHFzTDFulekT7YQQfolAHzilNitl3GaW0Da87rm3e/93iFkDrPfGUSd9UmcC2+EFVs 5cD7Ozg7ffHKPesRwOdlNhsh6vdv8peRlNwVeT/isklPUbpUvG2UAy6mVr66sKZ1BCJ1 L51g== 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:in-reply-to :references; bh=eMFDUMGPg9svBemR3kNl+I7JDj7h3EAZp1KY9ojzIcE=; b=c1dQwSo6X93aLR+X5JwvpTSFOrXwe/Fn3Fax7axuomGnHpT9ZUiTKeVfiPgfzHo9Zd de+vijzEorglyoTbLl30fs5bMtvRYMvBZcGAv2oqG7GIzNcWJySb3WnIfUTVBxJzTGwr z7DEOo4MtFvelUAihP3RuXhFdJoUk1VLXc18tqdYW5DLaFf2hCKRgNTXvnnbUDD2J/lX WFvrcVYAg5/1rxqavSHFeQFbkuR2OoTyUp5GcA7Ch3k0v6DLyciw4nUtcOUQ/zukkIYk ITz2n2Oxj+qScxtl2NqK9dVftcjtfRd5mysmn6JFKWj7G+RVGHJ8e06nVhbdfIorGJkK 78MQ== X-Gm-Message-State: APjAAAVdQjoaBwyEd8oN4KuBCGuuMgHEH89Bs1YRgFepL8ffAhLyS1n2 0jnOhoXk+pE+ydIE4yRqawMmWaNNjiA= X-Google-Smtp-Source: APXvYqywUZe67MMD7vU+EraF76aWxm0b0ZHyJFcqF1pio2hb63Lew//h5HGHhSc7MAvrgv2RC48DXA== X-Received: by 2002:a63:10c:: with SMTP id 12mr6846302pgb.276.1555719350968; Fri, 19 Apr 2019 17:15:50 -0700 (PDT) Received: from prsriva-linux.corp.microsoft.com ([2001:4898:80e8:2:5828:72bc:96ef:ce7c]) by smtp.gmail.com with ESMTPSA id a3sm8339902pfn.182.2019.04.19.17.15.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Apr 2019 17:15:49 -0700 (PDT) From: Prakhar Srivastava X-Google-Original-From: Prakhar Srivastava To: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, ebiederm@xmission.com, vgoyal@redhat.com, Prakhar Srivastava , Prakhar Srivastava Subject: [PATCH v2 2/3 RFC] use event name instead of enum to make the call generic Date: Fri, 19 Apr 2019 17:15:42 -0700 Message-Id: <20190420001543.6760-2-prsriva02@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190420001543.6760-1-prsriva02@gmail.com> References: <20190420001543.6760-1-prsriva02@gmail.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Prakhar Srivastava Signed-off-by: Prakhar Srivastava --- Currently for soft reboot(kexec_file_load) the kernel file and signature is measured by IMA. The cmdline args used to load the kernel is not measured. The boot aggregate that gets calculated will have no change since the EFI loader has not been triggered. Adding the kexec cmdline args measure and kernel version will add some attestable criteria. remove enums to control type of buffers entries, instead pass the event name to be used. include/linux/ima.h | 10 ++-------- kernel/kexec_file.c | 3 +++ security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_main.c | 30 ++++++++++-------------------- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 733d0cb9dedc..5e41507c57e5 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -14,12 +14,6 @@ #include struct linux_binprm; -enum __buffer_id { - KERNEL_VERSION, - KEXEC_CMDLINE, - MAX_BUFFER_ID = KEXEC_CMDLINE -} buffer_id; - #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask, int opened); @@ -29,7 +23,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); extern void ima_post_path_mknod(struct dentry *dentry); -extern void ima_buffer_check(const void *buff, int size, enum buffer_id id); +extern void ima_buffer_check(const void *buff, int size, char *eventname); #ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); #endif @@ -72,7 +66,7 @@ static inline void ima_post_path_mknod(struct dentry *dentry) } static inline void ima_buffer_check(const void *buff, int size, - enum buffer_id id) + char *eventname) { return; } diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index b118735fea9d..2a5234eb4b28 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -182,6 +182,9 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, ret = -EINVAL; goto out; } + + ima_buffer_check(image->cmdline_buf, cmdline_len - 1, + "kexec_cmdline"); } /* Call arch image load handlers */ diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b71f2f6f7421..fcade3c103ed 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -181,8 +181,8 @@ enum ima_hooks { FIRMWARE_CHECK, KEXEC_KERNEL_CHECK, KEXEC_INITRAMFS_CHECK, - BUFFER_CHECK, POLICY_CHECK, + BUFFER_CHECK, MAX_CHECK }; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 6408cadaadbb..da82c705a5ed 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -160,8 +160,7 @@ void ima_file_free(struct file *file) * (Instead of using the file hash the buffer hash is used). * @buff - The buffer that needs to be added to the log * @size - size of buffer(in bytes) - * @id - buffer id, this is differentiator for the various buffers - * that can be measured. + * @id - eventname, event name to be used for buffer measurement. * * The buffer passed is added to the ima logs. * If the sig template is used, then the sig field contains the buffer. @@ -170,7 +169,7 @@ void ima_file_free(struct file *file) * On error cases surface errors from ima calls. */ static int process_buffer_measurement(const void *buff, int size, - enum buffer_id id) + char *eventname) { int ret = -EINVAL; struct ima_template_entry *entry = NULL; @@ -185,23 +184,13 @@ static int process_buffer_measurement(const void *buff, int size, int violation = 0; int pcr = CONFIG_IMA_MEASURE_PCR_IDX; - if (!buff || size == 0) + if (!buff || size == 0 || !eventname) goto err_out; if (ima_get_action(NULL, 0, BUFFER_CHECK, &pcr) != IMA_MEASURE) goto err_out; - switch (buffer_id) { - case KERNEL_VERSION: - name = "Kernel-version"; - break; - case KEXEC_CMDLINE: - name = "Kexec-cmdline"; - break; - default: - goto err_out; - } - + name = eventname; memset(iint, 0, sizeof(*iint)); memset(&hash, 0, sizeof(hash)); @@ -452,15 +441,16 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) * ima_buffer_check - based on policy, collect & store buffer measurement * @buf: pointer to buffer * @size: size of buffer - * @buffer_id: caller identifier + * @eventname: caller identifier * * Buffers can only be measured, not appraised. The buffer identifier - * is used as the measurement list entry name (eg. boot_cmdline). + * is used as the measurement list entry name (eg. boot_cmdline, + * kernel_version). */ -void ima_buffer_check(const void *buf, int size, enum buffer_id id) +void ima_buffer_check(const void *buf, int size, char *eventname) { - if (buf && size != 0) - process_buffer_measurement(buf, size, id); + if (buf && size != 0 && eventname) + process_buffer_measurement(buf, size, eventname); return; } From patchwork Sat Apr 20 00:15:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prakhar Srivastava X-Patchwork-Id: 10909877 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 259EC14DB for ; Sat, 20 Apr 2019 00:15:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1481228CBB for ; Sat, 20 Apr 2019 00:15:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 082C728CD7; Sat, 20 Apr 2019 00:15:59 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 8808128CBB for ; Sat, 20 Apr 2019 00:15:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725858AbfDTAPx (ORCPT ); Fri, 19 Apr 2019 20:15:53 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:43128 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727385AbfDTAPx (ORCPT ); Fri, 19 Apr 2019 20:15:53 -0400 Received: by mail-pl1-f193.google.com with SMTP id n8so3208101plp.10; Fri, 19 Apr 2019 17:15:52 -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:in-reply-to:references; bh=89tWsU/OT5SYrbjwn65xtN7OxFoXBZMgUvk/yoALgYk=; b=caxaNmAr98e1Z07q/VdVXR2cdbkxvt0ij/qD+nz6st0OJIM66GbQdII6QNhy2G683g GcefLJltQFAWVCX+J1EkWLoC9k9fG2YB04sREBg51JY6Q172mvr7kRMf9e63J6ijHm5O mLAFGvTIJ71j/q5mFEM89+wuPyMfIJm2qZAzLo6pvBlxm4+u/ycM7/vWLqzPpUmbpKyG 4+4utrKZxBxIx8se+azpuwQ/U4+K3qdXbRHYsNijuRNIcI7qNCObPlQhjEoWyYpOBMLy /ZdTWacRBSYVJbWQrVAwF4Zf8sPQBFM2DQ2Uk/YFDInx1WnWhCMcScnCkGleN2PQXcT5 4mtg== 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:in-reply-to :references; bh=89tWsU/OT5SYrbjwn65xtN7OxFoXBZMgUvk/yoALgYk=; b=Y7kAMaLNyPebPHI0BgJDZuCAhi9ovbktER1uZtbXPtapW+Fu1NRFxBqsoDmcqku/Jc cqOH2+Y+xN3AZvlasm4GO/Hcs+U4fuc97LuhqnCJ8MCFpHmTIuIplZa9yKjai62u/llC QGJVzuJi2d8suae5CwoVE49TTw6Ly5kPL4mgxzMFMhOsGIBmwQMIoHiGH6SpT2RVM6Xi MlnBq7GZo0rInkeR7sBOdCczoVzJlAmWxF2L3ujoF+Zs15E9+MSyWFcgpzQqJyjgNQKs eNASMRimO+fsziYkbW/8PwJQGFGGRG3WLCY+tZvoU1LTyZjb9zJvD6GpgEYFyxwzg+G1 g7jA== X-Gm-Message-State: APjAAAU1a0SLRbTKYPk6LxuAbKwWhCbbZW3014EQ/YOxaLs9P5KvVNwg XsT4VPSaUuPsCdDoE9WWtsjEZGDpj1E= X-Google-Smtp-Source: APXvYqyTxq2Z5dU4I+e4VPdnoXkBsRm6nfrvXB314dNiWiHFwvVNPMKMA8xHlPMfe5wK+uMnS5XiJA== X-Received: by 2002:a17:902:ea8d:: with SMTP id cv13mr65059plb.23.1555719352046; Fri, 19 Apr 2019 17:15:52 -0700 (PDT) Received: from prsriva-linux.corp.microsoft.com ([2001:4898:80e8:2:5828:72bc:96ef:ce7c]) by smtp.gmail.com with ESMTPSA id a3sm8339902pfn.182.2019.04.19.17.15.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Apr 2019 17:15:51 -0700 (PDT) From: Prakhar Srivastava X-Google-Original-From: Prakhar Srivastava To: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, ebiederm@xmission.com, vgoyal@redhat.com, Prakhar Srivastava , Prakhar Srivastava Subject: [PATCH v2 3/3 RFC] since cmdline args can be same for multiple kexec, log entry hash will collide. Prepend the kernel file name to the cmdline args to distinguish between cmdline args passed to subsequent kexec calls Date: Fri, 19 Apr 2019 17:15:43 -0700 Message-Id: <20190420001543.6760-3-prsriva02@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190420001543.6760-1-prsriva02@gmail.com> References: <20190420001543.6760-1-prsriva02@gmail.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Prakhar Srivastava Signed-off-by: Prakhar Srivastava --- Currently for soft reboot(kexec_file_load) the kernel file and signature is measured by IMA. The cmdline args used to load the kernel is not measured. The boot aggregate that gets calculated will have no change since the EFI loader has not been triggered. Adding the kexec cmdline args measure and kernel version will add some attestable criteria. Cmdline args can be same for multiple kexec, log entry hash will collide. Prepend the kernel file name to the cmdline args to distinguish between cmdline args passed to subsequent kexec calls kernel/kexec_core.c | 57 +++++++++++++++++++++++++++++++++++++++++ kernel/kexec_file.c | 14 ++++++++-- kernel/kexec_internal.h | 3 +++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index ae1a3ba24df5..97b77c780311 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1151,3 +1151,60 @@ void __weak arch_kexec_protect_crashkres(void) void __weak arch_kexec_unprotect_crashkres(void) {} + +/** + * kexec_cmdline_prepend_img_name - prepare the buffer with cmdline + * that needs to be measured + * @outbuf - out buffer that contains the formated string + * @kernel_fd - the file identifier for the kerenel image + * @cmdline_ptr - ptr to the cmdline buffer + * @cmdline_len - len of the buffer. + * + * This generates a buffer in the format Kerenelfilename::cmdline + * + * On success return 0. + * On failure return -EINVAL. + */ +int kexec_cmdline_prepend_img_name(char **outbuf, int kernel_fd, + const char *cmdline_ptr, + unsigned long cmdline_len) +{ + int ret = -EINVAL; + struct fd f = {}; + int size = 0; + char *buf = NULL; + char delimiter[] = "::"; + + if (!outbuf || !cmdline_ptr) + goto out; + + f = fdget(kernel_fd); + if (!f.file) + goto out; + + size = (f.file->f_path.dentry->d_name.len + cmdline_len - 1+ + ARRAY_SIZE(delimiter)) - 1; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + goto out; + + memcpy(buf, f.file->f_path.dentry->d_name.name, + f.file->f_path.dentry->d_name.len); + memcpy(buf + f.file->f_path.dentry->d_name.len, + delimiter, ARRAY_SIZE(delimiter) - 1); + memcpy(buf + f.file->f_path.dentry->d_name.len + + ARRAY_SIZE(delimiter) - 1, + cmdline_ptr, cmdline_len - 1); + + *outbuf = buf; + ret = size; + + pr_debug("kexec cmdline buff: %s\n", buf); + +out: + if (f.file) + fdput(f); + + return ret; +} diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 2a5234eb4b28..a487491d55b9 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -126,6 +126,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, int ret = 0; void *ldata; loff_t size; + char *buff_to_measure = NULL; + int buff_to_measure_size = 0; ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf, &size, INT_MAX, READING_KEXEC_IMAGE); @@ -183,8 +185,13 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, goto out; } - ima_buffer_check(image->cmdline_buf, cmdline_len - 1, - "kexec_cmdline"); + /* IMA measures the cmdline args passed to the next kernel*/ + buff_to_measure_size = kexec_cmdline_prepend_img_name(&buff_to_measure, + kernel_fd, image->cmdline_buf, image->cmdline_buf_len); + + ima_buffer_check(buff_to_measure, buff_to_measure_size, + "kexec_cmdline"); + } /* Call arch image load handlers */ @@ -200,6 +207,9 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, /* In case of error, free up all allocated memory in this function */ if (ret) kimage_file_post_load_cleanup(image); + + kfree(buff_to_measure); + return ret; } diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index 799a8a452187..4d34a8ef4637 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h @@ -11,6 +11,9 @@ int kimage_load_segment(struct kimage *image, struct kexec_segment *segment); void kimage_terminate(struct kimage *image); int kimage_is_destination_range(struct kimage *image, unsigned long start, unsigned long end); +int kexec_cmdline_prepend_img_name(char **outbuf, int kernel_fd, + const char *cmdline_ptr, + unsigned long cmdline_len); extern struct mutex kexec_mutex;