]> git.pld-linux.org Git - packages/glibc.git/blame - fstat.patch
update git patch (fixes CVE-2023-4911); rel 7
[packages/glibc.git] / fstat.patch
CommitLineData
067c64fe
AM
1From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2Subject: [PATCH v2] io: Do not implement fstat with fstatat
3Date: Mon, 11 Sep 2023 10:25:48 -0300
4
5AT_EMPTY_PATH is a requirement to implement fstat over fstatat,
6however it does not prevent the kernel to read the path argument.
7It is not an issue, but on x86-64 with SMAP-capable CPUs the kernel is
8forced to perform expensive user memory access. After that regular
9lookup is performed which adds even more overhead.
10
11Instead, issue the fstat syscall directly on LFS fstat implementation
12(32 bit architectures will still continue to use statx, which is
13required to have 64 bit time_t support). it should be even a
14small performance gain on non x86_64, since there is no need
15to handle the path argument.
16
17Checked on x86_64-linux-gnu.
18---
19 sysdeps/unix/sysv/linux/fstat64.c | 37 +++++++++++++++++++++++--
20 sysdeps/unix/sysv/linux/fstatat64.c | 12 ++------
21 sysdeps/unix/sysv/linux/internal-stat.h | 31 +++++++++++++++++++++
22 3 files changed, 68 insertions(+), 12 deletions(-)
23 create mode 100644 sysdeps/unix/sysv/linux/internal-stat.h
24
25diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c
26index 124384e57f..a291f0825b 100644
27--- a/sysdeps/unix/sysv/linux/fstat64.c
28+++ b/sysdeps/unix/sysv/linux/fstat64.c
29@@ -19,20 +19,53 @@
30 #define __fstat __redirect___fstat
31 #define fstat __redirect_fstat
32 #include <sys/stat.h>
33+#undef __fstat
34+#undef fstat
35 #include <fcntl.h>
36-#include <kernel_stat.h>
37-#include <stat_t64_cp.h>
38+#include <internal-stat.h>
39 #include <errno.h>
40
41 int
42 __fstat64_time64 (int fd, struct __stat64_t64 *buf)
43 {
44+#if !FSTATAT_USE_STATX
45+# if XSTAT_IS_XSTAT64
46+# ifdef __NR_fstat
47+ /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and
48+ x86_64. */
49+ return INLINE_SYSCALL_CALL (fstat, fd, buf);
50+# elif defined __NR_fstat64
51+# if STAT64_IS_KERNEL_STAT64
52+ /* 64-bit kABI outlier, e.g. alpha */
53+ return INLINE_SYSCALL_CALL (fstat64, fd, buf);
54+# else
55+ /* 64-bit kABI outlier, e.g. sparc64. */
56+ struct kernel_stat64 kst64;
57+ int r = INLINE_SYSCALL_CALL (fstat64, fd, &kst64);
58+ if (r == 0)
59+ __cp_stat64_kstat64 (buf, &kst64);
60+ return r;
61+# endif /* STAT64_IS_KERNEL_STAT64 */
62+# endif
63+# else /* XSTAT_IS_XSTAT64 */
64+ /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */
65+ struct kernel_stat kst;
66+ int r = INLINE_SYSCALL_CALL (fstat, fd, &kst);
67+ if (r == 0)
68+ __cp_kstat_stat64_t64 (&kst, buf);
69+ return r;
70+# endif
71+#else /* !FSTATAT_USE_STATX */
72+ /* All kABIs with non-LFS support and with old 32-bit time_t support
73+ e.g. arm, csky, i386, hppa, m68k, microblaze, nios2, sh, powerpc32,
74+ and sparc32. */
75 if (fd < 0)
76 {
77 __set_errno (EBADF);
78 return -1;
79 }
80 return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH);
81+#endif
82 }
83 #if __TIMESIZE != 64
84 hidden_def (__fstat64_time64)
85diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
86index 3509d3ca6d..127c6ff601 100644
87--- a/sysdeps/unix/sysv/linux/fstatat64.c
88+++ b/sysdeps/unix/sysv/linux/fstatat64.c
89@@ -21,12 +21,10 @@
90 #include <sys/stat.h>
91 #include <fcntl.h>
92 #include <string.h>
93-#include <kernel_stat.h>
94 #include <sysdep.h>
95 #include <time.h>
96-#include <kstat_cp.h>
97-#include <stat_t64_cp.h>
98 #include <sys/sysmacros.h>
99+#include <internal-stat.h>
100
101 #if __TIMESIZE == 64 \
102 && (__WORDSIZE == 32 \
103@@ -40,11 +38,7 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
104 "__blkcnt_t and __blkcnt64_t must match");
105 #endif
106
107-#if (__WORDSIZE == 32 \
108- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
109- || defined STAT_HAS_TIME32 \
110- || (!defined __NR_newfstatat && !defined __NR_fstatat64)
111-# define FSTATAT_USE_STATX 1
112+#if FSTATAT_USE_STATX
113
114 static inline int
115 fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
116@@ -79,8 +73,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
117
118 return r;
119 }
120-#else
121-# define FSTATAT_USE_STATX 0
122 #endif
123
124 /* Only statx supports 64-bit timestamps for 32-bit architectures with
125diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h
126new file mode 100644
127index 0000000000..e3b0569853
128--- /dev/null
129+++ b/sysdeps/unix/sysv/linux/internal-stat.h
130@@ -0,0 +1,31 @@
131+/* Internal stat definitions.
132+ Copyright (C) 2023 Free Software Foundation, Inc.
133+ This file is part of the GNU C Library.
134+
135+ The GNU C Library is free software; you can redistribute it and/or
136+ modify it under the terms of the GNU Lesser General Public
137+ License as published by the Free Software Foundation; either
138+ version 2.1 of the License, or (at your option) any later version.
139+
140+ The GNU C Library is distributed in the hope that it will be useful,
141+ but WITHOUT ANY WARRANTY; without even the implied warranty of
142+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
143+ Lesser General Public License for more details.
144+
145+ You should have received a copy of the GNU Lesser General Public
146+ License along with the GNU C Library; if not, see
147+ <https://www.gnu.org/licenses/>. */
148+
149+#include <sysdep.h>
150+#include <stat_t64_cp.h>
151+#include <kernel_stat.h>
152+#include <kstat_cp.h>
153+
154+#if (__WORDSIZE == 32 \
155+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
156+ || defined STAT_HAS_TIME32 \
157+ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
158+# define FSTATAT_USE_STATX 1
159+#else
160+# define FSTATAT_USE_STATX 0
161+#endif
This page took 0.088886 seconds and 4 git commands to generate.