From patchwork Wed Oct 9 20:40:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksa Sarai X-Patchwork-Id: 834359 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8E8E1E2303; Wed, 9 Oct 2024 20:41:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506478; cv=none; b=ARwmx1lzrlvMiOX9Xs65cK18p3mElTpQK/fTUxLODhAkXPG4vVTrR0UnADr06aeo6sXFeqxMfrDS4mLUz/FySZObVY6UBQTDXfptm09hcVk4BcRJJn3dDhG/yqrW82JFkjrvk6ecqJ+VD2Pc/zi/nM2es7MH2IPEaqK0M9yLRIY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506478; c=relaxed/simple; bh=fw6NmghdWQJRbb6RKSne5chbZWIJNjzAVYycSf77biE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kivOxU8eQFwbFfDwzFxbxWTJ8g5KFCMHesNRiJGS2FbpeLxCXEvS27REcuI/R/PaNaaG5rEkKG5tC/SpX7/3t702lIMoHqYa5RHKAeC6OWuwYorwrtsDU414qNx5qaroHyrSP2IqOZcad5mpvYoJsECOuFBtAa/F+P4X7AS2f20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com; spf=pass smtp.mailfrom=cyphar.com; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b=d0cusp5a; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cyphar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b="d0cusp5a" Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4XP4Y468Xwz9t71; Wed, 9 Oct 2024 22:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyphar.com; s=MBO0001; t=1728506472; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1P8cNzAS3QpRLvITBT/YZAmoxZc69iafbOErsnmv8M8=; b=d0cusp5aOQS+zxTKsiY9G0oBNEDsP4r+JvUychTD/xubem40zbjVR/80wQyZu2nScva925 rRpzaGPGTPUOsEPvfnFmF+wan2C/PY71r1HeG8atgeB6efo4q1wWezk5i2x/nvcdkDcmtg MkOPsTjPuHbC/J6lGKg7LCzgd6tfQDeKJ6mtgSIvF3FKwmF3mM2OrTasu6GsJ4fFKKcB0d v3HzOFT/TWeJb4Ng73ySvVvR+6BlBEGPlbHqfALx0zN8NTf7tdMlMal8B2pylTV339QqFw t/RTblGjTmY67L2XEYTCqHp5Q9Q3QMAEsUwQ5XgxitYse3EikyUn1OvDO96tLw== From: Aleksa Sarai Date: Thu, 10 Oct 2024 07:40:34 +1100 Subject: [PATCH RFC v3 01/10] uaccess: add copy_struct_to_user helper Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241010-extensible-structs-check_fields-v3-1-d2833dfe6edd@cyphar.com> References: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> In-Reply-To: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Alexander Viro , Christian Brauner , Jan Kara , Arnd Bergmann , Shuah Khan Cc: Kees Cook , Florian Weimer , Arnd Bergmann , Mark Rutland , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, Aleksa Sarai X-Developer-Signature: v=1; a=openpgp-sha256; l=7216; i=cyphar@cyphar.com; h=from:subject:message-id; bh=fw6NmghdWQJRbb6RKSne5chbZWIJNjzAVYycSf77biE=; b=owGbwMvMwCWmMf3Xpe0vXfIZT6slMaSzvQrcbnDvTVP9j1cv7glL3+eWvKi+6HTI5nyJuZqGG /XKJZ2lO0pZGMS4GGTFFFm2+XmGbpq/+Eryp5VsMHNYmUCGMHBxCsBEbm5j+F98NpFV6tguZcum sy+2rd9wt7thu6T186OfrU00b+svYtFmZJjFJHFNlO3MG9H1S5fovVuXvklLtEk0zffhSr6/kww f32ICAA== X-Developer-Key: i=cyphar@cyphar.com; a=openpgp; fpr=C9C370B246B09F6DBCFC744C34401015D1D2D386 This is based on copy_struct_from_user(), but there is one additional case to consider when creating a syscall that returns an extensible-struct to userspace -- how should data in the struct that cannot fit into the userspace struct be handled (ksize > usize)? There are three possibilies: 1. The interface is like sched_getattr(2), where new information will be silently not provided to userspace. This is probably what most interfaces will want to do, as it provides the most possible backwards-compatibility. 2. The interface is like lsm_list_modules(2), where you want to return an error like -EMSGSIZE if not providing information could result in the userspace program making a serious mistake (such as one that could lead to a security problem) or if you want to provide some flag to userspace so they know that they are missing some information. 3. The interface is like statx(2), where there some kind of a request mask that indicates what data userspace would like. One could imagine that statx2(2) (using extensible structs) would want to return -EMSGSIZE if the user explicitly requested a field that their structure is too small to fit, but not return an error if the field was not explicitly requested. This is kind of a mix between (1) and (2) based on the requested mask. The copy_struct_to_user() helper includes a an extra argument that is used to return a boolean flag indicating whether there was a non-zero byte in the trailing bytes that were not copied to userspace. This can be used in the following ways to handle all three cases, respectively: 1. Just pass NULL, as you don't care about this case. 2. Return an error (say -EMSGSIZE) if the argument was set to true by copy_struct_to_user(). 3. If the argument was set to true by copy_struct_to_user(), check if there is a flag that implies a field larger than usize. This is the only case where callers of copy_struct_to_user() should check usize themselves. This will probably require scanning an array that specifies what flags were added for each version of the flags struct and returning an error if the request mask matches any of the flags that were added in versions of the struct that are larger than usize. At the moment we don't have any users of (3), so this patch doesn't include any helpers to make the necessary scanning easier, but it should be fairly easy to add some if necessary. Signed-off-by: Aleksa Sarai --- include/linux/uaccess.h | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index d8e4105a2f21..cf0994605c10 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -387,6 +387,103 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src, return 0; } +/** + * copy_struct_to_user: copy a struct to userspace + * @dst: Destination address, in userspace. This buffer must be @ksize + * bytes long. + * @usize: (Alleged) size of @dst struct. + * @src: Source address, in kernel space. + * @ksize: Size of @src struct. + * @ignored_trailing: Set to %true if there was a non-zero byte in @src that + * userspace cannot see because they are using an smaller struct. + * + * Copies a struct from kernel space to userspace, in a way that guarantees + * backwards-compatibility for struct syscall arguments (as long as future + * struct extensions are made such that all new fields are *appended* to the + * old struct, and zeroed-out new fields have the same meaning as the old + * struct). + * + * Some syscalls may wish to make sure that userspace knows about everything in + * the struct, and if there is a non-zero value that userspce doesn't know + * about, they want to return an error (such as -EMSGSIZE) or have some other + * fallback (such as adding a "you're missing some information" flag). If + * @ignored_trailing is non-%NULL, it will be set to %true if there was a + * non-zero byte that could not be copied to userspace (ie. was past @usize). + * + * While unconditionally returning an error in this case is the simplest + * solution, for maximum backward compatibility you should try to only return + * -EMSGSIZE if the user explicitly requested the data that couldn't be copied. + * Note that structure sizes can change due to header changes and simple + * recompilations without code changes(!), so if you care about + * @ignored_trailing you probably want to make sure that any new field data is + * associated with a flag. Otherwise you might assume that a program knows + * about data it does not. + * + * @ksize is just sizeof(*src), and @usize should've been passed by userspace. + * The recommended usage is something like the following: + * + * SYSCALL_DEFINE2(foobar, struct foo __user *, uarg, size_t, usize) + * { + * int err; + * bool ignored_trailing; + * struct foo karg = {}; + * + * if (usize > PAGE_SIZE) + * return -E2BIG; + * if (usize < FOO_SIZE_VER0) + * return -EINVAL; + * + * // ... modify karg somehow ... + * + * err = copy_struct_to_user(uarg, usize, &karg, sizeof(karg), + * &ignored_trailing); + * if (err) + * return err; + * if (ignored_trailing) + * return -EMSGSIZE: + * + * // ... + * } + * + * There are three cases to consider: + * * If @usize == @ksize, then it's copied verbatim. + * * If @usize < @ksize, then the kernel is trying to pass userspace a newer + * struct than it supports. Thus we only copy the interoperable portions + * (@usize) and ignore the rest (but @ignored_trailing is set to %true if + * any of the trailing (@ksize - @usize) bytes are non-zero). + * * If @usize > @ksize, then the kernel is trying to pass userspace an older + * struct than userspace supports. In order to make sure the + * unknown-to-the-kernel fields don't contain garbage values, we zero the + * trailing (@usize - @ksize) bytes. + * + * Returns (in all cases, some data may have been copied): + * * -EFAULT: access to userspace failed. + */ +static __always_inline __must_check int +copy_struct_to_user(void __user *dst, size_t usize, const void *src, + size_t ksize, bool *ignored_trailing) +{ + size_t size = min(ksize, usize); + size_t rest = max(ksize, usize) - size; + + /* Double check if ksize is larger than a known object size. */ + if (WARN_ON_ONCE(ksize > __builtin_object_size(src, 1))) + return -E2BIG; + + /* Deal with trailing bytes. */ + if (usize > ksize) { + if (clear_user(dst + size, rest)) + return -EFAULT; + } + if (ignored_trailing) + *ignored_trailing = ksize < usize && + memchr_inv(src + size, 0, rest) != NULL; + /* Copy the interoperable parts of the struct. */ + if (copy_to_user(dst, src, size)) + return -EFAULT; + return 0; +} + bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size); long copy_from_kernel_nofault(void *dst, const void *src, size_t size); From patchwork Wed Oct 9 20:40:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksa Sarai X-Patchwork-Id: 834358 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0F4BC1E1A04; Wed, 9 Oct 2024 20:41:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506497; cv=none; b=Ea1ub5Guo7jvHR99pArhDMS2FeyknWVd73JMdNG/vsEUeN9P0H7PTLdhJWpd+X+vmdpJbWSx/G6Kstw+/jXZn8tNZoQmgdy9prTm4P0NQO71cQyPEMO7/x7NuGK+6MrfFjlyQonYXHemUQelepp4GLEKETpsp2DiwNQCrMXAKM4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506497; c=relaxed/simple; bh=HHdoaMHdkVQWx0FkhugGfSdSqGDM4p2QXOJQBPWZ+bQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ttOT4AfQzXgVZEwfQICSvctCDtwwQ87ypN8xj/B4pvggi0NAkdg9ANgFpNOQP95RI173pqquIcmVJlnCwRvO7l6Wijn68cbUgDEs3y8qpfJaqEnrHDyhtHrYmmunKFNfNelUXGCZ6FJGQ+18ZaYIwX5mIaA/lmDHrVj51cPJp4I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com; spf=pass smtp.mailfrom=cyphar.com; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b=slXIN3T8; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cyphar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b="slXIN3T8" Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4XP4YR4vTPz9tnm; Wed, 9 Oct 2024 22:41:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyphar.com; s=MBO0001; t=1728506491; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KHaYV9nP73oZ6uB0oR4WRKvQDPGRHwYwcifbf4Jh92g=; b=slXIN3T8XIYncnTRetCVjUj8DfJg+NOBD0EOn9mTZhv/LyNq4wmwsFqcKmGyK95SsmfWCA HLIWf16K7r+OqxGan2slZ7copCdWJjfpNw0CnO9aMYYNEDv1GYLvKOBT6kFfQrrjfkLkeM wdHJ5DzF84d40Aa56Sklwu3Oe80IzT6A/865354ssZfpiz5WNximqOlRJhhYplRvmNN143 mqv03TdvJvdUXfEzi5E02XGbuYaChPaVL7DIxtyWFSgk/AMT218/aV/udDqRsqLvj64087 8nEzxLwlDcCeodXPKksXi+IKwKZRHBn3tLB2Bh1Mzr499xU0UaJBAVCivXadbA== From: Aleksa Sarai Date: Thu, 10 Oct 2024 07:40:36 +1100 Subject: [PATCH RFC v3 03/10] openat2: explicitly return -E2BIG for (usize > PAGE_SIZE) Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241010-extensible-structs-check_fields-v3-3-d2833dfe6edd@cyphar.com> References: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> In-Reply-To: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Alexander Viro , Christian Brauner , Jan Kara , Arnd Bergmann , Shuah Khan Cc: Kees Cook , Florian Weimer , Arnd Bergmann , Mark Rutland , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, Aleksa Sarai , stable@vger.kernel.org X-Developer-Signature: v=1; a=openpgp-sha256; l=891; i=cyphar@cyphar.com; h=from:subject:message-id; bh=HHdoaMHdkVQWx0FkhugGfSdSqGDM4p2QXOJQBPWZ+bQ=; b=owGbwMvMwCWmMf3Xpe0vXfIZT6slMaSzvQr87Z/06/j0Nffc1sXu3nRypSM/175w9yWKFUfju GXky9LedJSyMIhxMciKKbJs8/MM3TR/8ZXkTyvZYOawMoEMYeDiFICJnHjByNDBIftiE9u7Ystv CfnfqwRDpJYFOp6Kme66aFLW9wMWgvWMDHv3Tp2aesyN7dzMZ3W88nvWWpzYw77gsv/ubyyPZXm 2PecHAA== X-Developer-Key: i=cyphar@cyphar.com; a=openpgp; fpr=C9C370B246B09F6DBCFC744C34401015D1D2D386 X-Rspamd-Queue-Id: 4XP4YR4vTPz9tnm While we do currently return -EFAULT in this case, it seems prudent to follow the behaviour of other syscalls like clone3. It seems quite unlikely that anyone depends on this error code being EFAULT, but we can always revert this if it turns out to be an issue. Cc: # v5.6+ Fixes: fddb5d430ad9 ("open: introduce openat2(2) syscall") Signed-off-by: Aleksa Sarai --- fs/open.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/open.c b/fs/open.c index 22adbef7ecc2..30bfcddd505d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1458,6 +1458,8 @@ SYSCALL_DEFINE4(openat2, int, dfd, const char __user *, filename, if (unlikely(usize < OPEN_HOW_SIZE_VER0)) return -EINVAL; + if (unlikely(usize > PAGE_SIZE)) + return -E2BIG; err = copy_struct_from_user(&tmp, sizeof(tmp), how, usize); if (err) From patchwork Wed Oct 9 20:40:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksa Sarai X-Patchwork-Id: 834357 Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [80.241.56.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 677721E230F; Wed, 9 Oct 2024 20:41:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506515; cv=none; b=A+EtDe1T5Ad+nMTMs/ENRwhuoxLPEWh5lMpdLxs4WOfqej8qLJNDsr508D2F9qltSz2lQNCbiSZIyikh3mAJexUx0uGieMCdD73Od6Cus9DkVYQykJR5RvfKsRfvnOfruMcwEXG0W8uwUHlOvpOqnJl4B9u5bW1hyavp8nmJyIw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506515; c=relaxed/simple; bh=M9iWszswoUm+ACdoBR6OSZmDmOZ0gV76Hvojwn9eqxg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QLmhlSQRTK9cDHAWlf4VaORU1xTDXEVxAXJjnQ+QIzQcnOGEEuT9YmwGp5PvlfEInbRVK/zb+qidx/WBOXPIK2HxSXNAMZAp4qKp1YntG6oNJt3st3ZANoH3UHvb25btrjd2zgDyFPy+MdsKXJUV/YW0ukJU0KtqWDTW2IFCnPk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com; spf=pass smtp.mailfrom=cyphar.com; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b=dK5pokPQ; arc=none smtp.client-ip=80.241.56.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cyphar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b="dK5pokPQ" Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4XP4Yn5rqSz9stM; Wed, 9 Oct 2024 22:41:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyphar.com; s=MBO0001; t=1728506509; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ICm4bzvlgrwdJ59X+goTMMQMK+SqT/1B0scZvKOBQTs=; b=dK5pokPQPwhS6hvQWb4G/R+lf0fAFk8NSut94azvuDIVK6tn1w/g7zwucLdIO1XSkbU+2q HrPW6B6fgMKPPJ2KNgbBIRou7R2RdaXSFqxgB/8Zcy7pO1hokarxIo/c1W4x+U1Fw/IRX/ VN2BLam3lFDCKX/ULiriBfubnuXNHPtsaKazWAg3/Z+UrZI//jfR73fuiuuVYxyiVEXOXb wBfjvmt3cb6Haf9/vxwu2jjbBiwg7XEsLuPE3PHlUs8Ohr6HsJeNV+uakMHDdM6grawp+u skDl+KqlBCZKVExZCQ7zT6uMgzZCAB6ugP8boNif9iiF/wU3cw2rZBdGoOAUHg== From: Aleksa Sarai Date: Thu, 10 Oct 2024 07:40:38 +1100 Subject: [PATCH RFC v3 05/10] selftests: openat2: add 0xFF poisoned data after misaligned struct Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241010-extensible-structs-check_fields-v3-5-d2833dfe6edd@cyphar.com> References: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> In-Reply-To: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Alexander Viro , Christian Brauner , Jan Kara , Arnd Bergmann , Shuah Khan Cc: Kees Cook , Florian Weimer , Arnd Bergmann , Mark Rutland , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, Aleksa Sarai X-Developer-Signature: v=1; a=openpgp-sha256; l=1132; i=cyphar@cyphar.com; h=from:subject:message-id; bh=M9iWszswoUm+ACdoBR6OSZmDmOZ0gV76Hvojwn9eqxg=; b=owGbwMvMwCWmMf3Xpe0vXfIZT6slMaSzvQoMsvl4dsUWLUPVxvLwfKcdlqtcfZK+/MlYn/Gk8 HTzybffOkpZGMS4GGTFFFm2+XmGbpq/+Eryp5VsMHNYmUCGMHBxCsBE5GwYGS5HVKhYHmNycL9i yNAf/9q6yXp79C6XGw3rtvwL0sg7so6R4cK8zrjrolp9+r8Wtat3JaY4nPHqWrj1f3B08pWb/27 7MAMA X-Developer-Key: i=cyphar@cyphar.com; a=openpgp; fpr=C9C370B246B09F6DBCFC744C34401015D1D2D386 We should also verify that poisoned data after a misaligned struct is also handled correctly by is_zeroed_user(). This test passes with no kernel changes needed, so is_zeroed_user() was correct already. Fixes: b28a10aedcd4 ("selftests: add openat2(2) selftests") Signed-off-by: Aleksa Sarai --- tools/testing/selftests/openat2/openat2_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c index 5790ab446527..4ca175a16ad6 100644 --- a/tools/testing/selftests/openat2/openat2_test.c +++ b/tools/testing/selftests/openat2/openat2_test.c @@ -112,9 +112,9 @@ void test_openat2_struct(void) * * This is effectively to check that is_zeroed_user() works. */ - copy = malloc(misalign + sizeof(how_ext)); + copy = malloc(misalign*2 + sizeof(how_ext)); how_copy = copy + misalign; - memset(copy, 0xff, misalign); + memset(copy, 0xff, misalign*2 + sizeof(how_ext)); memcpy(how_copy, &how_ext, sizeof(how_ext)); } From patchwork Wed Oct 9 20:40:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksa Sarai X-Patchwork-Id: 834356 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C47CE1E1C3A; Wed, 9 Oct 2024 20:42:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506534; cv=none; b=lox6pB9piFcE3PnsV4Z7hy2WNlNM0VlQtoqdTyLmjLyEB6h+aWb1HE12Cj3wMepY16v4Cjji6ut9HEBKMAm+1hhWrePS702BdPNAwmrUArx/OnwgrqIOYNH6vErydd9H9WdiHcm+O9+Kre268uGWochW9R57bQyvkRBEJD6bQ/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506534; c=relaxed/simple; bh=o94o6Toa1Pf4WLXPtt6pgYs8bPe/h3R8eYg1DJcRyfA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cVbwDj/t/AKokRAWofaKHQmCxj+KciNzm3Xl8KqZQ7jqG0lyJlFRnLCkwkoN4aynoeDeu1e5p3+7296mxlA++lUKmhw/aRihXg+I5qQsYfiMUs74t+IbnJnS+qiRfJlCvuDFqIDP2gJIq/X3fX+YPtBNxvzP0Ml08C28Q7lf2Pk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com; spf=pass smtp.mailfrom=cyphar.com; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b=YHdhUXRB; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cyphar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b="YHdhUXRB" Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4XP4Z83lbZz9tWL; Wed, 9 Oct 2024 22:42:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyphar.com; s=MBO0001; t=1728506528; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JvFZhzQibMAuUvYkTNP2DH0255R8R25uInAVXxNHfKg=; b=YHdhUXRBKlxTgq4+K/HlwfGxQBDTI71pIUfYv584e8mB89gfH9rI/6vEcB6c53DJO7+iIP KkFAT4YwWVBW7EDf9WhVmCG9FIIhYJV4bBsovbzxKDjunp6m6xzWPVXT3Vt5lwQDFZQJTD vBVlEZhhRXvv7bzJIIn2XRD0Bq/bkZFwoupWWfJ+qUYO+VMur0YzDszJoGdwTv7YieL41L I8evJBQzvv7oUrHP4+RgPV3QsgbxEvLamvfo6IHlsJNOhwbfV/VxtMzGl/Zuj5Rc9IlvQZ LNHXmTNRzMAfCbDOoDBsa+FGbpC/rrUUiQdCJXRZhuWkdpstPMdbSKlRhJstKg== From: Aleksa Sarai Date: Thu, 10 Oct 2024 07:40:40 +1100 Subject: [PATCH RFC v3 07/10] clone3: add CHECK_FIELDS flag to usize argument Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241010-extensible-structs-check_fields-v3-7-d2833dfe6edd@cyphar.com> References: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> In-Reply-To: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Alexander Viro , Christian Brauner , Jan Kara , Arnd Bergmann , Shuah Khan Cc: Kees Cook , Florian Weimer , Arnd Bergmann , Mark Rutland , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, Aleksa Sarai X-Developer-Signature: v=1; a=openpgp-sha256; l=3623; i=cyphar@cyphar.com; h=from:subject:message-id; bh=o94o6Toa1Pf4WLXPtt6pgYs8bPe/h3R8eYg1DJcRyfA=; b=owGbwMvMwCWmMf3Xpe0vXfIZT6slMaSzvQpi/nFmTv/HWQZ/e9iOrts0+5HWpvx/mrO//3+Zq xnXNi+htaOUhUGMi0FWTJFlm59n6Kb5i68kf1rJBjOHlQlkCAMXpwBMpCaIkeHJlqsuiUyc07jr 1kZXfOsz7tDIu7xi45pKHeWZvc5CE9wZ/gpmfeUW+7bTzl9xftEHkb8qAVdqVJh31nrN6fPb8ex HDisA X-Developer-Key: i=cyphar@cyphar.com; a=openpgp; fpr=C9C370B246B09F6DBCFC744C34401015D1D2D386 As with openat2(2), this allows userspace to easily figure out what flags and fields are supported by clone3(2). For fields which are not flag-based, we simply set every bit in the field so that a naive bitwise-and would show that any value of the field is valid. For args->exit_signal, since we have an explicit bitmask for the field defined already (CSIGNAL) we can indicate that only those bits are supported by current kernels. If we add some extra bits to exit_signal in the future, being able to detect them as new features would be quite useful. The intended way of using this interface to get feature information looks something like the following: static bool clone3_clear_sighand_supported; static bool clone3_cgroup_supported; int check_clone3_support(void) { int err; struct clone_args args = {}; err = clone3(&args, CHECK_FIELDS | sizeof(args)); assert(err < 0); switch (errno) { case EFAULT: case E2BIG: /* Old kernel... */ check_support_the_old_way(); break; case EEXTSYS_NOOP: clone3_clear_sighand_supported = (how.flags & CLONE_CLEAR_SIGHAND); clone3_cgroup_supported = (how.flags & CLONE_INTO_CGROUP) && (how.cgroup != 0); break; } } Signed-off-by: Aleksa Sarai --- kernel/fork.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index cc760491f201..bded93f4f5f4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2925,11 +2925,15 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, } #endif + +#define CLONE3_VALID_FLAGS (CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP) + noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, struct clone_args __user *uargs, size_t usize) { int err; + bool check_fields; struct clone_args args; pid_t *kset_tid = kargs->set_tid; @@ -2941,11 +2945,34 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, CLONE_ARGS_SIZE_VER2); BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER2); + check_fields = usize & CHECK_FIELDS; + usize &= ~CHECK_FIELDS; + if (unlikely(usize > PAGE_SIZE)) return -E2BIG; if (unlikely(usize < CLONE_ARGS_SIZE_VER0)) return -EINVAL; + if (unlikely(check_fields)) { + memset(&args, 0, sizeof(args)); + args = (struct clone_args) { + .flags = CLONE3_VALID_FLAGS, + .pidfd = 0xFFFFFFFFFFFFFFFF, + .child_tid = 0xFFFFFFFFFFFFFFFF, + .parent_tid = 0xFFFFFFFFFFFFFFFF, + .exit_signal = (u64) CSIGNAL, + .stack = 0xFFFFFFFFFFFFFFFF, + .stack_size = 0xFFFFFFFFFFFFFFFF, + .tls = 0xFFFFFFFFFFFFFFFF, + .set_tid = 0xFFFFFFFFFFFFFFFF, + .set_tid_size = 0xFFFFFFFFFFFFFFFF, + .cgroup = 0xFFFFFFFFFFFFFFFF, + }; + + err = copy_struct_to_user(uargs, usize, &args, sizeof(args), NULL); + return err ?: -EEXTSYS_NOOP; + } + err = copy_struct_from_user(&args, sizeof(args), uargs, usize); if (err) return err; @@ -3025,8 +3052,7 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) static bool clone3_args_valid(struct kernel_clone_args *kargs) { /* Verify that no unknown flags are passed along. */ - if (kargs->flags & - ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP)) + if (kargs->flags & ~CLONE3_VALID_FLAGS) return false; /* From patchwork Wed Oct 9 20:40:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksa Sarai X-Patchwork-Id: 834355 Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [80.241.56.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D9AC1E7C3E; Wed, 9 Oct 2024 20:42:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506552; cv=none; b=lROuajdjjudj3CKmxCdHZMCjb8U01UWVgSgFCHEc4fB4dulbKAakwGdJNQIzcgeLvwZvUKaGT1puvE63aYiqqCO/X3c/TerfNR65Df3g1avJXCP1QkVAlc0zQohiO1jlqHUKQvEvpUfUg94G18J7oc7xWUOHun1wROtr1qkktkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728506552; c=relaxed/simple; bh=uMJLkf5QTDuvdiBzRMepbN6IKFXf5n7a7YM4+FwWbAk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=s1vUdknFbtyK87O4FKY9cXmfyI+Y66fCzTFsXn2WSbHhKF2zk6LwXtzMJpqONge6TWIj0ccEfrNpc0Ia/nXvmpJq/WPs0nXlV/TVOJkcX37p8WV7waF/94ZJUJcGnHU/Cb973ndHB7e4uzDW2OPBtwZnJ4frDL9y8HszIUuWyvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com; spf=pass smtp.mailfrom=cyphar.com; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b=ZjNZHALZ; arc=none smtp.client-ip=80.241.56.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cyphar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cyphar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cyphar.com header.i=@cyphar.com header.b="ZjNZHALZ" Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4XP4ZW0rLNz9ssh; Wed, 9 Oct 2024 22:42:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyphar.com; s=MBO0001; t=1728506547; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QWYXRXXrADdO6m0g06MFjKfnGjcDChbWetducV/F6Dk=; b=ZjNZHALZWFcrjZgV9gAg0JNFBkQlLD2SaCQY1YF2e9E23GDiBLPflEaL4boR0gyEkEggy9 XLW0KNc2DSCBqByqxm4hir/o531UXgDTzDdW7RM3USRTyWq/7xWwMLdzLltrlm2iwi+xTu dnI8SqSL6O5KB6eaScMcP/O4DqJpN835gz5ToETv3Stveq+0CsK/knfKzpL9OLNz8np2nx Izz2LyEEKAxM1VpL1PSxeaTLgF8JS7uPy79iP8fjiq7LCGE5FXFXgkplKUkOJhJDXe01N9 4XTdDzNYLqSzB8r/MefbtcWeIDTSPyv1RKHwKOzF4mQYmaWFpCURYPQExJqO8Q== From: Aleksa Sarai Date: Thu, 10 Oct 2024 07:40:42 +1100 Subject: [PATCH RFC v3 09/10] mount_setattr: add CHECK_FIELDS flag to usize argument Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241010-extensible-structs-check_fields-v3-9-d2833dfe6edd@cyphar.com> References: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> In-Reply-To: <20241010-extensible-structs-check_fields-v3-0-d2833dfe6edd@cyphar.com> To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , Alexander Viro , Christian Brauner , Jan Kara , Arnd Bergmann , Shuah Khan Cc: Kees Cook , Florian Weimer , Arnd Bergmann , Mark Rutland , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, Aleksa Sarai X-Developer-Signature: v=1; a=openpgp-sha256; l=2453; i=cyphar@cyphar.com; h=from:subject:message-id; bh=uMJLkf5QTDuvdiBzRMepbN6IKFXf5n7a7YM4+FwWbAk=; b=owGbwMvMwCWmMf3Xpe0vXfIZT6slMaSzvQp6eOwQr3GCiIjonTCWo6sOZps53Up4lHl7G8OVC 9vY+Q5c7ChlYRDjYpAVU2TZ5ucZumn+4ivJn1aywcxhZQIZwsDFKQATeeDB8D/p0qE1VzfuzLXq 9HnMcv/w/70FyysO/284OdtAa9PfgsiVDP9snyots6z2r8j6EH89oeyRSUzpmdfTUz3VXkrl3as NsWYEAA== X-Developer-Key: i=cyphar@cyphar.com; a=openpgp; fpr=C9C370B246B09F6DBCFC744C34401015D1D2D386 X-Rspamd-Queue-Id: 4XP4ZW0rLNz9ssh As with openat2(2), this allows userspace to easily figure out what flags and fields are supported by mount_setattr(2). As with clone3(2), for fields which are not flag-based, we simply set every bit in the field so that a naive bitwise-and would show that any value of the field is valid. The intended way of using this interface to get feature information looks something like the following: static bool mountattr_nosymfollow_supported; static bool mountattr_idmap_supported; int check_clone3_support(void) { int err; struct mount_attr attr = {}; err = mount_attr(-EBADF, "", 0, &args, CHECK_FIELDS | sizeof(args)); assert(err < 0); switch (errno) { case EFAULT: case E2BIG: /* Old kernel... */ check_support_the_old_way(); break; case EEXTSYS_NOOP: mountattr_nosymfollow_supported = ((attr.attr_clr | attr.attr_set) & MOUNT_ATTR_NOSYMFOLLOW); mountattr_idmap_supported = ((attr.attr_clr | attr.attr_set) & MOUNT_ATTR_IDMAP) && (attr.userns_fd != 0); break; } } Signed-off-by: Aleksa Sarai --- fs/namespace.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index 328087a4df8a..c7ae8d96b7b7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4771,6 +4771,7 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, size_t, usize) { int err; + bool check_fields; struct path target; struct mount_attr attr; struct mount_kattr kattr; @@ -4783,11 +4784,27 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, AT_NO_AUTOMOUNT)) return -EINVAL; + check_fields = usize & CHECK_FIELDS; + usize &= ~CHECK_FIELDS; + if (unlikely(usize > PAGE_SIZE)) return -E2BIG; if (unlikely(usize < MOUNT_ATTR_SIZE_VER0)) return -EINVAL; + if (unlikely(check_fields)) { + memset(&attr, 0, sizeof(attr)); + attr = (struct mount_attr) { + .attr_set = MOUNT_SETATTR_VALID_FLAGS, + .attr_clr = MOUNT_SETATTR_VALID_FLAGS, + .propagation = MOUNT_SETATTR_PROPAGATION_FLAGS, + .userns_fd = 0xFFFFFFFFFFFFFFFF, + }; + + err = copy_struct_to_user(uattr, usize, &attr, sizeof(attr), NULL); + return err ?: -EEXTSYS_NOOP; + } + if (!may_mount()) return -EPERM;