Change UID/GID only of one thread in Linux
Asked Answered
K

2

10

Is there a way to change UID/GID only of one thread in a multithreaded process?

The reason for this is writing a file-serving application - the ACL's and quota are not enforced unless the uid/gid of the caller is set to the correct user, new files/directories are not created with correct uid/gid etc.

The network applications can usually fork() themselves at the beginning and process each user request in separate process. If there is a need for shared data, it must go through some kind of shared memory. However, e.g. the FUSE (linux user filesystem) by default uses multithreading and in conjuction with python bindings it wouldn't be practical to try to use a forking model.

The 'consistent' UID for a whole process seems to be according to the POSIX standard, however old Linuxes didn't follow the POSIX and allowed different uids for different threads. The new kernels seem to follow POSIX, is there some way to allow the old 'broken' behaviour?

Kyd answered 3/8, 2009 at 17:36 Comment(0)
D
11

The Linux-specific setfsuid() / setfsgid() are per-thread rather than per-process. They're designed specifically for this use case (file server).

Note that access() will still check access using the real uid and gid - that is by design (it is intended to answer the question "should the user who ran this binary have the given access to this file"). For the setfsuid() / setfsgid() case you should just try the requested operation and detect failure due to lack of permission at that point.

Dhumma answered 4/8, 2009 at 2:26 Comment(5)
This is better - I have checked and surprisingly found out that they are really per-thread. This would probably be the preferred way. However - the reason I did not test it is, that quota() and access() do not work. Other things do work - so this is probably Linux bug.Kyd
Yes, that does sound like a bug, since the comments in the kernel code for sys_setfsuid() specifically mention access()...Dhumma
@Ondrej, please post code (or a link to it), demonstrating that fsuid is, unlike other UID/GID constructs, per-thread and not per-process. Please also specify your kernel and glibc versions, as well as your threading implementation (NPTL, LinuxThreads, OndrejThreads, etc.).Armenta
pilcrow, I did some really simple tests using python and threads. However: the quota() works, but one must drop some capability (CAP_RESOURCE, I think) before checking. access() does not work, and 'should not' work according to the POSIX. To me it seems to be a bug in POSIX (second I have found) and it doesn't seem that anyone in Linux would be interested in changing it :(Kyd
pthreads stands (aka posix threads) are designed with the posix standard in mind. because fsuid is not a posix construct it is not sent to the other threads and host process like setuid is. It is per process but in the case of pthreads the processes are usually LWPs and not forksLevina
B
13

To change the uid only for one thread you need to use the syscall directly: syscall(SYS_setresuid, ...); The libc function setresuid() will synchronize it for all threads (using a singal which it sends to all threads)!

Binetta answered 19/9, 2014 at 11:48 Comment(0)
D
11

The Linux-specific setfsuid() / setfsgid() are per-thread rather than per-process. They're designed specifically for this use case (file server).

Note that access() will still check access using the real uid and gid - that is by design (it is intended to answer the question "should the user who ran this binary have the given access to this file"). For the setfsuid() / setfsgid() case you should just try the requested operation and detect failure due to lack of permission at that point.

Dhumma answered 4/8, 2009 at 2:26 Comment(5)
This is better - I have checked and surprisingly found out that they are really per-thread. This would probably be the preferred way. However - the reason I did not test it is, that quota() and access() do not work. Other things do work - so this is probably Linux bug.Kyd
Yes, that does sound like a bug, since the comments in the kernel code for sys_setfsuid() specifically mention access()...Dhumma
@Ondrej, please post code (or a link to it), demonstrating that fsuid is, unlike other UID/GID constructs, per-thread and not per-process. Please also specify your kernel and glibc versions, as well as your threading implementation (NPTL, LinuxThreads, OndrejThreads, etc.).Armenta
pilcrow, I did some really simple tests using python and threads. However: the quota() works, but one must drop some capability (CAP_RESOURCE, I think) before checking. access() does not work, and 'should not' work according to the POSIX. To me it seems to be a bug in POSIX (second I have found) and it doesn't seem that anyone in Linux would be interested in changing it :(Kyd
pthreads stands (aka posix threads) are designed with the posix standard in mind. because fsuid is not a posix construct it is not sent to the other threads and host process like setuid is. It is per process but in the case of pthreads the processes are usually LWPs and not forksLevina

© 2022 - 2024 — McMap. All rights reserved.