Barnyard2 and MariaDB
-
I was wrong about source code doesn't include clang. It is in
usr.bin
source code folder.But I'm right about poudriere regarding to its emulation nature. I built a poudriere jail as you instructed:
sudo poudriere jails -c -j pfsense-port-11-2-armv6 -a arm.armv6 -m svn -v release/11.2.0
I found that the compiler cc in the armv6 architecture is actually ARM binary. That means when we build anything inside the jail, we compile in ARM emulation in AMD64 platform. It is not going to be fast compared to cross compile.
Ricky@freebsd ~ $ file /usr/local/poudriere/jails/pfsense-port-11-2-armv6/usr/bin/cc /usr/local/poudriere/jails/pfsense-port-11-2-armv6/usr/bin/cc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (FreeBSD), statically linked, for FreeBSD 11.2, FreeBSD-style, stripped
-
Yes, the building of the ARM packages is much slower in the pfSense builder than the AMD64 packages. You can selectively build for each architecture independently using arguments for the
build.sh
script provided in the pfSense builder tools. I have been building only AMD64 versions of my Snort and Suricata packages because of the problems with Golang that you mentioned. The Golang issue prevents the ARM build process from completing successfully.However, if you turn off all of the ARM packages except for just the ones required for Barnyard2 the ARM build might suceed. I have not tried. You can turn packages "on" and "off" by manipulating the Poudriere "bulk" files. If using the pfSense build tree, those will be in pfsense/tools/conf. The
make.conf
file in that same path controls the various option knobs for each port. That's where you selectively enable or disable particular build options. -
I'm still studying how to use poudriere. As I have tried the build process in AMD64, it is fairly easy to run
make
command in pfsense port tree to build Barnyard2 package. It also works correctly.I wrote my notes here. You can see that I listed two approaches to build ARM ports. In the 1st approach a.k.a cross compile approach, I succeeded in building cross compile tool chain for armv6 (This mean you can run the build process in native AMD64 way. It is much faster than emulation). But I haven't figured it out how to override default cc and link command by my cross compile tool chain. FreeBSD port Makefile does not work like Linux way. Please let me know if you know the answer.
Regarding to poudriere emulation approach, I'm thinking:
- Create a poudriere port from a local cloned pfsense port directory.
- Choose Baryard2 package from a package list file.
- Run poudriere bulk
I read the build.sh script from pfsense. It is a lot of bash reading to figure out how it works. Gosh... pfsense make it hard for us to build it.
-
@rickyzhang said in Barnyard2 and MariaDB:
I'm still studying how to use poudriere. As I have tried the build process in AMD64, it is fairly easy to run
make
command in pfsense port tree to build Barnyard2 package. It also works correctly.I wrote my notes here. You can see that I listed two approaches to build ARM ports. In the 1st approach a.k.a cross compile approach, I succeeded in building cross compile tool chain for armv6 (This mean you can run the build process in native AMD64 way. It is much faster than emulation). But I haven't figured it out how to override default cc and link command by my cross compile tool chain. FreeBSD port Makefile does not work like Linux way. Please let me know if you know the answer.
Regarding to poudriere emulation approach, I'm thinking:
- Create a poudriere port from a local cloned pfsense port directory.
- Choose Baryard2 package from a package list file.
- Run poudriere bulk
I read the build.sh script from pfsense. It is a lot of bash reading to figure out how it works. Gosh... pfsense make it hard for us to build it.
Just running
make
from inside the pfSense ports tree is not the same as running theirbuild.sh
script with the proper arguments. The build process uses Poudriere with a proper Poudriere Jail that has the correct port revisions within it needed to make things work on pfSense itself. Running the build within the jail is a key part of the process, especially if you want a final package file that you can install usingpkg
on the firewall with all the correct dependencies listed.pfSense builds their packages using the method I described to you. They do not use your cross-compile method because it has issues on FreeBSD as you are experiencing.
-
First of all, I think we should never call using poudriere jail to compile ARM in AMD64 platform is cross compile. It is emulation. Basically, it use qemu-arm-static to run ARM binary tool chain like cc in emulation mode. The performance really sucks even in my 8 cores i9-9900K CPU.
I enabled the following in
/usr/local/etc/poudriere.conf
. But after 30 minutes run, it still compiling dependencies of Barnyard2.PARALLEL_JOBS=8 ALLOW_MAKE_JOBS=yes
The fastest way should be cross compile tool chain. I remember last time I used
make
command to build Barnyard2 in amd64. It took less than 10 minutes. I'm surprised FreeBSD community or pfsense has not improved it. I'm thinking of creating amd64 jail and override tool chain with cross compile ones. But that's my next step. First thing first: patch Barnyard2....Right now, my poudriere bulk got stuck in fetching textinfo package. I believed the server must be down. I will give it a try later.
[00:29:11] [01] [00:00:15] Finished print/texinfo | texinfo-6.5,1: Failed: fetch [00:29:11] [01] [00:00:15] Skipping devel/autoconf | autoconf-2.69_1: Dependent port print/texinfo | texinfo-6.5,1 failed [00:29:11] [01] [00:00:15] Skipping devel/automake | automake-1.16.1: Dependent port print/texinfo | texinfo-6.5,1 failed [00:29:11] [01] [00:00:15] Skipping security/barnyard2 | barnyard2-1.13_1: Dependent port print/texinfo | texinfo-6.5,1 failed [00:29:11] [01] [00:00:15] Skipping devel/libtool | libtool-2.4.6: Dependent port print/texinfo | texinfo-6.5,1 failed [00:29:11] [01] [00:00:15] Skipping devel/m4 | m4-1.4.18,1: Dependent port print/texinfo | texinfo-6.5,1 failed
-
I got stuck in building Barnyard2 dependencies. I tried it again this morning. It still failed at fetching. I bet the file checksum or the size has been changed. Do you have a good suggestion?
=========================================================================== =======================<phase: fetch-depends >============================ =========================================================================== =======================<phase: fetch >============================ ===> License GPLv3+ accepted by the user => texinfo-6.5.tar.xz doesn't seem to exist in /portdistfiles/texinfo/6.5. => Attempting to fetch https://ftpmirror.gnu.org/texinfo/texinfo-6.5.tar.xz texinfo-6.5.tar.xz 0 B 0 Bps => htmlxref.cnf doesn't seem to exist in /portdistfiles/texinfo/6.5. => Attempting to fetch http://distcache.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf fetch: http://distcache.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf: Not Found => Attempting to fetch http://distcache.us-east.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf fetch: http://distcache.us-east.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf: Not Found => Attempting to fetch http://distcache.eu.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf fetch: http://distcache.eu.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf: Not Found => Attempting to fetch http://distcache.us-west.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf fetch: http://distcache.us-west.FreeBSD.org/local-distfiles/sunpoet/texinfo/6.5/htmlxref.cnf: Not Found => Attempting to fetch http://distcache.FreeBSD.org/ports-distfiles/texinfo/6.5/htmlxref.cnf fetch: http://distcache.FreeBSD.org/ports-distfiles/texinfo/6.5/htmlxref.cnf: size mismatch: expected 20137, actual 20076 => Couldn't fetch it - please try to retrieve this => port manually into /portdistfiles/texinfo/6.5 and try again. *** Error code 1 Stop. make: stopped in /usr/ports/print/texinfo =>> Cleaning up wrkdir ===> Cleaning for texinfo-6.5,1 build of print/texinfo | texinfo-6.5,1 ended at Tue Aug 6 08:14:30 UTC 2019 build time: 00:00:13 !!! build failure encountered !!!
Do you have a detail step to use pfsense build process to compile to ARM target platform from AMD64 platform?
I'm slow. I have to have some detailed step in the notes like this.
I grep pfsense repo and see how they use poudriere. It doesn't seem like they use my 2nd approach in my notes where you create emulation ARM jail in poudriere. I don't know if they build in a beefy ARM board or they use cross compiler in AMD64 with ARM target.
I saw your name in pfsense's commit. I beg you are quite active from community to send PR. You are the right person I should talk to.
Thanks!
-
For some reason your builder is having problems downloading the source code for that port. You might want to try the download manually from other Internet locations. If the required tarball is in /usr/ports/distfiles, then the
make
process won't attempt to download it.I am the maintainer for the Snort and Suricata packages on pfSense, so yeah, I have a number of commits to the FreeBSD-ports tree in pfSense. That's also why I use their builder script when compiling my packages for testing before submitting them to the upstream master tree.
Using the builder environment for packages is not that difficult. Here are the basic steps. I'm assuming you want to build your package for pfSense-2.4.4, so my instructions are based on that. However, I don't target that environment. I build for the DEVEL branch, so I'm not 100% sure that everything I have outlined below works on the RELENG_2_4_4 branch.
- Begin by installing
qemu-user-static
on your FreeBSD machine with this command:
pkg install qemu-user-static
- Make sure you have cloned both the FreeBSD-ports and pfsense repos onto your FreeBSD machine.
- Change into the FreeBSD-ports directory and execute this command to switch to the pfSense-2.4.4 branch.
git checkout RELENG_2_4_4
- Then go back up one directory level and change down into the pfsense directory.
- To see all the options for the
build.sh
script, execute it with no arguments like this:
./build.sh
- Execute this command to set up an intial builder environment:
./build.sh --setup
- After that completes, execute the command to pull down the latest FreeBSD source code in preparation for building a poudriere jail. Note that you will need to edit the file
/pfsense/tools/builder_common.sh
and comment out two sections in that file having to do with pulling down the source tree for the Netgate ID stuff (gnid) as that is proprietary source and source code update will fail when it can't pull down that code. Use an editor and search for the phrase "gnid" in the script file. You will find it used in two "if" blocks in the script. Comment out both "if" blocks entirely and then save the file. After editing and saving the file, execute this command:
./build.sh --update-sources
- When that finishes, it's time to actually create the Poudriere ports tree and the jails for building using this command (note, this will take at least an hour and probably nearly twice that long to complete depending on your hardware):
./build.sh --setup-poudriere
- To actually start a package build process after the ports tree and pourdriere jails are ready, execute this command:
./build.sh --update-pkg-repo
- There are some additional command line options for the previous command. You can use
-a [arch]
to control which CPU architectures to target. The default is to build both AMD64 and ARM packages. If you want to build say just AMD64 packages, the argument would be-a amd64.amd64
. For just ARM packages, the argument would be-a arm.armv7
.
The completed packages will be stored in sub-directories under /usr/local/poudriere/data/packages on your FreeBSD machine.
Because of the issues with some packages under
qemu-user-static
, you will want to edit the filepfsense/tools/conf/pfPorts/poudriere.bulk.exclude.arm.armv7
to remove all of the ports that depend on the problematic packages such as Golang. You can open and examine the file to see the required syntax. This may become a trial and error process to get everything excluded.The above process will work, but it might take a few iterations and some trial and error to get it all going. There is no official documentation, but if you wade through the
builder_common.sh
script you can figure out how things work by looking at the code.Also note that the setup process only has to be performed once. Thereafter, you can simply execute
./build.sh --update-pkg-repo
to build a new version of a package. To make poudriere start a new build of a modified package, you will have to either bump the port version string or go to the /usr/local/poudriere/data/packages tree and remove the package file that you want to rebuild. Either of these two methods will alert poudriere that a build of that package is required.
- Begin by installing
-
I really appreciate your help! I will give a try tonight.
Please let me know if you are OK with me to copy your steps to my wiki.
I found the culprit why I got stuck. The file size of texinfo/6.5/htmlxref.cnf specified by
print/texinfo/distinfo
doesn't match what it downloads from Internet../distinfo:5:SIZE (texinfo/6.5/htmlxref.cnf) = 20137
I check out my FreeBSD-ports repo on
tag: v2.4.4_3
which match the release of my pfsense router current firmware. But it looks like the build can't replicate due to the dependency of hell.I will switch to devel branch. I found that it change the file size.
-
@rickyzhang said in Barnyard2 and MariaDB:
v2.4.4_3
I haven't tried your build.sh approach. But I succeeded in building Barnyard2 in poudriere ARM jail. I applied the make.conf from pfsense. So I don't need to answer the build options during the build.
The whole build process took about 2hrs! But I went into dependency hell. I manually substitute original barnyard2 binary in
/usr/local/bin
with my new one. The new one needslibmysqlclient.so.20
, while the original one needslibmysqlclient.so.18
.Although I have new mysqlclient package, I don't think it is a good idea to replace it.
[2.4.4-RELEASE][admin@pfSense.localdomain]/root/Download/mysql57: ldd /usr/local/bin/barnyard2.orig /usr/local/bin/barnyard2.orig: libmysqlclient.so.18 => /usr/local/lib/mysql/libmysqlclient.so.18 (0x20100000) libz.so.6 => /lib/libz.so.6 (0x20087000) libpcap.so.1 => /usr/local/lib/libpcap.so.1 (0x200a6000) libm.so.5 => /lib/libm.so.5 (0x20425000) libbroccoli.so.5 => /usr/local/lib/libbroccoli.so.5 (0x2044a000) libc.so.7 => /lib/libc.so.7 (0x20500000) libssl.so.8 => /usr/lib/libssl.so.8 (0x2046f000) libcrypto.so.8 => /lib/libcrypto.so.8 (0x20700000) libexecinfo.so.1 => /usr/lib/libexecinfo.so.1 (0x200f5000) libc++.so.1 => /usr/lib/libc++.so.1 (0x2089e000) libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x204d1000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x20666000) libthr.so.3 => /lib/libthr.so.3 (0x20675000) libelf.so.2 => /lib/libelf.so.2 (0x206a2000) [2.4.4-RELEASE][admin@pfSense.localdomain]/root/Download: ldd arm-pkg/barnyard2 arm-pkg/barnyard2: libmysqlclient.so.20 => not found (0) libz.so.6 => /lib/libz.so.6 (0x20089000) libpcap.so.1 => /usr/local/lib/libpcap.so.1 (0x200a8000) libm.so.5 => /lib/libm.so.5 (0x200f7000) libbroccoli.so.5 => /usr/local/lib/libbroccoli.so.5 (0x2011c000) libc.so.7 => /lib/libc.so.7 (0x20200000) libssl.so.8 => /usr/lib/libssl.so.8 (0x20141000) libcrypto.so.8 => /lib/libcrypto.so.8 (0x20400000)
The root of the problem is that my port tree is forked from devel branch which is different from v2.4.4.4_3.
But obviously I have to manually fix Barnyard2 dependency distinfo file. The whole build in pfsense is not repeatable. Because its dependencies come from Internet. That doesn't seem to be a good sign.
-
I keep telling you what to do and you keep ignoring my advice... . Build it within the pfSense builder environment using the
build.sh
script and the various arguments I gave you in the previous post farther up above.Yes, DEVEL in pfSense is based on FreeBSD 12.0 which has a slightly different version of various libraries. pfSense-2.4.4_3 is based on FreeBSD 11.2.
You can probably switch to the RELENG_2_4_4 branch within the pfSense builder environment and build Barnyard2 from there. That is the current RELEASE branch. The initial build of any package is going to take a while because all of the dependencies have to built first. Subsequent builds of just the Barnyard2 module will be much faster.
-
I know I looks like an idiot. When in Rome, do as the Romans do. I will definitely follow your advice later.
Before you give me your detailed instruction for pfsense, I can't find any documents from pfsense so I have to figure this out by myself. It is kind of painful.
As a lazy developer, I look for an easy and quick way to build thing for pfSense.
Because I'm more familiar with
make
command andautoconf
way. So I tried this approach first and then hit the wall when do cross compiling.Later I tried 2nd approach: use poudriere jail. I have to read poudriere user guide. I figured out it is slow ARM emulation rather than cross compile. The pfsense build.sh use poudriere jail as well. So I'm very close to what Romans do now.
I bet most Linux developer who wants to contribute to pfSense will go through the same path like me. I wish we could publish this in our forum so that people can avoid wasting time on build problem and focus on contributing.
-
I create a patch and build the port successfully targeting to ARM platform by using poudriere arm jail.
Barnyard passed the SQL syntax road block. But the daemon crashed after 2+ hours with no log message to indicate why.
I checked the tables in MariaDB. The patched Barnyard2 did populate all meta data table like detail, encoding, reference, reference_system and sensor. However, the alert logging information like event and data table are empty even there were alerts popping up during that time.
I haven't deep dived into how SNORT notifies Barnyard2 to log alert. That may be a rabbit hole to patch it further. I will call it stop.
In any case, if anyone are interested in fixing it, I shared my stuffs below:
-
Fix checksum for texinfo port and SQL syntax for Barnyard2 port in my Github repo. The commit is based on pfSense v2.4.4-p3 release.
-
My notes on how to jump start FreeBSD port development, poudriere port build and port patching.
Thanks @bmeeks for sharing your wisdom!
Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: --== Initializing Barnyard2 ==-- Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Initializing Output Plugins! Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Running in Continuous mode Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Initializing Input Plugins! Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Parsing config file "/usr/local/etc/snort/snort_55529_mvneta2/barnyard2.conf" Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: +[ Signature Suppress list ]+ ---------------------------- Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: Found pid path directive (/var/run) Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: +[No entry in Signature Suppress List]+ Aug 7 15:50:26 pfsense.localdomain barnyard2[49355]: ---------------------------- +[ Signature Suppress list ]+ Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: Barnyard2 spooler: Event cache size set to [8192] Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: Log directory = /var/log/snort/snort_mvneta255529 Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: INFO database: Defaulting Reconnect/Transaction Error limit to 10 Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: INFO database: Defaulting Reconnect sleep time to 5 second Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: Initializing daemon mode Aug 7 15:50:28 pfsense.localdomain barnyard2[50346]: Daemon initialized, signaled parent pid: 49355 Aug 7 15:50:28 pfsense.localdomain barnyard2[49355]: Daemon parent exiting Aug 7 15:50:28 pfsense.localdomain barnyard2[50346]: PID path stat checked out ok, PID path set to /var/run Aug 7 15:50:28 pfsense.localdomain barnyard2[50346]: Writing PID "50346" to file "/var/run/barnyard2_mvneta255529.pid" Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: configured to use mysql Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: compiled support for (mysql) Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: schema version = 107 Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: host = 192.168.2.30 Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: user = snort Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: database name = snort_db_wan Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: sensor name = pfSense.localdomain:mvneta2 Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: sensor cid = 2 Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: sensor id = 1 Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: data encoding = hex Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: detail level = full Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: ignore_bpf = no Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: database: using the "log" facility Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: --== Initialization Complete ==-- Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: Barnyard2 initialization completed successfully (pid=50346) Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: WARNING: Ignoring corrupt/truncated waldofile '/var/log/snort/snort_mvneta255529/barnyard2/55529_mvneta2.waldo' Aug 7 15:52:11 pfsense.localdomain barnyard2[50346]: Opened spool file '/var/log/snort/snort_mvneta255529/snort_55529_mvneta2.u2.1565207426'
-
-
Snort simply writes records to the unified2 log file for each event. Barnyard2 constantly monitors that file to see when something new comes in and then writes the alert data to the configured DB. There are some configuration options within the Barnyard2 tab of Snort to control exactly what gets written to where.
There is a command line utility included with Snort that can dump the contents of the U2 log. The utility path and filename is
/usr/local/bin/u2spewfoo
. You could use that to see what events, if any, Snort recorded to the unified2 log file that Barnyard2 is monitoring.When the Barnyard2 daemon crashed, did you look to see if anything related was in the pfSense system log? Since you are running on ARM hardware, my first suspicion would be perhaps a Signal 10 Bus Error message in the system log. If you see that, it means the Barnyard2 binary attempted to access unaligned data in memory.
-
@bmeeks said in Barnyard2 and MariaDB:
u2spewfoo
I used rsyslog to receive stream logging from pfsense. I found the error in kernel.log
233 Aug 7 18:26:42 pfsense.localdomain kernel: pid 50346 (barnyard2), uid 0: exited on signal 10 (core dumped)
According to FreeBSD signal error, signal 10 is bus error just as your described.
I can't find the core dump anywhere. How can I enable core dump or access the dump file?
-
@rickyzhang said in Barnyard2 and MariaDB:
@bmeeks said in Barnyard2 and MariaDB:
u2spewfoo
I used rsyslog to receive stream logging from pfsense. I found the error in kernel.log
233 Aug 7 18:26:42 pfsense.localdomain kernel: pid 50346 (barnyard2), uid 0: exited on signal 10 (core dumped)
According to FreeBSD signal error, signal 10 is bus error just as your described.
I can't find the core dump anywhere. How can I enable core dump or access the dump file?
Right off hand I don't recall where pfSense will store the dump.
I have/had this same issue with both Snort and Suricata on the Netgate ARM appliances. It is a long story about why, but I will try and condense it a bit.
Intel CPUs have basically forever performed something called an "automatic fix-up" when program code attempted to access unaligned data in memory. You can do some Google research on the term "unaligned access", but it basically has to do with the actual hardwired logic within the CPU design that governs how data is dumped from memory addresses. As a programmer, you should always pay careful attention to insure data is stored and retrieved on word-aligned boundaries. However, the details of this get sketchy because of differences in hardware design among various CPUs. It gets even more sketchy when you start talking about higher level languages such as C and C++. This is because the compilers for these languages hide a lot things from the programmer when converting say a C source file into binary executable code for a given architecture.
So back to what Intel's design choice has produced in today's software. Intel decided long ago to have the internal microcode inside their CPUs perform an automatic fix-up if a programmer attempted to access a memory location that is not word-aligned (that is, the address of the desired data was not evenly divisible by 2). The hardware of the CPU would actually perform a word-aligned access and then throw away the unneeded portion of the data. For example, you are trying to read a single byte of data but you can only read and write to memory in 16-bit, or word-aligned, chunks. The hardware would read a 16-bit data value from memory but then compute which half (upper or lower 8 bits) to ignore. This is a bit oversimplified, but you can get the basic point. Thus programmers got lazy and never really worried about unaligned access in their code because even if they performed such a "bad" move, the CPU would fix it for them under the covers. I would even venture so far as to say there is a large number of C programmers out there who have no idea what unaligned access even is!
Non-Intel CPUs will frequently choose not to perform an auto-fixup operation. Instead, they throw a hardware exception interrupt and terminate the offending process. The ARM CPU used in the SG-3100 appliance is such a device. It has some instructions for loading registers with data from memory that will cause auto-fixups of unaligned acccess; but it also has other instructions that will not. Now is where the vagaries of compilers come into play. The llvm compiler used by default in FreeBSD will, when optimization is enabled, choose to use the ever so slightly faster CPU instructions for loading data from memory that do NOT perform an auto-fixup. This can lead to a Signal 10 crash using C code that works perfectly fine on Intel hardware (because Intel hardware will always perform an auto-fixup). So now consider you wrote Snort or Suricata or Barnyard2 or whatever piece of software, and that software runs just fine as is on all Intel hardware out there. But it does once in a while choke on say someone's ARM hardware. Is it worth your time and effort to scour thousands of lines of C source code to find the places where unaligned access might happen? By the way, this usually happens in code sections where the C programmer is casting one variable type to another - and that is usually a lot of places! You can see where this is going ... the folks who maintain the upstream binary portions of these packages don't want to put in the necessary time and effort to ferret out all the little casting problems that cause the Signal 10 issue because, frankly, there is no problem on any of the Intel-based hardware out there, and Intel has by far the largest market share anyway.
So long story to say don't expect an immediate fix for the Signal 10 problem. This is just me talking, but the folks out there who are making these little hardware appliances should really think long and hard about the unintentional consequences of choosing non-Intel hardware when you also want to run a lot of commonly available compiled software on the device (meaning popular C source code programs). It is very likely that such software (most commonly C source code based) has hidden unaligned access time bombs hiding in it. In the case here of pfSense and the ARM appliances, I know of at least four and maybe five packages that crash for this very reason on the ARM-based appliances (Snort, Suricata, clamav and now Barnyard2). I think there was maybe one other one that would be five. I've partially worked around this in Snort and Suricata by telling the llvm compiler to switch off all optimizations when creating the binary executable for ARM platforms. This results in a slower binary on ARM hardware, but without that workaround Snort would not even start up on the SG-3100. So for your Barnyard2 Signal 10 crash, try turning off optimizations in llvm. You can do that either by enabling the DEBUG build of the package or by changing some compile time arguments to the compiler. Look at the patch files for Snort on ARM to get a hint on what to do.
-
This is very good pieces of educational reading. I read some alignment code in C struct in Linux kernel. But I never knew why until now. Thanks!
As you said, this memory access alignment problem can be mitigated by a compiler (Perhaps, it is not ideal to disable optimization). I ported some C/C++ file from Intel to iOS which runs on ARM. But I haven't heard of the alignment issue. The build tool like XCode will flag this during development. See doc here.
Can all memory misalignment access be caught at compile time? If yes, compiler can generate correct machine code or IDE can flag it.
In any case, I will give a try and see how you address this in Suricata or Snort port.
-
I added a CFLAGS
-Wpadded
which flags memory misalignment in struct. I got 543 red flags from the build log:grep "[\-Wpadded]" barnyard2-1.13_1.log | wc -l 543
I will give a try on adding a CFLAGS like
-fpack-struct
to see if it can automatically pad them. -
@rickyzhang said in Barnyard2 and MariaDB:
I added a CFLAGS
-Wpadded
which flags memory misalignment in struct. I got 543 red flags from the build log:grep "[\-Wpadded]" barnyard2-1.13_1.log | wc -l 543
I will give a try on adding a CFLAGS like
-fpack-struct
to see if it can automatically pad them.That may cause more bugs. There are many places within the Snort code where certain functions make assumptions about the alignment of data in structures. For instance, code may assume bytes are immediately adjacent to each other in a given structure. Having the compiler add padding behind the scenes can create more bugs. Would not be surprised to see the same issue exist in Barnyard2.
This is why fixing these issues is a major pain. If it was really as simple as adding a compiler directive the upstream maintainers would have already done that. It's not that simple in practice.
-
You are correct. With the CFLAGS
-fpack-struct
enabled, Barnyard2 crashed immediately with signal 11 segmentation fault.I replaced it with
-mno-unaligned-access
. It crashed with signal 10 again. It seem to be a clang bug because the no unaligned access flag doesn't work.Any suggestion? I can't find the fix commit in snort's Makefile under your name. How can you address it?
-
@rickyzhang said in Barnyard2 and MariaDB:
This is very good pieces of educational reading. I read some alignment code in C struct in Linux kernel. But I never knew why until now. Thanks!
As you said, this memory access alignment problem can be mitigated by a compiler (Perhaps, it is not ideal to disable optimization).
No, disabling optimization is not ideal, but the choice was that or no Snort on the SG-3100 (or any other ARM-based appliance running pfSense). So we (me and the pfSense developer team) chose the "at least make it work" option.
The real fix for this is to never have the error within the source code to start with. This unaligned access problem almost always happens when "casting" a pointer variable from one type to another. But this is frequently required in C programming in order to stop the compiler from complaining about mismatched or wrong type function arguments. Going through C source code that you didn't write and trying to figure out where casting problems exist and then determine if fixing them will break something else or not is a tall order.