From patchwork Mon Aug 10 14:57:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin M Romer X-Patchwork-Id: 1342865 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BQJwb27Jzz9sTh; Tue, 11 Aug 2020 00:57:35 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1k59Ex-0007t8-Hm; Mon, 10 Aug 2020 14:57:31 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1k59Eu-0007rL-Iw for kernel-team@lists.ubuntu.com; Mon, 10 Aug 2020 14:57:28 +0000 Received: from mail-qv1-f69.google.com ([209.85.219.69]) by youngberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1k59Eu-0002CC-5Y for kernel-team@lists.ubuntu.com; Mon, 10 Aug 2020 14:57:28 +0000 Received: by mail-qv1-f69.google.com with SMTP id x4so7384739qvu.18 for ; Mon, 10 Aug 2020 07:57:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JXqno7DMgoaa58aXOfXuoOxQRZwr6fPDncHDpCJPHi4=; b=q4tYYDSLOIC2Nih2NP+cyMyjR0A6iB4JonNMl3VQApWa81sefjEUka5RmxwbQzqaoJ 2h+kFQgo3+b4Xf7VwN5v5ieHjx+xmCqewXr2DKtSkjHS7jQnd8ifuBueBz/YY+XHqECy XE+p+T8AZlEhgYZzzcH7LCXZ9OMosfBOGVaZ7UvOIs4kZAqPBaNWc8XROtEt+nvoByaX MCKECa6t2AhWrkJ8SCCewnehGnYAMtxWbv2kcK0vDNRHiUgiWIk61vyDVhrSfs4dDCai J3GFy1rcvP8Z9T+ytPc6Wmd2wBVookZh1SVh222aPqCjdnChxhfbfZzh/dpd2GW8gPw6 xmQw== X-Gm-Message-State: AOAM531+QWfKMoMRHufdaI4qf9iNhjnrNUkMqXMH+/f9KPp8rAIBKYnj W+344cz0K5Ycbt2lWrCBABSagd2segVhHFrQlYk29qFRtlIri56Ftvs2VPtHdryhx5kyMdK0IrU chnhfJz3oyfRS0t+73uqls3c31z4nsJ5AMjE19HpZCQ== X-Received: by 2002:a0c:b791:: with SMTP id l17mr29501224qve.44.1597071446861; Mon, 10 Aug 2020 07:57:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwwc77UOGTvN/khuOa37tQqtZm95si/GmbVCEBLDJcsr0n4wPdPlpLVef30KdsdQWPGOXLZAQ== X-Received: by 2002:a0c:b791:: with SMTP id l17mr29501196qve.44.1597071446597; Mon, 10 Aug 2020 07:57:26 -0700 (PDT) Received: from beast (c-68-80-13-9.hsd1.pa.comcast.net. [68.80.13.9]) by smtp.gmail.com with ESMTPSA id d124sm14817683qkg.65.2020.08.10.07.57.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Aug 2020 07:57:26 -0700 (PDT) Received: from ben by beast with local (Exim 4.93) (envelope-from ) id 1k59Eq-000DIR-SE for kernel-team@lists.ubuntu.com; Mon, 10 Aug 2020 10:57:24 -0400 From: Benjamin M Romer To: kernel-team@lists.ubuntu.com Subject: [xenial 4.4.0-188.218][PATCH 1/2] f2fs: fix to avoid accessing xattr across the boundary Date: Mon, 10 Aug 2020 10:57:23 -0400 Message-Id: <20200810145724.51067-2-benjamin.romer@canonical.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200810145724.51067-1-benjamin.romer@canonical.com> References: <20200810145724.51067-1-benjamin.romer@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Randall Huang When we traverse xattr entries via __find_xattr(), if the raw filesystem content is faked or any hardware failure occurs, out-of-bound error can be detected by KASAN. Fix the issue by introducing boundary check. [ 38.402878] c7 1827 BUG: KASAN: slab-out-of-bounds in f2fs_getxattr+0x518/0x68c [ 38.402891] c7 1827 Read of size 4 at addr ffffffc0b6fb35dc by task [ 38.402935] c7 1827 Call trace: [ 38.402952] c7 1827 [] dump_backtrace+0x0/0x6bc [ 38.402966] c7 1827 [] show_stack+0x20/0x2c [ 38.402981] c7 1827 [] dump_stack+0xfc/0x140 [ 38.402995] c7 1827 [] print_address_description+0x80/0x2d8 [ 38.403009] c7 1827 [] kasan_report_error+0x198/0x1fc [ 38.403022] c7 1827 [] kasan_report_error+0x0/0x1fc [ 38.403037] c7 1827 [] __asan_load4+0x1b0/0x1b8 [ 38.403051] c7 1827 [] f2fs_getxattr+0x518/0x68c [ 38.403066] c7 1827 [] f2fs_xattr_generic_get+0xb0/0xd0 [ 38.403080] c7 1827 [] __vfs_getxattr+0x1f4/0x1fc [ 38.403096] c7 1827 [] inode_doinit_with_dentry+0x360/0x938 [ 38.403109] c7 1827 [] selinux_d_instantiate+0x2c/0x38 [ 38.403123] c7 1827 [] security_d_instantiate+0x68/0x98 [ 38.403136] c7 1827 [] d_splice_alias+0x58/0x348 [ 38.403149] c7 1827 [] f2fs_lookup+0x608/0x774 [ 38.403163] c7 1827 [] lookup_slow+0x1e0/0x2cc [ 38.403177] c7 1827 [] walk_component+0x160/0x520 [ 38.403190] c7 1827 [] path_lookupat+0x110/0x2b4 [ 38.403203] c7 1827 [] filename_lookup+0x1d8/0x3a8 [ 38.403216] c7 1827 [] user_path_at_empty+0x54/0x68 [ 38.403229] c7 1827 [] SyS_getxattr+0xb4/0x18c [ 38.403241] c7 1827 [] el0_svc_naked+0x34/0x38 Signed-off-by: Randall Huang [Jaegeuk Kim: Fix wrong ending boundary] Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim CVE-2019-9453 [back-ported from commit 2777e654371dd4207a3a7f4fb5fa39550053a080] [ben_r: adjusted patch, add def for VALID_XATTR_BLOCK_SIZE ] Signed-off-by: Benjamin M Romer --- fs/f2fs/xattr.c | 28 ++++++++++++++++++++++------ fs/f2fs/xattr.h | 4 +++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 862368a32e53..80e98235720e 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -248,12 +248,17 @@ static inline const struct xattr_handler *f2fs_xattr_handler(int index) return handler; } -static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index, - size_t len, const char *name) +static struct f2fs_xattr_entry *__find_xattr(void *base_addr, + void *last_base_addr, int index, + size_t len, const char *name) { struct f2fs_xattr_entry *entry; list_for_each_xattr(entry, base_addr) { + if ((void *)(entry) + sizeof(__u32) > last_base_addr || + (void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) + return NULL; + if (entry->e_name_index != index) continue; if (entry->e_name_len != len) @@ -401,9 +406,10 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, void *buffer, size_t buffer_size, struct page *ipage) { struct f2fs_xattr_entry *entry; - void *base_addr; + void *base_addr, *last_base_addr; int error = 0; size_t size, len; + nid_t xnid = F2FS_I(inode)->i_xattr_nid; if (name == NULL) return -EINVAL; @@ -416,7 +422,9 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, if (!base_addr) return -ENOMEM; - entry = __find_xattr(base_addr, index, len, name); + last_base_addr = (void *)base_addr + XATTR_SIZE(xnid, inode); + + entry = __find_xattr(base_addr, last_base_addr, index, len, name); if (IS_XATTR_LAST_ENTRY(entry)) { error = -ENODATA; goto cleanup; @@ -483,7 +491,9 @@ static int __f2fs_setxattr(struct inode *inode, int index, { struct f2fs_inode_info *fi = F2FS_I(inode); struct f2fs_xattr_entry *here, *last; - void *base_addr; + void *base_addr, *last_base_addr; + nid_t xnid = F2FS_I(inode)->i_xattr_nid; + int found, newsize; size_t len; __u32 new_hsize; @@ -507,8 +517,14 @@ static int __f2fs_setxattr(struct inode *inode, int index, if (!base_addr) goto exit; + last_base_addr = (void *)base_addr + XATTR_SIZE(xnid, inode); + /* find entry with wanted name. */ - here = __find_xattr(base_addr, index, len, name); + here = __find_xattr(base_addr, last_base_addr, index, len, name); + if (!here) { + error = -EFAULT; + goto exit; + } found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1; diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 71a7100d5492..cb87825a403c 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -72,7 +72,9 @@ struct f2fs_xattr_entry { for (entry = XATTR_FIRST_ENTRY(addr);\ !IS_XATTR_LAST_ENTRY(entry);\ entry = XATTR_NEXT_ENTRY(entry)) - +#define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer)) +#define XATTR_SIZE(x,i) (((x) ? VALID_XATTR_BLOCK_SIZE : 0) + \ + (inline_xattr_size(i))) #define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + PAGE_SIZE - \ sizeof(struct node_footer) - sizeof(__u32))