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



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

我的第一个想法,对我来说也是最安全的,是切换应用程序线程的用户上下文并在那里执行所有读/写操作。这可能吗?

如果这是可能的,性能会是什么样子?我认为每次请求进入时生成操作系统线程可能会产生非常高的开销。有没有更好的方法可以做到这一点?

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

在 GNU/Linux 上,不可能只为进程的单个线程切换 UID 和 GID。 Linux 内核维护每线程凭据,但 POSIX 要求每个进程一组凭据:POSIXsetuid必须更改所有线程的 UID 或不更改任何线程。 glibc不遗余力地模仿POSIX行为,尽管这相当困难。

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

我认为@Florian在他的原始答案中得到了这个倒退。man 2 setuid

C 库/内核差异

在内核级别,用户 ID 和组 ID 是每个线程的属性。 但是,POSIX 要求进程中的所有线程 共享相同的凭据。 NPTL 线程实现句柄 通过为各种包装器提供包装器函数来满足 POSIX 要求 更改过程的系统调用 定向识别和 GID。 这些包装函数(包括用于 setuid((的包装函数(采用基于信号的技术来确保当一个 线程更改凭据,进程中的所有其他线程 同时更改其凭据。 有关详细信息,请参阅nptl(7(。

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

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

最新更新