From patchwork Tue Sep 10 11:55:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11139291 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1ABD876 for ; Tue, 10 Sep 2019 11:57:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E3D8A21479 for ; Tue, 10 Sep 2019 11:57:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="CHldEZZf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729357AbfIJL5R (ORCPT ); Tue, 10 Sep 2019 07:57:17 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:36089 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388259AbfIJL4n (ORCPT ); Tue, 10 Sep 2019 07:56:43 -0400 Received: by mail-wr1-f65.google.com with SMTP id y19so19629789wrd.3 for ; Tue, 10 Sep 2019 04:56:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=goHxQO5WE56PjZrElqp9mWD4UyL0ez4HVWRIM6UzU3c=; b=CHldEZZfNkVRxXOpA/ZEWOkGHLNYox5M0eQi+ih3ANNwJcZssMhLi1RvrKo6pFLpIu O0krOoKt/DkqNYVlPOFbFJ/LCVr2AyI88WBCpVC/zADylr9USKLI3of2dqtzmKkjm1EM AkCKEJMXkpFGE+nb6HJM6DAYeR0LzGOGEhFgg= 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:mime-version:content-transfer-encoding; bh=goHxQO5WE56PjZrElqp9mWD4UyL0ez4HVWRIM6UzU3c=; b=WPy2Z/DPz4w9zqoNCDw24OZ3EGbOOkeUXVakCUYjUyYQ9mciQzMWK/Zx4l++JMWfrK 05jWs/vQNLi0q9JJPdbDriNYm2GtgP67DaU+znpyaBbtxwSoAhV1532NoZ7yMayhWMw7 ZT/EIopHT/59kBoCBdXpd5LQxlVKk0+hbu/u2q8iHYW5nv7dW8NJ/rdTKblkW7pU4Qsk G98sUs0zt3mqOToFhhCSu02KEx3oKykhoOBjYYrzBmFXaspjCPKUYFuW8KNBRnZksKAr XSQQPTu6Wn70mklnp0hg8cfWmMCTBeZwJkppw9TsrArVtq+/sYXrLB9kTfSSx2WgQHKR KIjQ== X-Gm-Message-State: APjAAAXajzs3SwroMB1eHSzv1Zy8SRU0M2uG7+ErznxPxdLLFR2o8CDv V05FZvH4JH8upw7wMqWTDL8HUQ== X-Google-Smtp-Source: APXvYqy41deBTxwWe2+aWhU+4LiCXFDvi6WI4YCLje4OsKhs9MTrTG1c6KpCz0h80p4KZoQRWYOFwg== X-Received: by 2002:a5d:4fcf:: with SMTP id h15mr25996339wrw.237.1568116602133; Tue, 10 Sep 2019 04:56:42 -0700 (PDT) Received: from kpsingh-kernel.c.hoisthospitality.com (110.8.30.213.rev.vodafone.pt. [213.30.8.110]) by smtp.gmail.com with ESMTPSA id q19sm23732935wra.89.2019.09.10.04.56.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Sep 2019 04:56:41 -0700 (PDT) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , =?utf-8?q?Micka=C3=ABl_Sala=C3=BCn?= , Florent Revest , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , Mauro Carvalho Chehab , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [RFC v1 11/14] krsi: Pin argument pages in bprm_check_security hook Date: Tue, 10 Sep 2019 13:55:24 +0200 Message-Id: <20190910115527.5235-12-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190910115527.5235-1-kpsingh@chromium.org> References: <20190910115527.5235-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh Pin the memory allocated to the the argv + envv for the new process and passes it in the context to the eBPF programs attached to the hook. The get_user_pages_remote cannot be called from an eBPF helper because the helpers run in atomic context and the get_user_pages_remote function can sleep. The following heuristics can be added as an optimization: - Don't pin the pages if no eBPF programs are attached. - Don't pin the pages if none of the eBPF programs depend on the information. This would require introspection of the byte-code and checking if certain helpers are called. Signed-off-by: KP Singh --- security/krsi/include/krsi_init.h | 3 ++ security/krsi/krsi.c | 56 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/security/krsi/include/krsi_init.h b/security/krsi/include/krsi_init.h index 4e17ecacd4ed..6152847c3b08 100644 --- a/security/krsi/include/krsi_init.h +++ b/security/krsi/include/krsi_init.h @@ -16,6 +16,9 @@ extern int krsi_fs_initialized; struct krsi_bprm_ctx { struct linux_binprm *bprm; + char *arg_pages; + unsigned long num_arg_pages; + unsigned long max_arg_offset; }; /* diff --git a/security/krsi/krsi.c b/security/krsi/krsi.c index d3a4a361c192..00a7150c1b22 100644 --- a/security/krsi/krsi.c +++ b/security/krsi/krsi.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "krsi_init.h" @@ -17,6 +19,53 @@ struct krsi_hook krsi_hooks_list[] = { #undef KRSI_HOOK_INIT }; +static int pin_arg_pages(struct krsi_bprm_ctx *ctx) +{ + int ret = 0; + char *kaddr; + struct page *page; + unsigned long i, pos, num_arg_pages; + struct linux_binprm *bprm = ctx->bprm; + char *buf; + + /* + * The bprm->vma_pages does not have the correct count + * for execution that is done by a kernel thread using the UMH. + * vm_pages is updated in acct_arg_size and bails + * out if current->mm is NULL (which is the case for a kernel thread). + * It's safer to use vma_pages(struct linux_binprm*) to get the + * actual number + */ + num_arg_pages = vma_pages(bprm->vma); + if (!num_arg_pages) + return -ENOMEM; + + buf = kmalloc_array(num_arg_pages, PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < num_arg_pages; i++) { + pos = ALIGN_DOWN(bprm->p, PAGE_SIZE) + i * PAGE_SIZE; + ret = get_user_pages_remote(current, bprm->mm, pos, 1, + FOLL_FORCE, &page, NULL, NULL); + if (ret <= 0) { + kfree(buf); + return -ENOMEM; + } + + kaddr = kmap(page); + memcpy(buf + i * PAGE_SIZE, kaddr, PAGE_SIZE); + kunmap(page); + put_page(page); + } + + ctx->arg_pages = buf; + ctx->num_arg_pages = num_arg_pages; + ctx->max_arg_offset = num_arg_pages * PAGE_SIZE; + + return 0; +} + static int krsi_process_execution(struct linux_binprm *bprm) { int ret; @@ -26,7 +75,14 @@ static int krsi_process_execution(struct linux_binprm *bprm) .bprm = bprm, }; + ret = pin_arg_pages(&ctx.bprm_ctx); + if (ret < 0) + goto out_arg_pages; + ret = krsi_run_progs(PROCESS_EXECUTION, &ctx); + kfree(ctx.bprm_ctx.arg_pages); + +out_arg_pages: return ret; }