From patchwork Wed Sep 14 07:24:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Micka=C3=ABl_Sala=C3=BCn?= X-Patchwork-Id: 9330581 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 045F860231 for ; Wed, 14 Sep 2016 07:28:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB08A29A12 for ; Wed, 14 Sep 2016 07:28:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DE8FD29A5D; Wed, 14 Sep 2016 07:28: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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 523B629A12 for ; Wed, 14 Sep 2016 07:28:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758116AbcINH2Z (ORCPT ); Wed, 14 Sep 2016 03:28:25 -0400 Received: from smtp-sh.infomaniak.ch ([128.65.195.4]:59211 "EHLO smtp-sh.infomaniak.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760588AbcINH0I (ORCPT ); Wed, 14 Sep 2016 03:26:08 -0400 Received: from smtp6.infomaniak.ch (smtp6.infomaniak.ch [83.166.132.19]) by smtp-sh.infomaniak.ch (8.14.5/8.14.5) with ESMTP id u8E7PB4x011472 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 14 Sep 2016 09:25:11 +0200 Received: from localhost (ns3096276.ip-94-23-54.eu [94.23.54.103]) (authenticated bits=0) by smtp6.infomaniak.ch (8.14.5/8.14.5) with ESMTP id u8E7PBcP008495; Wed, 14 Sep 2016 09:25:11 +0200 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= To: linux-kernel@vger.kernel.org Cc: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Alexei Starovoitov , Andy Lutomirski , Arnd Bergmann , Casey Schaufler , Daniel Borkmann , Daniel Mack , David Drysdale , "David S . Miller" , Elena Reshetova , "Eric W . Biederman" , James Morris , Kees Cook , Paul Moore , Sargun Dhillon , "Serge E . Hallyn" , Tejun Heo , Will Drewry , kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org, linux-security-module@vger.kernel.org, netdev@vger.kernel.org, cgroups@vger.kernel.org Subject: [RFC v3 21/22] bpf, landlock: Add optional skb pointer in the Landlock context Date: Wed, 14 Sep 2016 09:24:14 +0200 Message-Id: <20160914072415.26021-22-mic@digikod.net> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160914072415.26021-1-mic@digikod.net> References: <20160914072415.26021-1-mic@digikod.net> MIME-Version: 1.0 X-Antivirus: Dr.Web (R) for Unix mail servers drweb plugin ver.6.0.2.8 X-Antivirus-Code: 0x100000 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This is a proof of concept to expose optional values that could depend of the process access rights. There is two dedicated flags: LANDLOCK_FLAG_ACCESS_SKB_READ and LANDLOCK_FLAG_ACCESS_SKB_WRITE. Each of them can be activated to access eBPF functions manipulating a skb in a read or write way. Signed-off-by: Mickaël Salaün Cc: Alexei Starovoitov Cc: Andy Lutomirski Cc: Daniel Borkmann Cc: David S. Miller Cc: Kees Cook Cc: Sargun Dhillon --- include/linux/bpf.h | 2 ++ include/uapi/linux/bpf.h | 7 ++++++- kernel/bpf/verifier.c | 6 ++++++ security/landlock/lsm.c | 26 ++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index f7325c17f720..218973777612 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -88,6 +88,7 @@ enum bpf_arg_type { ARG_PTR_TO_STRUCT_FILE, /* pointer to struct file */ ARG_CONST_PTR_TO_LANDLOCK_HANDLE_FS, /* pointer to Landlock FS handle */ + ARG_PTR_TO_STRUCT_SKB, /* pointer to struct skb */ }; /* type of values returned from helper functions */ @@ -150,6 +151,7 @@ enum bpf_reg_type { /* Landlock */ PTR_TO_STRUCT_FILE, CONST_PTR_TO_LANDLOCK_HANDLE_FS, + PTR_TO_STRUCT_SKB, }; struct bpf_prog; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 8cfc2de2ab76..7d9e56952ed9 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -586,7 +586,9 @@ enum landlock_hook_id { /* context of function access flags */ #define LANDLOCK_FLAG_ACCESS_UPDATE (1 << 0) #define LANDLOCK_FLAG_ACCESS_DEBUG (1 << 1) -#define _LANDLOCK_FLAG_ACCESS_MASK ((1ULL << 2) - 1) +#define LANDLOCK_FLAG_ACCESS_SKB_READ (1 << 2) +#define LANDLOCK_FLAG_ACCESS_SKB_WRITE (1 << 3) +#define _LANDLOCK_FLAG_ACCESS_MASK ((1ULL << 4) - 1) /* Handle check flags */ #define LANDLOCK_FLAG_FS_DENTRY (1 << 0) @@ -619,12 +621,15 @@ struct landlock_handle { * @args: LSM hook arguments, see include/linux/lsm_hooks.h for there * description and the LANDLOCK_HOOK* definitions from * security/landlock/lsm.c for their types. + * @opt_skb: optional skb pointer, accessible with the + * LANDLOCK_FLAG_ACCESS_SKB_* flags for network-related hooks. */ struct landlock_data { __u32 hook; /* enum landlock_hook_id */ __u16 origin; /* LANDLOCK_FLAG_ORIGIN_* */ __u16 cookie; /* seccomp RET_LANDLOCK */ __u64 args[6]; + __u64 opt_skb; }; #endif /* _UAPI__LINUX_BPF_H__ */ diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8d7b18574f5a..a95154c1a60f 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -247,6 +247,7 @@ static const char * const reg_type_str[] = { [PTR_TO_PACKET_END] = "pkt_end", [PTR_TO_STRUCT_FILE] = "struct_file", [CONST_PTR_TO_LANDLOCK_HANDLE_FS] = "landlock_handle_fs", + [PTR_TO_STRUCT_SKB] = "struct_skb", }; static void print_verifier_state(struct verifier_state *state) @@ -559,6 +560,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type) case CONST_PTR_TO_MAP: case PTR_TO_STRUCT_FILE: case CONST_PTR_TO_LANDLOCK_HANDLE_FS: + case PTR_TO_STRUCT_SKB: return true; default: return false; @@ -984,6 +986,10 @@ static int check_func_arg(struct verifier_env *env, u32 regno, expected_type = CONST_PTR_TO_LANDLOCK_HANDLE_FS; if (type != expected_type) goto err_type; + } else if (arg_type == ARG_PTR_TO_STRUCT_SKB) { + expected_type = PTR_TO_STRUCT_SKB; + if (type != expected_type) + goto err_type; } else if (arg_type == ARG_PTR_TO_STACK || arg_type == ARG_PTR_TO_RAW_STACK) { expected_type = PTR_TO_STACK; diff --git a/security/landlock/lsm.c b/security/landlock/lsm.c index 56c45abe979c..8b0e6f0eb6b7 100644 --- a/security/landlock/lsm.c +++ b/security/landlock/lsm.c @@ -281,6 +281,7 @@ static bool __is_valid_access(int off, int size, enum bpf_access_type type, break; case offsetof(struct landlock_data, args[0]) ... offsetof(struct landlock_data, args[5]): + case offsetof(struct landlock_data, opt_skb): expected_size = sizeof(__u64); break; default: @@ -299,6 +300,13 @@ static bool __is_valid_access(int off, int size, enum bpf_access_type type, if (*reg_type == NOT_INIT) return false; break; + case offsetof(struct landlock_data, opt_skb): + if (!(prog_subtype->landlock_hook.access & + (LANDLOCK_FLAG_ACCESS_SKB_READ | + LANDLOCK_FLAG_ACCESS_SKB_WRITE))) + return false; + *reg_type = PTR_TO_STRUCT_SKB; + break; } return true; @@ -401,6 +409,24 @@ static inline bool bpf_landlock_is_valid_subtype( if (prog_subtype->landlock_hook.access & LANDLOCK_FLAG_ACCESS_DEBUG && !capable(CAP_SYS_ADMIN)) return false; + /* + * Capability checks must be enforced for every landlocked process. + * To support user namespaces/capabilities, we must then check the + * namespaces of a task before putting it in a landlocked cgroup. + * This could be implemented in the future. + */ + if (prog_subtype->landlock_hook.access & LANDLOCK_FLAG_ACCESS_SKB_READ && + !capable(CAP_NET_ADMIN)) + return false; + /* + * It is interesting to differentiate read and write access to be able + * to securely delegate some work to unprivileged (and potentially + * compromised/untrusted) processes. This different type of access can + * be checked for function calls or context accesses. + */ + if (prog_subtype->landlock_hook.access & LANDLOCK_FLAG_ACCESS_SKB_WRITE && + !capable(CAP_NET_ADMIN)) + return false; return true; }