Can an executable dynamically resolve its location on the filesystem or its actual "resting place" vs just the working directory of the user? - linux

If I have an executable in /usr/bin and call it while I'm located at ~/dev/wikis/ (that is user#HAL:~/dev/wikis$ the_executable), the ioutil.ReadFile("file.txt") function in the executable will look in /home/user/dev/wikis/file.txt, but is it possible to make it look in /usr/bin/file.txt instead without the user or developer knowing beforehand that the executable will be located in /usr/bin (it could just as well be located in /home/user/dev/my_program/the_executable)?
And then to add a layer of complexity, another situation, say I call the executable from a symbolic link in /usr/bin with the "source" of the executable actually being in /home/user/dev/my_program/the_executable, and I want the program to know about /home/user/dev/my_program/ in this case, dynamically, rather then /usr/bin.
In short: How can an executable dynamically resolve its location on the filesystem or its actual "resting place" vs the working directory of the user (which can easily be gotten through os.Getwd() and which other commands like ioutil.ReadFile use, or use something comparible, for resolving paths).
My best bet is that I have to get the PID of the running program (os.Getpid) and then somehow use that integer to access information about the instance of the program running under that PID, and hopefully that information contains a string of its directory which I can then use.

In Linux (and perhaps in other Unixy systems) you'll find a symbolic link to the actual executable running as pid under /proc/pid/exe, checking that one will give what you want if it is a binary. If it is a script of some sort, that will probably just give the interpreter.
But note that it is perfectly possible to start a process and delete the executable while it is running, leaving either a dangling link or just nothing.

This will depend on the language but as far as I know most programming languages have a way to get either the 'basename' of the program, e.g. helloworld, or the full path, e.g. /usr/bin/helloworld. Often this is provided as the first argument to the program, inserted by the OS/runtime library/interpreter, etc. For example, in C, argv[0] (as we start counting from 0 in C) gives the name of the current program, but the calling process initialises this special argument so the exact format can vary, and in bash, $0 will expand into the path of the script as given when executed (I think). From here: https://gobyexample.com/command-line-arguments, "os.Args provides access to raw command-line arguments. Note that the first value in this slice is the path to the program, and os.Args[1:] holds the arguments to the program." So it appears you don't need to worry about /proc but if you're interested, How do I find the location of the executable in C?

The exported variable os.Args (which is a slice: []string) holds the program arguments, its first element being the executable name with full path.
If the executable is not a symlink, you can use the path or filepath packages to get the folder of the executable like this:
folder := filepath.Dir(os.Args[0])
And you can use os.Readlink() to resolve a symbolic link.
And to test if your executable is a symlink, you can use os.Lstat() which makes no attempt to follow a link (as opposed to os.Stat()).
So your final version should look like this:
s := os.Args[0]
fi, err := os.Lstat(s)
if err != nil {
panic(err) // Failed to get stats
}
// Check if it's a symlink and if so, try to resolve it
if fi.Mode()&os.ModeSymlink != 0 {
if s, err = os.Readlink(s); err != nil {
panic(err) // Failed to resolve symlink
}
}
s = filepath.Dir(s) // We only want the folder part

Related

Replace a file temporarily during an sh script run

I use an sh script to start an application in the background after setting several environment variables. I use temporary variables to start binaries from different places using LD_LIBRARY_PATH and temporary variables. Problem is that the application loads one *.so file from a hardcoded path which I cannot change. Currently I solve this problem manually by replacing the hardcoded file location with a symbolic link.
Can you tell me if there is a clean solution to solve this from the sh script? Basically what I want is that a certain file location is switched with a different binary only for open calls from the application the script starts, for all other processes it should stay the same.
Regards.
Example methods to replace open("/the/original") with open("/some/other"):
One simple method is modifying a pathname within an executable.
First copy the original executable to something like "modified" and run
a utility like bvi (similar to vim).
Consider 2 cases from comparing the length of the new vs. original pathnames:
when (new-length <= original-length), overwrite the original pathname in place
when (new-length > original-length), create a short symlink that references
the new longer pathname like the example below, then overwrite the original pathname
with the short symlink pathname,
ln -s /full/path/some/new/file /shorter
For both cases, remember to include a trailing NULL byte.
After saving changes with bvi, test the newly copied+altered executable.
Once "modified" is working to plan, could also rename for convenience:
mv xyz xyz.orig
mv modified xyz
Another method can serve a transparency requirement.
Create a dynamic library (eg custom.so) with a wrapper routine for
open() which conditionally replaces the pathname and calls the real
libc open(). Run the unmodified original executable (xyz) with another
environment variable, eg:
LD_PRELOAD=/path/to/custom.so xyz
There are some tradeoffs with versatility and modest complexity;
the original xyz is left unchanged and can always be run with/without LD_PRELOAD;
some might consider added overhead from a wrapper as undesirable;
doesn't work with statically-linked or set-uid executables.
Many articles provide instructions for creating a preload library, re-using
an original symbol like open() (frequent example is malloc()), call dlsym() once to find the regular libc open(), saving the result as a function pointer, and calling libc open() indirectly.

PWM without sysfs

I am pretty new to linux kernel.I am trying to generate PWM through linux. The API man talks about a sysfs interface. I want to implement a userspace program in C. But using PWM forces me to use a command line. Furthermore, using read, write is a problem in C as when I am using cd, it is changing path directory.
Thus the path is variable. Is there any way I can pass values to pwm_config() without using sysfs? Perhaps through ioctl? If yes, then what would be the procedure?
Application C code:
void main(){
int export = open("/sys/class/pwm/pmwchip0/export",O_WRONLY);
int period,duty_cycle,enable;
if(export == -1)
{
perror("Export:");
}
and so on for other files like period and duty cycle.
When I try to run my application I get the following error.
Export:: No such file or directory
Export_write: Bad file descriptor
Period_write:: Bad file descriptor
Duty_cycle_write:: Bad file descriptor
Enable_write:: Bad file descriptor
As far as I know, the sysfs is the only standard userspace interface to PWM. But anything you can do from the command line can be done in C (the shell is written in C, after all).
The problem you are having with cd is not actually a problem. Inside sysfs the directories in /sys/class/pwd/* are actually symbolic links to the proper devices. In your case /sys/class/pwm/pwmchip0 is a symlink to /sys/devices/soc0/amba/f8001000.timer/pwm/pwmchip0.
The funny thing is that some shells, when you cd a symbolic link will resolve to the real directory, but other shells will actually keep the symlink name as the current directory.
But that issue with the directory symlinks should not be an issue for you. A C program willing to manage PWM devices should not change the working directory. Instead open the files with the full path:
open("/sys/class/pwm/pwmchip0/npwm", O_RDONLY);
and so on.

Reversing/Debugging - Identifying symlinks in applications

I was wondering, is there any guidlines for identifying symlink related function in an application binary?
Let's take BusyBox for example, /bin/ping is a symlink to /bin/BusyBox.
How can I know identify the ping related functions within the BusyBox binary?
Thanks in advance :)
You can't generally do that.
In case of BusyBox, it checks upon startup which commandline was invoked to execute the binary (including the path to the binary itself). It then calls functions that provide the functionality that was selected based on the basename of the binary / symlink.
Again in case of BusyBox, most of the times the funktion names are closely related to the command name. But this is basically just coincidence: it could well be that someone created an exectable "A" that would call a function "X" when started via a symlink name "B" and function "Y" when called as "C".

build variable in Linux kernel Makefile

I am currently trying to understand the build process for the Linux kernel. While looking through the Makefiles, I found several rules in the form
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
which all recursively call other make processes and also pass the directory to process. Simultaneously, there seems to be a variable, which is passed, indicating what to do with the subdirectory (the $(build) part.
Looking at the make process, as far as I can see, this always seems to be obj, I cannot find any other value for this variable so far during the make process. Also, I cannot seem to find any place where this variable is set.
So what exactely is this variable for and how is it used (e.g., where is set and processed).
Not exactly. The relevant bit is in scripts/Kbuild.include, where it says
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
What this means is that if $(KBUILD_SRC) is not empty, the path to scripts/Makefile.build is given as an absolute path (or at least with a path that can be found from the working directory) by prepending the path to the top of the kernel source tree. As far as I can tell, this is to make the sub-makes all use the same Makefile and avoid having the same make code several dozen times.

is there a way to change the target of symlink /proc/self/exe?

hi all:
recently i'm working on make checkpoint on linux process and encountered a problem,it looks like that when i munmap memory map of the executable to current process,the symlink /proc/self/exe is dead.what i want is to make this symlink pointing to a other executable(the one for my resumed processs),is that possible?i tried delete it and recreate, permission denied. english is not my native language, i hope i've made my point,thanx
prctl(PR_SET_MM_EXE_FILE, ...)
Supersede the /proc/pid/exe symbolic link with a new one pointing to a new executable file identified by the file descriptor provided in arg3 argument. The file descriptor should be obtained with a regular open(2) call.
No. /proc is completely managed by the kernel and does not allow changes like that.
But you may be able to start a new process (with fork() perhaps) and map your memory snapshot into that.

Resources