bpf: fix handling the read timeout on ppc64

On platforms other than amd64, BIOCSRTIMEOUT is equal to
BIOCSRTIMEOUT32. Therefore, running the COMPAT_FREEBSD32 code
basically clears tv_usec on big endian platforms. When tcpdump is
used, the timeout requested is 100ms, which gets cleared to 0 on
ppc64 platforms. This results in tcpdump showing the packets only
when the read buffer is full.
Thanks to kib for guiding me to the correct fix.

Reported by:		ivy
Reviewed by:		adrian, kib
MFC after:		3 days
Differential Revision:	https://reviews.freebsd.org/D56399
This commit is contained in:
Michael Tuexen
2026-04-15 21:24:05 +02:00
parent 92c69c791c
commit 04b994d19e
+22 -20
View File
@@ -1201,7 +1201,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BIOCGDLTLIST32:
case BIOCGRTIMEOUT32:
case BIOCSRTIMEOUT32:
if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
if (SV_CURPROC_FLAG(SV_ILP32)) {
BPFD_LOCK(d);
d->bd_compat32 = 1;
BPFD_UNLOCK(d);
@@ -1209,6 +1209,19 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
}
#endif
#if defined(COMPAT_FREEBSD32)
if (SV_CURPROC_FLAG(SV_ILP32)) {
/*
* On platforms other than amd64, BIOC[GS]RTIMEOUT32 is equal to
* BIOC[GS]RTIMEOUT. Since this is difficult to handle in the
* switch command, map them.
*/
if (cmd == BIOCSRTIMEOUT32)
cmd = BIOCSRTIMEOUT;
if (cmd == BIOCGRTIMEOUT32)
cmd = BIOCGRTIMEOUT;
}
#endif
CURVNET_SET(TD_TO_VNET(td));
switch (cmd) {
default:
@@ -1419,23 +1432,19 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set read timeout.
*/
case BIOCSRTIMEOUT:
#if defined(COMPAT_FREEBSD32) && defined(__amd64__)
case BIOCSRTIMEOUT32:
#endif
{
struct timeval *tv = (struct timeval *)addr;
#if defined(COMPAT_FREEBSD32)
#ifdef COMPAT_FREEBSD32
struct timeval32 *tv32;
struct timeval tv64;
if (cmd == BIOCSRTIMEOUT32) {
if (SV_CURPROC_FLAG(SV_ILP32)) {
tv32 = (struct timeval32 *)addr;
tv = &tv64;
tv->tv_sec = tv32->tv_sec;
tv->tv_usec = tv32->tv_usec;
} else
}
#endif
tv = (struct timeval *)addr;
/*
* Subtract 1 tick from tvtohz() since this isn't
@@ -1450,31 +1459,24 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get read timeout.
*/
case BIOCGRTIMEOUT:
#if defined(COMPAT_FREEBSD32) && defined(__amd64__)
case BIOCGRTIMEOUT32:
#endif
{
struct timeval *tv;
#if defined(COMPAT_FREEBSD32) && defined(__amd64__)
struct timeval *tv = (struct timeval *)addr;
#ifdef COMPAT_FREEBSD32
struct timeval32 *tv32;
struct timeval tv64;
if (cmd == BIOCGRTIMEOUT32)
if (SV_CURPROC_FLAG(SV_ILP32))
tv = &tv64;
else
#endif
tv = (struct timeval *)addr;
tv->tv_sec = d->bd_rtout / hz;
tv->tv_usec = (d->bd_rtout % hz) * tick;
#if defined(COMPAT_FREEBSD32) && defined(__amd64__)
if (cmd == BIOCGRTIMEOUT32) {
#ifdef COMPAT_FREEBSD32
if (SV_CURPROC_FLAG(SV_ILP32)) {
tv32 = (struct timeval32 *)addr;
tv32->tv_sec = tv->tv_sec;
tv32->tv_usec = tv->tv_usec;
}
#endif
break;
}