Skip to content

Commit

Permalink
Add DEBUG_POISON_POINTER
Browse files Browse the repository at this point in the history
If you have a pointer which you know points to stale data, you can
fill it with junk so that dereference later will trap

Reviewed by:	kib
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D40946
  • Loading branch information
mjguzik committed Nov 28, 2023
1 parent c7368cc commit e1e8473
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
6 changes: 6 additions & 0 deletions sys/kern/vfs_bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ nbufp(unsigned i)
}

caddr_t __read_mostly unmapped_buf;
#ifdef INVARIANTS
caddr_t poisoned_buf = (void *)-1;
#endif

/* Used below and for softdep flushing threads in ufs/ffs/ffs_softdep.c */
struct proc *bufdaemonproc;
Expand Down Expand Up @@ -1211,6 +1214,9 @@ bufinit(void)
mtx_init(&bdirtylock, "dirty buf lock", NULL, MTX_DEF);

unmapped_buf = (caddr_t)kva_alloc(maxphys);
#ifdef INVARIANTS
poisoned_buf = unmapped_buf;
#endif

/* finally, initialize each buffer header and stick on empty q */
for (i = 0; i < nbuf; i++) {
Expand Down
31 changes: 31 additions & 0 deletions sys/sys/kassert.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,37 @@ extern const char *panicstr; /* panic message */
extern bool panicked;
#define KERNEL_PANICKED() __predict_false(panicked)

/*
* Trap accesses going through a pointer. Moreover if kasan is available trap
* reading the pointer itself.
*
* Sample usage: you have a struct with numerous fields and by API contract
* only some of them get populated, even if the implementation temporary writes
* to them. You can use DEBUG_POISON_POINTER so that the consumer which should
* no be looking at the field gets caught.
*
* DEBUG_POISON_POINTER(obj->ptr);
* ....
* if (obj->ptr != NULL) // traps with kasan, does not trap otherwise
* ....
* if (obj->ptr->field) // traps with and without kasan
*/
#ifdef INVARIANTS

#include <sys/asan.h>

extern caddr_t poisoned_buf;
#define DEBUG_POISON_POINTER_VALUE poisoned_buf

#define DEBUG_POISON_POINTER(x) ({ \
x = (void *)(DEBUG_POISON_POINTER_VALUE); \
kasan_mark(&x, 0, sizeof(x), KASAN_GENERIC_REDZONE); \
})

#else
#define DEBUG_POISON_POINTER(x)
#endif

#ifdef INVARIANTS /* The option is always available */
#define VNASSERT(exp, vp, msg) do { \
if (__predict_false(!(exp))) { \
Expand Down

0 comments on commit e1e8473

Please sign in to comment.