⬢ DragonFlyBSD Kernel Audit
DF-4711 / dbg4.c
← back to finding ↓ download raw
/*
 * dbg4.c — deliberate demonstration of the missing SND_CHN_MAX guard in
 * feed_eq_init (feeder_eq.c:362): the real, unmodified feeder_eq.c compiled
 * in userland; a >8-channel format flows unchecked into info->channels while
 * the tone state arrays are [SND_CHN_MAX=8] (feeder_eq.c:109-115).
 * Build at -O0 for deterministic field placement.
 */
#include "eqshim.h"
#include "feeder_eq.c"
static uint32_t src_remaining, src_pattern = 4, src_partial;
static uint32_t prng_state = 1;
static uint32_t prng(void){prng_state^=prng_state<<13;prng_state^=prng_state>>17;prng_state^=prng_state<<5;return prng_state;}
static void fill_pattern(uint8_t *b, uint32_t n){uint32_t i;int32_t v;for(i=0;i+4<=n;i+=4){v=(int32_t)prng();memcpy(b+i,&v,4);}for(;i<n;i++)b[i]=(uint8_t)prng();}
uint32_t eqshim_source_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, uint32_t count, void *src){uint32_t g=count;(void)f;(void)c;(void)src;if(g>src_remaining)g=src_remaining;fill_pattern(b,g);src_remaining-=g;return g;}
int eqshim_set(struct pcm_feeder *f,int w,int v){return feed_eq_set(f,w,v);}
int main(int argc, char **argv) {
	struct pcm_feeder f; struct pcm_feederdesc d;
	struct feed_eq_info *info;
	uint32_t ch = argc > 1 ? (uint32_t)atoi(argv[1]) : 16;
	memset(&f,0,sizeof(f)); memset(&d,0,sizeof(d));
	d.type = FEEDER_EQ; d.in = d.out = SND_FORMAT(AFMT_S16_LE, ch, 0);
	f.desc = &d;
	int r = feed_eq_init(&f);
	info = f.data;
	printf("init=%d channels=%u align=%u treble.gain=%d bass.gain=%d\n",
	    r, info->channels, info->align, info->treble.gain, info->bass.gain);
	uint8_t *buf = malloc(65536);
	int tg0 = info->treble.gain;
	src_remaining = 16384;
	uint32_t got = feed_eq_feed(&f, NULL, buf, 16384, NULL);
	kfree_canary_check(info, sizeof(*info));
	printf("got=%u treble.gain=%d (was %d) bass.gain=%d canary=%d(%s)\n",
	    got, info->treble.gain, tg0, info->bass.gain,
	    eqshim_canary_hit, eqshim_canary_where);
	return 0;
}