Custom ld-linux.so for subprocesses - shared-libraries

I am running a program with a set of custom libraries as follows:
/path/to/my/ld-linux-x86-64.so.2 --library-path /path/to/my/libs /path/to/my/executable
This works great for most of the programs I am trying to run, but it doesn't seem to work for one which spawns subprocesses. I'm pretty sure the subprocesses are being spawned with standard glibc execve. The subprocess is failing with a library error which appears to be caused by it not being executed properly. The program works with LD_LIBRARY_PATH set to the a directory containing all of the libraries except libc in a distroless Docker container, so I am pretty sure that I have all of the libraries correct.
I also tried using both setting LD_LIBRARY_PATH and invoking with ld-linux-x86-64.so.2, but that doesn't work either.
I think the problem is that the subprocess is reverting to the system /lib64/ld-linux-x86-64.so.2.
For context, I have a binary (and a second binary which the first invokes as a subprocess) that I didn't build that I want to run on various systems with different sets of dynamic libraries installed. Using LD_LIBRARY_PATH and providing all libraries except libc works for most environments, except for one with a really old glibc installed.

I think the problem is that the subprocess is reverting to the system /lib64/ld-linux-x86-64.so.2.
That is what one should expect to happen if the execve argument is /path/to/subprocess or subprocess.
If you want the subprocess to use explicit loader invocation /path/to/my/ld-linux-x86-64.so.2 --library-path /path/to/my/libs /path/to/subprocess, then you must arrange for execve arguments to be exactly that.
This is why using patchelf or other solutions from this answer is generally a better approach.

Related

daemonizing a lua script

I want to daemonize a lua script;
Fortunately, I see that the luaposix package offers a unistd interface, so I can call fork() etc. Unfortunately, it DOES NOT offer the setsid() function, so though I've been able to write a simple daemon, it's not complete.
I also saw that there's a luarocks package named luadaemon available spefically for this. Unfortunately, it fails to compile correctly and seems to not really be supported or developed.
I'm thinking of writing my own 'luadaemon' in C if I can't find an alternative, but I wanted to double-check first.
Is there any way to daemonize a lua script?
PS:
I'm not interested in systemd etc options
I already know about start-stop-daemon
What I'm interested in is if there's any way to write a daemon in lua directly only using lua modules.

Ptracing Process Trees

I'm looking for code examples on how to use the Linux system call ptrace() to trace system calls of a process and all its child, grandchild, etc processes. Similar to the behaviour of strace when it is fed the fork flag -f.
I'm aware of the alternative of looking into the sources of strace but I'm asking for a clean tutorial first in the hopes of getting a more isolated explanation.
I'm gonna use this to implement a fast generic system call memoizer similar to https://github.com/nordlow/strace-memoize but written in a compiled language. My current code examples I want to extend with this logic is my fork of ministrace at https://github.com/nordlow/ministrace/blob/master/ministrace.c
RTFM PTRACE_SETOPTIONS with the PTRACE_O_TRACECLONE, PTRACE_O_TRACEFORK and PTRACE_O_TRACEVFORK flags. In a nutshell, if you set it on a process, any time it creates children, those will automatically be traced as well.

strace 'open' calls in a library of an executable

I have a program with no source code.
When I run it, I have a "Can't open file..." error in the logs.
I called strace to trace the open calls on the kernel, in that way:
strace -e trace=open,close,read,write,connect,accept your-command-here
However, it seems there is none of the open calls I am expecting (that shall happen before that the log says "Can't open file...")
The executable indeed delegated the open call to a tierce library.
It seems that strace only trace the calls from the executable on the kernel, not those of the libraries depencies.
I tried to use ltrace to trace what happens in the subsequent libraries, but it doesnt display the same informations as strace, only the function calls (which are not human-readable).
Is there a way to run strace on the executable and the libraires in the same time ?
strace should be showing all of the open calls. However:
Perhaps your application calls a subprocess to do work. For that case, you can add a -f option.
On the other hand, it may be doing the work by opening a socket (or similar) connection to another process. For that case, you will not see any trace. Likewise, if you are using the syslog interface, then the actual work may be done outside your process, potentially in the kernel where you cannot trace with this tool.

Init process interaction with shell cripts

Nearly all linux courses say that init process, given the run level, will execute appropriate shell scripts to initialize the enivronment. But non of the courses describe in detail how init process does it.
As I understand the init process is basically a C program, much like any Hello World C code. Only much more sophisticated. Does anyone knows how this C program actually runs through all the scripts and invokes them?
I would really appreciate any answer and especially if you have a link to an example source code.
You can find explanations of what it does in different documentation:
http://www.centos.org/docs/5/html/5.1/Installation_Guide/s2-boot-init-shutdown-init.html
http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=4
and you can find its source code over there:
init.h
init.c
basically, init as process 1, has for role to fork() every application on your system. If you boot linux with the command line init=/bin/sh at boot time, process 1 forked by the kernel will be a shell. The sysvinit program makes it a bit more easy to handle a complex boot. It adds the concept of runlevels, define basic environment etc.. so that makes it easy to boot a system and have many services, and not only a shell. All that part is well explained in the documentations I gave you.
Does anyone knows how this C program actually runs through all the scripts and invokes them?
Well, is as simple as in your question. When you boot your system, init reads the inittab file, figures out what are your preferences (what is the default runlevel? what program to spawn? how many consoles?..), and for the chosen runlevel will fork a shell that will execute the startup script. Then that shell script will makes its way up to the shell script you activated from /etc/init.d. Usually the shell script part is very distribution-specific, that's why I gave you two links about that, and you may find it is different on ubuntu and debian...
For more details on the source code, you may want to start at the bottom of init.c which contains init's mainloop.
And +1 on your question for your curiosity!

Difference between execv and just running an app?

We have an stub that we are launching from inittab that execv's our process. (ARM Linux Kernel 2.6.25)
When testing the process it fails only if launched from inittab and execv'd. If launched on the command line it work perfectly, every time.
The process makes heavy use of SYS V IPC.
Are there any differences between the two launch methods that I should be aware of?
As Matthew mentioned it, it is probably an env variable issue. Try to dump yout env list before calling your program in both case - through the stub or 'by hand'.
BTW It could help a lot if you could provide more information why your program did crash. Log file ? core dump/gdb ? return value from execve ?
Edit:
Other checks: are you sure to pass exactly the same parameter list (if there are parameters)?
To answer your question , there is no differences between the 2 methods. Actually your shell fork() and finally call execve() to launch your process, feeding it with parameters you've provided by hand, and the environement variables you've set in your shell. Btw when launching your program through init it could launch it during an early stage of your machine startup. Are you sure everything is ready for the good running of your application at that point?
Could it be an issue of environment variables? If so, consider using execve or execle with an appropriate envp argument.
The environment variable suggestion is pretty good - specifically I'd check $PATH to make sure your dependent libraries are being found (if you have any). Another thing you could check is, are you running under the same uid/gid when run as inittab?
And if you replace your stub with a shell script ?
If it works from the command line, it should work from a shell script, and you can know wether it is your stub or the fact that it is in inittab.
Could it be a controlling tty issue ?
Another advantage of the shell script is you can edit it and strace your program to see where it fails
Was a mismatched kernel/library issue. Everything cleaned up after a full recompile.

Resources