Namespaces
What are Linux namespaces? They..
- Partition kernel resources from a process-perspective.
- Power most of Linux containerization tools.
- Appear in many Linux subsystems.
- Are used by many sandboxing solutions in browsers.
Available Linux namespaces
- mnt: Mounts
- pid: Process IDs
- net: Networking
- ipc: Interprocess Communication
- uts: Unix Timesharing (hostname)
- user: User identification & privileges
- cgroup: Process Control Groups
- time: System time
But what exactly is a namespace?
- Can be identified by a file descriptor
- A namespace can have multiple processes assigned to it
- It lives as long as there is still at least one remaining process
- Child processes inherit parent namespaces
How do I create a namespace?
unshare(2)
func main() {
err := syscall.Unshare(syscall.CLONE_NEWNS);
}
How do I create a namespace?
static int child(void *arg) {
struct utsname uts;
sethostname(arg, "ernie")
uname(&uts)
printf("nodename in child: %s\n", uts.nodename);
return 0;
}
int main() {
struct utsname uts;
// Allocate stack for child
char *stack = malloc(STACK_SIZE);
if (stack == NULL)
return -1;
// Start new kernel task in new UTS namespace
pid_t child_pid = clone(child, stack + STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL);
// Output hostname
uname(&uts)
printf("nodename in parent: %s\n", uts.nodename);
}
How can I share a namespace with other processes?
Joining namespace of another process: /proc
You can join the namespace of another process by using /proc/{pid}/ns/*
fd := syscall.Open("/proc/1234/ns/uts", syscall.O_RDONLY);
err := unix.Setns(fd, syscall.CLONE_NEWUTS);
Note: Can only set a single namespace per netns(2)
invocation.
Joining namespace of another process: pidfd_open
You can join the namespace of another process by using pidfd_open(2)
pid_t pid = 1234;
int fd = pidfd_open(pid, 0);
setns(fd, CLONE_NEWUTS | CLONE_NEWNET);
Note: Can only set a multiple namespaces per netns(2)
invocation.
Persisting namespaces
err := syscall.Mount("/proc/self/ns/uts",
"/home/acs/my_uts_namespace", "", syscall.MS_BIND, nil);
And in another process...
fd := syscall.Open("/home/acs/my_uts_namespace", syscall.O_RDONLY);
err := unix.Setns(fd, syscall.CLONE_NEWUTS);