bpftrace: uprobe target file does not exist or is not executable - linux

I want to use bpftrace to trace functions inside libasan library, which is inside /usr/lib/x86_64-linux-gnu/.
However
sudo bpftrace -e 'uretprobe:/usr/lib/x86_64-linux-gnu/libasan.so.4: __interceptor_malloc { printf("pid: %d, malloc %p\n", pid, retval); }'
gives error: uprobe target file '/usr/lib/x86_64-linux-gnu/libasan.so.4' does not exist or is not executable
I have tried: export LD_LIBRARY_PATH="/lib:/usr/lib:/usr/local/lib" but it does not help.
How can make the library executable for bpftrace? I need it to trace allocations done in a Firefox process. Thanks!
EDIT: I just found out that the permission on libasan is -rw-r--r--, which means it is indeed not executable. How should I make it executable?

I fixed it by doing chmod +x libasan.so.4.0.0

Related

echo into '/proc/filename' gives "Operation Not Permitted" error

Platform: Ubuntu 5.15.0-43-generic.
I have written a loadable kernel module to create a file under /proc called testproc. The kernel module loads perfectly and created the /proc/testproc. The permissions on /proc/testproc are 0666 and owned by root. I am logged in as root for all operations.
I have implemented the read and write handler in my kernel module and they get called too.
When I run the command
echo "Hello" > /proc/testproc
the error seen is
bash: echo: write error: Operation not permitted
I am using the call
proc_create("testproc", 0666, NULL, &procfsFuncs)
to create the entry under /proc
Any pointers much appreciated.
I figured out my (trivial) mistake. I was expecting a non-zero result from copy_from_user(), when in reality copy_from_user returns 0 on success.

no core dump in /var/crash

I am trying to understand a bit how the core dump work.
I use the test.c file to generate a core dump :
#include <stdio.h>
void foo()
{
int *ptr = 0;
*ptr = 7;
}
int main()
{
foo();
return 0;
}
I compile with
gcc test.c -o test
Which gives me the following message when I run ./test
Segmentation fault (core dumped)
My file
/proc/sys/kernel/core_pattern
contains :
|/usr/share/apport/apport %p %s %c %d %P
I checked that I have the permissions to write to the directory
/var/crash/
but after the core dump there is nothing in this folder (/var/crash/).
I am using Linux release 17.04.
Do you know what can go wrong here?
edit
I forgot to mention that I set the limits with :
ulimit -c unlimited
so the output of
ulimit -c
reads :
unlimited
I even tried to do what they say here in section How to enable apport, so I added a hash sign in front of
'problem_types': ['Bug', 'Package']
But with all of this the core dump cannot be found in /var/cash
This link contains a checklist for why coredump is not generated. Adding the list below in case link becomes inaccessible in future.
The core would have been larger than the current limit.
You don't have the necessary permissions to dump core (directory and file). Notice that core dumps are placed in the dumping process' current directory which could be different from the parent process.
Verify that the file system is writeable and have sufficient free space.
If a sub directory named core exist in the working directory no core will be dumped.
If a file named core already exist but has multiple hard links the kernel will not dump core.
Verify the permissions on the executable, if the executable has the suid or sgid bit enabled core dumps will by default be disabled. The same will be the case if you have execute permissions but no read permissions on the file.
Verify that the process has not changed working directory, core size limit, or dumpable flag.
Some kernel versions cannot dump processes with shared address space (AKA threads). Newer kernel versions can dump such processes but will append the pid to the file name.
The executable could be in a non-standard format not supporting core dumps. Each executable format must implement a core dump routine.
The segmentation fault could actually be a kernel Oops, check the system logs for any Oops messages.
The application called exit() instead of using the core dump handler.
I was also struggling to get coredumps and I had the same problem with ulimit. The session specific setting suggested by Niranjan also didn't work for me.
Finally I found the solution at https://serverfault.com/questions/216656/how-to-set-systemwide-ulimit-on-ubuntu
in /etc/security/limits.conf add:
root - core unlimited
* - core unlimited
And log out / log in.
Then
ulimit -c
on the terminal should return "unlimited" and core dumps are generated.
What filesize limit have you set for coredumps in your machine?
You can check it using
$ ulimit -c
If it is set to 0, then no coredumps will be generated - This is the default setting in most distros.
You can enable coredumps by setting it to 'unlimited' or using a specific filesize limit.
$ ulimit -c unlimited

Perf: kernel module symbols not showing up in profiling

On loading and running a kernel module and then profiling through perf.
$perf record -a -g --call-graph dwarf sleep 30'
$perf report
my kernel module's symbols are not present in the perf's report.
Although the symbols are present in /proc/kallsyms.
Also the module is not present in perf buildid-list
As this answer says to make the module a kernel module, I tried but didn't help.
What are the possible reasons that could lead to this?
The message Failed to open [thrUserCtrl], continuing without symbols sounds like perf was unable to find your module. Try installing it into
/lib/modules/`uname -r`/extra
directory as said in https://wiki.centos.org/HowTos/BuildingKernelModules:
6. In this example, the file cifs.ko has just been created.
As root, copy the .ko file to the /lib/modules/<kernel-version>/extra/
directory.
[root#host linux-2.6.18.i686]# cp fs/cifs/cifs.ko /lib/modules/`uname -r`/extra
(don't forget depmod -a command after changing files in /lib/modules)
This message is generated in map__load: http://elixir.free-electrons.com/linux/v4.11/source/tools/perf/util/map.c#L284
int map__load(struct map *map)
{
const char *name = map->dso->long_name;
int nr;
...
nr = dso__load(map->dso, map);
if (nr < 0) {
if (map->dso->has_build_id) {
...
} else
pr_warning("Failed to open %s", name);
pr_warning(", continuing without symbols\n");
return -1;
when dso__load function returns error.

How to get cwd for relative paths?

How can I get current working directory in strace output, for system calls that are being called with relative paths? I'm trying to debug complex application that spawns multiple processes and fails to open particular file.
stat("some_file", 0x7fff6b313df0) = -1 ENOENT (No such file or directory)
Since some_file exists I believe that its located in the wrong directory. I'd tried to trace chdir calls too, but since output is interleaved its hard to deduce working directory that way. Is there a better way?
You can use the -y option and it will print the full path. Another useful flag in this situation is -P which only traces syscalls relating to a specific path, e.g.
strace -y -P "some_file"
Unfortunately -y will only print the path of file descriptors, and since your call doesn't load any it doesn't have one. A possible workaround is to interrupt the process when that syscall is run in a debugger, then you can get its working directory by inspecting /proc/<PID>/cwd. Something like this (totally untested!)
gdb --args strace -P "some_file" -e inject=open:signal=SIGSEGV
Or you may be able to use a conditional breakpoint. Something like this should work, but I had difficulty with getting GDB to follow child processes after a fork. If you only have one process it should be fine I think.
gdb your_program
break open if $_streq((char*)$rdi, "some_file")
run
print getpid()
It is quite easy, use the function char *realpath(const char *path, char *resolved_path) for the current directory.
This is my example:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
char *abs;
abs = realpath(".", NULL);
printf("%s\n", abs);
return 0;
}
output
root#ubuntu1504:~/patches_power_spec# pwd
/root/patches_power_spec
root#ubuntu1504:~/patches_power_spec# ./a.out
/root/patches_power_spec

linux: getting umask of an already running process?

How can I check the umask of a program which is currently running?
[update: another process, not the current process.]
You can attach gdb to a running process and then call umask in the debugger:
(gdb) attach <your pid>
...
(gdb) call umask(0)
[Switching to Thread -1217489200 (LWP 11037)]
$1 = 18 # this is the umask
(gdb) call umask(18) # reset umask
$2 = 0
(gdb)
(note: 18 corresponds to a umask of O22 in this example)
This suggests that there may be a really ugly way to get the umask using ptrace.
Beginning with Linux kernel 4.7, the umask is available in /proc/<pid>/status.
From the GNU C Library manual:
Here is an example showing how to read the mask with umask
without changing it permanently:
mode_t
read_umask (void)
{
mode_t mask = umask (0);
umask (mask);
return mask;
}
However, it is better to use getumask if you just want to read
the mask value, because it is reentrant (at least if you use the
GNU operating system).
getumask is glibc-specific, though. So if you value portability, then the non-reentrant solution is the only one there is.
Edit: I've just grepped for ->umask all through the Linux source code. There is nowhere that will get you the umask of a different process. Also, there is no getumask; apparently that's a Hurd-only thing.
If you're the current process, you can write a file to /tmp and check its setting. A better solution is to call umask(3) passing zero - the function returns the setting prior to the call - and then reset it back by passing that value back into umask.
The umask for another process doesn't seem to be exposed.
A colleague just showed me this command line pattern for this. I always have emacs running, so that's in the example below. The perl is my contribution:
sudo gdb --pid=$(pgrep emacs) --batch -ex 'call/o umask(0)' -ex 'call umask($1)' 2> /dev/null | perl -ne 'print("$1\n")if(/^\$1 = (\d+)$/)'

Resources