[SOLVED] freshly compiled pfctl fails with DIOCGETRULES permission denied

  • Hi there,

    I am trying to understand what is going on in there. I've compiled clean pfctl on my development VM (runs FreeBSD 10.3)

    ethicius@vm:~$ uname -a
    FreeBSD vm-freebsd10-32b 10.3-RELEASE-p4 FreeBSD 10.3-RELEASE-p4 #0: Sat May 28 09:52:35 UTC 2016     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  i386

    and run it on my pfSense (2.3.1)

    [2.3-RELEASE][root@pfSense]/tmp: uname -a
    FreeBSD pfSense.cybernet.lan 10.3-RELEASE FreeBSD 10.3-RELEASE #5 05adf0a(RELENG_2_3_0): Mon Apr 11 19:05:10 CDT 2016     root@ce23-i386-builder:/builder/pfsense-230/tmp/obj/builder/pfsense-230/tmp/FreeBSD-src/sys/pfSense_wrap  i386

    with the following result:

    [2.3-RELEASE][root@pfSense]/tmp: ./pfctl -s rules
    pfctl: DIOCGETRULES: Permission denied

    whereas on the VM it runs correctly.

    For completion, the output of file is:

    [2.3-RELEASE][root@pfSense]/tmp: file ./pfctl
    ./pfctl: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 10.3, not stripped

    and that of the original pfctl is:

    [2.3-RELEASE][root@pfSense]/tmp: file /sbin/pfctl
    /sbin/pfctl: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 10.3, stripped

    Interestingly, pfctl -s Anchors (DIOCGETRULESETS + DIOCGETRULESET) completes correctly.

    Can anybody be so kind and explain to me why certain ioctls do not work on seemingly same binaries?

    Is the system hardened in a way which would only allow specific fingerprinted binaries to call certain ioctls? If so, what is the mechanism for adding this new pfctl to the list?

    Any help is much appreciated!

  • The pfctl binary in stock FreeBSD isn't the same as ours, you have to build using our FreeBSD-src repo.

  • Thanks for the quick response! Will build the right pfctl.

    In the meantime, I wrote a simple program:

      int fd = open("/dev/pf", O_RDWR);
      if (fd == -1) {
        return 1;
      struct pf_status status;
      if (ioctl(fd, DIOCGETSTATUS, &status) == -1 || !status.running) {
        perror("ioctl DIOCGETSTATUS");
        return 1;

    which fails with

    ioctl DIOCGETSTATUS: Operation not supported by device

    Do you know what the reason for this error is?

    The same happens for DIOCGETRULES.

  • I have managed to successfully build and run the above simple example as well as the pfctl. For those interested, here are the steps I took:

    a) downloaded source from https://github.com/pfsense/FreeBSD-src
    b) make buildworld
    c) compiled the above test with```
    clang -I/usr/obj/usr/home/ethicius/develop/FreeBSD-src/tmp/usr/include -o sample sample.c

    ~~I still don't quite understand what the underlying problem is. Could it be that the _IOWR macro constructs a different number? I might have to disassemble those two files to find the culprit…~~
    It's simply just a different API. pfSense has modified sys/pfvar.h and related files.

Log in to reply