syscall(SYS_getuid)的返回值与getuid()不同。

5

我想使用系统调用来获取当前用户的ID。我尝试了以下代码:

#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    int uid = syscall(SYS_getuid);
    
    printf("%d\n", uid);
    
    return 0;
}

我以root身份运行它,但它打印出的是-1而不是0

如果我用int uid = syscall(SYS_getuid);替换它,则可以正确返回0。我错在哪里了?如何使用syscall获取当前用户ID?

我在 Docker镜像上运行它,因为我必须创建32位可执行文件。


最小可重现示例:

Dockerfile

FROM i686/ubuntu

RUN apt-get update
RUN apt-get install --assume-yes --no-install-recommends --quiet \
        gcc libc6-dev
RUN apt-get clean all

main.c

#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(int argc, char *argv[])
{
    
    int uid = syscall(SYS_getuid);//getuid();//
    
    if(uid == -1)
        printf("Error: %s\n", strerror(errno));
    
    printf("%d\n", uid);
    
    return 0;
}

在x64 Windows10上运行:

docker build --platform linux/386 -t my-gcc .
docker run --platform linux/386 --rm -v ${pwd}:/usr/local/src/:rw my-gcc gcc -m32 -xc /usr/local/src/main.c -o /usr/local/src/main
docker run --platform linux/386 --rm -v ${pwd}:/usr/local/src/:rw my-gcc /usr/local/src/main

结果是:

Error: Function not implemented
-1

我在i686 / ubuntu docker镜像上运行它。您是在哪里以及如何编译的?像往常一样 - [MCVE]。您的主机架构和系统是什么?对我来说,docker run -ti --rm i686/ubuntu然后apt-get update && apt-get install gcc && printf'%s\n' '#include <unistd.h>' '#include <sys/syscall.h>' '#include <stdio.h>' 'main() { printf("%d\n", syscall(SYS_getuid)); }' | gcc -m32 -xc - && ./a.out可以正常工作并返回0。请创建一个完整的[MCVE]。 - KamilCuk
1
@KamilCuk 我提供了一个最小的示例。 - Iter Ator
1
我想使用系统调用来获取当前用户的ID。为什么?这不是获取当前用户UID的标准方式,因此不能保证获得相同的结果。请注意,标准的getuid()函数返回一个uid_t,它不一定是一个int。您认为使用syscall(SYS_getuid)解决了什么问题? - Andrew Henle
1
@AndrewHenle 我想学习/练习使用系统调用。获取用户ID似乎是一个简单的第一步练习。我想了解这为什么不起作用,以及其中的区别。 - Iter Ator
1
你可以打印出 SYS_getuid 常量的值吗?如果这是一个32位的Linux程序,它应该等于24,如https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86-32_bit所示。如果它是102,则意味着你不知何故包括了64位头文件。 - Nate Eldredge
1个回答

5

针对 getuid(2):

原始的 Linux getuid() 和 geteuid() 系统调用仅支持 16 位用户 ID。随后,Linux 2.4 添加了 getuid32() 和 geteuid32(),支持 32 位 ID。glibc 的 getuid() 和 geteuid() 包装函数透明地处理跨内核版本的变化。

显然,您正在运行程序的内核中编译了旧的 getuid 系统调用,并且只有在 x86-32 上可用 getuid32。如果您运行 fgrep CONFIG_UID16 "/boot/config-$(uname -r)",您将能够看到您正在运行的内核是否支持 16 位系统调用。如果此命令打印除 CONFIG_UID16=y 之外的任何内容,则表示旧的系统调用不可用。

如果您调用SYS_getuid32,它应该可以正常工作。请注意,SYS_getuid32在其他架构上可能无法使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接