forked from OSchip/llvm-project
[Sanitizers] intercept FreeBSD procctl
Reviewers: vitalybuka, emaster Reviewed-By: viatelybuka Differential Revision: https://reviews.llvm.org/D127069
This commit is contained in:
parent
6eb0f8e285
commit
c06ef17359
|
@ -10349,6 +10349,42 @@ INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
|
||||||
#define INIT_SIGALTSTACK
|
#define INIT_SIGALTSTACK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SANITIZER_INTERCEPT_PROCCTL
|
||||||
|
INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
|
||||||
|
void *ctx;
|
||||||
|
COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
|
||||||
|
static const int PROC_REAP_ACQUIRE = 2;
|
||||||
|
static const int PROC_REAP_RELEASE = 3;
|
||||||
|
static const int PROC_REAP_STATUS = 4;
|
||||||
|
static const int PROC_REAP_GETPIDS = 5;
|
||||||
|
static const int PROC_REAP_KILL = 6;
|
||||||
|
if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
|
||||||
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
|
||||||
|
} else {
|
||||||
|
// reap_acquire/reap_release bears no arguments.
|
||||||
|
if (cmd > PROC_REAP_RELEASE) {
|
||||||
|
unsigned int reapsz;
|
||||||
|
switch (cmd) {
|
||||||
|
case PROC_REAP_STATUS:
|
||||||
|
reapsz = struct_procctl_reaper_status_sz;
|
||||||
|
break;
|
||||||
|
case PROC_REAP_GETPIDS:
|
||||||
|
reapsz = struct_procctl_reaper_pids_sz;
|
||||||
|
break;
|
||||||
|
case PROC_REAP_KILL:
|
||||||
|
reapsz = struct_procctl_reaper_kill_sz;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return REAL(procctl)(idtype, id, cmd, data);
|
||||||
|
}
|
||||||
|
#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
|
||||||
|
#else
|
||||||
|
#define INIT_PROCCTL
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_INTERCEPT_UNAME
|
#if SANITIZER_INTERCEPT_UNAME
|
||||||
INTERCEPTOR(int, uname, struct utsname *utsname) {
|
INTERCEPTOR(int, uname, struct utsname *utsname) {
|
||||||
#if SANITIZER_LINUX
|
#if SANITIZER_LINUX
|
||||||
|
@ -10708,6 +10744,7 @@ static void InitializeCommonInterceptors() {
|
||||||
INIT_QSORT_R;
|
INIT_QSORT_R;
|
||||||
INIT_BSEARCH;
|
INIT_BSEARCH;
|
||||||
INIT_SIGALTSTACK;
|
INIT_SIGALTSTACK;
|
||||||
|
INIT_PROCCTL
|
||||||
INIT_UNAME;
|
INIT_UNAME;
|
||||||
INIT___XUNAME;
|
INIT___XUNAME;
|
||||||
|
|
||||||
|
|
|
@ -901,6 +901,10 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
|
||||||
return k_set->sig[idx] & ((uptr)1 << bit);
|
return k_set->sig[idx] & ((uptr)1 << bit);
|
||||||
}
|
}
|
||||||
#elif SANITIZER_FREEBSD
|
#elif SANITIZER_FREEBSD
|
||||||
|
uptr internal_procctl(int type, int id, int cmd, void *data) {
|
||||||
|
return internal_syscall(SYSCALL(procctl), type, id, cmd, data);
|
||||||
|
}
|
||||||
|
|
||||||
void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
|
void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
|
||||||
sigset_t *rset = reinterpret_cast<sigset_t *>(set);
|
sigset_t *rset = reinterpret_cast<sigset_t *>(set);
|
||||||
sigdelset(rset, signum);
|
sigdelset(rset, signum);
|
||||||
|
@ -2186,7 +2190,8 @@ void CheckASLR() {
|
||||||
}
|
}
|
||||||
#elif SANITIZER_FREEBSD
|
#elif SANITIZER_FREEBSD
|
||||||
int aslr_status;
|
int aslr_status;
|
||||||
if (UNLIKELY(procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status) == -1)) {
|
int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status);
|
||||||
|
if (UNLIKELY(r == -1)) {
|
||||||
// We're making things less 'dramatic' here since
|
// We're making things less 'dramatic' here since
|
||||||
// the cmd is not necessarily guaranteed to be here
|
// the cmd is not necessarily guaranteed to be here
|
||||||
// just yet regarding FreeBSD release
|
// just yet regarding FreeBSD release
|
||||||
|
|
|
@ -82,6 +82,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
||||||
#endif
|
#endif
|
||||||
int internal_uname(struct utsname *buf);
|
int internal_uname(struct utsname *buf);
|
||||||
#elif SANITIZER_FREEBSD
|
#elif SANITIZER_FREEBSD
|
||||||
|
uptr internal_procctl(int type, int id, int cmd, void *data);
|
||||||
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
|
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
|
||||||
#elif SANITIZER_NETBSD
|
#elif SANITIZER_NETBSD
|
||||||
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
|
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
|
||||||
|
|
|
@ -593,6 +593,7 @@
|
||||||
#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
|
#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
|
||||||
#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
|
#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
|
||||||
#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
|
#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
|
||||||
|
#define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD
|
||||||
|
|
||||||
// This macro gives a way for downstream users to override the above
|
// This macro gives a way for downstream users to override the above
|
||||||
// interceptor macros irrespective of the platform they are on. They have
|
// interceptor macros irrespective of the platform they are on. They have
|
||||||
|
|
|
@ -205,6 +205,10 @@ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
|
||||||
unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
|
unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
|
||||||
unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
|
unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
|
||||||
unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
|
unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
|
||||||
|
unsigned struct_procctl_reaper_status_sz = sizeof(struct __sanitizer_procctl_reaper_status);
|
||||||
|
unsigned struct_procctl_reaper_pidinfo_sz = sizeof(struct __sanitizer_procctl_reaper_pidinfo);
|
||||||
|
unsigned struct_procctl_reaper_pids_sz = sizeof(struct __sanitizer_procctl_reaper_pids);
|
||||||
|
unsigned struct_procctl_reaper_kill_sz = sizeof(struct __sanitizer_procctl_reaper_kill);
|
||||||
const unsigned long __sanitizer_bufsiz = BUFSIZ;
|
const unsigned long __sanitizer_bufsiz = BUFSIZ;
|
||||||
|
|
||||||
const unsigned IOCTL_NOT_PRESENT = 0;
|
const unsigned IOCTL_NOT_PRESENT = 0;
|
||||||
|
|
|
@ -424,6 +424,38 @@ struct __sanitizer__ttyent {
|
||||||
char *ty_group;
|
char *ty_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// procctl reaper data for PROCCTL_REAPER flags
|
||||||
|
struct __sanitizer_procctl_reaper_status {
|
||||||
|
unsigned int rs_flags;
|
||||||
|
unsigned int rs_children;
|
||||||
|
unsigned int rs_descendants;
|
||||||
|
pid_t rs_reaper;
|
||||||
|
pid_t rs_pid;
|
||||||
|
unsigned int rs_pad0[15];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __sanitizer_procctl_reaper_pidinfo {
|
||||||
|
pid_t pi_pid;
|
||||||
|
pid_t pi_subtree;
|
||||||
|
unsigned int pi_flags;
|
||||||
|
unsigned int pi_pad0[15];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __sanitizer_procctl_reaper_pids {
|
||||||
|
unsigned int rp_count;
|
||||||
|
unsigned int rp_pad0[15];
|
||||||
|
struct __sanitize_procctl_reapper_pidinfo *rp_pids;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __sanitizer_procctl_reaper_kill {
|
||||||
|
int rk_sig;
|
||||||
|
unsigned int rk_flags;
|
||||||
|
pid_t rk_subtree;
|
||||||
|
unsigned int rk_killed;
|
||||||
|
pid_t rk_fpid;
|
||||||
|
unsigned int rk_pad[15];
|
||||||
|
};
|
||||||
|
|
||||||
# define IOC_NRBITS 8
|
# define IOC_NRBITS 8
|
||||||
# define IOC_TYPEBITS 8
|
# define IOC_TYPEBITS 8
|
||||||
# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
|
# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
|
||||||
|
@ -480,6 +512,11 @@ extern unsigned struct_ppp_stats_sz;
|
||||||
extern unsigned struct_sioc_sg_req_sz;
|
extern unsigned struct_sioc_sg_req_sz;
|
||||||
extern unsigned struct_sioc_vif_req_sz;
|
extern unsigned struct_sioc_vif_req_sz;
|
||||||
|
|
||||||
|
extern unsigned struct_procctl_reaper_status_sz;
|
||||||
|
extern unsigned struct_procctl_reaper_pidinfo_sz;
|
||||||
|
extern unsigned struct_procctl_reaper_pids_sz;
|
||||||
|
extern unsigned struct_procctl_reaper_kill_sz;
|
||||||
|
|
||||||
// ioctl request identifiers
|
// ioctl request identifiers
|
||||||
|
|
||||||
// A special value to mark ioctls that are not present on the target platform,
|
// A special value to mark ioctls that are not present on the target platform,
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// RUN: %clangxx %s -o %t && %run %t %p
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/procctl.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
struct procctl_reaper_status status = {0};
|
||||||
|
int res, aslr;
|
||||||
|
res = procctl(P_PID, getpid(), PROC_REAP_STATUS, &status);
|
||||||
|
if (res < 0) {
|
||||||
|
assert(errno == EPERM);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(status.rs_flags >= REAPER_STATUS_OWNED);
|
||||||
|
|
||||||
|
res = procctl(P_PID, getpid(), PROC_ASLR_STATUS, &aslr);
|
||||||
|
if (res < 0) {
|
||||||
|
assert(errno == EPERM);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(aslr >= PROC_ASLR_FORCE_ENABLE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue