From patchwork Thu Mar 1 10:19:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: kpark3469@gmail.com X-Patchwork-Id: 10250839 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 7E38760211 for ; Thu, 1 Mar 2018 10:32:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 66118285B6 for ; Thu, 1 Mar 2018 10:32:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5A89228630; Thu, 1 Mar 2018 10:32:45 +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=-4.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 734D7285B6 for ; Thu, 1 Mar 2018 10:32:44 +0000 (UTC) Received: (qmail 21649 invoked by uid 550); 1 Mar 2018 10:32:32 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Delivered-To: moderator for kernel-hardening@lists.openwall.com Received: (qmail 12281 invoked from network); 1 Mar 2018 10:22:39 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pItgJ35Rfh4Dqgo+FevuWotJuBGhQDBhL66MBQtKCm0=; b=WHKhG1alPgVL8BSHaGPlND2H+qn5nLMqPkNFMm/63Hd8u9o9sxIWxK8VbAqoCHtvQK qze6rwrzUTyiBG2TkhGcJ7CtHZL+3Y/MCgnB7KJgX0h3WV3dRI4Pk+xY3TlxltpvKjCy su2vnr1Qvj9NLw7bkjpv/fj3M0MNhxtfjK3vnhfEBicOx5093oN1+Uwh7n6ERWsCi7xj KxvHx6fLeaz35Cqs7SgNrwpuwdmHBklDQHG4z423yBsiMeXHxCH7Lsx55xJenDgxyu3X eAxC+BE11mbzbiIqKRmk3BXz2WRnA+kS/Sn7j9kmD6PFXxsNEKM99mcVCw6EkoLM4JHr N3bw== 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; bh=pItgJ35Rfh4Dqgo+FevuWotJuBGhQDBhL66MBQtKCm0=; b=kEPkVxeak+7mbGdW6Iey7rus+yDB19trc1h6a4qyq1lt2UbopSyEQ+ThuZhQfnJRq4 iJYc57itS4GKAsBdmzCoithpA48kxyTwDBKDjxWPa9MUQxCTTU7yPpoZ6scT89qC5Bzf iCJplC1ZVhzIRskWKT2vGlA8h91uiPBRvn2hSptCL/yAUIGZUIgzK1i7h8MQaaVCgsW7 rSHpJx2nF1R3bhmS8eaVlzhcfYlBdKC2dzQSzpBXqZjRvENY3FoAl/k4mN7VvqgVSPb7 Ylqkzvrepxgkhg7grhklOGpa4ogPyTexmy42w0o3XR0ktsT6Kri9+QLZbDyTH0el0bxs vX3w== X-Gm-Message-State: APf1xPBl8014KbClsh4jHdCgLQjLgfuJcCEU6FNODufbM8FHoZGRo0t+ eMM3lxahwVANhLJUN8/AgCt6LA== X-Google-Smtp-Source: AG47ELuQ7g5DD1JYHEAM3+X/Z6k3BZuc5a25T/lgO9TCs+EqG5jZqFYi4T/uRc7oE5+f/2hB+qz6pw== X-Received: by 10.80.247.195 with SMTP id i3mr2171660edn.121.1519899747180; Thu, 01 Mar 2018 02:22:27 -0800 (PST) From: kpark3469@gmail.com To: kernel-hardening@lists.openwall.com Cc: keescook@chromium.org, james.morse@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, mark.rutland@arm.com, keun-o.park@darkmatter.ae Subject: [PATCH 2/4] arm64: usercopy: implement arch_within_stack_frames Date: Thu, 1 Mar 2018 14:19:49 +0400 Message-Id: <1519899591-29761-3-git-send-email-kpark3469@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1519899591-29761-2-git-send-email-kpark3469@gmail.com> References: <1519899591-29761-1-git-send-email-kpark3469@gmail.com> <1519899591-29761-2-git-send-email-kpark3469@gmail.com> X-Virus-Scanned: ClamAV using ClamSMTP From: James Morse This implements arch_within_stack_frames() for arm64 that should validate if a given object is contained by a kernel stack frame. Signed-off-by: James Morse Reviewed-by: Sahara Reviewed-by: Kees Cook --- arch/arm64/Kconfig | 1 + arch/arm64/kernel/stacktrace.c | 76 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 5361287..b6c3b52 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -127,6 +127,7 @@ config ARM64 select HAVE_SYSCALL_TRACEPOINTS select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_ARCH_WITHIN_STACK_FRAMES select IOMMU_DMA if IOMMU_SUPPORT select IRQ_DOMAIN select IRQ_FORCED_THREADING diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index fbc366d..6d37fad 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -26,6 +26,11 @@ #include #include +#define FAKE_FRAME(frame, my_func) do { \ + frame.fp = (unsigned long)__builtin_frame_address(0); \ + frame.pc = (unsigned long)my_func; \ +} while (0) + /* * AArch64 PCS assigns the frame pointer to x29. * @@ -94,6 +99,77 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, } } +struct check_frame_arg { + unsigned long obj_start; + unsigned long obj_end; + unsigned long frame_start; + int discard_frames; + int err; +}; + +static int check_frame(struct stackframe *frame, void *d) +{ + struct check_frame_arg *arg = d; + unsigned long frame_end = frame->fp; + + /* object overlaps multiple frames */ + if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) { + arg->err = BAD_STACK; + return 1; + } + + /* + * Discard frames and check object is in a frame written early + * enough. + */ + if (arg->discard_frames) + arg->discard_frames--; + else if ((arg->frame_start <= arg->obj_start && + arg->obj_start < frame_end) && + (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end)) + return 1; + + /* object exists in a previous frame */ + if (arg->obj_end < arg->frame_start) { + arg->err = BAD_STACK; + return 1; + } + + arg->frame_start = frame_end + 0x10; + + return 0; +} + +/* Check obj doesn't overlap a stack frame record */ +int arch_within_stack_frames(const void *stack, + const void *stack_end, + const void *obj, unsigned long obj_len) +{ + struct stackframe frame; + struct check_frame_arg arg; + + if (!IS_ENABLED(CONFIG_FRAME_POINTER)) + return NOT_STACK; + + arg.err = GOOD_FRAME; + arg.obj_start = (unsigned long)obj; + arg.obj_end = arg.obj_start + obj_len; + + FAKE_FRAME(frame, arch_within_stack_frames); + arg.frame_start = frame.fp; + + /* + * Skip 4 non-inlined frames: , + * arch_within_stack_frames(), check_stack_object() and + * __check_object_size(). + */ + arg.discard_frames = 4; + + walk_stackframe(current, &frame, check_frame, &arg); + + return arg.err; +} + #ifdef CONFIG_STACKTRACE struct stack_trace_data { struct stack_trace *trace;