From 4a7199a3daaf0f4b9360203fd89d9e290c1d256a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 18 Jun 2020 10:21:55 +0000 Subject: [PATCH] netns-exec: add c program to execute commands in netns c program allows executing commands in nb-bitcoind, nb-lnd, nb-liquidd (the netns's needed for operator cli scripts). --- pkgs/default.nix | 1 + pkgs/netns-exec/default.nix | 11 +++++ pkgs/netns-exec/src/Makefile | 2 + pkgs/netns-exec/src/main.c | 86 ++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 pkgs/netns-exec/default.nix create mode 100644 pkgs/netns-exec/src/Makefile create mode 100644 pkgs/netns-exec/src/main.c diff --git a/pkgs/default.nix b/pkgs/default.nix index ee95b3e..f710f04 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -10,6 +10,7 @@ liquid-swap = pkgs.python3Packages.callPackage ./liquid-swap { }; generate-secrets = pkgs.callPackage ./generate-secrets { }; nixops19_09 = pkgs.callPackage ./nixops { }; + netns-exec = pkgs.callPackage ./netns-exec { }; pinned = import ./pinned.nix; } diff --git a/pkgs/netns-exec/default.nix b/pkgs/netns-exec/default.nix new file mode 100644 index 0000000..bafd516 --- /dev/null +++ b/pkgs/netns-exec/default.nix @@ -0,0 +1,11 @@ +{ stdenv, pkgs }: + +stdenv.mkDerivation { + name = "netns-exec"; + buildInputs = [ pkgs.libcap ]; + src = ./src; + installPhase = '' + mkdir -p $out + cp main $out/netns-exec + ''; +} diff --git a/pkgs/netns-exec/src/Makefile b/pkgs/netns-exec/src/Makefile new file mode 100644 index 0000000..8fa3e95 --- /dev/null +++ b/pkgs/netns-exec/src/Makefile @@ -0,0 +1,2 @@ +main: main.c + gcc -lcap -o main main.c diff --git a/pkgs/netns-exec/src/main.c b/pkgs/netns-exec/src/main.c new file mode 100644 index 0000000..aec799c --- /dev/null +++ b/pkgs/netns-exec/src/main.c @@ -0,0 +1,86 @@ +/* This program must be run with CAP_SYS_ADMIN. This can be achieved for example + * with + * # setcap CAP_SYS_ADMIN+ep ./main + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +static char *available_netns[] = { + "nb-lnd", + "nb-bitcoind", + "nb-liquidd" +}; + +int check_netns(char *netns) { + int i; + int n_available_netns = sizeof(available_netns) / sizeof(available_netns[0]); + for (i = 0; i < n_available_netns; i++) { + if (strcmp(available_netns[i], netns) == 0) { + return 1; + } + } + return 0; +} + +void print_capabilities() { + cap_t caps = cap_get_proc(); + printf("Capabilities: %s\n", cap_to_text(caps, NULL)); + cap_free(caps); +} +void drop_capabilities() { + cap_t caps = cap_get_proc(); + cap_clear(caps); + cap_set_proc(caps); + cap_free(caps); +} + +int main(int argc, char **argv) { + int fd; + char netns_path[256]; + + if (argc < 3) { + printf("usage: %s \n", argv[0]); + return 1; + } + + if (!check_netns(argv[1])) { + printf("Failed checking %s against available netns.\n", argv[1]); + return 1; + } + + if(snprintf(netns_path, sizeof(netns_path), "/var/run/netns/%s", argv[1]) < 0) { + printf("Failed concatenating %s to the netns path.\n", argv[1]); + return 1; + } + + fd = open(netns_path, O_RDONLY); + if (fd < 0) { + printf("Failed opening netns %s: %d, %s \n", netns_path, errno, strerror(errno)); + return 1; + } + + if (setns(fd, CLONE_NEWNET) < 0) { + printf("Failed setns %d, %s \n", errno, strerror(errno)); + return 1; + } + + /* Drop capabilities */ + #ifdef DEBUG + print_capabilities(); + #endif + drop_capabilities(); + #ifdef DEBUG + print_capabilities(); + #endif + + execvp(argv[2], &argv[2]); + return 0; +} +