Skip to content

Commit

Permalink
pinns: allow sysctls to be passed
Browse files Browse the repository at this point in the history
sysctls must be passed to pinns of the format -s 'key=value'+'key2=value2'
also, move the pinns source code to `pinns/src` to clean up the top level directory a bit

Signed-off-by: Peter Hunt <[email protected]>
  • Loading branch information
haircommander committed Sep 11, 2020
1 parent 3f655aa commit 26de5b6
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 2 deletions.
5 changes: 4 additions & 1 deletion pinns/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
src = $(wildcard *.c)
src = $(wildcard src/*.c)
obj = $(src:.c=.o)

STRIP ?= strip
Expand All @@ -12,6 +12,9 @@ all: ../bin/pinns
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
$(STRIP) -s $@

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -O3 -o $@ -c $<

../bin:
mkdir -p $@

Expand Down
12 changes: 11 additions & 1 deletion pinns/pinns.c → pinns/src/pinns.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sys/wait.h>

#include "utils.h"
#include "sysctl.h"

static int bind_ns(const char *pin_path, const char *filename, const char *ns_name, pid_t pid);
static int directory_exists_or_create(const char* path);
Expand All @@ -42,6 +43,7 @@ int main(int argc, char **argv) {
bool bind_ipc = false;
bool bind_user = false;
bool bind_cgroup = false;
char *sysctls = NULL;

static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
Expand All @@ -54,9 +56,10 @@ int main(int argc, char **argv) {
{"filename", required_argument, NULL, 'f'},
{"uid-mapping", optional_argument, NULL, UID_MAPPING},
{"gid-mapping", optional_argument, NULL, GID_MAPPING},
{"sysctl", optional_argument, NULL, 's'},
};

while ((c = getopt_long(argc, argv, "pchuUind:f:", long_options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "pchuUind:f:s:", long_options, NULL)) != -1) {
switch (c) {
case 'u':
unshare_flags |= CLONE_NEWUTS;
Expand Down Expand Up @@ -89,6 +92,9 @@ int main(int argc, char **argv) {
case 'd':
pin_path = optarg;
break;
case 's':
sysctls = optarg;
break;
case 'f':
filename = optarg;
break;
Expand Down Expand Up @@ -174,6 +180,10 @@ int main(int argc, char **argv) {
pexit("Cannot write gid mappings");
}

if (sysctls && configure_sysctls(sysctls) < 0) {
pexit("Failed to configure sysctls after unshare");
}

if (bind_user) {
if (bind_ns(pin_path, filename, "user", pid) < 0) {
return EXIT_FAILURE;
Expand Down
120 changes: 120 additions & 0 deletions pinns/src/sysctl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#define _GNU_SOURCE

#include <string.h>
#include <fcntl.h>

#include "sysctl.h"
#include "utils.h"

static int separate_sysctl_key_value (char* sysctl_key_value, char** sysctl_key, char** sysctl_value);
static int write_sysctl_to_file (char * sysctl_key, char* sysctl_value);
const char *sysctl_delim = "+";

int configure_sysctls (char * const sysctls)
{
char* sysctl = strtok(sysctls, sysctl_delim);
char* key = NULL;
char* value = NULL;
while (sysctl)
{
if (separate_sysctl_key_value (sysctl, &key, &value) < 0)
return -1;

if (write_sysctl_to_file (key, value) < 0)
return -1;
sysctl = strtok (NULL, sysctl_delim);
}

return 0;
}

// key_value should be in the form `'k=v'`
static int separate_sysctl_key_value (char* key_value, char** key, char** value)
{
// begin by stripping the `'`, we now have `k=v'`
bool quote_stripped = false;
if (*key_value == '\'')
{
key_value++;
quote_stripped = true;
}

// now find the `=` and convert it to a delimiter
char * equals_token = strchr (key_value, '=');
if (!equals_token)
{
nwarnf ("sysctl must be in the form of 'key=value'; '=' missing from %s", key_value);
return -1;
}

// if the location of the equals sign is the beginning of the string
// key is empty
if (equals_token == key_value)
{
nwarnf ("sysctl must be in the form of 'key=value'; key is empty");
return -1;
}

// we now have `k\0v'`
*equals_token = '\0';

// key is now `k`
*key = key_value;

// equals_token is now `v'`
++equals_token;

// if we stripped the beginning single quote
// we should find and strip the ending, as well as anything after
if (quote_stripped)
{
char* ending_char = strchr (equals_token, '\'');
if (ending_char)
*ending_char = '\0';
}

// value is now `v`
*value = equals_token;
if (!strlen (*value))
{
nwarnf ("sysctl must be in the form of 'key=value'; value is empty");
return -1;
}
return 0;
}

static int write_sysctl_to_file (char * sysctl_key, char* sysctl_value)
{
if (!sysctl_key || !sysctl_value)
{
pwarn ("sysctl key or value not initialized");
return -1;
}

// replace periods with / to create the sysctl path
for (char* it = sysctl_key; *it; it++)
if (*it == '.')
*it = '/';

_cleanup_close_ int dirfd = open ("/proc/sys", O_DIRECTORY | O_PATH | O_CLOEXEC);
if (UNLIKELY (dirfd < 0))
{
pwarn ("failed to open /proc/sys");
return -1;
}

_cleanup_close_ int fd = openat (dirfd, sysctl_key, O_WRONLY);
if (UNLIKELY (fd < 0))
{
pwarnf ("failed to open /proc/sys/%s", sysctl_key);
return -1;
}

int ret = TEMP_FAILURE_RETRY (write (fd, sysctl_value, strlen (sysctl_value)));
if (UNLIKELY (ret < 0))
{
pwarnf ("failed to write to /proc/sys/%s", sysctl_key);
return -1;
}
return 0;
}
7 changes: 7 additions & 0 deletions pinns/src/sysctl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#if !defined(SYSCTL_H)
#define SYSCTL_H

int configure_sysctls (char * const sysctls);

#endif // SYSCTL_H
4 changes: 4 additions & 0 deletions pinns/utils.h → pinns/src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <syslog.h>
#include <unistd.h>
Expand Down Expand Up @@ -93,4 +94,7 @@ static inline void fclosep(FILE **fp) {
#define _cleanup_close_ _cleanup_(closep)
#define _cleanup_fclose_ _cleanup_(fclosep)

# define LIKELY(x) __builtin_expect((x),1)
# define UNLIKELY(x) __builtin_expect((x),0)

#endif /* !defined(UTILS_H) */

0 comments on commit 26de5b6

Please sign in to comment.