DF-3055 / knote.c
/* * DF-3055 — TU2: the kqueue machinery, as a separate translation unit. * In the real kernel KNOTE() lands in sys/kern/kern_event.c (knote()) and * sys/sys/event.h; dirfs_knote (dirfs_vnops.c:139-145) calls it with * vp = *ap->a_vpp. In this TU vp is opaque to the compiler, exactly as a * cross-function kernel argument is, so the NULL deref cannot be folded away. */ #include <unistd.h> /* * volatile-qualified head pointer: every access is a volatile access and * cannot be elided by the optimizer (models the kernel's klist traversal, * whose first load is what faults on vp == NULL). */ struct kqinfo { struct { void * volatile slh_first; } ki_note; }; struct klist { void * volatile slh_first; }; struct vnode { unsigned char pad_v_data_etc[0x38]; /* v_data ... up to v_pollinfo */ struct { struct kqinfo vpi_kqinfo; } v_pollinfo; }; #define NOTE_WRITE_TU 0x0002 #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define KNOTE(list, hint) do { if (!SLIST_EMPTY((list))) knote((struct klist *)(list), (hint)); } while (0) __attribute__((noinline)) static void knote(struct klist *list, long hint) { /* * The real knote() walks the note list starting at list->slh_first; * loading the (volatile) head is what faults on a NULL vp. */ char *first = list->slh_first; if (first == (char *)&hint) /* opaque use, never true */ if (write(2, first, 1) == 42) return; } /* * verbatim dirfs_knote (dirfs_vnops.c:139-145) */ void dirfs_knote(struct vnode *vp, int flags) { if (flags) KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); /* :144 */ } |