From patchwork Mon Aug 29 11:46:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 9303689 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 9A9CE607F0 for ; Mon, 29 Aug 2016 11:47:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8BC9F285E2 for ; Mon, 29 Aug 2016 11:47:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7EA17287B6; Mon, 29 Aug 2016 11:47:01 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 D14B7285E2 for ; Mon, 29 Aug 2016 11:47:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932960AbcH2Lqq (ORCPT ); Mon, 29 Aug 2016 07:46:46 -0400 Received: from mail-it0-f42.google.com ([209.85.214.42]:38812 "EHLO mail-it0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932956AbcH2Lqn (ORCPT ); Mon, 29 Aug 2016 07:46:43 -0400 Received: by mail-it0-f42.google.com with SMTP id g62so91819501ith.1 for ; Mon, 29 Aug 2016 04:46:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=7RYpeShgmhmv7jnhZKewweXten+/T8ynZUJdULBPRfw=; b=te/h8JIYUnZM2SYPjYzMzR9ade/dKYGnvKG0ONf/fqRnCRPuF60Qzyf76jpFf/P+q3 Y889ezsDhRn7bV4tyWWUMUTbKvdjMGgxR8XB+GEBh/ZCsHy2XQ4xKXfLkqQc9br5OrMg mJHOHakgkfPgSndPyCea82OZMSfcPRg0MPJmI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=7RYpeShgmhmv7jnhZKewweXten+/T8ynZUJdULBPRfw=; b=TLnFJCnFy9wLLFU+xc3tb6MSOKLYYQeNPEtI4e9N43tO3N1M0fmKwSdz2q9vb+30PV jSsE2fvPln3xHAjKCGrt/lqmQ3Bu5ZlrKc+otvDYXkgS7ZJok8eP2TapuDeYFnv5/LDi cL3GsnpOmnFpgrMbul8Ax6ag6VWdq0h0p9vGrzxnbHbg4bghs2d/wlKgnL17ohLOnLfo Q3riHT2OJfCkvWb/T6vMMRrKHKuB68/UzgxfG+GooJuFJCb6FFlzHPsISLbR0gr2+rCv 4mLv333zIKyWYX0sbhepgN3dQbaa4JNKOJR/kMEdjyh6QNkT6sGebO8Eh3PiLqMbADpB rG+Q== X-Gm-Message-State: AE9vXwPphylNaTidgrvbwbuvai+LDyCbfQiQ8KSel+OXVtrsp20hzQ3ShjNkwAN+mXXhYg== X-Received: by 10.36.31.18 with SMTP id d18mr14805359itd.84.1472471202880; Mon, 29 Aug 2016 04:46:42 -0700 (PDT) Received: from ircssh.c.rugged-nimbus-611.internal (55.145.251.23.bc.googleusercontent.com. [23.251.145.55]) by smtp.gmail.com with ESMTPSA id o186sm4326562itg.15.2016.08.29.04.46.42 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 29 Aug 2016 04:46:42 -0700 (PDT) Date: Mon, 29 Aug 2016 04:46:41 -0700 From: Sargun Dhillon To: netdev@vger.kernel.org Cc: cgroups@vger.kernel.org, linux-security-module@vger.kernel.org, daniel@iogearbox.net, ast@fb.com Subject: [net-next RFC v2 5/9] bpf: Add bpf_probe_write_checmate helper Message-ID: <20160829114639.GA20871@ircssh.c.rugged-nimbus-611.internal> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This patch adds bpf_probe_write_checmate. This is a specific type of helper for the Checmate subsystem. It allows safe writes to kernel memory based on inspection of the Checmate ctx. In this patch, it only allows writes during the socket_bind, and socket_connect hooks to sockaddr. It can used to implement behaviour that's common in containerzation platforms that either perform DNAT/SNAT, or proxying to veil the true location of address to service mapping. Since this occurs only once, as opposed to per packet, it allows for much higher performance. Not only this, but the standard BSD API for introspecting sockets (getpeername) still works. Signed-off-by: Sargun Dhillon --- include/uapi/linux/bpf.h | 11 ++++++++ security/checmate/checmate_bpf.c | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 91bc92f..3971456 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -398,6 +398,17 @@ enum bpf_func_id { */ BPF_FUNC_skb_change_tail, + /** + * bpf_probe_write_checmate(ctx, void *dst, void *src, int len) + * safely attempt to write to memory pointed to by a Checmate context + * @ctx: struct checmate_ctx* + * @dst: destination address in userspace + * @src: source address on stack + * @len: number of bytes to copy + * Return: 0 on success or negative error + */ + BPF_FUNC_probe_write_checmate, + __BPF_FUNC_MAX_ID, }; diff --git a/security/checmate/checmate_bpf.c b/security/checmate/checmate_bpf.c index 001225c..24d6935 100644 --- a/security/checmate/checmate_bpf.c +++ b/security/checmate/checmate_bpf.c @@ -12,6 +12,59 @@ #include #include +static int probe_write_socket_bind(struct checmate_socket_bind_ctx *ctx, + void *unsafe_ptr, void *src, int size) +{ + if (unsafe_ptr < (void *)ctx->address || + (unsafe_ptr + size) > ((void *)ctx->address + ctx->addrlen)) + return -EPERM; + + memcpy(unsafe_ptr, src, size); + + return 0; +} + +static int probe_write_socket_connect(struct checmate_socket_connect_ctx *ctx, + void *unsafe_ptr, void *src, int size) +{ + if (unsafe_ptr < (void *)ctx->address || + (unsafe_ptr + size) > ((void *)ctx->address + ctx->addrlen)) + return -EPERM; + + memcpy(unsafe_ptr, src, size); + + return 0; +} + +static u64 bpf_probe_write_checmate(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) +{ + struct checmate_ctx *ctx = (struct checmate_ctx *) (long) (r1); + void *unsafe_ptr = (void *) (long) r2; + void *src = (void *) (long) r3; + int size = (int) r4; + + switch (ctx->hook) { + case CHECMATE_HOOK_SOCKET_BIND: + return probe_write_socket_bind(&ctx->socket_bind, unsafe_ptr, + src, size); + case CHECMATE_HOOK_SOCKET_CONNECT: + return probe_write_socket_connect(&ctx->socket_connect, + unsafe_ptr, src, size); + } + + return -EPERM; +} + +static const struct bpf_func_proto bpf_probe_write_user_proto = { + .func = bpf_probe_write_checmate, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_PTR_TO_STACK, + .arg4_type = ARG_CONST_STACK_SIZE, +}; + static const struct bpf_func_proto * checmate_prog_func_proto(enum bpf_func_id func_id) { @@ -34,6 +87,8 @@ checmate_prog_func_proto(enum bpf_func_id func_id) return &bpf_get_current_uid_gid_proto; case BPF_FUNC_get_current_comm: return &bpf_get_current_comm_proto; + case BPF_FUNC_probe_write_checmate: + return &bpf_probe_write_user_proto; case BPF_FUNC_trace_printk: return bpf_get_trace_printk_proto(); default: