我正在尝试保护我的应用程序免受缓冲区溢出攻击.除此之外,我正在使用不可执行的堆栈并将我的二进制文件与noexecstack标志链接(通过传递-Wl,-z,noexecstack给gcc).
一切似乎都很好 - readelf确认PT_GNU_STACK指定了正确的权限:
$ readelf -l target | grep -A1 GNU_STACK
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
Run Code Online (Sandbox Code Playgroud)
那样做execstack:
$ execstack -q target
- target
Run Code Online (Sandbox Code Playgroud)
只有一个问题.我的所有堆栈实际上都是可执行的:
root@170ubuntu16p04-64smp-1:~# cat /proc/12878/task/*/maps | grep stack
7ffcac654000-7ffcac675000 rwxp 00000000 00:00 0 [stack]
7fe540e66000-7fe541666000 rwxp 00000000 00:00 0 [stack]
7fe540665000-7fe540e65000 rwxp 00000000 00:00 0 [stack]
7fe53b800000-7fe53c000000 rwxp 00000000 00:00 0 [stack]
Run Code Online (Sandbox Code Playgroud)
我已经捕获了allocate_stack调用并检查了保护标志.从理论上讲,它们应该按照初始化PT_GNU_STACK.但在我的情况下,似乎PT_GNU_STACK被忽略并_dl_stack_flags使用默认权限进行初始化.
有谁知道是什么原因造成的?一切似乎都是正确的,但堆栈仍然是可执行的.
我正在使用gcc …
我从fanotify接收文件系统事件.有时我想获得正在访问的文件的绝对路径.
通常情况下,这不是一个问题- fanotify_event_metadata包含一个文件描述符fd,这样我就可以叫readlink上/proc/self/fd/<fd>,让我的道路.
但是,如果路径超出,PATH_MAX readlink则无法再使用 - 它失败了ENAMETOOLONG.我想知道在这种情况下是否有办法获得文件路径.
显然,我可以fstat通过fanotify获取描述符并遍历整个文件系统,查找具有相同设备ID和inode编号的文件.但是这种方法对我来说在性能方面是不可行的(即使我优化它以忽略短于的路径PATH_MAX).
我试图通过重新打开获得父目录fd与O_PATH和调用openat(fd, "..", ...).显然,失败是因为fd没有引用目录.我也尝试在readlink调用失败后检查缓冲区的内容(希望它包含部分路径).那也行不通.
到目前为止,我已经设法为打开它们的进程的工作目录中的文件获取长路径(fanotify事件包含pid一个目标进程,因此我可以/proc/<pid>/cwd从那里读取并获取到根路径).但这是部分解决方案.
有没有办法从文件描述符获取绝对路径而不遍历整个文件系统?最好是与内核2.6.32/glibc 2.11一起使用的那个.
更新:对于好奇.我已经弄清楚为什么readlink("/proc/self/fd/<fd>", ...用足够大的缓冲区调用来存储整个路径是行不通的.
看看do_proc_readlink的实现.请注意,它不buffer直接使用提供.相反,它会分配一个页面,并在调用d_path时将其用作临时缓冲区.换句话说,无论多大buffer,d_path总是限于一个页面的大小.这是amd64上的4096字节.一样PATH_MAX!在-ENAMETOOLONG本身是由返回前插,当它用完提到的页面.