Skip to main content

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);