0

Is there a way to give a process on Linux based systems unique permissions in C? I basically want to restrict a process (launched by a host, like an event handler) from editing any files outside it's working directory, and creating sockets and such.

Would the only way to do it is to have a host process create a new user for each process it spawns and destroy the user afterwards?

Jeroen
  • 15,257
  • 12
  • 59
  • 102
  • 1
    It might be overkill, but this sort of thing can be handled with `chroot()`. – jxh Feb 23 '14 at 20:37
  • 1
    The danger is that most of the possible mechanisms require root privileges to effect the change. You can look up `chroot()` — but be aware that it is tricky to create an appropriate environment for a `chroot()` program; you can look up BSD 'jails'; you can consider simply setting the real and effective UID and GID to a user/group that can't change anything outside the directory (but note that it will still be able to read publicly accessible files, such as `/etc/passwd`). – Jonathan Leffler Feb 23 '14 at 20:42

2 Answers2

2

The standard answer to this is chroot, which sets the process's root directory (and that of its children) to be the given directory.

However, if you want a better answer allowing you to isolate all aspects of the process and not just its file system, look at the unshare system call (wrapped in a modern glibc as a function). This is how containers are built.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • Do I need root permissions do an `unshare` call? – Jeroen Feb 23 '14 at 21:12
  • 1
    This http://man7.org/linux/man-pages/man2/unshare.2.html implies not for `CLONE_FS`. You will need root (more accurately `CAP_SYS_ADMIN`) for some of the other `unshare` calls. Personally I've not used `CLONE_FS` without others. – abligh Feb 23 '14 at 21:16
  • 1
    Also note technically `chroot()` requires `CAP_SYS_CHROOT` rather than root or `CAP_SYS_ADMIN`, though normally they come together. – abligh Feb 23 '14 at 21:18
  • Would LXC be a thing worthy looking into? – Jeroen Feb 28 '14 at 19:35
  • 1
    `lxc` under the hood just uses the `unshare` system call. It's going to be heavier weight than your question implies the need for as you are going to need a complete container copy of the OS - not just one process. If you want that, the lightest weight solution is Docker (http://docker.io/) – abligh Feb 28 '14 at 20:17
  • I'm confused now, as Googling taught me that Docker uses LXC? – Jeroen Feb 28 '14 at 20:35
  • `lxc` is used both for the kernel capabilities (in that sense `unshare` is part of `lxc`) and for a set of command line userspace tools (which is what I thought you meant). My understanding is Docker uses the former but not the latter. See http://linuxcontainers.org/ http://stackoverflow.com/questions/17989306/what-does-docker-add-to-just-plain-lxc http://lxc.sourceforge.net/man/lxc.html – abligh Feb 28 '14 at 21:54
  • Will `unshare` be sufficient to block malicious code? – Jeroen Mar 01 '14 at 14:18
  • 1
    It depends what kind of malicious code. Malicious code that exploits a kernel vulnerability may still succeed. Malicious code that exhausts resources (e.g. disk I/O, memory) may still succeed unless you use `cgroups` or similar to control them. – abligh Mar 01 '14 at 14:21
  • Well, I understand that due to a weakness in the kernel a program might still succeed exploiting the system, but at that point it's beyond my control anyway. I might go with `unshare` and control groups then. That seems to create a pretty secure container. Just can't figure out how `unshare` works. I know it sets up new namespaces, but what to do once you've done that? – Jeroen Mar 01 '14 at 14:23
  • Run `init` or a new process or whatever you want. You might also look at http://openvz.org/ – abligh Mar 01 '14 at 14:43
1

You could use old setuid techniques to switch your process to the nobody uid and nogroup gid. Theses ids are designed to make a process unable to write any files (except inside all-writable directories).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547