โฌข DragonFlyBSD Kernel Audit
DF-4952 / fxshim.h
โ† back to finding โ†“ download raw
/*
 * fxshim.h โ€” userland shim so the REAL sys/dev/sound/pcm/feeder_{format,
 * matrix,volume,mixer}.c files compile verbatim outside the kernel, for the
 * GLM 5.3 pass-2 FXROUND follow-up audit (DF-4846..DF-4849).
 *
 * Real headers are included (pcm.h, intpcm.h, g711.h โ€” copied verbatim into
 * the build dir); kernel-only glue is provided here, following the pattern
 * of findings/poc/DF-4710/eqshim.h.
 */
#ifndef FXSHIM_H
#define FXSHIM_H

#include <sys/types.h>
#include <sys/param.h>		/* LONG_BIT */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <errno.h>

/* ---- real PCM sample machinery, verbatim ---- */
#include "pcm.h"
#include "g711.h"
#include "intpcm.h"

/* ---- AFMT_* values: real sys/sys/soundcard.h + sound.h macro layer ---- */
#include <sys/soundcard.h>	/* AFMT_S16_LE .. numeric values */

#define AFMT_ENCODING_MASK	0xf00fffff
#define AFMT_CHANNEL_MASK	0x01f00000
#define AFMT_CHANNEL_SHIFT	20
#define AFMT_EXTCHANNEL_MASK	0x0e000000
#define AFMT_EXTCHANNEL_SHIFT	25
#define AFMT_ENCODING(v)	((v) & AFMT_ENCODING_MASK)
#define AFMT_EXTCHANNEL(v)	(((v) & AFMT_EXTCHANNEL_MASK) >>	\
				 AFMT_EXTCHANNEL_SHIFT)
#define AFMT_CHANNEL(v)		(((v) & AFMT_CHANNEL_MASK) >>		\
				 AFMT_CHANNEL_SHIFT)
#define AFMT_BIT(v)		(((v) & 0x0000f000) ? 32 :		\
				 (((v) & 0x000f0000) ? 24 :	\
				 (((v) & 0x000000f0) ? 16 : 8)))
#define AFMT_BPS(v)		(AFMT_BIT(v) >> 3)
#define AFMT_ALIGN(v)		(AFMT_BPS(v) * AFMT_CHANNEL(v))
#define SND_FORMAT(f, c, e)	(AFMT_ENCODING(f) |			\
				 (((c) << AFMT_CHANNEL_SHIFT) &		\
				 AFMT_CHANNEL_MASK) |			\
				 (((e) << AFMT_EXTCHANNEL_SHIFT) &	\
				 AFMT_EXTCHANNEL_MASK))

#define SND_CHN_MIN	1
#define SND_CHN_MAX	8

/* native-endian aliases (sound.h:252-256; LE guest) */
#define AFMT_U8_NE	AFMT_U8
#define AFMT_S8_NE	AFMT_S8
#ifndef AFMT_S16_NE
#define AFMT_S16_NE	AFMT_S16_LE
#endif
#ifndef AFMT_U16_NE
#define AFMT_U16_NE	AFMT_U16_LE
#endif
#ifndef AFMT_S24_NE
#define AFMT_S24_NE	AFMT_S24_LE
#endif
#ifndef AFMT_U24_NE
#define AFMT_U24_NE	AFMT_U24_LE
#endif
#ifndef AFMT_S32_NE
#define AFMT_S32_NE	AFMT_S32_LE
#endif
#ifndef AFMT_U32_NE
#define AFMT_U32_NE	AFMT_U32_LE
#endif

/* feeder.h set() enums used by the files under test */
enum { FEEDFORMAT_CHANNELS };
enum { FEEDMIXER_CHANNELS };
enum {
	FEEDVOLUME_CLASS, FEEDVOLUME_CHANNELS, FEEDVOLUME_STATE,
	FEEDVOLUME_ENABLE, FEEDVOLUME_BYPASS
};

/* ---- real matrix machinery, verbatim (no kernel deps) ---- */
#include "matrix.h"

/* struct pcmchan_matrix (verbatim from channel.h:37-45; needs matrix.h) */
struct pcmchan_matrix {
	int id;
	uint8_t channels, ext;
	struct {
		int type;
		uint32_t members;
	} map[SND_CHN_T_MAX + 1];
	uint32_t mask;
	int8_t offset[SND_CHN_T_MAX];
};

#include "matrix_map.h"

/* ---- kernel bits ---- */
#define kprintf printf
#define __unused
#ifndef M_DEVBUF
#define M_DEVBUF	1
#endif
#define M_WAITOK	0
#define M_ZERO		0

extern int fx_canary_hit;	/* set when a guard byte is found clobbered */

#define FX_GUARD_FRONT	256
#define FX_GUARD_REAR	(64 * 1024)	/* fat rear: absorb bounded overruns so we log, not segv */

static inline void *
kmalloc(size_t sz, int m, int fl)
{
	unsigned char *base;
	size_t i;

	(void)m;
	base = malloc(sz + FX_GUARD_FRONT + FX_GUARD_REAR);
	if (base == NULL)
		return (NULL);
	if (fl & M_ZERO)
		memset(base + FX_GUARD_FRONT, 0, sz);
	for (i = 0; i < FX_GUARD_FRONT; i++)
		base[i] = (unsigned char)0xCB;
	for (i = 0; i < FX_GUARD_REAR; i++)
		base[sz + FX_GUARD_FRONT + i] = (unsigned char)0xCA;
	return (base + FX_GUARD_FRONT);
}

static inline void
kfree(void *p, int m)
{
	(void)m;
	if (p != NULL)
		free((unsigned char *)p - FX_GUARD_FRONT);
}

/* ---- feeder infrastructure (feeder.h / feeder_if.h semantics) ---- */
enum {
	FEEDER_ROOT, FEEDER_FORMAT, FEEDER_MIXER, FEEDER_RATE, FEEDER_EQ,
	FEEDER_VOLUME, FEEDER_MATRIX, FEEDER_LAST,
};

struct pcm_feederdesc {
	u_int32_t type;
	u_int32_t in, out;
	u_int32_t flags;
	int idx;
};

struct feeder_class {
	const char		*name;
	void			*methods;
	int			size;
	struct pcm_feederdesc	*desc;
	void			*data;
};

typedef struct kobj_method { int dummy; } kobj_method_t;
#define KOBJMETHOD(m, f)	{ 0 }
#define KOBJMETHOD_END		{ 0 }
#define FEEDER_DECLARE(feeder, pdata)					\
	static struct feeder_class feeder ## _class = {			\
		.name = #feeder, .methods = NULL, .size = 0,		\
		.desc = NULL, .data = pdata,				\
	}

struct pcm_channel;		/* opaque per-file */

struct pcm_feeder {
	struct feeder_class	*class;
	struct pcm_feederdesc	*desc;
	struct pcm_feederdesc desc_static;
	void			*data;
	struct pcm_feeder	*source, *parent;
};

/* the harness source feeder; each driver implements this.
 * fx_arena_base/fx_arena_limit bracket the whole guarded allocation (front
 * guard + window + rear guard): writes that land IN a guard are permitted
 * (that is the detection mechanism โ€” fx_win_check scans the guards);
 * only truly wild pointers (underflow re-arm, dst+4GiB) are skipped and
 * recorded via fx_audit_wild. */
extern uint64_t fx_src_ready;		/* bytes the source has available */
extern uint32_t fx_src_give;		/* 0 = min(asked, ready), else force */
extern uint64_t fx_audit_max_off;	/* farthest offset written vs win base */
extern uint64_t fx_audit_max_ask;	/* largest count ever asked of source */
extern uint64_t fx_audit_given;		/* total bytes returned by source */
extern int fx_audit_asks;		/* number of source asks per feed */
extern int fx_audit_wild;		/* source was asked to write out of range */
extern uintptr_t fx_win_base, fx_win_limit;
extern uintptr_t fx_arena_base, fx_arena_limit;

static inline int
fx_in_range(uint8_t *b, uint32_t n)
{
	return ((uintptr_t)b >= fx_arena_base && (uintptr_t)b + n <= fx_arena_limit);
}

uint32_t fx_source_feed_impl(struct pcm_feeder *f, struct pcm_channel *c,
    uint8_t *b, uint32_t count, void *source);

#define FEEDER_FEED(f, c, b, cnt, src)	fx_source_feed_impl((f), (c), (b), (cnt), (src))

/* driver-provided SET dispatch (needed by mixer init) */
extern int fx_feeder_set(struct pcm_feeder *f, int what, int value);
#define FEEDER_SET(f, w, v)	fx_feeder_set((f), (w), (v))

/* cross-file prototypes (verbatim from feeder.h:151-163) */
int feeder_matrix_default_id(uint32_t);
struct pcmchan_matrix *feeder_matrix_default_channel_map(uint32_t);
uint32_t feeder_matrix_default_format(uint32_t);
int feeder_matrix_format_id(uint32_t);
struct pcmchan_matrix *feeder_matrix_format_map(uint32_t);
struct pcmchan_matrix *feeder_matrix_id_map(int);
int feeder_matrix_setup(struct pcm_feeder *, struct pcmchan_matrix *,
    struct pcmchan_matrix *);
int feeder_volume_apply_matrix(struct pcm_feeder *, struct pcmchan_matrix *);

/* the real generated fast-division macros โ€” exact kernel arithmetic */
#define SND_USE_FXDIV
#include "snd_fxdiv_gen.h"

/* window allocation with guards: exactly `sz` usable bytes at *win */
extern uint8_t *fx_win_alloc(uint32_t sz);
extern int fx_win_check(uint8_t *win, uint32_t sz, const char **where);
extern void fx_win_free(uint8_t *win);

#endif /* FXSHIM_H */