Re: git: e1882428dcbb - main - ifnet/mbuf: provide KPI to serialize/restore m->m_pkthdr.rcvif

From: Gleb Smirnoff <glebius_at_freebsd.org>
Date: Thu, 27 Jan 2022 17:11:01 UTC
  Mateusz,

On Thu, Jan 27, 2022 at 05:59:03PM +0100, Mateusz Guzik wrote:
M> --- trap 0xc, rip = 0xffffffff80616d98, rsp = 0xfffffe06462889e0, rbp
M> = 0xfffffe06462889e0 ---
M> m_rcvif_serialize() at m_rcvif_serialize+0x8/frame 0xfffffe06462889e0
M> netisr_queue_src() at netisr_queue_src+0x15c/frame 0xfffffe0646288a30
M> route_output() at route_output+0x890/frame 0xfffffe0646288c70
M> sosend_generic() at sosend_generic+0x456/frame 0xfffffe0646288d10
M> soo_write() at soo_write+0x43/frame 0xfffffe0646288d40
M> dofilewrite() at dofilewrite+0x81/frame 0xfffffe0646288d90
M> sys_write() at sys_write+0xbc/frame 0xfffffe0646288e00
M> amd64_syscall() at amd64_syscall+0x107/frame 0xfffffe0646288f30
M> fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0646288f30
M> --- syscall (4, FreeBSD ELF64, sys_write), rip = 0x3b000ba6703a, rsp =

The breaking commit is 6871de9363e559fef6765f0e49acc47f77544999,
not exactly this one.

This means route_output() tries to queue on netisr an mbuf without
rcvif set. And by means of route protocol it is legitimate.

The question is how did that work before?

If we look at netisr.c before my change, we see that on dequeuing we
would require the rcvif for VIMAGE case:

netisr_process_workstream_proto():

		VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
		    ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
		CURVNET_SET(m->m_pkthdr.rcvif->if_vnet);
		netisr_proto[proto].np_handler(m);

This won't panic without VIMAGE however.

It also is dereferenced in netisr_drain_proto_vnet(), but apparently
this function is also disabled without VIMAGE.


-- 
Gleb Smirnoff