Background
I have an embedded Linux devices and need to invoke a subprocess. I try to avoid it but sometimes it's the most practical thing to do, e.g. calling networking commands like ip
, networkmanager
or doing data processing using an proprietary program.
The simplest thing to do is to call system(3)
but then these bad things can happen:
- Neither program name or arguments are sanitized.
- PATH is modified by an attacker causing the wrong program to be executed
- Another environment variable such as `IFS is modified by the attacker
- If the attacker has been able to gain access to the child program, he may see open files which were not closed
- And he/she may be able to gain elevated privileges if root privileges were not dropped.
So I probably should not rely on system(3)
but write my own fork+exec function; pass the full path to the binary to be executed; make any arguments to the child process hard-coded; sanitize the environment variable; close open files; and drop privileges.
I've read the advice given in TAOSSA and John Viegas Secure Programming Cookbook. Thomas Ptacek gives a survey of sandboxing and isolation techniques for Linux in Sandboxing and Workflow Isolation but I haven't found anything discussing smaller, embedded systems. The OWASP Security guidelines discusses command injection but only mentions sanitizing of environment and ensuring that the path to the binary can't be altered.
My Question
- Are these steps sufficient?
- Can someone point to generic implementation of procedures for safely executing subprocesses in C and C++
- Do I have to drop capabilities as well?
- Should I consider running child processes in more isolation? If so, what options are available to me? seccomp filters? Namespace sandboxing?
The Generic Question
- How should an embedded Linux system be partitioned? What isolation should exist between different processes? Is it worthwhile to implement a safe
system(3)
or is the isolation provided thereby to fine-grained to be meaningful?