This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC v4 08/24] sysdeps/stat: Copy the statx struct to stat instead of stat64
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: arnd at arndb dot de, adhemerval dot zanella at linaro dot org, fweimer at redhat dot com, palmer at sifive dot com, macro at wdc dot com, zongbox at gmail dot com, alistair dot francis at wdc dot com, alistair23 at gmail dot com
- Date: Fri, 9 Aug 2019 18:00:08 -0700
- Subject: [RFC v4 08/24] sysdeps/stat: Copy the statx struct to stat instead of stat64
- Ironport-sdr: lzGgB3u8tFV25RX4LCIhR9LYCDYqX4yeRX4gSgVhkpeZQbSGt1w2N0M7gxmGnmJe/pm8LjFDia Db6wYy4Dzg12mH6+zKidc4th5HdU8Nzza2GwPoqFNpOPsCsfcsNsylPtLXbJZRKKen9elsOwIU l0A6LUB1i1JCmoJID+JIQZUJfVmne/MJsRe8LIz653wo3cvbgE7ABULkIc+QMLNh/OTL2yaq0D W6OKC4sbmcoBQPEWHQIvWOkT44hM69uUGzxaruxPcbEl42b6eNHo3xPnGy0u985wDZNCfGfH0F 0uA=
- Ironport-sdr: z1BsQUbf0dmX1q4khIK8OqLQnxQ6WWpTYRnA1t0SQ4QS+owbzH8g8S9LylODmzQ0+rv8S/I1Wv FYPcBixPlXqHkk0LoDib1MKUsJsIa7+K6Q+dfSv364r2UWPXp/BYYP6nVJZcSgJrL5MsIwuI39 wFBlrjjlKGqH0LltMjTxLXtVsFaOhINQtllroMjQXZ4zyDvTaT1K1ovniibDPpFWnZvygscBgO zHxyjA8fVT25ZfN/lJXgTxVhzlw2l3RsWmz34uA6HWRbnr1MZVZLD08HL/ethPWxXjCMb92z2X yseAZ6DAfPTnrh//qi4cIaMt
- Ironport-sdr: bqS3vsHCjeqKz/T5KdXfBtfKYx3cfvTacfYPPoWq789BQh+Gc10Qj2JYC5aSCkuAeMCaPiPHd2 /dZNXv3w3tzV2c8dDyZitEgHTwfW/H6wYTj+r8fN74tEbbjJYX92FKKgWReMpJgQlFMB6YireV Km96ylEgIkjcrz66NjQ0moV4Cf99SK0kGl+MXxnAXEfI+j4IwAH7Ytrg3XZxAWVtwSQVV6VM2x GMYsVWsJZu7WSmZj6hIWeJmT1/Cx4x4mMaJmgqFD3VwnrbK8R3Q7gKKSiH6NYMZ06YzbWXzfsI +SA=
- References: <cover.1565398513.git.alistair.francis@wdc.com>
When copying the statx struct to the stat stuct use the original stat
struct instead of the stat64 struct. As the padding in the original is
type 'unsigned short int' but the padding in the stat64 is 'unsigned int'
the copy can result in misallgined data. This would then incorrectly
trigger the stat_overflow() failure.
This would be very obvious when using a 64-bit ino_t type on a 32-bit
system, such as the RV32 port.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
.../sysv/linux/generic/wordsize-32/fxstat.c | 2 +-
.../sysv/linux/generic/wordsize-32/fxstatat.c | 2 +-
.../sysv/linux/generic/wordsize-32/lxstat.c | 2 +-
.../sysv/linux/generic/wordsize-32/xstat.c | 2 +-
sysdeps/unix/sysv/linux/statx_cp.c | 24 +++++++++++++++++++
sysdeps/unix/sysv/linux/statx_cp.h | 3 +++
6 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
index 81e137c585b..234098b5199 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
@@ -43,7 +43,7 @@ __fxstat (int vers, int fd, struct stat *buf)
int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
STATX_BASIC_STATS, &tmp);
if (rc == 0)
- __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+ __cp_stat_statx (buf, &tmp);
# endif
return rc ?: stat_overflow (buf);
}
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
index e203260485c..bd3bfc101cd 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
@@ -44,7 +44,7 @@ __fxstatat (int vers, int fd, const char *file, struct stat *buf, int flag)
AT_NO_AUTOMOUNT | flag,
STATX_BASIC_STATS, &tmp);
if (rc == 0)
- __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+ __cp_stat_statx (buf, &tmp);
# endif
return rc ?: stat_overflow (buf);
}
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
index 2d4dfbaf527..01edf9f22cc 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
@@ -44,7 +44,7 @@ __lxstat (int vers, const char *name, struct stat *buf)
AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW,
STATX_BASIC_STATS, &tmp);
if (rc == 0)
- __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+ __cp_stat_statx (buf, &tmp);
#endif
return rc ?: stat_overflow (buf);
}
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
index 5f1f53c0f3f..dea6ec525e9 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
@@ -42,7 +42,7 @@ __xstat (int vers, const char *name, struct stat *buf)
int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT,
STATX_BASIC_STATS, &tmp);
if (rc == 0)
- __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+ __cp_stat_statx (buf, &tmp);
# endif
return rc ?: stat_overflow (buf);
}
diff --git a/sysdeps/unix/sysv/linux/statx_cp.c b/sysdeps/unix/sysv/linux/statx_cp.c
index 3b4e5583e9a..2574d05563c 100644
--- a/sysdeps/unix/sysv/linux/statx_cp.c
+++ b/sysdeps/unix/sysv/linux/statx_cp.c
@@ -46,4 +46,28 @@ __cp_stat64_statx (struct stat64 *to, struct statx *from)
to->st_blocks = from->stx_blocks;
to->st_blksize = from->stx_blksize;
}
+
+void
+__cp_stat_statx (struct stat *to, struct statx *from)
+{
+ memset (to, 0, sizeof (struct stat64));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
#endif
diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h
index f08a7a8dcc8..2bb1d0605fd 100644
--- a/sysdeps/unix/sysv/linux/statx_cp.h
+++ b/sysdeps/unix/sysv/linux/statx_cp.h
@@ -18,3 +18,6 @@
extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
attribute_hidden;
+
+extern void __cp_stat_statx (struct stat *to, struct statx *from)
+ attribute_hidden;
--
2.22.0