From dd5eb3b9e310a55c9f13e98540f916266042808a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 23 Jan 2018 13:25:16 +0900 Subject: [PATCH] make: validate C format Signed-off-by: Akihiro Suda --- Makefile | 1 + libcontainer/nsenter/nsexec.c | 107 +++++++++++++++++----------------- script/validate-c | 42 +++++++++++++ 3 files changed, 96 insertions(+), 54 deletions(-) create mode 100755 script/validate-c diff --git a/Makefile b/Makefile index 005dedec..c6de11d5 100644 --- a/Makefile +++ b/Makefile @@ -112,6 +112,7 @@ clean: validate: script/validate-gofmt + script/validate-c $(GO) vet $(allpackages) ci: validate test release diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index a6a107e6..2c69cee5 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -22,7 +22,6 @@ #include #include - #include #include #include @@ -32,15 +31,15 @@ /* Synchronisation values. */ enum sync_t { - SYNC_USERMAP_PLS = 0x40, /* Request parent to map our users. */ - SYNC_USERMAP_ACK = 0x41, /* Mapping finished by the parent. */ - SYNC_RECVPID_PLS = 0x42, /* Tell parent we're sending the PID. */ - SYNC_RECVPID_ACK = 0x43, /* PID was correctly received by parent. */ - SYNC_GRANDCHILD = 0x44, /* The grandchild is ready to run. */ - SYNC_CHILD_READY = 0x45, /* The child or grandchild is ready to return. */ + SYNC_USERMAP_PLS = 0x40, /* Request parent to map our users. */ + SYNC_USERMAP_ACK = 0x41, /* Mapping finished by the parent. */ + SYNC_RECVPID_PLS = 0x42, /* Tell parent we're sending the PID. */ + SYNC_RECVPID_ACK = 0x43, /* PID was correctly received by parent. */ + SYNC_GRANDCHILD = 0x44, /* The grandchild is ready to run. */ + SYNC_CHILD_READY = 0x45, /* The child or grandchild is ready to return. */ /* XXX: This doesn't help with segfaults and other such issues. */ - SYNC_ERR = 0xFF, /* Fatal error, no turning back. The error code follows. */ + SYNC_ERR = 0xFF, /* Fatal error, no turning back. The error code follows. */ }; /* longjmp() arguments. */ @@ -73,7 +72,7 @@ struct nlconfig_t { char *oom_score_adj; size_t oom_score_adj_len; - /* User namespace settings.*/ + /* User namespace settings. */ char *uidmap; size_t uidmap_len; char *gidmap; @@ -82,7 +81,7 @@ struct nlconfig_t { size_t namespaces_len; uint8_t is_setgroup; - /* Rootless container settings.*/ + /* Rootless container settings. */ uint8_t is_rootless; char *uidmappath; size_t uidmappath_len; @@ -167,7 +166,7 @@ static int write_file(char *data, size_t data_len, char *pathfmt, ...) goto out; } -out: + out: close(fd); return ret; } @@ -184,16 +183,16 @@ static void update_setgroups(int pid, enum policy_t setgroup) char *policy; switch (setgroup) { - case SETGROUPS_ALLOW: - policy = "allow"; - break; - case SETGROUPS_DENY: - policy = "deny"; - break; - case SETGROUPS_DEFAULT: - default: - /* Nothing to do. */ - return; + case SETGROUPS_ALLOW: + policy = "allow"; + break; + case SETGROUPS_DENY: + policy = "deny"; + break; + case SETGROUPS_DEFAULT: + default: + /* Nothing to do. */ + return; } if (write_file(policy, strlen(policy), "/proc/%d/setgroups", pid) < 0) { @@ -226,14 +225,14 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len) if (!child) { #define MAX_ARGV 20 char *argv[MAX_ARGV]; - char *envp[] = {NULL}; + char *envp[] = { NULL }; char pid_fmt[16]; int argc = 0; char *next; snprintf(pid_fmt, 16, "%d", pid); - argv[argc++] = (char *) app; + argv[argc++] = (char *)app; argv[argc++] = pid_fmt; /* * Convert the map string into a list of argument that @@ -319,7 +318,7 @@ static int clone_parent(jmp_buf *env, int jmpval) __attribute__ ((noinline)); static int clone_parent(jmp_buf *env, int jmpval) { struct clone_t ca = { - .env = env, + .env = env, .jmpval = jmpval, }; @@ -533,7 +532,7 @@ void nsexec(void) int pipenum; jmp_buf env; int sync_child_pipe[2], sync_grandchild_pipe[2]; - struct nlconfig_t config = {0}; + struct nlconfig_t config = { 0 }; /* * If we don't have an init pipe, just return to the go routine. @@ -630,21 +629,21 @@ void nsexec(void) */ switch (setjmp(env)) { - /* - * Stage 0: We're in the parent. Our job is just to create a new child - * (stage 1: JUMP_CHILD) process and write its uid_map and - * gid_map. That process will go on to create a new process, then - * it will send us its PID which we will send to the bootstrap - * process. - */ - case JUMP_PARENT: { + /* + * Stage 0: We're in the parent. Our job is just to create a new child + * (stage 1: JUMP_CHILD) process and write its uid_map and + * gid_map. That process will go on to create a new process, then + * it will send us its PID which we will send to the bootstrap + * process. + */ + case JUMP_PARENT:{ int len; pid_t child, first_child = -1; char buf[JSON_MAX]; bool ready = false; /* For debugging. */ - prctl(PR_SET_NAME, (unsigned long) "runc:[0:PARENT]", 0, 0, 0); + prctl(PR_SET_NAME, (unsigned long)"runc:[0:PARENT]", 0, 0, 0); /* Start the process of getting a container. */ child = clone_parent(&env, JUMP_CHILD); @@ -702,7 +701,7 @@ void nsexec(void) bail("failed to sync with child: write(SYNC_USERMAP_ACK)"); } break; - case SYNC_RECVPID_PLS: { + case SYNC_RECVPID_PLS:{ first_child = child; /* Get the init_func pid. */ @@ -781,16 +780,16 @@ void nsexec(void) exit(0); } - /* - * Stage 1: We're in the first child process. Our job is to join any - * provided namespaces in the netlink payload and unshare all - * of the requested namespaces. If we've been asked to - * CLONE_NEWUSER, we will ask our parent (stage 0) to set up - * our user mappings for us. Then, we create a new child - * (stage 2: JUMP_INIT) for PID namespace. We then send the - * child's PID to our parent (stage 0). - */ - case JUMP_CHILD: { + /* + * Stage 1: We're in the first child process. Our job is to join any + * provided namespaces in the netlink payload and unshare all + * of the requested namespaces. If we've been asked to + * CLONE_NEWUSER, we will ask our parent (stage 0) to set up + * our user mappings for us. Then, we create a new child + * (stage 2: JUMP_INIT) for PID namespace. We then send the + * child's PID to our parent (stage 0). + */ + case JUMP_CHILD:{ pid_t child; enum sync_t s; @@ -799,7 +798,7 @@ void nsexec(void) close(sync_child_pipe[1]); /* For debugging. */ - prctl(PR_SET_NAME, (unsigned long) "runc:[1:CHILD]", 0, 0, 0); + prctl(PR_SET_NAME, (unsigned long)"runc:[1:CHILD]", 0, 0, 0); /* * We need to setns first. We cannot do this earlier (in stage 0) @@ -901,13 +900,13 @@ void nsexec(void) exit(0); } - /* - * Stage 2: We're the final child process, and the only process that will - * actually return to the Go runtime. Our job is to just do the - * final cleanup steps and then return to the Go runtime to allow - * init_linux.go to run. - */ - case JUMP_INIT: { + /* + * Stage 2: We're the final child process, and the only process that will + * actually return to the Go runtime. Our job is to just do the + * final cleanup steps and then return to the Go runtime to allow + * init_linux.go to run. + */ + case JUMP_INIT:{ /* * We're inside the child now, having jumped from the * start_child() code after forking in the parent. @@ -921,7 +920,7 @@ void nsexec(void) close(sync_child_pipe[1]); /* For debugging. */ - prctl(PR_SET_NAME, (unsigned long) "runc:[2:INIT]", 0, 0, 0); + prctl(PR_SET_NAME, (unsigned long)"runc:[2:INIT]", 0, 0, 0); if (read(syncfd, &s, sizeof(s)) != sizeof(s)) bail("failed to sync with parent: read(SYNC_GRANDCHILD)"); diff --git a/script/validate-c b/script/validate-c new file mode 100755 index 00000000..7c01b51e --- /dev/null +++ b/script/validate-c @@ -0,0 +1,42 @@ +#!/bin/bash + +source "$(dirname "$BASH_SOURCE")/.validate" + +IFS=$'\n' +files=($(validate_diff --diff-filter=ACMR --name-only -- '*.c' | grep -v '^vendor/' || true)) +unset IFS + +# indent(1): "You must use the ‘-T’ option to tell indent the name of all the typenames in your program that are defined by typedef." +INDENT="indent -linux -l120 -T size_t -T jmp_buf" +if [ -z "$(indent --version 2>&1 | grep GNU)" ]; then + echo "Skipping C indentation checks, as GNU indent is not installed." + exit 0 +fi + +badFiles=() +for f in "${files[@]}"; do + orig=$(mktemp) + formatted=$(mktemp) + # we use "git show" here to validate that what's committed is formatted + git show "$VALIDATE_HEAD:$f" > ${orig} + ${INDENT} ${orig} -o ${formatted} + if [ "$(diff -u ${orig} ${formatted})" ]; then + badFiles+=("$f") + fi + rm -f ${orig} ${formatted} +done + +if [ ${#badFiles[@]} -eq 0 ]; then + echo 'Congratulations! All C source files are properly formatted.' +else + { + echo "These files are not properly formatted:" + for f in "${badFiles[@]}"; do + echo " - $f" + done + echo + echo "Please reformat the above files using \"${INDENT}\" and commit the result." + echo + } >&2 + false +fi