1356843Sdim//===-- sanitizer_common_interceptors_netbsd_compat.inc ---------*- C++ -*-===//
2356843Sdim//
3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4356843Sdim// See https://llvm.org/LICENSE.txt for license information.
5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6356843Sdim//
7356843Sdim//===----------------------------------------------------------------------===//
8356843Sdim//
9356843Sdim// Common function interceptors for tools like AddressSanitizer,
10356843Sdim// ThreadSanitizer, MemorySanitizer, etc.
11356843Sdim//
12356843Sdim// Interceptors for NetBSD old function calls that have been versioned.
13356843Sdim//
14356843Sdim// NetBSD minimal version supported 9.0.
15356843Sdim// NetBSD current version supported 9.99.26.
16356843Sdim//
17356843Sdim//===----------------------------------------------------------------------===//
18356843Sdim
19356843Sdim#if SANITIZER_NETBSD
20356843Sdim
21356843Sdim// First undef all mangled symbols.
22356843Sdim// Next, define compat interceptors.
23356843Sdim// Finally, undef INIT_ and redefine it.
24356843Sdim// This allows to avoid preprocessor issues.
25356843Sdim
26356843Sdim#undef fstatvfs
27356843Sdim#undef fstatvfs1
28356843Sdim#undef getmntinfo
29356843Sdim#undef getvfsstat
30356843Sdim#undef statvfs
31356843Sdim#undef statvfs1
32356843Sdim
33356843SdimINTERCEPTOR(int, statvfs, char *path, void *buf) {
34356843Sdim  void *ctx;
35356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
36356843Sdim  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
37356843Sdim  // FIXME: under ASan the call below may write to freed memory and corrupt
38356843Sdim  // its metadata. See
39356843Sdim  // https://github.com/google/sanitizers/issues/321.
40356843Sdim  int res = REAL(statvfs)(path, buf);
41356843Sdim  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
42356843Sdim  return res;
43356843Sdim}
44356843Sdim
45356843SdimINTERCEPTOR(int, fstatvfs, int fd, void *buf) {
46356843Sdim  void *ctx;
47356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
48356843Sdim  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
49356843Sdim  // FIXME: under ASan the call below may write to freed memory and corrupt
50356843Sdim  // its metadata. See
51356843Sdim  // https://github.com/google/sanitizers/issues/321.
52356843Sdim  int res = REAL(fstatvfs)(fd, buf);
53356843Sdim  if (!res) {
54356843Sdim    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
55356843Sdim    if (fd >= 0)
56356843Sdim      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
57356843Sdim  }
58356843Sdim  return res;
59356843Sdim}
60356843Sdim
61356843Sdim#undef INIT_STATVFS
62356843Sdim#define INIT_STATVFS \
63356843Sdim  COMMON_INTERCEPT_FUNCTION(statvfs); \
64356843Sdim  COMMON_INTERCEPT_FUNCTION(fstatvfs); \
65356843Sdim  COMMON_INTERCEPT_FUNCTION(__statvfs90); \
66356843Sdim  COMMON_INTERCEPT_FUNCTION(__fstatvfs90)
67356843Sdim
68356843SdimINTERCEPTOR(int, __getmntinfo13, void **mntbufp, int flags) {
69356843Sdim  void *ctx;
70356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, __getmntinfo13, mntbufp, flags);
71356843Sdim  int cnt = REAL(__getmntinfo13)(mntbufp, flags);
72356843Sdim  if (cnt > 0 && mntbufp) {
73356843Sdim    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
74356843Sdim    if (*mntbufp)
75356843Sdim      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs90_sz);
76356843Sdim  }
77356843Sdim  return cnt;
78356843Sdim}
79356843Sdim
80356843Sdim#undef INIT_GETMNTINFO
81356843Sdim#define INIT_GETMNTINFO \
82356843Sdim  COMMON_INTERCEPT_FUNCTION(__getmntinfo13); \
83356843Sdim  COMMON_INTERCEPT_FUNCTION(__getmntinfo90)
84356843Sdim
85356843SdimINTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
86356843Sdim  void *ctx;
87356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
88356843Sdim  int ret = REAL(getvfsstat)(buf, bufsize, flags);
89356843Sdim  if (buf && ret > 0)
90356843Sdim    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs90_sz);
91356843Sdim  return ret;
92356843Sdim}
93356843Sdim
94356843Sdim#undef INIT_GETVFSSTAT
95356843Sdim#define INIT_GETVFSSTAT \
96356843Sdim  COMMON_INTERCEPT_FUNCTION(getvfsstat); \
97356843Sdim  COMMON_INTERCEPT_FUNCTION(__getvfsstat90)
98356843Sdim
99356843SdimINTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
100356843Sdim  void *ctx;
101356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
102356843Sdim  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
103356843Sdim  int res = REAL(statvfs1)(path, buf, flags);
104356843Sdim  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
105356843Sdim  return res;
106356843Sdim}
107356843Sdim
108356843SdimINTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
109356843Sdim  void *ctx;
110356843Sdim  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
111356843Sdim  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
112356843Sdim  int res = REAL(fstatvfs1)(fd, buf, flags);
113356843Sdim  if (!res) {
114356843Sdim    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
115356843Sdim    if (fd >= 0)
116356843Sdim      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
117356843Sdim  }
118356843Sdim  return res;
119356843Sdim}
120356843Sdim
121356843Sdim#undef INIT_STATVFS1
122356843Sdim#define INIT_STATVFS1 \
123356843Sdim  COMMON_INTERCEPT_FUNCTION(statvfs1); \
124356843Sdim  COMMON_INTERCEPT_FUNCTION(fstatvfs1); \
125356843Sdim  COMMON_INTERCEPT_FUNCTION(__statvfs190); \
126356843Sdim  COMMON_INTERCEPT_FUNCTION(__fstatvfs190)
127356843Sdim
128356843Sdim#endif
129