⬢ DragonFlyBSD Kernel Audit
DF-5674 / race_probe.c
← back to finding ↓ download raw
/* DF-5674 probe: counts keysym frees that run WITHOUT the tree mutex */
#define _GNU_SOURCE
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <dlfcn.h>
#include <pthread.h>
#include <libprop/proplib.h>

#if defined(WITH_PROBE)
extern int DF5674_unlocked_frees;
#endif

#define NKEYS     96
#define NREMOVERS 3
#define NALLOCERS 2
#define ITERS     400000

static char keys[NKEYS][24];
static prop_string_t shared_str;

static void
segv(int sig, siginfo_t *si, void *uc)
{
	ucontext_t *u = uc;
	Dl_info d;
	void *rip = (void *)(uintptr_t)u->uc_mcontext.mc_rip;
	if (dladdr(rip, &d) != 0 && d.dli_sname != NULL)
		fprintf(stderr, "SIGSEGV in %s addr=%p\n", d.dli_sname, si->si_addr);
	else
		fprintf(stderr, "SIGSEGV addr=%p\n", si->si_addr);
#if defined(WITH_PROBE)
	fprintf(stderr, "DF5674_unlocked_frees=%d\n", DF5674_unlocked_frees);
#endif
	_exit(139);
}

static void *
remover(void *arg)
{
	int it, i;
	for (it = 0; it < ITERS; it++) {
		prop_dictionary_t d = prop_dictionary_create();
		if (d == NULL) break;
		for (i = 0; i < NKEYS; i++)
			prop_dictionary_set(d, keys[i], shared_str);
		for (i = 0; i < NKEYS; i++)
			prop_dictionary_remove(d, keys[i]);
		prop_object_release(d);
	}
	return NULL;
}

static void *
allocer(void *arg)
{
	int it, i;
	for (it = 0; it < ITERS; it++) {
		prop_dictionary_t d = prop_dictionary_create();
		if (d == NULL) break;
		for (i = 0; i < NKEYS; i++)
			prop_dictionary_set(d, keys[i], shared_str);
		prop_object_release(d);
	}
	return NULL;
}

int
main(void)
{
	pthread_t thr[NREMOVERS + NALLOCERS];
	struct sigaction sa;
	int i;

	memset(&sa, 0, sizeof(sa));
	sa.sa_sigaction = segv;
	sa.sa_flags = SA_SIGINFO;
	sigaction(SIGSEGV, &sa, NULL);
	sigaction(SIGBUS, &sa, NULL);

	for (i = 0; i < NKEYS; i++)
		snprintf(keys[i], sizeof(keys[i]), "key%04d", i * 7 % NKEYS);
	shared_str = prop_string_create_cstring("value");
	{
		prop_dictionary_t d = prop_dictionary_create();
		for (i = 0; i < NKEYS; i++)
			prop_dictionary_set(d, keys[i], shared_str);
		prop_object_release(d);
	}
	for (i = 0; i < NREMOVERS; i++)
		pthread_create(&thr[i], NULL, remover, NULL);
	for (i = 0; i < NALLOCERS; i++)
		pthread_create(&thr[NREMOVERS + i], NULL, allocer, NULL);
	for (i = 0; i < NREMOVERS + NALLOCERS; i++)
		pthread_join(thr[i], NULL);
	printf("survived\n");
#if defined(WITH_PROBE)
	printf("DF5674_unlocked_frees=%d\n", DF5674_unlocked_frees);
#endif
	return 0;
}