gpt4 book ai didi

close() x86_64系统调用奇怪的返回值

转载 作者:太空狗 更新时间:2023-10-29 16:32:46 25 4
gpt4 key购买 nike

我的 xinetd 守护程序在内核升级后突然停止工作(从 2.6.24 到 2.6.33)。我运行了一个 strace 并发现了这个:

[...]
close(3) = 0
munmap(0x7f1a93b43000, 4096) = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=8*1024, rlim_max=16*1024}) = 0
setrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0
close(3) = 4294967287
exit_group(1) = ?

所以基本上,close 系统调用看起来返回了不同于 0 或 -1 的东西

我做了几次测试,它似乎只发生在 64 位可执行文件上:

$ file closetest32
closetest32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
$ strace closetest32
execve("./closetest32", ["closetest32"], [/* 286 vars */]) = 0
[ Process PID=4731 runs in 32 bit mode. ]
open("/proc/mounts", O_RDONLY) = 3
close(3) = 0
close(3) = -1 EBADF (Bad file descriptor)
_exit(0) = ?


$ file closetest64
closetest64: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), statically linked, not stripped
$ strace closetest64
execve("./closetest64", ["closetest64"], [/* 286 vars */]) = 0
open("/proc/mounts", O_RDONLY) = 3
close(3) = 0
close(3) = 4294967287
_exit(0) = ?

我正在运行以下内核:

Linux foobar01 2.6.33.9-rt31.64.el5rt #1 SMP PREEMPT RT Wed May 4 10:34:12 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux

最糟糕的是,我无法在具有相同内核的另一台机器上重现该错误。

有什么想法吗?

编辑:根据要求:这是用于 closetest32 和 closetest64 的代码

closetest32.asm:

.section .data

filename:
.ascii "/proc/mounts"

.section .text
.globl _start
_start:
xorl %edi, %edi
movl $5, %eax # open() i386 system call
leal filename, %ebx # %ebx ---> filename
movl $0, %esi # O_RDONLY flag into esi
int $0x80

xorl %edi, %edi
movl $6, %eax # close() i386 system call
movl $3, %ebx # fd 3
int $0x80

xorl %edi, %edi
movl $6, %eax # close() i386 system call
movl $3, %ebx # fd 3
int $0x80

## terminate program via _exit () system call
movl $1, %eax # %eax = _exit() i386 system call
xorl %ebx, %ebx # %ebx = 0 normal program return code
int $0x80

编译为:

as test32.asm -o test32.o --32
ld -m elf_i386 test32.o -o closetest32

closetest64.asm:

.section .data

filename:
.ascii "/proc/mounts"

.section .text
.globl _start
_start:
xorq %rdi, %rdi
movq $2, %rax # open() system call
leaq filename, %rdi # %rdi ---> filename
movq $0, %rsi # O_RDONLY flag into rsi
syscall

xorq %rdi, %rdi
movq $3, %rax # close() system call
movq $3, %rdi # fd 3
syscall

xorq %rdi, %rdi
movq $3, %rax # close() system call
movq $3, %rdi # fd 3
syscall

## terminate program via _exit () system call
movq $60, %rax # %rax = _exit() system call
xorq %rdi, %rdi # %rdi = 0 normal program return code
syscall

编译:

as test64.asm -o test64.o
ld test64.o -o closetest64

最佳答案

正如预期的那样,回滚到以前的内核版本解决了这个问题。我不是真正的内核专家,但据我所知,@R.. 给出的答案是有道理的:

This is a 64-bit machine, so 1<<32-9 should never appear. The problem is that the kernel is internally using unsigned instead of int for the return value of some of these functions, then returning -EBADF which gets reduced modulo 2^32 rather than modulo 2^64

The problem is that the generic code in the libc syscall wrappers that handles syscall error returns has to treat the return value as a long (since it could be a pointer or long for some syscalls) when making the comparison to see if it's a small negative value that would indicate an error. But the kernel returned (long)(unsigned)-9 which is very different from (long)-9. or (unsigned long)-9 (either of which would have worked).

关于close() x86_64系统调用奇怪的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10335448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com