Skip to content

Commit

Permalink
i#2833 user data: add syscall events with user data (#2879)
Browse files Browse the repository at this point in the history
Adds new versions of drmgr's pre and post syscall events that take in user data parameters.
Adds tests of the new functions.

Issue: #2833
  • Loading branch information
johnfxgalea authored and derekbruening committed Mar 15, 2018
1 parent 13e4f95 commit 3f2dd1d
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 11 deletions.
4 changes: 4 additions & 0 deletions api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ Further non-compatibility-affecting changes include:
physical cpus.
- Added #DR_DISALLOW_UNSAFE_STATIC and dr_disallow_unsafe_static_behavior()
for sanity checks to help support statically-linked clients.
- Added drmgr_register_pre_syscall_event_user_data() and
drmgr_unregister_pre_syscall_event_user_data() to enable passing of user data.
- Added drmgr_register_post_syscall_event_user_data() and
drmgr_unregister_post_syscall_event_user_data() to enable passing of user data.

**************************************************
<hr>
Expand Down
76 changes: 69 additions & 7 deletions ext/drmgr/drmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,21 @@ typedef struct _generic_event_entry_t {
void (*cb_user_data)(void *, void *);
} thread_cb;
void (*cls_cb)(void *, bool);
bool (*presys_cb)(void *, int);
void (*postsys_cb)(void *, int);
union {
bool (*cb_no_user_data)(void *, int);
bool (*cb_user_data)(void *, int, void *);
} presys_cb;
union {
void (*cb_no_user_data)(void *, int);
void (*cb_user_data)(void *, int, void *);
} postsys_cb;
union {
void (*cb_no_user_data)(void *, const module_data_t *, bool);
void (*cb_user_data)(void *, const module_data_t *, bool, void *user_data);
void (*cb_user_data)(void *, const module_data_t *, bool, void *);
} modload_cb;
union {
void (*cb_no_user_data)(void *, const module_data_t *);
void (*cb_user_data)(void *, const module_data_t *, void *user_data);
void (*cb_user_data)(void *, const module_data_t *, void *);
} modunload_cb;
void (*kernel_xfer_cb)(void *, const dr_kernel_xfer_info_t *);
#ifdef UNIX
Expand Down Expand Up @@ -1360,6 +1366,16 @@ drmgr_register_pre_syscall_event_ex(bool (*func)(void *drcontext, int sysnum),
(void (*)(void)) func, priority, false, NULL);
}

DR_EXPORT
bool
drmgr_register_pre_syscall_event_user_data(bool (*func)(void *drcontext, int sysnum,
void *user_data),
drmgr_priority_t *priority, void *user_data)
{
return drmgr_generic_event_add(&cblist_presys, presys_event_lock,
(void (*)(void)) func, priority, true, user_data);
}

DR_EXPORT
bool
drmgr_unregister_pre_syscall_event(bool (*func)(void *drcontext, int sysnum))
Expand All @@ -1368,6 +1384,15 @@ drmgr_unregister_pre_syscall_event(bool (*func)(void *drcontext, int sysnum))
(void (*)(void)) func);
}

DR_EXPORT
bool
drmgr_unregister_pre_syscall_event_user_data(bool (*func)(void *drcontext, int sysnum,
void *user_data))
{
return drmgr_generic_event_remove(&cblist_presys, presys_event_lock,
(void (*)(void)) func);
}

static bool
drmgr_presyscall_event(void *drcontext, int sysnum)
{
Expand All @@ -1383,7 +1408,18 @@ drmgr_presyscall_event(void *drcontext, int sysnum)
for (i = 0; i < iter.num; i++) {
if (!iter.cbs.generic[i].pri.valid)
continue;
execute = (*iter.cbs.generic[i].cb.presys_cb)(drcontext, sysnum) && execute;
bool is_using_user_data = iter.cbs.generic[i].is_using_user_data;
void *user_data = iter.cbs.generic[i].user_data;
if (is_using_user_data == false) {
execute = (*iter.cbs.generic[i].cb.presys_cb.cb_no_user_data)(drcontext,
sysnum)
&& execute;
} else {
execute = (*iter.cbs.generic[i].cb.presys_cb.cb_user_data)(drcontext,
sysnum,
user_data)
&& execute;
}
}

/* We used to track NtCallbackReturn for CLS (before DR provided the kernel xfer
Expand All @@ -1407,12 +1443,22 @@ drmgr_register_post_syscall_event(void (*func)(void *drcontext, int sysnum))
DR_EXPORT
bool
drmgr_register_post_syscall_event_ex(void (*func)(void *drcontext, int sysnum),
drmgr_priority_t *priority)
drmgr_priority_t *priority)
{
return drmgr_generic_event_add(&cblist_postsys, postsys_event_lock,
(void (*)(void)) func, priority, false, NULL);
}

DR_EXPORT
bool
drmgr_register_post_syscall_event_user_data(void (*func)(void *drcontext, int sysnum,
void *user_data),
drmgr_priority_t *priority, void *user_data)
{
return drmgr_generic_event_add(&cblist_postsys, postsys_event_lock,
(void (*)(void)) func, priority, true, user_data);
}

DR_EXPORT
bool
drmgr_unregister_post_syscall_event(void (*func)(void *drcontext, int sysnum))
Expand All @@ -1421,6 +1467,15 @@ drmgr_unregister_post_syscall_event(void (*func)(void *drcontext, int sysnum))
(void (*)(void)) func);
}

DR_EXPORT
bool
drmgr_unregister_post_syscall_event_user_data(void (*func)(void *drcontext, int sysnum,
void *user_data))
{
return drmgr_generic_event_remove(&cblist_postsys, postsys_event_lock,
(void (*)(void)) func);
}

static void
drmgr_postsyscall_event(void *drcontext, int sysnum)
{
Expand All @@ -1435,7 +1490,14 @@ drmgr_postsyscall_event(void *drcontext, int sysnum)
for (i = 0; i < iter.num; i++) {
if (!iter.cbs.generic[i].pri.valid)
continue;
(*iter.cbs.generic[i].cb.postsys_cb)(drcontext, sysnum);
bool is_using_user_data = iter.cbs.generic[i].is_using_user_data;
void *user_data = iter.cbs.generic[i].user_data;
if (is_using_user_data == false)
(*iter.cbs.generic[i].cb.postsys_cb.cb_no_user_data)(drcontext, sysnum);
else {
(*iter.cbs.generic[i].cb.postsys_cb.cb_user_data)(drcontext, sysnum,
user_data);
}
}
cblist_delete_local(drcontext, &iter, BUFFER_SIZE_ELEMENTS(local));
}
Expand Down
48 changes: 47 additions & 1 deletion ext/drmgr/drmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,19 @@ bool
drmgr_register_pre_syscall_event_ex(bool (*func)(void *drcontext, int sysnum),
drmgr_priority_t *priority);

DR_EXPORT
/**
* Registers a callback function for the pre-syscall event,
* ordered by \p priority. Allows for the passing of user data \p user_data
* which is available upon the execution of the callback.
* \return whether successful.
*/
bool
drmgr_register_pre_syscall_event_user_data(bool (*func)(void *drcontext, int sysnum,
void *user_data),
drmgr_priority_t *priority,
void *user_data);

DR_EXPORT
/**
* Unregister a callback function for the pre-syscall event.
Expand All @@ -868,6 +881,16 @@ DR_EXPORT
bool
drmgr_unregister_pre_syscall_event(bool (*func)(void *drcontext, int sysnum));

DR_EXPORT
/**
* Unregister a callback function, which takes user data, for the pre-syscall event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
drmgr_unregister_pre_syscall_event_user_data(bool (*func)(void *drcontext, int sysnum,
void *user_data));

DR_EXPORT
/**
* Registers a callback function for the post-syscall event, which
Expand All @@ -889,7 +912,20 @@ DR_EXPORT
*/
bool
drmgr_register_post_syscall_event_ex(void (*func)(void *drcontext, int sysnum),
drmgr_priority_t *priority);
drmgr_priority_t *priority);

DR_EXPORT
/**
* Registers a callback function for the post-syscall event,
* ordered by \p priority. Allows for the passing of user data \p user_data
* which is available upon the execution of the callback.
* \return whether successful.
*/
bool
drmgr_register_post_syscall_event_user_data(void (*func)(void *drcontext, int sysnum,
void *user_data),
drmgr_priority_t *priority,
void *user_data);

DR_EXPORT
/**
Expand All @@ -900,6 +936,16 @@ DR_EXPORT
bool
drmgr_unregister_post_syscall_event(void (*func)(void *drcontext, int sysnum));

DR_EXPORT
/**
* Unregister a callback function, which takes user data, for the post-syscall event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
drmgr_unregister_post_syscall_event_user_data(void (*func)(void *drcontext, int sysnum,
void *user_data));

DR_EXPORT
/**
* Registers a callback function for the module load event, which
Expand Down
97 changes: 94 additions & 3 deletions suite/tests/client-interface/drmgr-test.dll.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ static int cls_idx;
static thread_id_t main_thread;
static int cb_depth;
static volatile bool in_syscall_A;
static volatile bool in_syscall_A_user_data;
static volatile bool in_syscall_B;
static volatile bool in_syscall_B_user_data;
static volatile bool in_post_syscall_A;
static volatile bool in_post_syscall_A_user_data;
static volatile bool in_post_syscall_B;
static volatile bool in_post_syscall_B_user_data;
static volatile bool in_event_thread_init;
static volatile bool in_event_thread_init_ex;
static volatile bool in_event_thread_init_user_data;
Expand Down Expand Up @@ -97,9 +101,13 @@ static void event_mod_unload(void *drcontext, const module_data_t *mod,
void *user_data);
static bool event_filter_syscall(void *drcontext, int sysnum);
static bool event_pre_sys_A(void *drcontext, int sysnum);
static bool event_pre_sys_A_user_data(void *drcontext, int sysnum, void *user_data);
static bool event_pre_sys_B(void *drcontext, int sysnum);
static bool event_pre_sys_B_user_data(void *drcontext, int sysnum, void *user_data);
static void event_post_sys_A(void *drcontext, int sysnum);
static void event_post_sys_A_user_data(void *drcontext, int sysnum, void *user_data);
static void event_post_sys_B(void *drcontext, int sysnum);
static void event_post_sys_B_user_data(void *drcontext, int sysnum, void *user_data);
static dr_emit_flags_t event_bb_analysis(void *drcontext, void *tag, instrlist_t *bb,
bool for_trace, bool translating,
OUT void **user_data);
Expand Down Expand Up @@ -128,7 +136,11 @@ static dr_emit_flags_t one_time_bb_event(void *drcontext, void *tag, instrlist_t
bool for_trace, bool translating);
static void event_kernel_xfer(void *drcontext, const dr_kernel_xfer_info_t *info);

/* The following test values are arbitrary */

static const uintptr_t thread_user_data_test = 9090;
static const uintptr_t syscall_A_user_data_test = 7189;
static const uintptr_t syscall_B_user_data_test = 3218;
static const uintptr_t mod_user_data_test = 1070;

DR_EXPORT void
Expand All @@ -138,8 +150,15 @@ dr_init(client_id_t id)
drmgr_priority_t priority4 = {sizeof(priority), "drmgr-test4", NULL, NULL, 0};
drmgr_priority_t sys_pri_A = {sizeof(priority), "drmgr-test-A",
NULL, NULL, 10};
drmgr_priority_t sys_pri_A_user_data = {sizeof(priority),
"drmgr-test-A-usr-data-test",
"drmgr-test-A", NULL, 9};
drmgr_priority_t sys_pri_B = {sizeof(priority), "drmgr-test-B",
"drmgr-test-A", NULL, 5};
"drmgr-test-A-usr-data-test", NULL, 5};
drmgr_priority_t sys_pri_B_user_data = {sizeof(priority),
"drmgr-test-B-usr-data-test",
"drmgr-test-B",
NULL, 4};
drmgr_priority_t thread_init_null_user_data_pri = {sizeof(priority),
"drmgr-t-in-null-user-data-test",
NULL, NULL, -3};
Expand Down Expand Up @@ -217,10 +236,22 @@ dr_init(client_id_t id)

dr_register_filter_syscall_event(event_filter_syscall);
ok = drmgr_register_pre_syscall_event_ex(event_pre_sys_A, &sys_pri_A) &&
drmgr_register_pre_syscall_event_ex(event_pre_sys_B, &sys_pri_B);
drmgr_register_pre_syscall_event_user_data(event_pre_sys_A_user_data,
&sys_pri_A_user_data,
(void *) syscall_A_user_data_test) &&
drmgr_register_pre_syscall_event_ex(event_pre_sys_B, &sys_pri_B) &&
drmgr_register_pre_syscall_event_user_data(event_pre_sys_B_user_data,
&sys_pri_B_user_data,
(void *) syscall_B_user_data_test);
CHECK(ok, "drmgr register sys failed");
ok = drmgr_register_post_syscall_event_ex(event_post_sys_A, &sys_pri_A) &&
drmgr_register_post_syscall_event_ex(event_post_sys_B, &sys_pri_B);
drmgr_register_post_syscall_event_user_data(event_post_sys_A_user_data,
&sys_pri_A_user_data,
(void *) syscall_A_user_data_test) &&
drmgr_register_post_syscall_event_ex(event_post_sys_B, &sys_pri_B) &&
drmgr_register_post_syscall_event_user_data(event_post_sys_B_user_data,
&sys_pri_B_user_data,
(void *) syscall_B_user_data_test);
CHECK(ok, "drmgr register sys failed");

syslock = dr_mutex_create();
Expand Down Expand Up @@ -601,6 +632,22 @@ event_pre_sys_A(void *drcontext, int sysnum)
return true;
}

static bool
event_pre_sys_A_user_data(void *drcontext, int sysnum, void *user_data)
{
if (!in_syscall_A_user_data) {
dr_mutex_lock(syslock);
if (!in_syscall_A_user_data) {
dr_fprintf(STDERR, "in pre_sys_A_user_data\n");
in_syscall_A_user_data = true;
CHECK(user_data == (void *) syscall_A_user_data_test,
"incorrect user data pre-syscall A");
}
dr_mutex_unlock(syslock);
}
return true;
}

static bool
event_pre_sys_B(void *drcontext, int sysnum)
{
Expand All @@ -615,6 +662,22 @@ event_pre_sys_B(void *drcontext, int sysnum)
return true;
}

static bool
event_pre_sys_B_user_data(void *drcontext, int sysnum, void *user_data)
{
if (!in_syscall_B_user_data) {
dr_mutex_lock(syslock);
if (!in_syscall_B_user_data) {
dr_fprintf(STDERR, "in pre_sys_B_user_data\n");
in_syscall_B_user_data = true;
CHECK(user_data == (void *) syscall_B_user_data_test,
"incorrect user data pre-syscall B");
}
dr_mutex_unlock(syslock);
}
return true;
}

static void
event_post_sys_A(void *drcontext, int sysnum)
{
Expand All @@ -628,6 +691,21 @@ event_post_sys_A(void *drcontext, int sysnum)
}
}

static void
event_post_sys_A_user_data(void *drcontext, int sysnum, void *user_data)
{
if (!in_post_syscall_A_user_data) {
dr_mutex_lock(syslock);
if (!in_post_syscall_A_user_data) {
dr_fprintf(STDERR, "in post_sys_A_user_data\n");
in_post_syscall_A_user_data = true;
CHECK(user_data == (void *) syscall_A_user_data_test,
"incorrect user data post-syscall A");
}
dr_mutex_unlock(syslock);
}
}

static void
event_post_sys_B(void *drcontext, int sysnum)
{
Expand All @@ -641,6 +719,19 @@ event_post_sys_B(void *drcontext, int sysnum)
}
}

static void
event_post_sys_B_user_data(void *drcontext, int sysnum, void *user_data)
{
if (!in_post_syscall_B_user_data) {
dr_mutex_lock(syslock);
if (!in_post_syscall_B_user_data) {
dr_fprintf(STDERR, "in post_sys_B_user_data\n");
in_post_syscall_B_user_data = true;
}
dr_mutex_unlock(syslock);
}
}

/* test unregistering from inside an event */
static dr_emit_flags_t
one_time_bb_event(void *drcontext, void *tag, instrlist_t *bb,
Expand Down
Loading

0 comments on commit 3f2dd1d

Please sign in to comment.