Search code examples
c++linuxdlopen

dopen(): "failed to map segment from shared object" when not running as root


I am trying to load some self-written libraries under a self-made Yocto Linux.

It works fine when running the same program as root, but not as another, later added user.

for (<all files found in directory>)
{
    m_HModule = dlopen(Filename.c_str(), RTLD_NOW | RTLD_GLOBAL);

    if (m_HModule == NULL)
    {
        fprintf(stderr, "Error: %s\n", dlerror());
    }
    else
    {
        cout << "Loaded module " << Filename << endl;
    }
}

Unfortunately, my version of dlerror() does not return too terribly precise information:

Loaded module /opt/epic/libepicGpioToggle.so
Loaded module /opt/epic/libepicSaveImage.so
Error: libboost_filesystem.so.1.66.0: failed to map segment from shared object
Loaded module /opt/epic/libepicFpgaCommunicatorUserDemo.so
Error: /opt/epic/libepicCommunicatorFpga.so: failed to map segment from shared object
Error: /opt/epic/libepicDataproviderTimedData.so: failed to map segment from shared object
Error: /opt/epic/libepicDataproviderFromCamera.so: failed to map segment from shared object
Loaded module /opt/epic/libepicFramework.so
Error: /opt/epic/libepicTriggerMonitor.so: failed to map segment from shared object
Error: /opt/epic/libepicTemplate.so: failed to map segment from shared object

Even with maximum file permissions chmod 777 * and all libraries being owned by the calling user, it does not work. Everything works fine when running as root or via sudo.

Yes, some of these libraries use boost elements, which are all available unter /lib and accessible by the calling user. If I do not try to load the libraries referencing boost, the other failures persist.

It is always the same libraries failing to load; the order does not seem to matter. The compiler settings for all of my libraries look the same, and are all abbreviated from the same "template project".

I checked the dependencies with ldd, straced all system calls and do not see any difference, apart from the error messages.

The user's shell environment env is the same as for root.

With export LD_DEBUG=files, I see

      4231: file=/opt/epic/libepicSaveImage.so [0];  dynamically loaded by ./libepicFramework.so [0]
      4231: file=/opt/epic/libepicSaveImage.so [0];  generating link map
      4231:   dynamic: 0x0000ffff8b56fd60  base: 0x0000ffff8b524000   size: 0x000000000004d608
      4231:     entry: 0x0000ffff8b5487a0  phdr: 0x0000ffff8b524040  phnum:                  7
      4231: 
      4231: 
      4231: file=/opt/epic/libepicGpioToggle.so [0];  needed by /opt/epic/libepicSaveImage.so [0] (relocation dependency)
      4231: 
      4231: 
      4231: calling init: /opt/epic/libepicSaveImage.so
      4231: 
      4231: opening file=/opt/epic/libepicSaveImage.so [0]; direct_opencount=1
      4231: 
Loaded module /opt/epic/libepicSaveImage.s

for successful loadings, but

      4231: file=/opt/epic/libepicCommunicatorFpga.so [0];  dynamically loaded by ./libepicFramework.so [0]
      4231: file=/opt/epic/libepicCommunicatorFpga.so [0];  generating link map
Error: /opt/epic/libepicCommunicatorFpga.so: failed to map segment from shared object

for failures.

User limits ulimits -a look the same for both root and user:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 10974
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 10974
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

I increased max locked memory to 100's of MB, but no change.

What could be different from the user's perspective?


Solution

  • @JohnBollinger was right - it was the user's limits, with 16384 kbytes being too small for "max memory size".

    I had to increase the limit in /etc/security/limits.conf for the specific user by adding

    username soft memlock unlimited
    username hard memlock unlimited
    

    and then configuring SSHD to obey these limits by adding

    session    required     pam_limits.so
    

    to /etc/pam.d/sshd.

    Being root ignores all set limits, no matter if logged on through SSH, directly or via RS-232 TTY.

    Thanks for pointing me into the right direction!