Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp2825984pxv; Mon, 12 Jul 2021 02:53:58 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzE/yYYEizOtssP6xL3r7Hv9HngWO4FvJVom02BHIqk8vvauoGrIjvDrtzCbi3ioBY7NcvL X-Received: by 2002:a05:6638:3382:: with SMTP id h2mr17593553jav.131.1626083638628; Mon, 12 Jul 2021 02:53:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626083638; cv=none; d=google.com; s=arc-20160816; b=X4Up6IgGcInBP+23MBoEqmSlqbPeBd1h5Xcu/rJY9+f4DLvzVtLyGYnaUAWiq0rCw2 3/g/csvu/w2gapHhM/WsKaknACc0Wzjl9rcwGFXwXJ4SaQQAGdd0I+PCOYqYV0rwbVME KCWjK1FErM0ogH5PHZuODlYH8XyRnvn7VpONHANooDg2oAYgDkNuwnyR+U+5F0KBHMG5 qflGvXqS1mPfCVeCHgr0CNtUAARlZz4HnNOyJmEeoqQi9V17xKVsh99klYx0MOM99m2f S3d0ll5dX+cqffuE9lbSPGUng4S1msMJ6NhGvRaliFZ96gOr9iwfIm5aMGRC3Nm4KQgV XrDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=kf0scad1W6hrFkhoLjG4tYkTYE5X2a97ReDLGSzUDgc=; b=i0Fv49rHrhNOpwv3Xw0HvM8JNONh2iDsmdsbVlAhPC3UO7VwRqmnBdvKZ96RFy9bWx 7VYOt5IRji7p8LYKF4v9SlTCZ9+mJzYOb3EfuqlFYBn6/K9MNeqVphd1Q5+cRxrJcDI+ hzkmHUGkoBDc707zVOXVPyrVYTVZavzQuf9jfhm51JHfVAsjfZzFKIjShnpebt/JGC6j zHYdtdvhJhiG2XV1EKArDdoJb/PRICA9oTDsJnylmjCT4d3uVPlK4vS+cxru5bhoqbFy 2Q262104a7mJoqwX9Y5KYPxgobzFRj0SB+PUcrfGyjMfBsifSMkztCUj1pEHoZM416gf C/6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="G4/ykco5"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a5si16572994ioq.24.2021.07.12.02.53.47; Mon, 12 Jul 2021 02:53:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="G4/ykco5"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240240AbhGLGxn (ORCPT + 99 others); Mon, 12 Jul 2021 02:53:43 -0400 Received: from mail.kernel.org ([198.145.29.99]:34842 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237335AbhGLGjY (ORCPT ); Mon, 12 Jul 2021 02:39:24 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 87D9C60FE3; Mon, 12 Jul 2021 06:35:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1626071701; bh=Qdwvlvloc+EY50CgHCAEUBF3NINQSruHvX/lPYGFb/s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G4/ykco5lmqfHZeAsWKt0iGx3uJoaavcPm4L2krVirB17md2wYMYyZuBGmxdAzq4/ 7yzWSbvYQil/etLy4GCwUK4IoWrSBwOQM166CfBGhGhKAUdtnOhjtFNU6aDQ+dzCZv F18Qp+r0A+In99kgG0zmqfXjP2PK0lxubO0gSnho= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Christoph Hellwig , Aleksa Sarai , Al Viro , linux-fsdevel@vger.kernel.org, Richard Guy Briggs , Christian Brauner , Sasha Levin Subject: [PATCH 5.10 182/593] open: dont silently ignore unknown O-flags in openat2() Date: Mon, 12 Jul 2021 08:05:42 +0200 Message-Id: <20210712060903.043923805@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210712060843.180606720@linuxfoundation.org> References: <20210712060843.180606720@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Christian Brauner [ Upstream commit cfe80306a0dd6d363934913e47c3f30d71b721e5 ] The new openat2() syscall verifies that no unknown O-flag values are set and returns an error to userspace if they are while the older open syscalls like open() and openat() simply ignore unknown flag values: #define O_FLAG_CURRENTLY_INVALID (1 << 31) struct open_how how = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID, .resolve = 0, }; /* fails */ fd = openat2(-EBADF, "/dev/null", &how, sizeof(how)); /* succeeds */ fd = openat(-EBADF, "/dev/null", O_RDONLY | O_FLAG_CURRENTLY_INVALID); However, openat2() silently truncates the upper 32 bits meaning: #define O_FLAG_CURRENTLY_INVALID_LOWER32 (1 << 31) #define O_FLAG_CURRENTLY_INVALID_UPPER32 (1 << 40) struct open_how how_lowe32 = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID_LOWER32, }; struct open_how how_upper32 = { .flags = O_RDONLY | O_FLAG_CURRENTLY_INVALID_UPPER32, }; /* fails */ fd = openat2(-EBADF, "/dev/null", &how_lower32, sizeof(how_lower32)); /* succeeds */ fd = openat2(-EBADF, "/dev/null", &how_upper32, sizeof(how_upper32)); Fix this by preventing the immediate truncation in build_open_flags(). There's a snafu here though stripping FMODE_* directly from flags would cause the upper 32 bits to be truncated as well due to integer promotion rules since FMODE_* is unsigned int, O_* are signed ints (yuck). In addition, struct open_flags currently defines flags to be 32 bit which is reasonable. If we simply were to bump it to 64 bit we would need to change a lot of code preemptively which doesn't seem worth it. So simply add a compile-time check verifying that all currently known O_* flags are within the 32 bit range and fail to build if they aren't anymore. This change shouldn't regress old open syscalls since they silently truncate any unknown values anyway. It is a tiny semantic change for openat2() but it is very unlikely people pass ing > 32 bit unknown flags and the syscall is relatively new too. Link: https://lore.kernel.org/r/20210528092417.3942079-3-brauner@kernel.org Cc: Christoph Hellwig Cc: Aleksa Sarai Cc: Al Viro Cc: linux-fsdevel@vger.kernel.org Reported-by: Richard Guy Briggs Reviewed-by: Christoph Hellwig Reviewed-by: Aleksa Sarai Reviewed-by: Richard Guy Briggs Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/open.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/open.c b/fs/open.c index 4d7537ae59df..3aaaad47d9ca 100644 --- a/fs/open.c +++ b/fs/open.c @@ -993,12 +993,20 @@ inline struct open_how build_open_how(int flags, umode_t mode) inline int build_open_flags(const struct open_how *how, struct open_flags *op) { - int flags = how->flags; + u64 flags = how->flags; + u64 strip = FMODE_NONOTIFY | O_CLOEXEC; int lookup_flags = 0; int acc_mode = ACC_MODE(flags); - /* Must never be set by userspace */ - flags &= ~(FMODE_NONOTIFY | O_CLOEXEC); + BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS), + "struct open_flags doesn't yet handle flags > 32 bits"); + + /* + * Strip flags that either shouldn't be set by userspace like + * FMODE_NONOTIFY or that aren't relevant in determining struct + * open_flags like O_CLOEXEC. + */ + flags &= ~strip; /* * Older syscalls implicitly clear all of the invalid flags or argument -- 2.30.2