OPNsense Forum

English Forums => Development and Code Review => Topic started by: kraileth on July 21, 2017, 05:05:05 pm

Title: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: kraileth on July 21, 2017, 05:05:05 pm
Hi there,

while preparing to write a little howto on using Jails with OPNsense, I noticed that the distribution only packages a small subset of software that people might want to use. That's perfectly fine for a firewall OS, but it's all FreeBSD under the hood, right? So we can just add missing stuff ourselves. I thus figured I'll write about building packages for OPNsense first.

I was pretty happy to see that the ports tree can be used with OPNsense (it doesn't work with pfSense due to some customizations they are doing!). So I checked out the HardenedBSD ports tree and was able to build Synth, my package builder of choice. But then Synth would fail to build any package.

After running out of ideas, I created an issue with the project on Github. After a little back and forth the cause for failure was found: Synth uses the binary /bin/sh to detect the platform that it's running on. And this is where OPNsense differs from FreeBSD - running file on the binary will return a different string (and one that puzzles me to be honest).

Here's the output on my FreeBSD workstation:

Code: [Select]
% file /bin/sh
/bin/sh: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 11.1 (1101501), FreeBSD-style, stripped

And this is what OPNsense shows:

Code: [Select]
/bin/sh: ELF 64-bit LSB shared object, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 11.0 (1100122), FreeBSD-style, stripped
Pretty close, but mind that the FreeBSD binary is correctly detected to be an executable whereas OPNsense's binary claims to be a shared object!

I found out that this is also the case on HardenedBSD, and that's likely where OPNsense inherited it from. But why is it like that? I suppose that it has something to do with hardening measures that file doesn't know about and thus mistakes HardenedBSD/OPNsense executables as shared objects.

As a quick and dirty "fix" I scp'd the statically linked /rescue executable from my workstation over to my test machine with OPNsense and put that in /bin/sh's place. Synth then works like a charm. But I wonder what exactly is happening here. Can anybody shed some light on this? Would be interesting to know if it needs to be fixed e.g. with file or if string detection with Synth has to consider another possible case.
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: franco on July 21, 2017, 05:25:39 pm
I think this is because of PIE compilation. This should be a simple Synth fix? Why does it check, for Architecture?
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: lattera on July 21, 2017, 05:34:14 pm
This is indeed to building applications as Position-Independent Executables (PIEs). The linker will output the file as an executable dynamic shared object (ELF type: ET_DYN) rather than an executable (ELF type: ET_EXEC). The file(1) application is reporting the correct ELF type.

I wonder why Synth even checks what type of ELF file /bin/sh even is. The problem lies with Synth, not with file(1) nor with sh(1). Synth should either relax/remove its file type detection for /bin/sh or learn the concept of PIEs.
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: kraileth on July 21, 2017, 06:14:04 pm
Thanks for the very fast answer! That's some real dedication. :D
So it does indeed originate in HardenedBSD and it is fine the way it is. Good to know, "mystery" solved.

As far as I understood it, Synth needs to know what arch it is building for and checking a binary in a well-known place seemed to do the trick, I guess. Synth has been used on both FreeBSD and DragonFly for way over a year now, after all. Obviously nobody ever tried it on anything else.

But fortunately the author seems to care for issues like that enough to not close the issue with a comment like "nobody cares for OPNsense" - which is behavior that I've encountered far too often in Open Source (a lot of people only seem to care for their main OS, most often some Linux distro). So if this gets fixed upsteam I can write my tutorial. :)
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: lattera on July 21, 2017, 06:39:54 pm
I'm glad to help. :)

Since Synth is used on DragonflyBSD and DragonflyBSD has ASLR, Synth really should support PIEs. ASLR isn't useful when the application isn't compiled as a PIE.
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: kraileth on July 23, 2017, 07:53:19 am
Looks like I'm not really finding my way around on this forum. How can I mark this thread solved? Or is this a moderator thing? If it is, please mark it solved as the explanation that I was looking for was given. Thanks again!

And just as a quick note: The issue was solved upstream with a new release of Synth so I can begin writing my tutorial (as time permits).
Title: Re: Reason for strange state of /bin/sh ("shared object" instead of executable)?
Post by: fabian on July 23, 2017, 11:37:42 am
FYI: The Ticket is here: https://github.com/jrmarino/synth/issues/87