OPNsense update script apparently calling C compiler?

Started by tpearson-raptor, January 16, 2025, 07:40:09 PM

Previous topic - Next topic
Just a quick question for those who know more about the table update internals than I do...noticed something odd and just want to know if it's normal.

Logged into a development box this morning and saw a hung linker job, which in and of itself isn't a big deal (the linker does hang from time to time), but what was odd was that it seems to have been called with the following chain:

/usr/local/bin/python3 /usr/local/opnsense/scripts/filter/update_tables.py
/usr/local/bin/flock -n -E 0 -o /tmp/filter_update_tables.lock /usr/local/opnsense/scripts/filter/update_tables.py
/usr/bin/cc -Wl,-t -o /tmp/tmpz1a1k7md -lpthread
/usr/bin/ld --eh-frame-hdr -dynamic-linker /libexec/ld-elf.so.1 --enable-new-dtags -o /tmp/tmpz1a1k7md /usr/lib/crt1.o

Does the filter update script, through some dependency somewhere, end up trying to compile C code, or are we looking at a potentially compromised upstream rule server somewhere?

I'm missing a bit of context: what sort of "chain" are you posting? A ps process hierarchy? A shell history? Something else?

Nothing obvious from that block.  It appears rather technical/clinical in the way the commands are run which would suggest this could be normal.

But, again, context matters.


Cheers,
Franco

That's just the apparent process call chain (ps hierarchy).  The update process was fired by cron.  At the end of the day, it's unusual enough to see a C compiler being invoked on a security appliance that I want to know if it's intentional behavior on a stock OPNsense install or not.

It is, but then again Python objects are created on the fly and I'm confident I don't know enough about how it works.


Cheers,
Franco

Today at 02:31:07 AM #4 Last Edit: Today at 02:32:50 AM by tpearson-raptor
To close the loop on this, I found the same thing on another OPNSense box (hung ld process) and spent a little time digging around.  I'm thinking this is a harmless side effect of the way OPNSense "compiles" the rules after an alias update, and the only reason I even saw the compiler call is because /tmp was full on both boxes.  That led to a zero byte output file and a hung linker.

In case anyone is interested, this is why I'm thinking it's probably harmless / normal internal system operation (and a bit of a cheat sheet for anyone else that might run across a similar oddity and want to dig deeper):

pargs 94768
94768:  ld.lld
argv[0]: /usr/bin/ld
argv[1]: --eh-frame-hdr
argv[2]: -dynamic-linker
argv[3]: /libexec/ld-elf.so.1
argv[4]: --enable-new-dtags
argv[5]: -o
argv[6]: /tmp/tmp1jcrcfb7
argv[7]: /usr/lib/crt1.o
argv[8]: /usr/lib/crti.o
argv[9]: /usr/lib/crtbegin.o
argv[10]: -L/usr/lib
argv[11]: -t
argv[12]: -lpthread
argv[13]: -lgcc
argv[14]: --as-needed
argv[15]: -lgcc_s
argv[16]: --no-as-needed
argv[17]: -lc
argv[18]: -lgcc
argv[19]: --as-needed
argv[20]: -lgcc_s
argv[21]: --no-as-needed
argv[22]: /usr/lib/crtend.o
argv[23]: /usr/lib/crtn.o

OK, that seems fairly normal....this is invoked by 'cc':

/usr/bin/cc -Wl,-t -o /tmp/tmp1jcrcfb7 -lpthread
So something is invoking the compiler in a manner where it is reading from stdin and writing to a temporary binary file.  Let's go up another level and look....

root 94216 ... /usr/local/bin/python3 /usr/local/opnsense/scripts/filter/update_tables.py (python3.9)
procstat -f 94216
  PID COMM                FD T V FLAGS    REF  OFFSET PRO NAME
94216 python3.9         text v r r-------   -       - -   /usr/local/bin/python3.9
94216 python3.9          cwd v d r-------   -       - -   /root
94216 python3.9         root v d r-------   -       - -   /
94216 python3.9            0 p - rw------   4       0 -   -
94216 python3.9            1 v c -w------   2       0 -   /dev/null
94216 python3.9            2 p - rw------   2       0 -   -
94216 python3.9            3 v r r-------  14    9567 -   /usr/local/sbin/pluginctl
94216 python3.9            4 v r rw------  14  512073 -   /conf/config.xml
94216 python3.9            5 v r rw------   1       0 -   /tmp/tmp1jcrcfb7
94216 python3.9            6 p - rw------   2       0 -   -

Aha!  The python script wants to interact with the output file, and it's quite obviously in the middle of reading from 'config.xml', presumably for an update of some kind.  Doesn't look much like malware at this distance, and in fact explains why alias updates sometimes fail and require a reboot of the box to apply.

Just out of curiosity: I still cannot imagine why a compiler run should be neccessary to update the aliases from config.xml. The file has to be parsed, probably some URLs fetched, the output of which has to be parsed again (probably XML or JSON) and then fed into pf.

Using a C compiler in that process feels a little heavyweight...
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+