From: Alexandr Nedvedicky Subject: Re: sys/net/pf_ioctl.c: out of bounds read in pf_rule_copyin To: Johann H??pfner Cc: tech@openbsd.org Date: Mon, 6 Jul 2026 14:00:25 +0200 Hello, I've seen the report too. On Mon, Jul 06, 2026 at 12:05:31PM +0200, Johann H??pfner wrote: > Hello tech@ > > In testing an experimental kernel-address-sanitizer in syzkaller > the following issue was discovered. (and independently found by the > implementation running in syzbot this morning: > https://syzkaller.appspot.com/bug?extid=f028f6e8a734a5e8de11) > > pf_rule_copyin executes strlcpy on non-null-terminated fields from > userspace leading to a read beyond the allocation pointed to by "from", > only if userspace sends a struct pf_rule without zero-terminators, e.g. > as follows. > > #include > #include > #include > #include > #include > int main(){ > int fd = open("/dev/pf", O_RDWR); > struct pfioc_rule pr; > memset(&pr, 'A', sizeof(struct pfioc_rule)); > ioctl(fd, DIOCADDRULE, &pr); > } > > Due to "from" being allocated in a 4096 byte bucket this is very unlikely > to cause a crash without kasan. > I'm not sure how diff below helps. My understanding of the crash is that kasan fuzzer tries to load memory which is shorter than sizeof (struct pfioc_rule), the pfioc_rule size on amd64 is 3424. I have not seen the reproducer used by sanitizer, however my guess is the sanitizer passes buffer (&pr) to DIOCADDRULE rule ioctl(2) command which is smaller than sizeof (struct pfioc_rule). so the diff below will mostlikely die (crash) as soon as it does ...->whatever[sizeof(from->label) - 1] = '\0'; what is really missing here is check which ensures the DIOCADDRULE ioctl comes with the right size of data (size(from) == sizeof (struct pfioc_rule)). The pf(4) currently relies on fact that DIOCADDRULE command is available to root user only and root user should be executing the trusted code. perhaps we can either teach syzkaller to generate more sesnsible (realistic) reproducers. In this case explain syzcaller to always pass buffer of expected size. or fix the pf(4) ioctl to check the operation comes with expected size. Also I've tried simple shell script on my pf test machine. the machine did not crash. my understanding is that there is enough address space mapped on stack, so dereference is safe in kernel. I don't know what kind of magic is sanitizer doing to make kernel to dereference invalid address. Perhaps the pfioc_rule of invalid size is placed somewhere close to the end of the page. thanks and regards sashan --------8<---------------8<---------------8<------------------8<-------- #!/bin/sh SIZE=1 while [ ${SIZE} -le 3424 ] ; do echo "Trying ${SIZE}" cat < crash.c #include #include #include #include #include int main(){ int fd = open("/dev/pf", O_RDWR); char pfioc_rule[$SIZE]; memset(pfioc_rule, 'A', sizeof (pfioc_rule)); ioctl(fd, DIOCADDRULE, pfioc_rule); } EOF make crash ./crash SIZE=$((${SIZE} + 1)) done