Added tests for the linear hook APIs
This commit is contained in:
parent
8085a44f47
commit
5256dbbccb
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: shl.mi,v 1.927 2021/09/24 13:13:07 christos Exp $
|
||||
# $NetBSD: shl.mi,v 1.928 2021/09/30 02:00:19 yamaguchi Exp $
|
||||
#
|
||||
# Note: Don't delete entries from here - mark them as "obsolete" instead,
|
||||
# unless otherwise stated below.
|
||||
|
@ -741,6 +741,9 @@
|
|||
./usr/lib/librumpkern_nv.so base-rump-shlib rump
|
||||
./usr/lib/librumpkern_nv.so.0 base-rump-shlib rump
|
||||
./usr/lib/librumpkern_nv.so.0.0 base-rump-shlib rump
|
||||
./usr/lib/librumpkern_simplehook_tester.so base-rump-shlib rump
|
||||
./usr/lib/librumpkern_simplehook_tester.so.0 base-rump-shlib rump
|
||||
./usr/lib/librumpkern_simplehook_tester.so.0.0 base-rump-shlib rump
|
||||
./usr/lib/librumpkern_sljit.so base-rump-shlib rump,sljit
|
||||
./usr/lib/librumpkern_sljit.so.0 base-rump-shlib rump,sljit
|
||||
./usr/lib/librumpkern_sljit.so.0.0 base-rump-shlib rump,sljit
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: mi,v 1.2394 2021/09/30 01:26:07 yamaguchi Exp $
|
||||
# $NetBSD: mi,v 1.2395 2021/09/30 02:00:19 yamaguchi Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
./etc/mtree/set.comp comp-sys-root
|
||||
|
@ -4062,6 +4062,8 @@
|
|||
./usr/lib/librumpkern_ksem_p.a comp-obsolete obsolete
|
||||
./usr/lib/librumpkern_nv.a comp-c-lib rump
|
||||
./usr/lib/librumpkern_nv_p.a comp-c-proflib rump,profile
|
||||
./usr/lib/librumpkern_simplehook_tester.a comp-c-lib rump
|
||||
./usr/lib/librumpkern_simplehook_tester_p.a comp-c-proflib rump,profile
|
||||
./usr/lib/librumpkern_sljit.a comp-c-lib rump,sljit
|
||||
./usr/lib/librumpkern_sljit_p.a comp-c-proflib rump,sljit,profile
|
||||
./usr/lib/librumpkern_solaris.a comp-c-lib rump,zfs
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: mi,v 1.361 2021/09/19 15:51:28 thorpej Exp $
|
||||
# $NetBSD: mi,v 1.362 2021/09/30 02:00:19 yamaguchi Exp $
|
||||
./etc/mtree/set.debug comp-sys-root
|
||||
./usr/lib comp-sys-usr compatdir
|
||||
./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile
|
||||
|
@ -208,6 +208,7 @@
|
|||
./usr/lib/librumpkern_crypto_g.a comp-c-debuglib debuglib,rump
|
||||
./usr/lib/librumpkern_ksem_g.a comp-obsolete obsolete,compatfile
|
||||
./usr/lib/librumpkern_nv_g.a comp-c-debuglib debuglib,rump
|
||||
./usr/lib/librumpkern_simplehook_tester_g.a comp-c-debuglib debuglib,rump
|
||||
./usr/lib/librumpkern_sljit_g.a comp-c-debuglib debuglib,rump,sljit
|
||||
./usr/lib/librumpkern_solaris_g.a comp-c-debuglib debuglib,rump,zfs
|
||||
./usr/lib/librumpkern_sysproxy_g.a comp-c-debuglib debuglib,rump
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: shl.mi,v 1.284 2021/09/24 13:13:07 christos Exp $
|
||||
# $NetBSD: shl.mi,v 1.285 2021/09/30 02:00:19 yamaguchi Exp $
|
||||
./usr/lib/libbfd_g.a comp-c-debuglib debuglib,compatfile,binutils
|
||||
./usr/libdata/debug/lib base-sys-usr debug,dynamicroot,compatdir
|
||||
./usr/libdata/debug/lib/libavl.so.0.0.debug comp-zfs-debug debug,dynamicroot,zfs
|
||||
|
@ -261,6 +261,7 @@
|
|||
./usr/libdata/debug/usr/lib/librumpkern_crypto.so.0.0.debug comp-rump-debug debug,rump
|
||||
./usr/libdata/debug/usr/lib/librumpkern_ksem.so.0.0.debug comp-obsolete obsolete,compatfile
|
||||
./usr/libdata/debug/usr/lib/librumpkern_nv.so.0.0.debug comp-rump-debug debug,rump
|
||||
./usr/libdata/debug/usr/lib/librumpkern_simplehook_tester.so.0.0.debug comp-rump-debug debug,rump
|
||||
./usr/libdata/debug/usr/lib/librumpkern_sljit.so.0.0.debug comp-rump-debug debug,rump,sljit
|
||||
./usr/libdata/debug/usr/lib/librumpkern_solaris.so.0.0.debug comp-rump-debug debug,rump,zfs
|
||||
./usr/libdata/debug/usr/lib/librumpkern_sysproxy.so.0.0.debug comp-rump-debug debug,rump
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: mi,v 1.1130 2021/09/26 03:17:59 rillig Exp $
|
||||
# $NetBSD: mi,v 1.1131 2021/09/30 02:00:19 yamaguchi Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
|
@ -2237,6 +2237,7 @@
|
|||
./usr/tests/kernel/t_pty tests-kernel-tests compattestfile,atf
|
||||
./usr/tests/kernel/t_rnd tests-kernel-tests atf,rump
|
||||
./usr/tests/kernel/t_sigaction tests-obsolete obsolete
|
||||
./usr/tests/kernel/t_simplehook tests-kernel-tests atf,rump
|
||||
./usr/tests/kernel/t_subr_prf tests-kernel-tests compattestfile,atf
|
||||
./usr/tests/kernel/t_sysctl tests-kernel-tests compattestfile,atf
|
||||
./usr/tests/kernel/t_sysv tests-kernel-tests compattestfile,atf
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# $NetBSD: Makefile.rumpkerncomp,v 1.13 2018/09/22 12:54:34 rmind Exp $
|
||||
# $NetBSD: Makefile.rumpkerncomp,v 1.14 2021/09/30 02:00:20 yamaguchi Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
RUMPKERNCOMPS= crypto nv sysproxy tty z
|
||||
RUMPKERNCOMPS= crypto nv sysproxy tty z simplehook_tester
|
||||
RUMPSYSEMUS= sys_cygwin sys_linux sys_sunos
|
||||
|
||||
.if make(rumpdescribe)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
|
||||
LIB= rumpkern_simplehook_tester
|
||||
COMMENT=Tester for simplehook
|
||||
|
||||
SRCS= simplehook_tester.c
|
||||
|
||||
.ifdef RUMP_DEBUG
|
||||
CPPFLAGS.simplehook_tester.c+= -DSIMPLEHOOK_TESTER_DEBUG
|
||||
.endif
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
.include <bsd.klinks.mk>
|
|
@ -0,0 +1,724 @@
|
|||
/* $NetBSD: simplehook_tester.c,v 1.1 2021/09/30 02:00:20 yamaguchi Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2021 Internet Initiative Japan Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: simplehook_tester.c,v 1.1 2021/09/30 02:00:20 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/hook.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/workqueue.h>
|
||||
|
||||
#ifdef SIMPLEHOOK_TESTER_DEBUG
|
||||
#define HK_DPRINTF(a) printf a
|
||||
#else
|
||||
#define HK_DPRINTF(a) __nothing
|
||||
#endif
|
||||
|
||||
MODULE(MODULE_CLASS_MISC, simplehook_tester, NULL);
|
||||
extern int simplehook_tester_init(void);
|
||||
struct tester_context;
|
||||
|
||||
struct tester_hook {
|
||||
struct tester_context *th_ctx;
|
||||
khook_t *th_hook;
|
||||
size_t th_idx;
|
||||
int th_count;
|
||||
bool th_stopping;
|
||||
bool th_stopped;
|
||||
bool th_disestablish;
|
||||
};
|
||||
|
||||
static struct tester_context {
|
||||
kmutex_t ctx_mutex;
|
||||
kcondvar_t ctx_cv;
|
||||
struct sysctllog *ctx_sysctllog;
|
||||
struct workqueue *ctx_wq;
|
||||
struct work ctx_wk;
|
||||
bool ctx_wk_enqueued;
|
||||
bool ctx_wk_waiting;
|
||||
|
||||
khook_list_t *ctx_hooks;
|
||||
struct tester_hook ctx_hook[2];
|
||||
|
||||
khook_t *ctx_nbhook;
|
||||
} tester_ctx;
|
||||
|
||||
static int
|
||||
simplehook_tester_created(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
int error, val;
|
||||
size_t i;
|
||||
|
||||
node = *rnode;
|
||||
ctx = node.sysctl_data;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = ctx->ctx_hooks != NULL ? 1 : 0;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
if (val != 0 && val != 1)
|
||||
return EINVAL;
|
||||
|
||||
error = 0;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
if (val == 1) {
|
||||
if (ctx->ctx_hooks != NULL) {
|
||||
error = EEXIST;
|
||||
} else {
|
||||
HK_DPRINTF(("[%s, %d]: create hook list\n",
|
||||
__func__, __LINE__));
|
||||
ctx->ctx_hooks = simplehook_create(IPL_NONE,
|
||||
"tester hooks");
|
||||
KASSERT(ctx->ctx_hooks != NULL);
|
||||
}
|
||||
} else {
|
||||
if (ctx->ctx_hooks == NULL) {
|
||||
error = ENXIO;
|
||||
} else if (ctx->ctx_wk_waiting) {
|
||||
error = EBUSY;
|
||||
} else {
|
||||
ctx->ctx_wk_waiting = true;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
workqueue_wait(ctx->ctx_wq, &ctx->ctx_wk);
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
ctx->ctx_wk_waiting = false;
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: destroy hook list\n",
|
||||
__func__, __LINE__));
|
||||
simplehook_destroy(ctx->ctx_hooks);
|
||||
ctx->ctx_hooks = NULL;
|
||||
ctx->ctx_nbhook = NULL;
|
||||
for (i = 0; i < __arraycount(ctx->ctx_hook); i++) {
|
||||
ctx->ctx_hook[i].th_hook = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
simplehook_tester_work(struct work *wk, void *xctx)
|
||||
{
|
||||
struct tester_context *ctx;
|
||||
|
||||
ctx = xctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
ctx->ctx_wk_enqueued = false;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
simplehook_dohooks(ctx->ctx_hooks);
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_dohooks(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
int error, val;
|
||||
|
||||
node = *rnode;
|
||||
ctx = node.sysctl_data;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = ctx->ctx_wk_enqueued ? 1 : 0;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
if (val != 0 && val != 1)
|
||||
return EINVAL;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
if (val == 1) {
|
||||
if (ctx->ctx_wk_enqueued) {
|
||||
error = EEXIST;
|
||||
} else if (ctx->ctx_wk_waiting) {
|
||||
error = EBUSY;
|
||||
} else if (ctx->ctx_hooks == NULL) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
HK_DPRINTF(("[%s, %d]: dohook\n", __func__, __LINE__));
|
||||
ctx->ctx_wk_enqueued = true;
|
||||
workqueue_enqueue(ctx->ctx_wq,
|
||||
&ctx->ctx_wk, NULL);
|
||||
}
|
||||
} else {
|
||||
if (ctx->ctx_wk_waiting) {
|
||||
error = EBUSY;
|
||||
} else {
|
||||
ctx->ctx_wk_waiting = true;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
workqueue_wait(ctx->ctx_wq, &ctx->ctx_wk);
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
ctx->ctx_wk_waiting = false;
|
||||
}
|
||||
}
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
simplehook_tester_hook(void *xth)
|
||||
{
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
|
||||
th = xth;
|
||||
ctx = th->th_ctx;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: hook%zu called\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
|
||||
th->th_stopped = false;
|
||||
|
||||
while (th->th_stopping) {
|
||||
HK_DPRINTF(("[%s, %d]: hook%zu stopping\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
th->th_stopped = true;
|
||||
cv_wait(&ctx->ctx_cv, &ctx->ctx_mutex);
|
||||
}
|
||||
|
||||
if (th->th_stopped) {
|
||||
HK_DPRINTF(("[%s, %d]: hook%zu restart\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
th->th_stopped = false;
|
||||
}
|
||||
|
||||
th->th_count++;
|
||||
|
||||
if (th->th_disestablish && th->th_hook != NULL) {
|
||||
HK_DPRINTF(("[%s, %d]: disestablish runing hook%zu\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
simplehook_disestablish(ctx->ctx_hooks,
|
||||
th->th_hook, &ctx->ctx_mutex);
|
||||
th->th_hook = NULL;
|
||||
}
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: hook%zu exit\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
simplehook_tester_hook_nb(void *xctx)
|
||||
{
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: non-block hook called\n",
|
||||
__func__, __LINE__));
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: sleep 1 sec\n",
|
||||
__func__, __LINE__));
|
||||
kpause("smplhk_nb", true, 1 * hz, NULL);
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: non-block hook exit\n",
|
||||
__func__, __LINE__));
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_established(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
int val, error;
|
||||
|
||||
node = *rnode;
|
||||
th = node.sysctl_data;
|
||||
ctx = th->th_ctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = th->th_hook == NULL ? 0 : 1;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
error = 0;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
|
||||
if (val == 1) {
|
||||
if (th->th_hook != NULL) {
|
||||
error = EEXIST;
|
||||
} else {
|
||||
th->th_hook = simplehook_establish(ctx->ctx_hooks,
|
||||
simplehook_tester_hook, th);
|
||||
KASSERT(th->th_hook != NULL);
|
||||
HK_DPRINTF(("[%s, %d]: established hook%zu (%p)\n",
|
||||
__func__, __LINE__, th->th_idx, th->th_hook));
|
||||
}
|
||||
} else {
|
||||
if (th->th_hook == NULL) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
bool stopped = false;
|
||||
if (th->th_stopping) {
|
||||
HK_DPRINTF(("[%s, %d]: stopping = false\n",
|
||||
__func__, __LINE__));
|
||||
th->th_stopping = false;
|
||||
cv_broadcast(&ctx->ctx_cv);
|
||||
stopped = true;
|
||||
}
|
||||
HK_DPRINTF(("[%s, %d]: disestablish hook%zu (%p)\n",
|
||||
__func__, __LINE__, th->th_idx, th->th_hook));
|
||||
simplehook_disestablish(ctx->ctx_hooks,
|
||||
th->th_hook, &ctx->ctx_mutex);
|
||||
th->th_hook = NULL;
|
||||
if (stopped) {
|
||||
HK_DPRINTF(("[%s, %d]: disestablished hook%zu\n",
|
||||
__func__, __LINE__, th->th_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_established_nb(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
int val, error;
|
||||
|
||||
node = *rnode;
|
||||
ctx = node.sysctl_data;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = ctx->ctx_nbhook == NULL ? 0 : 1;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
error = 0;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
|
||||
if (val == 1) {
|
||||
if (ctx->ctx_nbhook != NULL) {
|
||||
error = EEXIST;
|
||||
} else {
|
||||
ctx->ctx_nbhook = simplehook_establish(ctx->ctx_hooks,
|
||||
simplehook_tester_hook_nb, ctx);
|
||||
KASSERT(ctx->ctx_nbhook != NULL);
|
||||
HK_DPRINTF(("[%s, %d]: established nbhook (%p)\n",
|
||||
__func__, __LINE__, ctx->ctx_nbhook));
|
||||
}
|
||||
} else {
|
||||
if (ctx->ctx_nbhook == NULL) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
HK_DPRINTF(("[%s, %d]: disestablish nbhook (%p)\n",
|
||||
__func__, __LINE__, ctx->ctx_nbhook));
|
||||
simplehook_disestablish(ctx->ctx_hooks,
|
||||
ctx->ctx_nbhook, NULL);
|
||||
ctx->ctx_nbhook = NULL;
|
||||
HK_DPRINTF(("[%s, %d]: disestablished\n",
|
||||
__func__, __LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_stopping(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
int error;
|
||||
bool val;
|
||||
|
||||
node = *rnode;
|
||||
th = node.sysctl_data;
|
||||
ctx = th->th_ctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = th->th_stopping;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
error = 0;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
if (val == true && !th->th_stopping) {
|
||||
th->th_stopping = true;
|
||||
} else if (val == false && th->th_stopping) {
|
||||
th->th_stopping = false;
|
||||
cv_broadcast(&ctx->ctx_cv);
|
||||
}
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_stopped(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
bool val;
|
||||
|
||||
node = *rnode;
|
||||
th = node.sysctl_data;
|
||||
ctx = th->th_ctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = th->th_stopped;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
return sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_disestablish(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
int error;
|
||||
bool val;
|
||||
|
||||
node = *rnode;
|
||||
th = node.sysctl_data;
|
||||
ctx = th->th_ctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = th->th_disestablish;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
if (val != 0 && val != 1)
|
||||
return EINVAL;
|
||||
|
||||
error = 0;
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
if (val == true && !th->th_disestablish) {
|
||||
th->th_disestablish = true;
|
||||
} else if (val == false && th->th_disestablish) {
|
||||
th->th_disestablish = false;
|
||||
}
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_count(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct sysctlnode node;
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
int error, val;
|
||||
|
||||
node = *rnode;
|
||||
th = node.sysctl_data;
|
||||
ctx = th->th_ctx;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
val = th->th_count;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
node.sysctl_data = &val;
|
||||
node.sysctl_size = sizeof(val);
|
||||
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
th->th_count = val;
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_create_sysctl(struct tester_context *ctx)
|
||||
{
|
||||
struct sysctllog **log;
|
||||
const struct sysctlnode *rnode, *cnode;
|
||||
void *ptr;
|
||||
char buf[32];
|
||||
int error;
|
||||
size_t i;
|
||||
|
||||
log = &ctx->ctx_sysctllog;
|
||||
ptr = (void *)ctx;
|
||||
|
||||
error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "simplehook_tester",
|
||||
SYSCTL_DESCR("simplehook testing interface"),
|
||||
NULL, 0, NULL, 0, CTL_KERN, CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &rnode, &cnode,
|
||||
CTLFLAG_PERMANENT, CTLTYPE_NODE, "hook_list",
|
||||
SYSCTL_DESCR("hook list"), NULL, 0, NULL, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
||||
"created", SYSCTL_DESCR("create and destroy hook list"),
|
||||
simplehook_tester_created, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
||||
"dohooks", SYSCTL_DESCR("do hooks"),
|
||||
simplehook_tester_dohooks, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &rnode, &cnode,
|
||||
CTLFLAG_PERMANENT, CTLTYPE_NODE, "nbhook",
|
||||
SYSCTL_DESCR("non-blocking hook"), NULL, 0, NULL, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "established",
|
||||
SYSCTL_DESCR("establish and disestablish hook"),
|
||||
simplehook_tester_established_nb,
|
||||
0, ptr, 0, CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
for (i = 0; i < __arraycount(ctx->ctx_hook); i++) {
|
||||
snprintf(buf, sizeof(buf), "hook%zu", i);
|
||||
ptr = (void *)&ctx->ctx_hook[i];
|
||||
|
||||
error = sysctl_createv(log, 0, &rnode, &cnode,
|
||||
CTLFLAG_PERMANENT, CTLTYPE_NODE, buf,
|
||||
SYSCTL_DESCR("hook information"), NULL, 0, NULL, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "established",
|
||||
SYSCTL_DESCR("establish and disestablish hook"),
|
||||
simplehook_tester_established,
|
||||
0, ptr, 0, CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_BOOL, "stopping",
|
||||
SYSCTL_DESCR("stopping at beginning of the hook"),
|
||||
simplehook_tester_stopping, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READONLY,
|
||||
CTLTYPE_BOOL, "stopped",
|
||||
SYSCTL_DESCR("the hook is stopped"),
|
||||
simplehook_tester_stopped, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_BOOL,
|
||||
"disestablish_in_hook",
|
||||
SYSCTL_DESCR("disestablish this hook in it"),
|
||||
simplehook_tester_disestablish, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
|
||||
error = sysctl_createv(log, 0, &cnode, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "count",
|
||||
SYSCTL_DESCR("the number of calls of the hook"),
|
||||
simplehook_tester_count, 0, ptr, 0,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
HK_DPRINTF(("[%s, %d]: created sysctls\n", __func__, __LINE__));
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
sysctl_teardown(log);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
simplehook_tester_init_ctx(struct tester_context *ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
mutex_init(&ctx->ctx_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
workqueue_create(&ctx->ctx_wq, "shook_tester_wq",
|
||||
simplehook_tester_work, ctx, PRI_NONE, IPL_NONE, WQ_MPSAFE);
|
||||
cv_init(&ctx->ctx_cv, "simplehook_tester_cv");
|
||||
|
||||
for (i = 0; i < __arraycount(ctx->ctx_hook); i++) {
|
||||
ctx->ctx_hook[i].th_ctx = ctx;
|
||||
ctx->ctx_hook[i].th_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
simplehook_tester_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
simplehook_tester_init_ctx(&tester_ctx);
|
||||
error = simplehook_tester_create_sysctl(&tester_ctx);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_fini(void)
|
||||
{
|
||||
struct tester_context *ctx;
|
||||
struct tester_hook *th;
|
||||
khook_list_t *hooks;
|
||||
size_t i;
|
||||
|
||||
ctx = &tester_ctx;
|
||||
|
||||
sysctl_teardown(&ctx->ctx_sysctllog);
|
||||
|
||||
mutex_enter(&ctx->ctx_mutex);
|
||||
|
||||
hooks = ctx->ctx_hooks;
|
||||
ctx->ctx_hooks = NULL;
|
||||
ctx->ctx_wk_waiting = true;
|
||||
|
||||
for (i = 0; i < __arraycount(ctx->ctx_hook); i++) {
|
||||
th = &ctx->ctx_hook[i];
|
||||
th->th_stopping = false;
|
||||
}
|
||||
cv_broadcast(&ctx->ctx_cv);
|
||||
|
||||
mutex_exit(&ctx->ctx_mutex);
|
||||
|
||||
workqueue_wait(ctx->ctx_wq, &ctx->ctx_wk);
|
||||
|
||||
workqueue_destroy(ctx->ctx_wq);
|
||||
if (hooks != NULL)
|
||||
simplehook_destroy(hooks);
|
||||
cv_destroy(&ctx->ctx_cv);
|
||||
mutex_destroy(&ctx->ctx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
simplehook_tester_modcmd(modcmd_t cmd, void *arg __unused)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
error = simplehook_tester_init();
|
||||
break;
|
||||
|
||||
case MODULE_CMD_FINI:
|
||||
error = simplehook_tester_fini();
|
||||
break;
|
||||
|
||||
case MODULE_CMD_STAT:
|
||||
default:
|
||||
error = ENOTTY;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.68 2020/07/01 13:49:26 jruoho Exp $
|
||||
# $NetBSD: Makefile,v 1.69 2021/09/30 02:00:20 yamaguchi Exp $
|
||||
|
||||
NOMAN= # defined
|
||||
|
||||
|
@ -32,6 +32,7 @@ TESTS_SH+= t_origin
|
|||
TESTS_SH+= t_procpath
|
||||
TESTS_SH+= t_fexecve
|
||||
TESTS_SH+= t_fpufork
|
||||
TESTS_SH+= t_simplehook
|
||||
|
||||
BINDIR= ${TESTSDIR}
|
||||
PROGS= h_fexecve
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
# $NetBSD: t_simplehook.sh,v 1.1 2021/09/30 02:00:20 yamaguchi Exp $
|
||||
#
|
||||
# Copyright (c) 2021 Internet Initiative Japan Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
DEBUG=${DEBUG:-false}
|
||||
SOCK=unix://commsock
|
||||
HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so \
|
||||
RUMPHIJACK=path=/rump,socket=all:nolocal,sysctl=yes"
|
||||
|
||||
atf_sysctl_rd()
|
||||
{
|
||||
local sysctl_key=$1
|
||||
local expected=$2
|
||||
|
||||
atf_check -s exit:0 -o match:"$expected" \
|
||||
rump.sysctl -n $sysctl_key
|
||||
}
|
||||
|
||||
atf_sysctl_wr()
|
||||
{
|
||||
local sysctl_key=$1
|
||||
local value=$2
|
||||
|
||||
atf_check -s exit:0 -o ignore rump.sysctl -w $sysctl_key=$value
|
||||
}
|
||||
|
||||
atf_sysctl_wait()
|
||||
{
|
||||
local sysctl_key=$1
|
||||
local expected=$2
|
||||
local n=10
|
||||
local i
|
||||
local v
|
||||
|
||||
for i in $(seq $n); do
|
||||
v=$(rump.sysctl -n $sysctl_key)
|
||||
if [ x"$v" = x"$expected" ]; then
|
||||
return
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
atf_fail "Couldn't get the value for $n seconds."
|
||||
}
|
||||
|
||||
atf_test_case simplehook_basic cleanup
|
||||
simplehook_basic_head()
|
||||
{
|
||||
|
||||
atf_set "descr" "tests for basically functions of simplehook"
|
||||
atf_set "require.progs" "rump_server"
|
||||
}
|
||||
|
||||
|
||||
simplehook_basic_body()
|
||||
{
|
||||
local key_hklist="kern.simplehook_tester.hook_list"
|
||||
local key_hk0="kern.simplehook_tester.hook0"
|
||||
local key_hk1="kern.simplehook_tester.hook1"
|
||||
|
||||
rump_server -lrumpkern_simplehook_tester $SOCK
|
||||
|
||||
export RUMP_SERVER=$SOCK
|
||||
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
atf_check -s exit:0 -o ignore rump.sysctl -e kern.simplehook_tester
|
||||
|
||||
# create and destroy
|
||||
atf_sysctl_rd ${key_hklist}.created '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
|
||||
# establish one hook
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk0}.count '0'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
atf_sysctl_rd ${key_hk0}.count '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
|
||||
# establish two hooks
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk1}.established '1'
|
||||
atf_sysctl_wr ${key_hk0}.count '0'
|
||||
atf_sysctl_wr ${key_hk1}.count '0'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
atf_sysctl_rd ${key_hk0}.count '1'
|
||||
atf_sysctl_rd ${key_hk1}.count '1'
|
||||
|
||||
atf_sysctl_wr ${key_hk0}.established '0'
|
||||
atf_sysctl_wr ${key_hk1}.established '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
}
|
||||
|
||||
simplehook_basic_cleanup()
|
||||
{
|
||||
export RUMP_SERVER=$SOCK
|
||||
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
$DEBUG && $HIJACKING dmesg
|
||||
rump.halt
|
||||
}
|
||||
|
||||
atf_test_case simplehook_disestablish cleanup
|
||||
simplehook_disestablish_head()
|
||||
{
|
||||
|
||||
atf_set "descr" "tests for disestablish of simplehook"
|
||||
atf_set "require.progs" "rump_server"
|
||||
}
|
||||
|
||||
simplehook_disestablish_body()
|
||||
{
|
||||
local key_hklist="kern.simplehook_tester.hook_list"
|
||||
local key_hk0="kern.simplehook_tester.hook0"
|
||||
local key_hk1="kern.simplehook_tester.hook1"
|
||||
|
||||
rump_server -lrumpkern_simplehook_tester $SOCK
|
||||
|
||||
export RUMP_SERVER=$SOCK
|
||||
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
atf_check -s exit:0 -o ignore rump.sysctl -e kern.simplehook_tester
|
||||
|
||||
#
|
||||
# disestablish on the running hook
|
||||
#
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk0}.disestablish_in_hook '1'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
|
||||
# already disestablished
|
||||
atf_sysctl_rd ${key_hk0}.established '0'
|
||||
atf_sysctl_wr ${key_hk0}.disestablish_in_hook '0'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
|
||||
#
|
||||
# disestablish called hook while doing other hook
|
||||
#
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk1}.established '1'
|
||||
|
||||
atf_sysctl_wr ${key_hk0}.count '0'
|
||||
atf_sysctl_wr ${key_hk1}.count '0'
|
||||
atf_sysctl_wr ${key_hk0}.stopping '1'
|
||||
|
||||
# calls hook1 -> hook0
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
|
||||
# stop in hook0
|
||||
atf_sysctl_wait ${key_hk0}.stopped '1'
|
||||
|
||||
atf_sysctl_rd ${key_hk1}.count '1'
|
||||
atf_sysctl_wr ${key_hk1}.established '0'
|
||||
|
||||
# wakeup hook0
|
||||
atf_sysctl_wr ${key_hk0}.stopping '0'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
|
||||
atf_sysctl_wr ${key_hk0}.established '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
|
||||
#
|
||||
# disestablish a hook in running hook list
|
||||
#
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk1}.established '1'
|
||||
|
||||
atf_sysctl_wr ${key_hk0}.count '0'
|
||||
atf_sysctl_wr ${key_hk1}.count '0'
|
||||
atf_sysctl_wr ${key_hk1}.stopping '1'
|
||||
|
||||
# calls hook1 -> hook0
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
|
||||
# stop in hook1
|
||||
atf_sysctl_wait ${key_hk1}.stopped '1'
|
||||
|
||||
atf_sysctl_wr ${key_hk0}.established '0'
|
||||
|
||||
# wakeup hook1
|
||||
atf_sysctl_wr ${key_hk1}.stopping '0'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
|
||||
# hook0 is not called
|
||||
atf_sysctl_rd ${key_hk0}.count '0'
|
||||
|
||||
atf_sysctl_wr ${key_hk1}.established '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
|
||||
#
|
||||
# disestablish the running hook
|
||||
#
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '1'
|
||||
atf_sysctl_wr ${key_hk0}.stopping '1'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
|
||||
atf_sysctl_wait ${key_hk0}.stopped '1'
|
||||
atf_sysctl_wr ${key_hk0}.established '0'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
}
|
||||
|
||||
simplehook_disestablish_cleanup()
|
||||
{
|
||||
export RUMP_SERVER=$SOCK
|
||||
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
$DEBUG && $HIJACKING dmesg
|
||||
rump.halt
|
||||
}
|
||||
|
||||
atf_test_case simplehook_nolock cleanup
|
||||
simplehook_nolock_head()
|
||||
{
|
||||
|
||||
atf_set "descr" "tests for hook that does not use lock in it"
|
||||
atf_set "require.progs" "rump_server"
|
||||
}
|
||||
|
||||
simplehook_nolock_body()
|
||||
{
|
||||
local key_hklist="kern.simplehook_tester.hook_list"
|
||||
local key_hk="kern.simplehook_tester.nbhook"
|
||||
|
||||
rump_server -lrumpkern_simplehook_tester $SOCK
|
||||
|
||||
export RUMP_SERVER=$SOCK
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
atf_check -s exit:0 -o ignore rump.sysctl -e kern.simplehook_tester
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.created '1'
|
||||
atf_sysctl_wr ${key_hk}.established '1'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '1'
|
||||
atf_sysctl_wr ${key_hk}.established '0'
|
||||
atf_sysctl_wr ${key_hklist}.dohooks '0'
|
||||
|
||||
atf_sysctl_wr ${key_hklist}.created '0'
|
||||
}
|
||||
|
||||
simplehook_nolock_cleanup()
|
||||
{
|
||||
export RUMP_SERVER=$SOCK
|
||||
|
||||
$DEBUG && rump.sysctl -e kern.simplehook_tester
|
||||
$DEBUG && $HIJACKING dmesg
|
||||
rump.halt
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
|
||||
atf_add_test_case simplehook_basic
|
||||
atf_add_test_case simplehook_disestablish
|
||||
atf_add_test_case simplehook_nolock
|
||||
}
|
Loading…
Reference in New Issue