NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60436: kqueue(2): random kernel null pointer deref in EVFILT_PROC NOTE_TRACK
>Number: 60436
>Category: kern
>Synopsis: kqueue(2): random kernel null pointer deref in EVFILT_PROC NOTE_TRACK
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 10 14:20:00 +0000 2026
>Originator: Taylor R Campbell
>Release: current, 11, 10
>Organization:
Go Fork Yourself, Inc.
>Environment:
>Description:
uvm_fault(0xffff9d171e3dbc80, 0x0, 2) -> e
fatal page fault in supervisor mode
trap type 6 code 0x2 rip 0xffffffff80e30191 cs 0x8 rflags 0x10246 cr2 0xb0 ilevel 0 rsp 0xffffc512650a0e08
curlwp 0xffff9d171d137400 pid 9969.9969 lowest kstack 0xffffc5126509c2c0
panic: trap
cpu6: Begin traceback...
vpanic() at netbsd:vpanic+0x189
panic() at netbsd:panic+0x3c
trap() at netbsd:trap+0xb35
--- trap (number 6) ---
_mutex_init() at netbsd:_mutex_init+0x33
knote_proc_fork() at netbsd:knote_proc_fork+0xa4
fork1() at netbsd:fork1+0x696
sys_fork() at netbsd:sys_fork+0x29
syscall() at netbsd:syscall+0x9d
--- syscall (number 2) ---
netbsd:syscall+0x9d:
cpu6: End traceback...
144 static inline struct knote *
145 knote_alloc(bool sleepok)
146 {
147 struct knote_impl *ki;
148
149 ki = kmem_zalloc(sizeof(*ki), sleepok ? KM_SLEEP : KM_NOSLEEP);
=> 150 mutex_init(&ki->ki_foplock, MUTEX_DEFAULT, IPL_NONE);
151
152 return KIMPL_TO_KNOTE(ki);
153 }
https://nxr.netbsd.org/xref/src/sys/kern/kern_event.c?r=1.152#144
>How-To-Repeat:
cd /usr/tests/kernel/queue && atf-run t_proc2
>Fix:
1. Stop-gap fix:
ki = kmem_zalloc(sizeof(*ki), sleepok ? KM_SLEEP : KM_NOSLEEP);
+ if (ki == NULL)
+ return NULL;
mutex_init(&ki->ki_foplock, MUTEX_DEFAULT, IPL_NONE);
2. Why do we use KM_NOSLEEP at all here? Why should this randomly fail
when the system is swapping? Why doesn't the one caller,
knote_proc_fork_track, just have its caller allocate storage up
front before any spin locks are held or knotes are in flux?
1039 static int __noinline
1040 knote_proc_fork_track(struct proc *p1, struct proc *p2, struct knote *okn)
1041 {
1042 struct kqueue *kq = okn->kn_kq;
1043
1044 KASSERT(mutex_owned(&kq->kq_lock));
1045 KASSERT(mutex_owned(p1->p_lock));
...
1053 if (!kn_enter_flux(okn)) {
1054 return 0;
1055 }
...
1102 knchild = knote_alloc(false);
1103 kntrack = knote_alloc(false);
1104 if (__predict_false(knchild == NULL || kntrack == NULL)) {
1105 error = SET_ERROR(ENOMEM);
1106 goto out;
1107 }
...
1199 if (kn_leave_flux(okn)) {
1200 KQ_FLUX_WAKEUP(kq);
1201 }
1202
1203 return error;
1204 }
...
1204 }
1205
1206 void
1207 knote_proc_fork(struct proc *p1, struct proc *p2)
1208 {
1209 struct knote *kn;
1210 struct kqueue *kq;
1211 uint32_t fflags;
1212
1213 mutex_enter(p1->p_lock);
...
1234 mutex_spin_enter(&kq->kq_lock);
1235 kn->kn_fflags |= (kn->kn_sfflags & NOTE_FORK);
1236 if (__predict_false(kn->kn_sfflags & NOTE_TRACK)) {
1237 /*
1238 * This will drop kq_lock and p_lock and
1239 * re-acquire them before it returns.
1240 */
1241 if (knote_proc_fork_track(p1, p2, kn)) {
1242 kn->kn_fflags |= NOTE_TRACKERR;
1243 }
https://nxr.netbsd.org/xref/src/sys/kern/kern_event.c?r=1.152#1039
Home |
Main Index |
Thread Index |
Old Index