Hide statfs/fstatfs' ST_VALID flag from userspace.
Spotted while debugging the strace 4.10 upgrade.
Change-Id: I1af1be9c9440151f55f74a835e1df71529b0e4fe
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 150dd14..b91f5bf 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -174,9 +174,9 @@
int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,mips,x86
-int fstatfs64|fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
+int __fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86
-int statfs64|statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
+int __statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
int fstat64|fstat:fstat64(int, struct stat*) arm,mips,x86
int fstat64|fstat:fstat(int, struct stat*) arm64,x86_64
diff --git a/libc/arch-arm64/syscalls/fstatfs64.S b/libc/arch-arm64/syscalls/__fstatfs.S
similarity index 73%
rename from libc/arch-arm64/syscalls/fstatfs64.S
rename to libc/arch-arm64/syscalls/__fstatfs.S
index 2ca2dcd..7e350d6 100644
--- a/libc/arch-arm64/syscalls/fstatfs64.S
+++ b/libc/arch-arm64/syscalls/__fstatfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(fstatfs64)
+ENTRY(__fstatfs)
mov x8, __NR_fstatfs
svc #0
@@ -11,7 +11,5 @@
b.hi __set_errno_internal
ret
-END(fstatfs64)
-
- .globl fstatfs
- .equ fstatfs, fstatfs64
+END(__fstatfs)
+.hidden __fstatfs
diff --git a/libc/arch-arm64/syscalls/statfs64.S b/libc/arch-arm64/syscalls/__statfs.S
similarity index 74%
rename from libc/arch-arm64/syscalls/statfs64.S
rename to libc/arch-arm64/syscalls/__statfs.S
index ec8c588..962c590 100644
--- a/libc/arch-arm64/syscalls/statfs64.S
+++ b/libc/arch-arm64/syscalls/__statfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(statfs64)
+ENTRY(__statfs)
mov x8, __NR_statfs
svc #0
@@ -11,7 +11,5 @@
b.hi __set_errno_internal
ret
-END(statfs64)
-
- .globl statfs
- .equ statfs, statfs64
+END(__statfs)
+.hidden __statfs
diff --git a/libc/arch-mips64/syscalls/fstatfs64.S b/libc/arch-mips64/syscalls/__fstatfs.S
similarity index 81%
rename from libc/arch-mips64/syscalls/fstatfs64.S
rename to libc/arch-mips64/syscalls/__fstatfs.S
index 12e885c..8766e22 100644
--- a/libc/arch-mips64/syscalls/fstatfs64.S
+++ b/libc/arch-mips64/syscalls/__fstatfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(fstatfs64)
+ENTRY(__fstatfs)
.set push
.set noreorder
li v0, __NR_fstatfs
@@ -22,7 +22,5 @@
j t9
move ra, t0
.set pop
-END(fstatfs64)
-
- .globl fstatfs
- .equ fstatfs, fstatfs64
+END(__fstatfs)
+.hidden __fstatfs
diff --git a/libc/arch-mips64/syscalls/statfs64.S b/libc/arch-mips64/syscalls/__statfs.S
similarity index 82%
rename from libc/arch-mips64/syscalls/statfs64.S
rename to libc/arch-mips64/syscalls/__statfs.S
index 74351f7..52db4e2 100644
--- a/libc/arch-mips64/syscalls/statfs64.S
+++ b/libc/arch-mips64/syscalls/__statfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(statfs64)
+ENTRY(__statfs)
.set push
.set noreorder
li v0, __NR_statfs
@@ -22,7 +22,5 @@
j t9
move ra, t0
.set pop
-END(statfs64)
-
- .globl statfs
- .equ statfs, statfs64
+END(__statfs)
+.hidden __statfs
diff --git a/libc/arch-x86_64/syscalls/fstatfs64.S b/libc/arch-x86_64/syscalls/__fstatfs.S
similarity index 75%
rename from libc/arch-x86_64/syscalls/fstatfs64.S
rename to libc/arch-x86_64/syscalls/__fstatfs.S
index f727350..b50e355 100644
--- a/libc/arch-x86_64/syscalls/fstatfs64.S
+++ b/libc/arch-x86_64/syscalls/__fstatfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(fstatfs64)
+ENTRY(__fstatfs)
movl $__NR_fstatfs, %eax
syscall
cmpq $-MAX_ERRNO, %rax
@@ -12,7 +12,5 @@
call __set_errno_internal
1:
ret
-END(fstatfs64)
-
- .globl fstatfs
- .equ fstatfs, fstatfs64
+END(__fstatfs)
+.hidden __fstatfs
diff --git a/libc/arch-x86_64/syscalls/statfs64.S b/libc/arch-x86_64/syscalls/__statfs.S
similarity index 77%
rename from libc/arch-x86_64/syscalls/statfs64.S
rename to libc/arch-x86_64/syscalls/__statfs.S
index 16f6bdd..607a809 100644
--- a/libc/arch-x86_64/syscalls/statfs64.S
+++ b/libc/arch-x86_64/syscalls/__statfs.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(statfs64)
+ENTRY(__statfs)
movl $__NR_statfs, %eax
syscall
cmpq $-MAX_ERRNO, %rax
@@ -12,7 +12,5 @@
call __set_errno_internal
1:
ret
-END(statfs64)
-
- .globl statfs
- .equ statfs, statfs64
+END(__statfs)
+.hidden __statfs
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 73f77be..50e4643 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -40,9 +40,7 @@
// System calls we need.
extern "C" int __fcntl64(int, int, void*);
-extern "C" int __fstatfs64(int, size_t, struct statfs*);
extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int);
-extern "C" int __statfs64(const char*, size_t, struct statfs*);
// For fcntl we use the fcntl64 system call to signal that we're using struct flock64.
int fcntl(int fd, int cmd, ...) {
@@ -55,18 +53,6 @@
return __fcntl64(fd, cmd, arg);
}
-// For fstatfs we need to add the extra argument giving the kernel the size of the buffer.
-int fstatfs(int fd, struct statfs* stat) {
- return __fstatfs64(fd, sizeof(*stat), stat);
-}
-__strong_alias(fstatfs64, fstatfs);
-
-// For statfs we need to add the extra argument giving the kernel the size of the buffer.
-int statfs(const char* path, struct statfs* stat) {
- return __statfs64(path, sizeof(*stat), stat);
-}
-__strong_alias(statfs64, statfs);
-
// For lseek64 we need to use the llseek system call which splits the off64_t in two and
// returns the off64_t result via a pointer because 32-bit kernels can't return 64-bit results.
off64_t lseek64(int fd, off64_t off, int whence) {
diff --git a/libc/bionic/statvfs.cpp b/libc/bionic/statvfs.cpp
index f1e2833..39ffb64 100644
--- a/libc/bionic/statvfs.cpp
+++ b/libc/bionic/statvfs.cpp
@@ -21,13 +21,17 @@
// Paper over the fact that 32-bit kernels use fstatfs64/statfs64 with an extra argument,
// but 64-bit kernels don't have the "64" bit suffix or the extra size_t argument.
#if __LP64__
-# define __fstatfs64(fd,size,buf) fstatfs(fd,buf)
-# define __statfs64(path,size,buf) statfs(path,buf)
+extern "C" int __fstatfs(int, struct statfs*);
+extern "C" int __statfs(const char*, struct statfs*);
+# define __fstatfs64(fd,size,buf) __fstatfs(fd,buf)
+# define __statfs64(path,size,buf) __statfs(path,buf)
#else
extern "C" int __fstatfs64(int, size_t, struct statfs*);
extern "C" int __statfs64(const char*, size_t, struct statfs*);
#endif
+// The kernel sets a private ST_VALID flag to signal to the C library whether the
+// f_flags field is valid. This flag should not be exposed to users of the C library.
#define ST_VALID 0x0020
static void __statfs_to_statvfs(const struct statfs& in, struct statvfs* out) {
@@ -40,13 +44,33 @@
out->f_ffree = in.f_ffree;
out->f_favail = in.f_ffree;
out->f_fsid = in.f_fsid.__val[0] | (static_cast<uint64_t>(in.f_fsid.__val[1]) << 32);
- out->f_flag = in.f_flags & ~ST_VALID;
+ out->f_flag = in.f_flags;
out->f_namemax = in.f_namelen;
}
+int fstatfs(int fd, struct statfs* result) {
+ int rc = __fstatfs64(fd, sizeof(*result), result);
+ if (rc != 0) {
+ return rc;
+ }
+ result->f_flags &= ~ST_VALID;
+ return 0;
+}
+__strong_alias(fstatfs64, fstatfs);
+
+int statfs(const char* path, struct statfs* result) {
+ int rc = __statfs64(path, sizeof(*result), result);
+ if (rc != 0) {
+ return rc;
+ }
+ result->f_flags &= ~ST_VALID;
+ return 0;
+}
+__strong_alias(statfs64, statfs);
+
int statvfs(const char* path, struct statvfs* result) {
struct statfs tmp;
- int rc = __statfs64(path, sizeof(tmp), &tmp);
+ int rc = statfs(path, &tmp);
if (rc != 0) {
return rc;
}
@@ -57,7 +81,7 @@
int fstatvfs(int fd, struct statvfs* result) {
struct statfs tmp;
- int rc = __fstatfs64(fd, sizeof(tmp), &tmp);
+ int rc = fstatfs(fd, &tmp);
if (rc != 0) {
return rc;
}
diff --git a/tests/sys_statvfs_test.cpp b/tests/sys_statvfs_test.cpp
index 6b19e13..bff9e20 100644
--- a/tests/sys_statvfs_test.cpp
+++ b/tests/sys_statvfs_test.cpp
@@ -30,6 +30,11 @@
EXPECT_EQ(0U, sb.f_ffree);
EXPECT_EQ(0U, sb.f_fsid);
EXPECT_EQ(255U, sb.f_namemax);
+
+ // The kernel sets a private bit to indicate that f_flags is valid.
+ // This flag is not supposed to be exposed to libc clients.
+ static const uint32_t ST_VALID = 0x0020;
+ EXPECT_TRUE((sb.f_flag & ST_VALID) == 0) << sb.f_flag;
}
TEST(sys_statvfs, statvfs) {
@@ -51,6 +56,7 @@
close(fd);
Check(sb);
}
+
TEST(sys_statvfs, fstatvfs64) {
struct statvfs64 sb;
int fd = open("/proc", O_RDONLY);
diff --git a/tests/sys_vfs_test.cpp b/tests/sys_vfs_test.cpp
index 4b05660..a521967 100644
--- a/tests/sys_vfs_test.cpp
+++ b/tests/sys_vfs_test.cpp
@@ -31,6 +31,11 @@
EXPECT_EQ(0, sb.f_fsid.__val[0]);
EXPECT_EQ(0, sb.f_fsid.__val[1]);
EXPECT_EQ(255, static_cast<int>(sb.f_namelen));
+
+ // The kernel sets a private bit to indicate that f_flags is valid.
+ // This flag is not supposed to be exposed to libc clients.
+ static const uint32_t ST_VALID = 0x0020;
+ EXPECT_TRUE((sb.f_flags & ST_VALID) == 0) << sb.f_flags;
}
TEST(sys_vfs, statfs) {
@@ -52,6 +57,7 @@
close(fd);
Check(sb);
}
+
TEST(sys_vfs, fstatfs64) {
struct statfs64 sb;
int fd = open("/proc", O_RDONLY);