Page MenuHomeFreeBSD

pf: Avoid taking the pf rules write lock in a couple of ioctls
ClosedPublic

Authored by markj on Dec 18 2025, 6:13 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Jan 16, 5:29 AM
Unknown Object (File)
Wed, Jan 14, 9:53 AM
Unknown Object (File)
Tue, Jan 13, 10:01 PM
Unknown Object (File)
Tue, Jan 13, 2:34 PM
Unknown Object (File)
Thu, Jan 8, 5:22 AM
Unknown Object (File)
Wed, Jan 7, 12:31 AM
Unknown Object (File)
Tue, Jan 6, 12:09 AM
Unknown Object (File)
Sat, Jan 3, 7:39 PM

Details

Summary

The DIOCGETRULES ioctl handlers has taken the write lock ever since
fine-grained locking was merged to pf, but I believe it's unneeded. Use
the read lock instead.

DIOCGETRULENV takes the write lock as well but I believe this is only
required when clearing rule counters. (It might not be required even
then, on platforms where counter increment is done atomically.) Acquire
the read lock if that is not the case.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj requested review of this revision.Dec 18 2025, 6:13 PM
This revision is now accepted and ready to land.Dec 18 2025, 8:04 PM

DIOCGETRULENV takes the write lock as well but I believe this is only
required when clearing rule counters. (It might not be required even
then, on platforms where counter increment is done atomically.) Acquire
the read lock if that is not the case.

I believe the intent behind the write lock is to enable a userspace pattern of repeated fetch+clear without missing counts. If we'd take the read lock to retrieve the counters we could be incrementing them while this is going on, before we clear them again. That'd mean we'd miss packets/bytes/evaluations.

In D54292#1241041, @kp wrote:

DIOCGETRULENV takes the write lock as well but I believe this is only
required when clearing rule counters. (It might not be required even
then, on platforms where counter increment is done atomically.) Acquire
the read lock if that is not the case.

I believe the intent behind the write lock is to enable a userspace pattern of repeated fetch+clear without missing counts. If we'd take the read lock to retrieve the counters we could be incrementing them while this is going on, before we clear them again. That'd mean we'd miss packets/bytes/evaluations.

Ah, that makes sense.