'pivot_root'ing a thread

Hi,
pivot_root manual says:

pivot_root() changes the root directory and the current working directory of each process or thread in the same mount namespace to new_root if they point to the old root directory.

That's what I'm trying to achieve (using nix crate) - spawning a thread, pivoting it to specific directory on filesystem so when performing FS operations on the spawned thread, it could only perform FS operations in selected directory. The problem is I have 0 idea how it could be done. By threads I assume they mean kernel threads but Rust thread (spawned by std::thread::spawn) is not equal to kernel thread so I'm completely lost how it should be done. I would really appreciate any help

I'm pretty sure std::thread:spawn uses native OS threads. You can find some of the system integration glue here: https://github.com/rust-lang/rust/tree/master/library/std/src/sys, and unix/thread.rs manages threads using pthread.

With that said -- are you sure you're not parsing the manual wrong? The way I read it is that it is meant to say that it will pivot root on the process, including any potential extra threads within those processes. (Though admittedly, it's not phrased the best possible way).

If I'm parsing it wrong, then I must say that being able to pivot root only a thread sounds quite suspicious.

pivot_root applies to a mount namespace. So you need to move the individual thread into a new mount ns, which is done with the unshare syscall. Unsharing a mountns in turn requires CAP_SYS_ADMIN, which can be obtained by unsharing the user namespace, which for non-root processes requires a kernel with unprivileged user namespace support.

That's all rather complicated and still not very secure because running a thread within the same process means you're sharing resources such as memory and file descriptors.
If all you want is to limit filename resolution when opening specific files then you can use the openat2 syscall instead which allows things like RESOLVE_BENEATH.

By threads I assume they mean kernel threads but Rust thread (spawned by std::thread::spawn) is not equal to kernel thread

Rust follows an 1:1 threading model. A std::thread::Thread corresponds to one OS thread.

I'm pretty sure std::thread:spawn uses native OS threads. You can find some of the system integration glue here: rust/library/std/src/sys at master · rust-lang/rust · GitHub , and unix/thread.rs manages threads using pthread.

Thank you for clarifying, my bad

With that said -- are you sure you're not parsing the manual wrong? The way I read it is that it is meant to say that it will pivot root on the process, including any potential extra threads within those processes. (Though admittedly, it's not phrased the best possible way)

Hmm, didn't think of that. I'll try to find out.

If I'm parsing it wrong, then I must say that being able to pivot root only a thread sounds quite suspicious.

Well if I remember correctly basically Linux see a thread as a process so it makes some sense

pivot_root applies to a mount namespace. So you need to move the individual thread into a new mount ns, which is done with the unshare syscall. Unsharing a mountns in turn requires CAP_SYS_ADMIN, which can be obtained by unsharing the user namespace, which for non-root processes requires a kernel with unprivileged user namespace support.

Thank you!

That's all rather complicated and still not very secure because running a thread within the same process means you're sharing resources such as memory and file descriptors.

That shouldn't be an issue. I'm trying to use it as some sort of extra "security layer" for path traversal prevention.

If all you want is to limit filename resolution when opening specific files then you can use the openat2 syscall instead which allows things like RESOLVE_BENEATH.

Thanks for suggestion but sadly it's not usable for my case.

The kernel does. But libraries may get confused when different threads within a process have different views on the filesystem. An absolute Path calculated on one thread and passed to another could end up pointing to the wrong location. It could even confuse libraries that cache handles to directories or files.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.