From patchwork Fri Dec 20 15:41:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11305827 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 C3A176C1 for ; Fri, 20 Dec 2019 15:43:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 98F6324686 for ; Fri, 20 Dec 2019 15:43:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="VETjIrwl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727499AbfLTPnG (ORCPT ); Fri, 20 Dec 2019 10:43:06 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:36211 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727489AbfLTPmK (ORCPT ); Fri, 20 Dec 2019 10:42:10 -0500 Received: by mail-wm1-f67.google.com with SMTP id p17so9701322wma.1 for ; Fri, 20 Dec 2019 07:42:09 -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=lGbC4jtkbenMhpDKup9C3+jqzXEqt+dJgjev6KEIOek=; b=VETjIrwlgBW+OUmHFNDHX0Zw88OSzly/p7nHYWblLY6Sa7Mb0z/OHhmgj8gGVu3ziR NZiUBuYscoE9SQixKMWe+y5BYzC+o9rLeenQZY0PJ7YFdIMGpxEcVg1r43b2O2w9+q0u 0sNNIQWuzU9puQcbjPYK83aY2M9InywGj1AgA= 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=lGbC4jtkbenMhpDKup9C3+jqzXEqt+dJgjev6KEIOek=; b=W8iGDkmwsWKr2oKAJ8bM5/+aIlUdELnmULcKwA5Ey5Q4HR8yPm7MjwkOWkcrFWXjv2 vrtJ8h7NvQpmNtlIioMDnBSeNgSQxZvF4XHqLvI99DAem7sJqa4Do5qLHjQVMCE+lBtL 0CUVFBgzyeqJK6mEmKemVgJerPY+kHVUAxKqWMxzmkSffjVqAnQdBGMQMQukJm8kRRq0 6VENlaJ6rBtdKAcLt80OHGCAJBE6DEytaMcp5sJT97SdsXQp7N5SCLNCX5I9brnbvuEI Cu1HQLYuzrsPSwbQyaasqPQnHX7Cgg6/+rNrNUOlFMzZ1+b0r9jRd53rCGHWkD8zM40c eOQA== X-Gm-Message-State: APjAAAUu3hNUtn55JFpRW4htUPbsRR0Vt5LRexA5dVYAKQaxhDJ4k6DT pHRIOM7+kR1Y1mMOumcK8oaocw== X-Google-Smtp-Source: APXvYqwtrwTRJzANfCKqBfDMYFXH9/CapY3ImHpG/kCN7tNJtEhkLmU9gs6jlTYpwZFGZgFqOD9DQA== X-Received: by 2002:a1c:6809:: with SMTP id d9mr17402626wmc.70.1576856528490; Fri, 20 Dec 2019 07:42:08 -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.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Dec 2019 07:42:08 -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 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks Date: Fri, 20 Dec 2019 16:41:59 +0100 Message-Id: <20191220154208.15895-5-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 Refactor and re-use most of the logic for BPF_PROG_TYPE_TRACING with a few changes. - The LSM hook BTF types are prefixed with "lsm_btf_" - These types do not need the first (void *) pointer argument. The verifier only looks for this argument if prod->aux->attach_btf_trace is set. Signed-off-by: KP Singh --- kernel/bpf/syscall.c | 1 + kernel/bpf/verifier.c | 83 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 5a773fc6f9f5..4fcaf6042c07 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1642,6 +1642,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type, { switch (prog_type) { case BPF_PROG_TYPE_TRACING: + case BPF_PROG_TYPE_LSM: if (btf_id > BTF_MAX_TYPE) return -EINVAL; break; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a0482e1c4a77..0d1231d9c1ef 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9504,7 +9504,71 @@ static void print_verification_stats(struct bpf_verifier_env *env) env->peak_states, env->longest_mark_read_walk); } -static int check_attach_btf_id(struct bpf_verifier_env *env) +/* + * LSM hooks have a typedef associated with them. The BTF information for this + * type is used by the verifier to validate memory accesses made by the + * attached information. + * + * For example the: + * + * int bprm_check_security(struct linux_binprm *brpm) + * + * has the following typedef: + * + * typedef int (*lsm_btf_bprm_check_security)(struct linux_binprm *bprm); + */ +#define BTF_LSM_PREFIX "lsm_btf_" + +static inline int check_attach_btf_id_lsm(struct bpf_verifier_env *env) +{ + struct bpf_prog *prog = env->prog; + u32 btf_id = prog->aux->attach_btf_id; + const struct btf_type *t; + const char *tname; + + if (!btf_id) { + verbose(env, "LSM programs must provide btf_id\n"); + return -EINVAL; + } + + t = btf_type_by_id(btf_vmlinux, btf_id); + if (!t) { + verbose(env, "attach_btf_id %u is invalid\n", btf_id); + return -EINVAL; + } + + tname = btf_name_by_offset(btf_vmlinux, t->name_off); + if (!tname) { + verbose(env, "attach_btf_id %u doesn't have a name\n", btf_id); + return -EINVAL; + } + + if (!btf_type_is_typedef(t)) { + verbose(env, "attach_btf_id %u is not a typedef\n", btf_id); + return -EINVAL; + } + if (strncmp(BTF_LSM_PREFIX, tname, sizeof(BTF_LSM_PREFIX) - 1)) { + verbose(env, "attach_btf_id %u points to wrong type name %s\n", + btf_id, tname); + return -EINVAL; + } + + t = btf_type_by_id(btf_vmlinux, t->type); + /* should never happen in valid vmlinux build */ + if (!btf_type_is_ptr(t)) + return -EINVAL; + t = btf_type_by_id(btf_vmlinux, t->type); + /* should never happen in valid vmlinux build */ + if (!btf_type_is_func_proto(t)) + return -EINVAL; + + tname += sizeof(BTF_LSM_PREFIX) - 1; + prog->aux->attach_func_name = tname; + prog->aux->attach_func_proto = t; + return 0; +} + +static int check_attach_btf_id_tracing(struct bpf_verifier_env *env) { struct bpf_prog *prog = env->prog; struct bpf_prog *tgt_prog = prog->aux->linked_prog; @@ -9519,9 +9583,6 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) long addr; u64 key; - if (prog->type != BPF_PROG_TYPE_TRACING) - return 0; - if (!btf_id) { verbose(env, "Tracing programs must provide btf_id\n"); return -EINVAL; @@ -9659,6 +9720,20 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) } } +static int check_attach_btf_id(struct bpf_verifier_env *env) +{ + struct bpf_prog *prog = env->prog; + + switch (prog->type) { + case BPF_PROG_TYPE_TRACING: + return check_attach_btf_id_tracing(env); + case BPF_PROG_TYPE_LSM: + return check_attach_btf_id_lsm(env); + default: + return 0; + } +} + int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, union bpf_attr __user *uattr) {