From patchwork Tue Oct 31 16:32:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 1857678 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=abqTJkwG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SKbKz0gtTz1yQf for ; Wed, 1 Nov 2023 03:33:27 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 059C13861800 for ; Tue, 31 Oct 2023 16:33:21 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by sourceware.org (Postfix) with ESMTPS id 6B1813857731 for ; Tue, 31 Oct 2023 16:32:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6B1813857731 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6B1813857731 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1133 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698769979; cv=none; b=yF45Rm0CCu/VHv4sZjvO6PtGr+rSsswIPfkF26D7levymrAp6wNLp+Dy6/yr8Qlo7x5hX2uyYOOv8yTJKQpn6FY9yifILy9yb8dq+DoPjPvQ5g9oU8C3w2r4EkhdFJ/Vz+K9tJQFIme5WEU2UBqva6slIVn1ye1hP3kXH0fluzQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698769979; c=relaxed/simple; bh=uTUUjt8dMQvY5p2oLM84YddUcUsc8oPh+mDe0s03l9w=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=QxmeBby7YBkRC34Ao8WTPdJYZDPwQrnU9REVwF2dOrQbFFWXo9KCN+FOlP1pEz6T2r+P1X3vyz9MGKr8nY+pXgzQzkSNh3ZDOwnJpIphvPLfxBfKnUTafyETXeI2KQIEIoPDp2I6V6RPPZrYIsjgsm82tbOqtx8mQ+INa+LC2Xg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-5afbdbf3a19so45438467b3.2 for ; Tue, 31 Oct 2023 09:32:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698769976; x=1699374776; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=l4KwHDLJ+TqgHxRwSnz+ubCiUC36qba9OJRc7mzQE0s=; b=abqTJkwGr7ixo3s5ylCWa5URQ/YIz4Ak2gh573w6Pn+Tw1ZJM/4DV9MIZ0+rbrvwSs AQUdleYT51ROChWXO+iQuvxSTDpHORau2p+yFdJrqH/58tBQ1nnZQytUY699u+AT+a4G 9CL9DrX2mCs7er0mYXx6ASgpGEg11LH7m3Y/eKLCvt0LYCVdfyjrmR6wDsEUeaz3Kq2u PkrvS5bNZFwbz0+cNKkGJYZlNRPok232rI/7LEiHN4JzZ4HUN/8XfqT64fR+z6SSyBk8 7o/GYuops0sM6S7ubfB2l1A2ghJNqBr3fYER24Pqh/6tGAo8HgCoLDRE+WvUlWwTO1Uv ihow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698769976; x=1699374776; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=l4KwHDLJ+TqgHxRwSnz+ubCiUC36qba9OJRc7mzQE0s=; b=SRmiAI5GMmA96OiQbTSVLFW0vLLVjV1gu2+0X8AESpxb/br8dFnqcXRCKcZ4oTn7Sj am8ll7DNpfybG2NX0/Ui55lQf8UL2FNBXhec+xJ5qi72JGzmg+wZy1zUBr24TNC0qqW2 o7iHpSmt/PTVAiV5OvbZKaJPhu0ZdyddlRnZNS5S2A2eqVTXWvP5kE1i7g2MU3ie+Hp9 VuRrdNHhek7ThXDI4agkVCwgfOdm94ZVnO90Rc2eG6IxTSOxIIHEYgZi7yrFKIdyRdvQ g3xGnphAv4KV2nhzdeung4NhuIeGYIBH6937fDWZJpWS2RDEY8WrOu0ajRdgOt7PRjst RFyQ== X-Gm-Message-State: AOJu0YyZmJ7Ou+PjIdE0o2K2opNksiC6NjoTzPi/cZR9P5KexeUnHr82 BNb/+nRP+lrjLYxh6JOPrg3Vu28VdfnPpxtzEkSNHQ== X-Google-Smtp-Source: AGHT+IEEY0+mDbuopXFLLJnOUnTN66PWh+l2UFcy4q3ySyBeBhSjvjDQlOx6LFS9xTCBeAyqpBxwKw== X-Received: by 2002:a81:b725:0:b0:5a7:af72:ad6a with SMTP id v37-20020a81b725000000b005a7af72ad6amr12381735ywh.43.1698769976101; Tue, 31 Oct 2023 09:32:56 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c0:3d3c:6c87:9be3:8cfc:976d]) by smtp.gmail.com with ESMTPSA id z76-20020a814c4f000000b0059f650f46b2sm1003638ywa.7.2023.10.31.09.32.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Oct 2023 09:32:55 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 7/7] linux: Use fchmodat2 on fchmod for flags different than 0 (BZ 26401) Date: Tue, 31 Oct 2023 13:32:39 -0300 Message-Id: <20231031163239.4020952-8-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231031163239.4020952-1-adhemerval.zanella@linaro.org> References: <20231031163239.4020952-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Linux 6.6 (09da082b07bbae1c) added support for fchmodat2, which is has similar semantic of fchmodat with an extra flag argument. This allow fchmodat to implement AT_SYMLINK_NOFOLLOW and AT_EMPTY_PATH without the need to procfs. The syscall is registered on all architectures (with value of 452 except on alpha which is 562, commit 78252deb023cf087). Checked on x86_64-linux-gnu on a 6.6 kernel. Reviewed-by: Florian Weimer --- io/tst-lchmod.c | 4 +- sysdeps/unix/sysv/linux/fchmodat.c | 120 ++++++++++++---------- sysdeps/unix/sysv/linux/kernel-features.h | 8 ++ 3 files changed, 77 insertions(+), 55 deletions(-) diff --git a/io/tst-lchmod.c b/io/tst-lchmod.c index 2bf4835b05..6496dc61e0 100644 --- a/io/tst-lchmod.c +++ b/io/tst-lchmod.c @@ -219,9 +219,9 @@ test_1 (bool do_relative_path, int (*chmod_func) (int fd, const char *, mode_t, /* The error code from the openat fallback leaks out. */ if (errno != ENFILE && errno != EMFILE) TEST_COMPARE (errno, EOPNOTSUPP); + xstat (path_file, &st); + TEST_COMPARE (st.st_mode & 0777, 3); } - xstat (path_file, &st); - TEST_COMPARE (st.st_mode & 0777, 3); /* Close the descriptors. */ for (int *pfd = fd_list_begin (&fd_list); pfd < fd_list_end (&fd_list); diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c index 99527a3727..99d3df6440 100644 --- a/sysdeps/unix/sysv/linux/fchmodat.c +++ b/sysdeps/unix/sysv/linux/fchmodat.c @@ -26,66 +26,80 @@ #include #include -int -fchmodat (int fd, const char *file, mode_t mode, int flag) +#if !__ASSUME_FCHMODAT2 +static int +fchmodat_fallback (int fd, const char *file, mode_t mode, int flag) { - if (flag == 0) - return INLINE_SYSCALL (fchmodat, 3, fd, file, mode); - else if (flag != AT_SYMLINK_NOFOLLOW) + if (flag != AT_SYMLINK_NOFOLLOW) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); - else - { - /* The kernel system call does not have a mode argument. - However, we can create an O_PATH descriptor and change that - via /proc (which does not resolve symbolic links). */ - int pathfd = __openat_nocancel (fd, file, - O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (pathfd < 0) - /* This may report errors such as ENFILE and EMFILE. The - caller can treat them as temporary if necessary. */ - return pathfd; + /* The kernel system call does not have a mode argument. + However, we can create an O_PATH descriptor and change that + via /proc (which does not resolve symbolic links). */ - /* Use fstatat because fstat does not work on O_PATH descriptors - before Linux 3.6. */ - struct __stat64_t64 st; - if (__fstatat64_time64 (pathfd, "", &st, AT_EMPTY_PATH) != 0) - { - __close_nocancel (pathfd); - return -1; - } + int pathfd = __openat_nocancel (fd, file, + O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (pathfd < 0) + /* This may report errors such as ENFILE and EMFILE. The + caller can treat them as temporary if necessary. */ + return pathfd; - /* Some Linux versions with some file systems can actually - change symbolic link permissions via /proc, but this is not - intentional, and it gives inconsistent results (e.g., error - return despite mode change). The expected behavior is that - symbolic link modes cannot be changed at all, and this check - enforces that. */ - if (S_ISLNK (st.st_mode)) - { - __close_nocancel (pathfd); - __set_errno (EOPNOTSUPP); - return -1; - } + /* Use fstatat because fstat does not work on O_PATH descriptors + before Linux 3.6. */ + struct __stat64_t64 st; + if (__fstatat64_time64 (pathfd, "", &st, AT_EMPTY_PATH) != 0) + { + __close_nocancel (pathfd); + return -1; + } - /* For most file systems, fchmod does not operate on O_PATH - descriptors, so go through /proc. */ - struct fd_to_filename filename; - int ret = __chmod (__fd_to_filename (pathfd, &filename), mode); - if (ret != 0) - { - if (errno == ENOENT) - /* /proc has not been mounted. Without /proc, there is no - way to upgrade the O_PATH descriptor to a full - descriptor. It is also not possible to re-open the - file without O_PATH because the file name may refer to - another file, and opening that without O_PATH may have - side effects (such as blocking, device rewinding, or - releasing POSIX locks). */ - __set_errno (EOPNOTSUPP); - } + /* Some Linux versions with some file systems can actually + change symbolic link permissions via /proc, but this is not + intentional, and it gives inconsistent results (e.g., error + return despite mode change). The expected behavior is that + symbolic link modes cannot be changed at all, and this check + enforces that. */ + if (S_ISLNK (st.st_mode)) + { __close_nocancel (pathfd); - return ret; + __set_errno (EOPNOTSUPP); + return -1; + } + + /* For most file systems, fchmod does not operate on O_PATH + descriptors, so go through /proc. */ + struct fd_to_filename filename; + int ret = __chmod (__fd_to_filename (pathfd, &filename), mode); + if (ret != 0) + { + if (errno == ENOENT) + /* /proc has not been mounted. Without /proc, there is no + way to upgrade the O_PATH descriptor to a full + descriptor. It is also not possible to re-open the + file without O_PATH because the file name may refer to + another file, and opening that without O_PATH may have + side effects (such as blocking, device rewinding, or + releasing POSIX locks). */ + __set_errno (EOPNOTSUPP); } + __close_nocancel (pathfd); + return ret; +} +#endif + +int +fchmodat (int fd, const char *file, mode_t mode, int flag) +{ +#if __ASSUME_FCHMODAT2 + return INLINE_SYSCALL_CALL (fchmodat2, fd, file, mode, flag); +#else + if (flag == 0) + return INLINE_SYSCALL_CALL (fchmodat, fd, file, mode); + + int r = INLINE_SYSCALL_CALL (fchmodat2, fd, file, mode, flag); + if (r != 0 && errno == ENOSYS) + return fchmodat_fallback (fd, file, mode, flag); + return r; +#endif } libc_hidden_def (fchmodat) diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 07b440f4ee..670d2604d2 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -252,4 +252,12 @@ # define __ASSUME_CLONE3 0 #endif +/* The fchmodat2 system call was introduced across all architectures + in Linux 6.6. */ +#if __LINUX_KERNEL_VERSION >= 0x060600 +# define __ASSUME_FCHMODAT2 1 +#else +# define __ASSUME_FCHMODAT2 0 +#endif + #endif /* kernel-features.h */