Skip to content

Commit

Permalink
[compiler-rt] [netbsd] Add support for versioned statvfs interceptors
Browse files Browse the repository at this point in the history
Summary:
Add support for NetBSD 9.0 and newer versions of interceptors
operating on struct statvfs: fstatvfs, fstatvfs1, getmntinfo,
getvfsstat, statvfs, statvfs1.

The default promoted interceptors are for NetBSD 9.99.26. Older
ones (currently 9.0) are kept in a new NetBSD specific file:
/sanitizer_common_interceptors_netbsd_compat.inc. This file
defines compat interceptors and mangles `INIT_*` macros,
concatenating the current interceptors and the compat ones.
This redefinition is not elegant, but it avoids preprocessor madness.

Define struct_statvfs90_sz for the compat purposes.

Reviewers: mgorny, kcc, vitalybuka, joerg

Reviewed By: mgorny

Subscribers: dberris, llvm-commits, #sanitizers

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D71700
  • Loading branch information
krytarowski committed Dec 27, 2019
1 parent b35c585 commit 84afd9c
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 1 deletion.
Expand Up @@ -79,13 +79,15 @@
#define devname __devname50
#define fgetpos __fgetpos50
#define fsetpos __fsetpos50
#define fstatvfs __fstatvfs90
#define fstatvfs1 __fstatvfs190
#define fts_children __fts_children60
#define fts_close __fts_close60
#define fts_open __fts_open60
#define fts_read __fts_read60
#define fts_set __fts_set60
#define getitimer __getitimer50
#define getmntinfo __getmntinfo13
#define getmntinfo __getmntinfo90
#define getpwent __getpwent50
#define getpwnam __getpwnam50
#define getpwnam_r __getpwnam_r50
Expand All @@ -95,6 +97,7 @@
#define getutxent __getutxent50
#define getutxid __getutxid50
#define getutxline __getutxline50
#define getvfsstat __getvfsstat90
#define pututxline __pututxline50
#define glob __glob30
#define gmtime __gmtime50
Expand All @@ -116,6 +119,8 @@
#define sigprocmask __sigprocmask14
#define sigtimedwait __sigtimedwait50
#define stat __stat50
#define statvfs __statvfs90
#define statvfs1 __statvfs190
#define time __time50
#define times __times13
#define unvis __unvis50
Expand Down Expand Up @@ -9708,6 +9713,8 @@ INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
#define INIT_QSORT_R
#endif

#include "sanitizer_common_interceptors_netbsd_compat.inc"

static void InitializeCommonInterceptors() {
#if SI_POSIX
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
Expand Down
@@ -0,0 +1,128 @@
//===-- sanitizer_common_interceptors_netbsd_compat.inc ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Common function interceptors for tools like AddressSanitizer,
// ThreadSanitizer, MemorySanitizer, etc.
//
// Interceptors for NetBSD old function calls that have been versioned.
//
// NetBSD minimal version supported 9.0.
// NetBSD current version supported 9.99.26.
//
//===----------------------------------------------------------------------===//

#if SANITIZER_NETBSD

// First undef all mangled symbols.
// Next, define compat interceptors.
// Finally, undef INIT_ and redefine it.
// This allows to avoid preprocessor issues.

#undef fstatvfs
#undef fstatvfs1
#undef getmntinfo
#undef getvfsstat
#undef statvfs
#undef statvfs1

INTERCEPTOR(int, statvfs, char *path, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
int res = REAL(statvfs)(path, buf);
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
return res;
}

INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
int res = REAL(fstatvfs)(fd, buf);
if (!res) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
if (fd >= 0)
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
}
return res;
}

#undef INIT_STATVFS
#define INIT_STATVFS \
COMMON_INTERCEPT_FUNCTION(statvfs); \
COMMON_INTERCEPT_FUNCTION(fstatvfs); \
COMMON_INTERCEPT_FUNCTION(__statvfs90); \
COMMON_INTERCEPT_FUNCTION(__fstatvfs90)

INTERCEPTOR(int, __getmntinfo13, void **mntbufp, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __getmntinfo13, mntbufp, flags);
int cnt = REAL(__getmntinfo13)(mntbufp, flags);
if (cnt > 0 && mntbufp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
if (*mntbufp)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs90_sz);
}
return cnt;
}

#undef INIT_GETMNTINFO
#define INIT_GETMNTINFO \
COMMON_INTERCEPT_FUNCTION(__getmntinfo13); \
COMMON_INTERCEPT_FUNCTION(__getmntinfo90)

INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
int ret = REAL(getvfsstat)(buf, bufsize, flags);
if (buf && ret > 0)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs90_sz);
return ret;
}

#undef INIT_GETVFSSTAT
#define INIT_GETVFSSTAT \
COMMON_INTERCEPT_FUNCTION(getvfsstat); \
COMMON_INTERCEPT_FUNCTION(__getvfsstat90)

INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
int res = REAL(statvfs1)(path, buf, flags);
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
return res;
}

INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
int res = REAL(fstatvfs1)(fd, buf, flags);
if (!res) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
if (fd >= 0)
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
}
return res;
}

#undef INIT_STATVFS1
#define INIT_STATVFS1 \
COMMON_INTERCEPT_FUNCTION(statvfs1); \
COMMON_INTERCEPT_FUNCTION(fstatvfs1); \
COMMON_INTERCEPT_FUNCTION(__statvfs190); \
COMMON_INTERCEPT_FUNCTION(__fstatvfs190)

#endif
Expand Up @@ -2414,4 +2414,42 @@ CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_flags);
CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_props);
CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_propslen);

// Compat with 9.0
struct statvfs90 {
unsigned long f_flag;
unsigned long f_bsize;
unsigned long f_frsize;
unsigned long f_iosize;

u64 f_blocks;
u64 f_bfree;
u64 f_bavail;
u64 f_bresvd;

u64 f_files;
u64 f_ffree;
u64 f_favail;
u64 f_fresvd;

u64 f_syncreads;
u64 f_syncwrites;

u64 f_asyncreads;
u64 f_asyncwrites;

struct {
s32 __fsid_val[2];
} f_fsidx;
unsigned long f_fsid;
unsigned long f_namemax;
u32 f_owner;

u32 f_spare[4];

char f_fstypename[32];
char f_mntonname[32];
char f_mntfromname[32];
};
unsigned struct_statvfs90_sz = sizeof(struct statvfs90);

#endif // SANITIZER_NETBSD
Expand Up @@ -2420,6 +2420,9 @@ struct __sanitizer_cdbw {

#define SIGACTION_SYMNAME __sigaction14

// Compat with 9.0
extern unsigned struct_statvfs90_sz;

#endif // SANITIZER_NETBSD

#endif

0 comments on commit 84afd9c

Please sign in to comment.