``` #include <fcntl.h> #include <stdio.h> #include <errno.h> #include <unistd.h> int fd = open("/etc/shadow", O_RDONLY); /* 普通用户打开,内核返回-1与错误号 */ if (fd < 0) { printf("errno=%d (%s)\n", errno, strerror(errno)); /* EACCES=13,用户态解读 */ } ``` 链路:系统调用陷入内核失败时,内核在 `rax` 返回 -1,并把错误编号(如 -EACCES 转为正数 13)通过返回路径带回。glibc 包装函数识别到 -1,把错误号写入当前线程 TLS 的 `errno` 再向调用方返回 -1。`perror/strerror` 只是在用户态查错误码表拼字符串,不再陷入内核。 ``` # 对比普通用户与root打开同一文件的errno差异(隔离靶场) strace -e trace=openat ./程序 ```