Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

syscall(SYS_getuid) returns different result from getuid()

I would like to use syscalls to get the id of the current user. I tried it like this:

#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;
}

I executed it with root, but it prints -1 instead of 0.

If I replace it with int uid = syscall(SYS_getuid);, then it correctly returns 0. What do I wrong? How to get the current user id using syscall?

I run it on i686/ubuntu docker image, because I have to create 32bit executables.


Minimal reproducible example:

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;
}

Run ( On 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

The result is:

Error: Function not implemented
-1
like image 211
Iter Ator Avatar asked Nov 21 '21 10:11

Iter Ator


Video Answer


1 Answers

Per getuid(2):

The original Linux getuid() and geteuid() system calls supported only 16-bit user IDs. Subsequently, Linux 2.4 added getuid32() and geteuid32(), supporting 32-bit IDs. The glibc getuid() and geteuid() wrapper functions transparently deal with the variations across kernel versions.

Apparently you are running your program on a kernel that has the old getuid system call compiled out, and only getuid32 is available on x86-32. If you run fgrep CONFIG_UID16 "/boot/config-$(uname -r)", you will be able to see if your running kernel supports the 16-bit syscall. If this command prints anything other than CONFIG_UID16=y, it means the old system call is unavailable.

If you invoke SYS_getuid32 instead, it should work fine. Note that SYS_getuid32 may fail to be available on other architectures.

like image 56
user3840170 Avatar answered Oct 17 '22 18:10

user3840170