是否可以切换应用程序线程的用户和组?

Is this possible to switch the user and group of an application thread?

我想用 Rust 构建一个小型 Web 应用程序,它应该能够代表用户读取和写入文件。用户应该使用他们的 UNIX 凭据进行身份验证,然后只能读取/写入他们有权访问的文件。

我的第一个想法(对我来说也是最安全的)是切换应用程序线程的用户上下文并在那里执行所有 read/write-stuff。这可能吗?

如果可以的话,效果会怎样?我假设每次收到请求时都生成一个操作系统线程可能会产生非常高的开销。有更好的方法吗?

我真的不想运行我的整个应用程序作为 root 并手动检查权限。

在GNU/Linux上,无法仅针对进程的单个线程切换UID 和GID。 Linux 内核维护每个线程的凭据,但 POSIX 每个进程需要一组凭据:POSIX setuid 必须更改所有线程的 UID 或 none. glibc 竭尽全力模仿 POSIX 行为,尽管这非常困难。

您必须为每个请求创建一个全新的进程,而不仅仅是一个新线程。在 Linux 上创建进程非常便宜,但它仍然可能是一个性能问题。您可以保留一个进程池,以避免重复创建进程的开销。另一方面,在很多年前,很多网站(包括一些比较大的网站)都使用CGI生成网页,设计简单就可以走得比较远。

我认为@Florian 在他原来的回答中把这个倒退了。 man 2 setuid

C library/kernel differences

At the kernel level, user IDs and group IDs are a per-thread attribute. However, POSIX requires that all threads in a process share the same credentials. The NPTL threading implementation handles the POSIX requirements by providing wrapper functions for the various system calls that change process UIDs and GIDs. These wrapper functions (including the one for setuid()) employ a signal-based technique to ensure that when one thread changes credentials, all of the other threads in the process also change their credentials. For details, see nptl(7).

由于 libc 会在整个过程中执行信号舞蹈,因此您必须直接进行系统调用才能绕过它。

请注意,这是 linux 特有的。大多数其他 unix 变体似乎在内核级别遵循 posix,而不是在 libc 中模拟它。