Failed to map segment from shared object

Recently, I was working with an AMD Geode LX800 with Debian 7.2 installed on it. I had a small CF and was running out of space, so I used an USB stick where I copied the binary to test (a Qt5 app) and when executing it as a normal user and as root I was getting the following error:

my_app: error while loading shared libraries: my_lib.so.5 :Failed to map segment from shared object: Operation not permitted...

I play around with file ownership (chown) and access permissions (chmod), but nothing changed.

Later I realized that the problem was that the USB stick was mounted with the noexec flag.
Mounting it without this flag allows the shared library to be properly loaded.

Searching around I found that this issue can happen under other similar scenarios like network mounted drives that contain shared libraries that were mounted with the noexec option or simply the /tmp partition that is normally mounted in memory but without execution permissions.

Cross-compiling a custom Net-SNMP agent

Building the default agents in Net-SNMP is quite easy if you’re using tools such as Buildroot, and even when building directly from the sources is not a problem. However, is not that easy if you want to cross-build a custom agent inside Net-SNMP.

This procedure worked for me, but keep in mind that it was not a clean procedure since it involves modifying the generated Makefiles, so every time that you ./configure you will loose your changes.

First, let’s export common environment variables that make our life easier:

export HOST=arm-linux
export BUILD=i386-linux
export PREFIX=/home/paguilar/rootfs

Download

Net-SNMP
Package: net-snmp-5.6.2.1

Configure

./configure \
--prefix=$PREFIX \
--host=$HOST \
--build=$BUILD \
--exec-prefix=$PREFIX/usr \
--sysconfdir=/etc \
--enable-static \
--enable-shared \
--with-persistent-directory=/var/lib/snmp \
--disable-static \
--with-defaults \
--enable-mini-agent \
--without-rpm \
--with-logfile=none \
--without-kmem-usage \
--enable-as-needed \
--disable-debugging \
--without-perl-modules \
--disable-embedded-perl \
--disable-perl-cc-checks \
--disable-scripts \
--with-default-snmp-version="1" \
--enable-silent-libtool \
--enable-mfd-rewrites \
--with-sys-contact="root@localhost" \
--with-sys-location="Unknown" \
--with-mib-modules="host ucd-snmp/dlmod examples/example my_mib/custom_mib" \
--with-out-transports="Unix" \
--with-endianness=little \
--without-openssl \
--disable-manuals \
--with-cflags="-I$PREFIX/usr/include -I$PREFIX/usr/include/glib-2.0 -I$PREFIX/usr/lib/glib-2.0/include" \
--with-ldflags="-L$PREFIX/lib" \
--with-mibdirs="$HOME/.snmp/mibs:/usr/share/snmp/mibs"

Instead of using the –with-cflags and –with-ldflags, you can define the CFLAGS and LDFLAGS:

CFLAGS="-I$PREFIX/usr/include -I$PREFIX/usr/include/glib-2.0 -I$PREFIX/usr/lib/glib-2.0/include" \
LDFLAGS="-L$PREFIX/usr/lib -pthread -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lxml2 -lintl -lsqlite3 -lntxipc -lntxmisc" \

The custom agent must be located inside the agent/mibgroup directory. In this case, create the directory agent/mibgroup/my_mib and write here the agent sources:

mkdir agent/mibgroup/my_mib
vi agent/mibgroup/my_mib/custom_mib.c
vi agent/mibgroup/my_mib/custom_mib.h

If these agent source use only libc it wouldn’t be an issue. But they use other libraries such as Glib2, SQLite3 and libxml2, thus we have to include these libraries by using the –with-cflags and –with-ldflags options or the CFLAGS and LDFLAGS environment variables.

However, when building, the linker didn’t find the GLib2, sqlite3 and libmlx2 shared libraries even though I specified the paths as above…
I got this kind of errors:

/home/paguilar/net-snmp-5.6.2.1/agent/.libs/libnetsnmpmibs.so: undefined reference to `sqlite3_close'
/home/paguilar/net-snmp-5.6.2.1/agent/.libs/libnetsnmpmibs.so: undefined reference to `sqlite3_exec'
/home/paguilar/net-snmp-5.6.2.1/agent/.libs/libnetsnmpmibs.so: undefined reference to `sqlite3_errmsg'
/home/paguilar/net-snmp-5.6.2.1/agent/.libs/libnetsnmpmibs.so: undefined reference to `sqlite3_open'
collect2: ld returned 1 exit status
Makefile:245: recipe for target 'snmptrapd' failed
make[1]: *** [snmptrapd] Error 1
make[1]: Leaving directory '/home/paguilar/net-snmp-5.6.2.1/apps'
Makefile:567: recipe for target 'subdirs' failed
make: *** [subdirs] Error 1

For solving this issue in a dirty but fast way, modify the files agent/Makefile and apps/Makefile. Set the LDFLAGS variable to the following value:

LDFLAGS = -L/home/paguilar/rootfs/usr/lib -pthread -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lxml2 -lintl -lsqlite3

In this way you can quickly build your custom SNMP agent inside Net-SNMP.

Missing requirements when building with Buildroot

Buildroot is a quite useful tool when working with small-to-medium embedded systems. It helps you to create the toolchain, the rootfs and, of course, building the kernel and hundreds of packages normally found in standard Linux distributions.

For using Buildroot you need several mandatory and optional requirements in your host machine. They’re listed in the Buildroot manual. However, there are some sub-requirements that aren’t mentioned since they belong to a global requirement. For example the package Thread/Queue.pm is a Perl module that belongs to the global requirement Perl.

The lack of one of these packages can cause building errors that can confuse new users since it could not be clear if it’s an issue with the package that it’s been built or if it’s an issue with the host machine that is missing something.

Normally, when you see an error like the following, you can be sure that there is a missing Perl module in your host machine:

Can't locate Thread/Queue.pm in @INC (you may need to install the Thread::Queue module) (@INC contains: /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/share/automake-1.15 /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/lib/perl /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/bin/automake line 55.
BEGIN failed--compilation aborted at /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/bin/automake line 58.
autoreconf: /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/bin/automake failed with exit status: 2
package/pkg-generic.mk:146: recipe for target '/home/projects/sunxi/buildroot-2015.08.1/output/build/alsa-lib-1.0.29/.stamp_configured' failed
make[1]: *** [/home/projects/sunxi/buildroot-2015.08.1/output/build/alsa-lib-1.0.29/.stamp_configured] Error 2
Makefile:36: recipe for target '_all' failed
make: *** [_all] Error 2

In this example, Buildroot fails to build the ALSA lib since it requires the Perl module Thread/Queue.pm that is missing.
You can easily install it, assuming that you already installed the CPAN module, by typing:

$ cpan
cpan shell -- CPAN exploration and modules installation (v2.00)
Enter 'h' for help.

cpan[1]> install Thread/Queue.pm

This kind of issues can also be present with other requirements, such as Python that can be installed with the pip utility.

Generally speaking, when you see a message like this one, there’s a good chance that the problem is a missing requirement:

autoreconf: /home/projects/sunxi/buildroot-2015.08.1/output/host/usr/bin/automake failed with exit status: 2
package/pkg-generic.mk:146: recipe for target '/home/projects/sunxi/buildroot-2015.08.1/output/build/alsa-lib-1.0.29/.stamp_configured' failed
make[1]: *** [/home/projects/sunxi/buildroot-2015.08.1/output/build/alsa-lib-1.0.29/.stamp_configured] Error 2