Page MenuHomeFreeBSD

Add DEBUG_POISON_POINTER
ClosedPublic

Authored by mjg on Jul 8 2023, 11:40 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, May 2, 2:11 PM
Unknown Object (File)
Thu, May 2, 2:10 PM
Unknown Object (File)
Thu, May 2, 2:10 PM
Unknown Object (File)
Thu, May 2, 2:10 PM
Unknown Object (File)
Thu, May 2, 2:10 PM
Unknown Object (File)
Thu, May 2, 2:09 PM
Unknown Object (File)
Thu, May 2, 11:08 AM
Unknown Object (File)
Sun, Apr 28, 10:31 PM
Subscribers

Details

Summary
commit 6ccee9c10b06465f44da97e4b10d57200ff87e69 (HEAD -> poison_ptr4)
Author: Mateusz Guzik <mjg@FreeBSD.org>
Date:   Tue Nov 28 15:23:25 2023 +0000

    Add DEBUG_POISON_POINTER
    
    If you have a pointer which you know points to stale data, you can
    fill it with junk so that dereference later will trap.g
    
    Reviewed by:
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D40946

Sample usage is nameidata, which leaks entirely to the caller and where use of stale pointers is very much a possibility. For example accessing ni_dvp when WANTPARENT nor LOCKPARENT were specified.

I don't care about the name or the specific implementation, feel free to roll your own. What I do care about is the functionality.

Test Plan

verified that this:

diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 1f62cf3e6652..8eb63eb3dc37 100644

  • a/sys/kern/vfs_lookup.c

+++ b/sys/kern/vfs_lookup.c
@@ -1240,7 +1240,13 @@ vfs_lookup(struct nameidata *ndp)
#endif

ndp->ni_dvp = dp;
ndp->ni_vp = NULL;
ASSERT_VOP_LOCKED(dp, "lookup");

+
+ DEBUG_POISON_POINTER(dp);
+ printf("%s: read off dp %p\n", func, dp);
+ printf("%s: deref dp->v_mount %p\n", func, dp->v_mount);
+

/*
 * If we have a shared lock we may need to upgrade the lock for the
 * last operation.

without kasan: prints the first line, traps on the other
with kasan: it traps on the first printf

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

mjg requested review of this revision.Jul 8 2023, 11:40 PM

No guarantee exists that your value is trapping, and e.g. it was often not on i386.

The value should be MD. On amd64 non-canonical pointer is much better then anything that can be actually mapped into kernel, so the usual 0xdeadc0de pattern is excellent in this regard. For i386, perhaps 0 is the best value now, but your 0xffffe000 is also mostly fine. No idea about other arches.

In fact, on arches where it is not immediately obvious what to use, you could use unmapped_buf (see vfs_bio.c), which already does exactly that for bufs. Still, on amd64 non-canonical value is better.

  • use unmapped_buf
  • add kasan support
mjg edited the test plan for this revision. (Show Details)
This revision is now accepted and ready to land.Jul 11 2023, 1:02 AM
sys/sys/asan.h
68 ↗(On Diff #124460)

Consumers should use kasan_mark() directly, there's no need for KASAN to provide this symbol.

  • remove kasan_poison_pointer
This revision now requires review to proceed.Jul 14 2023, 4:52 PM

I am confused by the current patch. Where is DEBUG_POISON_POINTER_VALUE provided?

First of all my apologies, this somehow fell through the cracks after i pinged.

Trying to use unmapped_buf directly was running into trouble due to __read_mostly annotation. I could not remove it, and including headers to make it available resulted in numerous build failures.

Thus the issue is dodged with a new var.

This revision is now accepted and ready to land.Nov 28 2023, 4:05 PM
This revision was automatically updated to reflect the committed changes.