gpt4 book ai didi

linux - 将系统调用读取到 x86_64 上 nasm 中的 mmap 分配缓冲区后,文件描述符错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:54:27 27 4
gpt4 key购买 nike

我的 code at github 怎么了? ?

  • Strace 显示第一个 read 正常,但第二个突然 EBADF
  • fd 硬编码为 3 使其成功读取并打印多个 block 中的文件。
  • 如 github 上的 master 分支所示,使用静态分配的缓冲区,其描述符仍通过 fd 绑定(bind)传递,这也能正常工作。
  • gdb 显示 fd 位置的内存内容在进行第一个 read 系统调用后立即损坏。

让我觉得 fd 背后的内存在读入 buf 时会被覆盖,但我不知道为什么。

主要.asm:

%define     SYS_READ    0
%define SYS_WRITE 1
%define SYS_OPEN 2
%define SYS_MMAP 9
%define SYS_EXIT 60

%define PROT_READ 0x1
%define PROT_WRITE 0x2

%define MAP_ANONYMOUS 0x20
%define MAP_PRIVATE 0x02

%define STD_OUT 1
%define STD_ERR 2
%define O_RDONLY 0

%define CHUNK_SIZE 0x10 ; small to get multiple chunk reads on
; small input
; %define CHUNK_SIZE 0x1000 ; 4KiB

section .data
buf dq 0
fd dq 0

merr_read_failed db "read() failed", 0xa
merr_read_failed_size equ $-merr_read_failed

merr_open_failed db "open() failed", 0xa
merr_open_failed_size equ $-merr_read_failed

section .text
global _start

_start:
; unused labels make it easier to set breakpoints in gdb

open_file:
pop rdi
pop rdi
; pop argv[1] into rdi
pop rdi
; exit if NULL
cmp rdi, 0
je exit_bad

; open argv[1]
mov rax, SYS_OPEN
mov rsi, O_RDONLY
syscall

cmp rax, 0
jl err_open_failed
mov [fd], rax
jmp read_chunk

allocate_buffer:
mov rax, SYS_MMAP
mov rdi, 0x0
mov rsi, CHUNK_SIZE
mov rdx, PROT_READ | PROT_WRITE
mov r10, MAP_ANONYMOUS | MAP_PRIVATE
mov r8, -1
mov r9, 0
syscall
mov [buf], rax

read_chunk:
mov rax, SYS_READ
mov rdi, [fd]
mov rsi, buf
mov rdx, CHUNK_SIZE
syscall

; check for error
cmp rax, 0
jl err_read_failed
; save read byte count to r10
mov r10, rax

print_chunk:
; if last read yielded 0 bytes, exit.
; as 0 signifies an EOF
cmp r10, 0
je exit_ok

mov rax, SYS_WRITE
mov rdi, STD_OUT
mov rsi, buf
mov rdx, r10
syscall

; repeat
jmp read_chunk

err_open_failed:
mov rax, SYS_WRITE
mov rdi, STD_ERR
mov rsi, merr_open_failed
mov rdx, merr_open_failed_size
syscall

jmp exit_bad

err_read_failed:

mov rax, SYS_WRITE
mov rdi, STD_ERR
mov rsi, merr_read_failed
mov rdx, merr_read_failed_size
syscall

jmp exit_bad

exit_bad:
mov rdi, 1
jmp exit

exit_ok:
mov rdi, 0
jmp exit

exit:
mov rax, SYS_EXIT
syscall

生成文件:

all:

nasm -g -f elf64 -o main.o main.asm
ld -o main main.o

跟踪:

% strace ./main Makefile
execve("./main", ["./main", "Makefile"], [/* 54 vars */]) = 0
open("Makefile", O_RDONLY) = 3
read(3, "all:\n\n\tnasm -g -", 16) = 16
write(1, "all:\n\n\tnasm -g -", 16all:

nasm -g -) = 16
read(544043873, 0x6001e8, 16) = -1 EBADF (Bad file descriptor)
write(2, "read() failed\n", 14read() failed
) = 14
_exit(1) = ?
+++ exited with 1 +++

gdb:

(gdb) disassemble
Dump of assembler code for function read_chunk:
=> 0x000000000040014c <+0>: mov $0x0,%eax
0x0000000000400151 <+5>: mov 0x6001ec,%rdi
0x0000000000400159 <+13>: movabs $0x6001e4,%rsi
0x0000000000400163 <+23>: mov $0x10,%edx
0x0000000000400168 <+28>: syscall
0x000000000040016a <+30>: cmp $0x0,%rax
0x000000000040016e <+34>: jl 0x4001b1 <err_read_failed>
0x0000000000400170 <+36>: mov %rax,%r10
End of assembler dump.
(gdb) p 0x6001ec
$1 = 6291948
(gdb) i r rdi
rdi 0x0 0
(gdb) si
0x0000000000400151 in read_chunk ()
(gdb) i r rdi
rdi 0x0 0
(gdb) p 0x6001ec
$2 = 6291948
(gdb) x 0x6001ec
0x6001ec <fd>: 0x00000003
(gdb) si
0x0000000000400159 in read_chunk ()
(gdb) x 0x6001ec
0x6001ec <fd>: 0x00000003
(gdb) si
0x0000000000400163 in read_chunk ()
(gdb) x 0x6001ec
0x6001ec <fd>: 0x00000003
(gdb) si
0x0000000000400168 in read_chunk ()
(gdb) x 0x6001ec
0x6001ec <fd>: 0x00000003
(gdb) si
0x000000000040016a in read_chunk ()
(gdb) x 0x6001ec
0x6001ec <fd>: 0x206d7361
(gdb) disassemble
Dump of assembler code for function read_chunk:
0x000000000040014c <+0>: mov $0x0,%eax
0x0000000000400151 <+5>: mov 0x6001ec,%rdi
0x0000000000400159 <+13>: movabs $0x6001e4,%rsi
0x0000000000400163 <+23>: mov $0x10,%edx
0x0000000000400168 <+28>: syscall
=> 0x000000000040016a <+30>: cmp $0x0,%rax
0x000000000040016e <+34>: jl 0x4001b1 <err_read_failed>
0x0000000000400170 <+36>: mov %rax,%r10
End of assembler dump.
(gdb)

最佳答案

您从不调用 allocate_buffer 指令,并且在 read_chunkprint_chunk 中使用了错误的间接级别。应用此补丁后,您的代码可以正常工作:

diff --git a/main.asm b/main.asm
index c9c98e4..8c44223 100644
--- a/main.asm
+++ b/main.asm
@@ -51,7 +51,6 @@ open_file:
cmp rax, 0
jl err_open_failed
mov [fd], rax
- jmp read_chunk

allocate_buffer:
mov rax, SYS_MMAP
@@ -67,7 +66,7 @@ allocate_buffer:
read_chunk:
mov rax, SYS_READ
mov rdi, [fd]
- mov rsi, buf
+ mov rsi, [buf]
mov rdx, CHUNK_SIZE
syscall

@@ -85,7 +84,7 @@ print_chunk:

mov rax, SYS_WRITE
mov rdi, STD_OUT
- mov rsi, buf
+ mov rsi, [buf]
mov rdx, r10
syscall

jmp 删除让 allocate_buffer 指令得以执行,另外两个更改使系统调用使用分配内存的地址而不是存储该地址的地址。

发生了什么事?

您没有像 strace 显示的那样为缓冲区分配内存(没有执行 mmap 系统调用)。 buf是数据段中8字节内存(dq)的地址,程序启动时初始化为0。

您的代码直接读入 buf,从而覆盖数据部分的内容,包括 buf 之后的 fpread_chunk 的第二次迭代在 fp 中发现一个奇怪的值并崩溃。

当您跳过分配并将代码更改为读入 [buf] 时,正如我们在评论中讨论的那样,您读入了地址 0,从现在显而易见的原因来看,这会更早地使您的程序崩溃。

关于linux - 将系统调用读取到 x86_64 上 nasm 中的 mmap 分配缓冲区后,文件描述符错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27581287/

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