From patchwork Fri Dec 20 15:42:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11305815 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 6F37014E3 for ; Fri, 20 Dec 2019 15:42:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4D5E324682 for ; Fri, 20 Dec 2019 15:42:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="gaLV8Raq" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727698AbfLTPmh (ORCPT ); Fri, 20 Dec 2019 10:42:37 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:34236 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727608AbfLTPmR (ORCPT ); Fri, 20 Dec 2019 10:42:17 -0500 Received: by mail-wm1-f65.google.com with SMTP id c127so2047713wme.1 for ; Fri, 20 Dec 2019 07:42:15 -0800 (PST) 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=CYWJ2URo8mjs0x8nMZWhI4jpk+MpL4wZVs4eBeXrsUE=; b=gaLV8RaqsIk6PcheutwFOcwCTJTOq+9pY0YnqLS9Xr93Q6kmHhWykg7wh6QBTREgG/ Q1ZxTakEI+XXkWBgO3FP19dUWHEKr00AV9goO9XBHAvtb52oMkP4GoZrjJwGS8BGgFji h9oePflZ4Ps1KAlC+m+cMvbA0ELtIGKOq+cys= 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=CYWJ2URo8mjs0x8nMZWhI4jpk+MpL4wZVs4eBeXrsUE=; b=huo5eaYcFMtKp0GXa5ZKqYHbp4thzjYntw2DFORedfDDLb4/m4wtuznCcd37nULyy5 VqywSFh90oVVmu8l2++iHyT0DOeauvgDAdPWh7LYUfxq3WQswjaqNq6gMjqE5lInAUif xeKkAYhd9TFMAT2yWFcrkJ773HhVJLt6nBqobBqKsnJ3JR58GjBwz4VmRaLcx6duCqTn txhvMSaNNnrGp2tXxoZ2RKFQ0pCU4zQ1JjbqXH+r29OOJvVLLVvow583ptLJOEowDSMu vTxDQhkXIzERQu46l33/9I8tE9Jd93R0+Wnx4a3xd58wMlvy13xuxdDwKCOSbjwEv0O9 SYmg== X-Gm-Message-State: APjAAAWh3LXvXPv6geXnqIH4sanhHzZBXnw9LbsOFwImshyGfMOx7H4c Nhk4+lbEkOtI1bpmnBK+nuWnCw== X-Google-Smtp-Source: APXvYqxza4vYJuCwfGbOtBIg2+UIbNuLIe8LlwTs049KCCz0BjChZd60j+gUte33pdPrBrNKcZPDLg== X-Received: by 2002:a7b:c775:: with SMTP id x21mr10365683wmk.59.1576856535130; Fri, 20 Dec 2019 07:42:15 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2a00:79e1:abc:308:c46b:b838:66cf:6204]) by smtp.gmail.com with ESMTPSA id x11sm10118062wmg.46.2019.12.20.07.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Dec 2019 07:42:14 -0800 (PST) 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 , Brendan Jackman , 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: [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output Date: Fri, 20 Dec 2019 16:42:04 +0100 Message-Id: <20191220154208.15895-10-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191220154208.15895-1-kpsingh@chromium.org> References: <20191220154208.15895-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh This helper is similar to bpf_perf_event_output except that it does need a ctx argument which is more usable in the BTF based LSM programs where the context is converted to the signature of the attacthed BTF type. An example usage of this function would be: struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(int)); __uint(value_size, sizeof(u32)); } perf_map SEC(".maps"); BPF_TRACE_1(bpf_prog1, "lsm/bprm_check_security, struct linux_binprm *, bprm) { char buf[BUF_SIZE]; int len; u64 flags = BPF_F_CURRENT_CPU; /* some logic that fills up buf with len data */ len = fill_up_buf(buf); if (len < 0) return len; if (len > BU) return 0; bpf_lsm_event_output(&perf_map, flags, buf, len); return 0; } Signed-off-by: KP Singh --- include/uapi/linux/bpf.h | 10 +++++++++- kernel/bpf/verifier.c | 1 + security/bpf/ops.c | 21 +++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 10 +++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index fc64ae865526..3511fa271c9b 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2823,6 +2823,13 @@ union bpf_attr { * Return * On success, the strictly positive length of the string, including * the trailing NUL character. On error, a negative value. + * + * int bpf_lsm_event_output(struct bpf_map *map, u64 flags, void *data, u64 size) + * Description + * This helper is similar to bpf_perf_event_output except that it + * it does not need a context argument. + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2940,7 +2947,8 @@ union bpf_attr { FN(probe_read_user), \ FN(probe_read_kernel), \ FN(probe_read_user_str), \ - FN(probe_read_kernel_str), + FN(probe_read_kernel_str), \ + FN(lsm_event_output), \ /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 0d1231d9c1ef..ff050fd71e9f 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3641,6 +3641,7 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, if (func_id != BPF_FUNC_perf_event_read && func_id != BPF_FUNC_perf_event_output && func_id != BPF_FUNC_skb_output && + func_id != BPF_FUNC_lsm_event_output && func_id != BPF_FUNC_perf_event_read_value) goto error; break; diff --git a/security/bpf/ops.c b/security/bpf/ops.c index eb8a8db28109..e9aae2ce718c 100644 --- a/security/bpf/ops.c +++ b/security/bpf/ops.c @@ -129,6 +129,25 @@ int bpf_lsm_detach(const union bpf_attr *attr) const struct bpf_prog_ops lsm_prog_ops = { }; +BPF_CALL_4(bpf_lsm_event_output, + struct bpf_map *, map, u64, flags, void *, data, u64, size) +{ + if (unlikely(flags & ~(BPF_F_INDEX_MASK))) + return -EINVAL; + + return bpf_event_output(map, flags, data, size, NULL, 0, NULL); +} + +static const struct bpf_func_proto bpf_lsm_event_output_proto = { + .func = bpf_lsm_event_output, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_CONST_SIZE_OR_ZERO, +}; + static const struct bpf_func_proto *get_bpf_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { @@ -137,6 +156,8 @@ static const struct bpf_func_proto *get_bpf_func_proto(enum bpf_func_id return &bpf_map_lookup_elem_proto; case BPF_FUNC_get_current_pid_tgid: return &bpf_get_current_pid_tgid_proto; + case BPF_FUNC_lsm_event_output: + return &bpf_lsm_event_output_proto; default: return NULL; } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index fc64ae865526..3511fa271c9b 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2823,6 +2823,13 @@ union bpf_attr { * Return * On success, the strictly positive length of the string, including * the trailing NUL character. On error, a negative value. + * + * int bpf_lsm_event_output(struct bpf_map *map, u64 flags, void *data, u64 size) + * Description + * This helper is similar to bpf_perf_event_output except that it + * it does not need a context argument. + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2940,7 +2947,8 @@ union bpf_attr { FN(probe_read_user), \ FN(probe_read_kernel), \ FN(probe_read_user_str), \ - FN(probe_read_kernel_str), + FN(probe_read_kernel_str), \ + FN(lsm_event_output), \ /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call