a2o / snoopy

Snoopy Command Logger is a small library that logs all program executions on your Linux/BSD system.
GNU General Public License v2.0
1.21k stars 155 forks source link

Loading dynamic libraries causes core dump #269

Closed wzyhay closed 2 months ago

wzyhay commented 3 months ago

Checklist before starting to submit this bug report

I confirm that:

Bug description

I compiled the code into a dynamic library file locally and loaded the dynamic library through the cp command, but a segmentation error occurred when I used this command for the second time. BossHi-20240806140831 BossHi-20240806140823 When something went wrong, there were disastrous consequences:

BossHi-20240806150834 BossHi-20240806150841

Bug reproduction steps

My debugging command is as follows: strace \cp -pf /root/hids-wazuh_agent4.3.8_0.4.1_0731/tools/snoopy/libsnoopy.so* /usr/local/lib/ BossHi-20240806150825

I think the cp command caused the so file to be truncated. I want to know how to ensure that replacing the so file is a safe operation in this environment where the process cannot be stopped and restarted. BossHi-20240806150802

Expected result

<FILLIN>

Actual result

<FILLIN>

bostjan commented 2 months ago

Hey @wzyhay, it took me a while to understand what (most likely) the problem is, mainly because I've never experienced anything like what you've described here.

So your problem here is that you're trying to manually update libsnoopy.so* on a system that is already running Snoopy and you're using the raw cp command to do it.

As you can see in your strace output, the cp indeed truncates the target file before writing the new content to it (by using the the O_TRUNC flag in the relevant open() system call). This nullifies the content of libsnoopy.so while it is already loaded into your program(s), eventually causing the crash. To understand the exact reasons for the crash, you need to be somewhat familiar with the concept of file descriptors that Linux is using behind the scenes to deal with files and their content.

On the other hand, if you'd be using the stock installer (the make install step if you're building from sources manually), it uses the program /usr/bin/install to copy the files to their target locations. I "straced" this program installing libsnoopy.so.0.0.0 onto my system and this is the (relevant) output:

# strace /usr/bin/install -c .libs/libsnoopy.so.0.0.0 /usr/local/lib/libsnoopy.so.0.0.0
...
stat("/usr/local/lib/libsnoopy.so.0.0.0", {st_mode=S_IFREG|0755, st_size=369312, ...}) = 0
stat(".libs/libsnoopy.so.0.0.0", {st_mode=S_IFREG|0755, st_size=369312, ...}) = 0
newfstatat(AT_FDCWD, "/usr/local/lib/libsnoopy.so.0.0.0", {st_mode=S_IFREG|0755, st_size=369312, ...}, AT_SYMLINK_NOFOLLOW) = 0

unlink("/usr/local/lib/libsnoopy.so.0.0.0") = 0

openat(AT_FDCWD, ".libs/libsnoopy.so.0.0.0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=369312, ...}) = 0
openat(AT_FDCWD, "/usr/local/lib/libsnoopy.so.0.0.0", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f516693c000

read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p9\0\0\0\0\0\0"..., 131072) = 131072
write(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p9\0\0\0\0\0\0"..., 131072) = 131072
read(3, "\\\236\0\0V\236\0\0\30\vk\0\0\0\0\0\0\4\5\0\0\31\1U\3\363\1U\31\1T\3"..., 131072) = 131072
write(4, "\\\236\0\0V\236\0\0\30\vk\0\0\0\0\0\0\4\5\0\0\31\1U\3\363\1U\31\1T\3"..., 131072) = 131072
read(3, "dy_locked\0__list\0pthread_mutex_u"..., 131072) = 107168
write(4, "dy_locked\0__list\0pthread_mutex_u"..., 107168) = 107168
read(3, "", 131072)                     = 0

fsetxattr(4, "system.posix_acl_access", "\2\0\0\0\1\0\6\0\377\377\377\377\4\0\0\0\377\377\377\377 \0\0\0\377\377\377\377", 28, 0) = 0

close(4)                                = 0
close(3)                                = 0

As you can see, the /usr/bin/install tool first deletes the target file, then creates a new one in its place. This way programs that have this library already loaded can continue to use the old version (by keeping its file descriptor open internally, which leads them to the original file content that Linux keeps around even after you've deleted the file itself from the filesystem, if at least one file descriptor referencing it is still kept open somewhere in the system). The newly started programs will load the new library content once it is available.

So, my suggestion here is to either use /usr/bin/install or maybe even mv after you've copied the content into a temporary file, to make your installation more transactional. I.e.:

cp /root/hids-wazuh_agent4.3.8_0.4.1_0731/tools/snoopy/libsnoopy.so.0.0.0 /usr/local/lib/libsnoopy.so.0.0.0-TMP
mv /usr/local/lib/libsnoopy.so.0.0.0-TMP /usr/local/lib/libsnoopy.so.0.0.0

(The example here is just that, an example. You'll need to figure out the exact method on your own.)

I hope this helps.