Skip to content

Commit

Permalink
Add interceptors for the sysctl(3) API family from NetBSD
Browse files Browse the repository at this point in the history
Summary:
Add new interceptors for:

 - sysctl
 - sysctlbyname
 - sysctlgetmibinfo
 - sysctlnametomib
 - asysctl
 - asysctlbyname

Cover the API with a new test file TestCases/NetBSD/sysctl.cc.

Reviewers: joerg, vitalybuka

Reviewed By: vitalybuka

Subscribers: devnexen, kubamracek, llvm-commits, mgorny, #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D54076

llvm-svn: 348228
  • Loading branch information
krytarowski committed Dec 4, 2018
1 parent 175d2b8 commit 5b8d585
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 0 deletions.
131 changes: 131 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7523,6 +7523,136 @@ INTERCEPTOR(int, fts_close, void *ftsp) {
#define INIT_FTS
#endif

#if SANITIZER_INTERCEPT_SYSCTL
INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
newlen);
if (name)
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
if (oldlenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
if (newp && newlen)
COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
if (!res) {
if (oldlenp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
if (oldp)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
}
}
return res;
}

INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
void *newp, SIZE_T newlen) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
newlen);
if (sname)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
if (oldlenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
if (newp && newlen)
COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
if (!res) {
if (oldlenp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
if (oldp)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
}
}
return res;
}

INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
int v) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
csz, rnode, v);
if (sname)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
if (namelenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
if (csz)
COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
// Skip rnode, it's rarely used and not trivial to sanitize
// It's also used mostly internally
int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
if (!res) {
if (namelenp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
if (name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
}
if (csz) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
if (cname)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
}
}
return res;
}

INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
SIZE_T *namelenp) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
if (sname)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
if (namelenp)
COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
int res = REAL(sysctlnametomib)(sname, name, namelenp);
if (!res) {
if (namelenp) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
if (name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
}
}
return res;
}

INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
if (name)
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
void *res = REAL(asysctl)(name, namelen, len);
if (res && len) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
}
return res;
}

INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
if (sname)
COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
void *res = REAL(asysctlbyname)(sname, len);
if (res && len) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
}
return res;
}
#define INIT_SYSCTL \
COMMON_INTERCEPT_FUNCTION(sysctl); \
COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo); \
COMMON_INTERCEPT_FUNCTION(sysctlnametomib); \
COMMON_INTERCEPT_FUNCTION(asysctl); \
COMMON_INTERCEPT_FUNCTION(asysctlbyname);
#else
#define INIT_SYSCTL
#endif

static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
Expand Down Expand Up @@ -7782,6 +7912,7 @@ static void InitializeCommonInterceptors() {
INIT_GETVFSSTAT;
INIT_REGEX;
INIT_FTS;
INIT_SYSCTL;

INIT___PRINTF_CHK;
}
Original file line number Diff line number Diff line change
Expand Up @@ -523,5 +523,6 @@
#define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD
#define SANITIZER_INTERCEPT_REGEX SI_NETBSD
#define SANITIZER_INTERCEPT_FTS SI_NETBSD
#define SANITIZER_INTERCEPT_SYSCTL SI_NETBSD

#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
101 changes: 101 additions & 0 deletions compiler-rt/test/sanitizer_common/TestCases/NetBSD/sysctl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s

#include <sys/param.h>
#include <sys/types.h>

#include <sys/sysctl.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void test_sysctl() {
char buf[100];
size_t len = sizeof(buf);
int mib[] = {CTL_KERN, KERN_OSTYPE};
int rv = sysctl(mib, __arraycount(mib), buf, &len, NULL, 0);
assert(!rv);

printf("sysctl: '%s' size: '%zu'\n", buf, len);
}

void test_sysctlbyname() {
char buf[100];
size_t len = sizeof(buf);
int mib[] = {CTL_KERN, KERN_OSTYPE};
int rv = sysctlbyname("kern.ostype", buf, &len, NULL, 0);
assert(!rv);

printf("sysctlbyname: '%s' size: '%zu'\n", buf, len);
}

void test_sysctlgetmibinfo() {
int mib[CTL_MAXNAME];
unsigned int mib_len = __arraycount(mib);
int rv = sysctlgetmibinfo("kern.ostype", &mib[0], &mib_len, NULL, NULL, NULL,
SYSCTL_VERSION);
assert(!rv);

char buf[100];
size_t len = sizeof(buf);
rv = sysctl(mib, mib_len, buf, &len, NULL, 0);
assert(!rv);

printf("sysctlgetmibinfo: '%s' size: '%zu'\n", buf, len);
}

void test_sysctlnametomib() {
int mib[CTL_MAXNAME];
size_t mib_len = __arraycount(mib);
int rv = sysctlnametomib("kern.ostype", &mib[0], &mib_len);
assert(!rv);

char buf[100];
size_t len = sizeof(buf);
rv = sysctl(mib, mib_len, buf, &len, NULL, 0);
assert(!rv);

printf("sysctlnametomib: '%s' size: '%zu'\n", buf, len);
}

void test_asysctl() {
int mib[] = {CTL_KERN, KERN_OSTYPE};
size_t len;
char *buf = (char *)asysctl(mib, __arraycount(mib), &len);
assert(buf);

printf("asysctl: '%s' size: '%zu'\n", buf, len);

free(buf);
}

void test_asysctlbyname() {
size_t len;
char *buf = (char *)asysctlbyname("kern.ostype", &len);
assert(buf);

printf("asysctlbyname: '%s' size: '%zu'\n", buf, len);

free(buf);
}

int main(void) {
printf("sysctl\n");

test_sysctl();
test_sysctlbyname();
test_sysctlgetmibinfo();
test_sysctlnametomib();
test_asysctl();
test_asysctlbyname();

// CHECK: sysctl
// CHECK: sysctl: '{{.*}}' size: '{{.*}}'
// CHECK: sysctlbyname: '{{.*}}' size: '{{.*}}'
// CHECK: sysctlgetmibinfo: '{{.*}}' size: '{{.*}}'
// CHECK: sysctlnametomib: '{{.*}}' size: '{{.*}}'
// CHECK: asysctl: '{{.*}}' size: '{{.*}}'
// CHECK: asysctlbyname: '{{.*}}' size: '{{.*}}'

return 0;
}

0 comments on commit 5b8d585

Please sign in to comment.