You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Execve系统调用未设置errno且未返回-1的问题排查

问题原因及解决方法

1. 系统调用参数完全错误

你对execve系统调用的参数传递存在两处关键错误:

  • execve的第一个参数(%ebx)需要是指向路径字符串的指针(即command[0],也就是"/bin/sh"的地址),但你传递的是command数组本身的地址(char**类型),内核无法识别这个错误路径,返回错误码ENOENT(数值2),对应系统调用返回值-2(即0xfffffffe)。
  • execve的第二个参数(%ecx)需要是指向argv数组的指针(即command的地址),但你错误地将其设为0,不符合系统调用的参数要求。

2. 直接调用int $0x80不会自动设置errno

C标准库的errno是由libc封装系统调用时负责设置的。当你直接用汇编指令int $0x80调用系统调用时,libc不会介入处理,errno会保持初始值0,这就是perror输出"Success"的原因。系统调用的错误码会直接通过%eax返回(失败时返回-errnum,比如-2对应错误码2)。

修复后的代码

#include <stdio.h>
#include <errno.h>

int main() {
    char *command[] = { "/bin/sh", NULL };

    asm volatile(
        "movl $11, %%eax\n"      // 32位execve系统调用号为11
        "movl %0, %%ebx\n"       // ebx: 路径字符串指针(command[0])
        "movl %1, %%ecx\n"       // ecx: argv数组指针(command)
        "xorl %%edx, %%edx\n"    // edx: 空环境变量数组
        "int $0x80\n"            // 触发系统调用
        "movl %%eax, %2\n"       // 将返回值存入临时变量
        : "=r"(command[0]), "=r"(command), "=m"(errno)
        :
        : "%eax", "%ebx", "%ecx", "%edx"
    );

    // 转换系统调用返回值为正确的errno格式
    if (errno < 0) {
        errno = -errno;
    }
    perror("execve failed");
    return 1;
}

额外说明

  • 如果只是为了获取shell,直接调用libc的execve函数更简单可靠:execve("/bin/sh", command, NULL);,无需手动编写汇编。
  • 32位Linux系统调用的参数传递规则:%eax存系统调用号,%ebx、%ecx、%edx依次存放第1到第3个参数。
  • 若execve调用成功,会直接替换当前进程的代码段,不会执行到后续的perror代码;一旦执行到perror,说明系统调用必然失败。

内容的提问来源于stack exchange,提问作者nadav levin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:07:26