Why ... in syscall uses a different dirfd than previously opened?

With LD_PRELOADI print all open file descriptors, but then syscalls ...atuse different file descriptors. Why?

The simplest example possible:

Here is my library foobar.c- it intercepts all calls open...and prints file descriptors, and also outputs arguments to callsunlinkat

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>

int open(const char *pathname, int flags, ...)
{
    int fd = ((int (*) (const char*, int, ...))dlsym(RTLD_NEXT, "open"))(pathname, flags);
    printf("open pathname %s fd %d\n", pathname, fd);
    return fd;  
}

int open64(const char *pathname, int flags, ...)
{
    int fd = ((int (*) (const char*, int, ...))dlsym(RTLD_NEXT, "open64"))(pathname, flags);
    printf("open64 pathname %s fd %d\n", pathname, fd);
    return fd;  
}

int openat(int dirfd, const char* pathname, int flags, ...) {
    int fd = ((int (*) (int, const char*, int, ...))dlsym(RTLD_NEXT, "openat"))(dirfd, pathname, flags);
    printf("openat pathname %s fd %d\n", pathname, fd);
    return fd;
}    

int unlinkat(int dirfd, const char *pathname, int flags) {
    printf("unlinkat dirfd %d pathname %s\n", dirfd, pathname); 
    return ((int (*) (int, const char*, int))dlsym(RTLD_NEXT, "unlinkat"))(dirfd, pathname, flags);
}

I did not dupenable hooks to make it simple, they are not called.

Now note that the library is working fine, I find that all file descriptors are open, they are all 3, but the open file descriptor that is being called unlinkatis 4. Why?

/tmp>mkdir -p dir/dir1
/tmp>gcc -shared  -fPIC -ldl foobar.c -o foobar.so
/tmp>LD_PRELOAD=$PWD/foobar.so rm -rf dir
openat pathname dir fd 3
openat pathname dir1 fd 3
unlinkat dirfd 4 pathname dir1
unlinkat dirfd -100 pathname dir
+4
1
[mitalia@mitalia /tmp]$ mkdir -p dir/dir1
[mitalia@mitalia /tmp]$ strace rm -rf dir
execve("/bin/rm", ["rm", "-rf", "dir"], [/* 76 vars */]) = 0
brk(0)                                  = 0x1538000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4c779a2000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=211009, ...}) = 0
mmap(NULL, 211009, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4c7796e000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4c773bd000
mprotect(0x7f4c77578000, 2093056, PROT_NONE) = 0
mmap(0x7f4c77777000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7f4c77777000
mmap(0x7f4c7777d000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f4c7777d000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4c7796d000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4c7796b000
arch_prctl(ARCH_SET_FS, 0x7f4c7796b740) = 0
mprotect(0x7f4c77777000, 16384, PROT_READ) = 0
mprotect(0x60d000, 4096, PROT_READ)     = 0
mprotect(0x7f4c779a4000, 4096, PROT_READ) = 0
munmap(0x7f4c7796e000, 211009)          = 0
brk(0)                                  = 0x1538000
brk(0x1559000)                          = 0x1559000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=5766672, ...}) = 0
mmap(NULL, 5766672, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4c76e3d000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
lstat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
newfstatat(AT_FDCWD, "dir", {st_mode=S_IFDIR|0775, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "dir", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 3 entries */, 32768)     = 72
close(3)                                = 0
openat(AT_FDCWD, "dir", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fcntl(3, F_GETFD)                       = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fcntl(3, F_DUPFD, 3)                    = 4
fcntl(4, F_GETFD)                       = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 3 entries */, 32768)     = 72
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
newfstatat(4, "dir1", {st_mode=S_IFDIR|0775, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(4, "dir1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 2 entries */, 32768)     = 48
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
unlinkat(4, "dir1", AT_REMOVEDIR)       = 0
close(4)                                = 0
unlinkat(AT_FDCWD, "dir", AT_REMOVEDIR) = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

4 - , fcntl F_DUPFD, dup2; , - .

, , (dup, dup2, dup3, fcntl F_DUPFD , , , t ).

, , LD_PRELOAD C, - "" (int 0x80 x86, sysenter x86_64 ) . - () ptrace ( PTRACE_SYSCALL ), , , strace.

+5

Source: https://habr.com/ru/post/1628975/


All Articles