From patchwork Mon Aug 29 11:47:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 9303695 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2C2D2607F0 for ; Mon, 29 Aug 2016 11:47:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C758285E2 for ; Mon, 29 Aug 2016 11:47:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 100AD287B6; Mon, 29 Aug 2016 11:47:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B461285E2 for ; Mon, 29 Aug 2016 11:47:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932984AbcH2Lrk (ORCPT ); Mon, 29 Aug 2016 07:47:40 -0400 Received: from mail-it0-f43.google.com ([209.85.214.43]:35813 "EHLO mail-it0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932745AbcH2Lri (ORCPT ); Mon, 29 Aug 2016 07:47:38 -0400 Received: by mail-it0-f43.google.com with SMTP id x131so97830651ite.0 for ; Mon, 29 Aug 2016 04:47:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=kb+xfqtnzMZ8q0WVXCVuaowm9TtxtieNleBHbRjI8Tg=; b=RZ1kAAoNBWYelwEmoaNukvbZPPGe+v4eRoqSmqONHvZy0vTbjII+VEf84LiPZuXHC4 vW/Sd9rMArFcgBgifPuDKgDJQfDB21n6R/GzPC5a2sMhDE54fvhmIRvCU4oRRqyjp/lK /HnFRsqOF9W//HXwBptEwl5dqLxFq3agpxBjY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=kb+xfqtnzMZ8q0WVXCVuaowm9TtxtieNleBHbRjI8Tg=; b=ERtn11Bwh9F15Rfu/jbmDv8vfwOl4+nfJ2jOiPco6fkc4V2Wfswc9poj5UxniUcZ+e Yh2bImNX6s3pv9CBsMx9cM61KXjDBWBYQpzS5QsYzdVLHW2K2XC4Nm5e8y8WWec6ClVS BwKNG+cxbeQmcbErNdxHPxNFrivAiS5vZ/YvMVBfzXtqA/nJAtZLFQksaKCt3/xcF3fW tRARHM+mfBdtbETQ5khI6gkt+jN1OMmhdfJ+lyjlz0887OXLL98Kk63pleiFVRuQHjyb LcfwhByAF1glv4xlCbi9epr+6PRctcA8Q1KzvD9PkLVdcfthx0z6W3U3dHDvYqqb+KV/ iVUA== X-Gm-Message-State: AE9vXwPLYdZkG7LkaRnkZtbg1HFFoz/PZA73ztpdSEHix2rHgGokYSpXYzJ2bQInAu+i3A== X-Received: by 10.36.26.70 with SMTP id 67mr15719449iti.4.1472471257900; Mon, 29 Aug 2016 04:47:37 -0700 (PDT) Received: from ircssh.c.rugged-nimbus-611.internal (55.145.251.23.bc.googleusercontent.com. [23.251.145.55]) by smtp.gmail.com with ESMTPSA id 15sm3181537itl.0.2016.08.29.04.47.37 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 29 Aug 2016 04:47:37 -0700 (PDT) Date: Mon, 29 Aug 2016 04:47:36 -0700 From: Sargun Dhillon To: netdev@vger.kernel.org Cc: cgroups@vger.kernel.org, linux-security-module@vger.kernel.org, daniel@iogearbox.net, ast@fb.com Subject: [net-next RFC v2 7/9] samples/bpf: Split out helper code from test_current_task_under_cgroup_user Message-ID: <20160829114734.GA20906@ircssh.c.rugged-nimbus-611.internal> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This splits out the cgroup helper code from test_current_task_under_cgroup_user.c This code can be used to test any program that needs to setup a cgroup v2 hierarchy temporarily, and put itself into said hierarchy. It also includes some functions that make moving around in the hierarchy a bit easier. This patch is used in follow on samples. Signed-off-by: Sargun Dhillon --- samples/bpf/Makefile | 2 +- samples/bpf/cgroup_helpers.c | 103 ++++++++++++++++++++++ samples/bpf/cgroup_helpers.h | 15 ++++ samples/bpf/test_current_task_under_cgroup_user.c | 72 +++------------ 4 files changed, 129 insertions(+), 63 deletions(-) create mode 100644 samples/bpf/cgroup_helpers.c create mode 100644 samples/bpf/cgroup_helpers.h diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index db3cb06..5d2c178 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -50,7 +50,7 @@ test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o xdp1-objs := bpf_load.o libbpf.o xdp1_user.o # reuse xdp1 source intentionally xdp2-objs := bpf_load.o libbpf.o xdp1_user.o -test_current_task_under_cgroup-objs := bpf_load.o libbpf.o \ +test_current_task_under_cgroup-objs := bpf_load.o libbpf.o cgroup_helpers.o \ test_current_task_under_cgroup_user.o # Tell kbuild to always build the programs diff --git a/samples/bpf/cgroup_helpers.c b/samples/bpf/cgroup_helpers.c new file mode 100644 index 0000000..e465497 --- /dev/null +++ b/samples/bpf/cgroup_helpers.c @@ -0,0 +1,103 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cgroup_helpers.h" + +#define CGROUP_MOUNT_PATH "/mnt" + +int add_controller(char *controller) +{ + int fd, rc = 0; + + fd = open("cgroup.subtree_control", O_WRONLY); + if (fd < 0) { + log_err("Unable to open subtree_control"); + return 1; + } + if (dprintf(fd, "+%s\n", controller) < 0) { + log_err("Adding Controller"); + rc = 1; + } + close(fd); + return rc; +} + +int mkdirp(char *path) +{ + int rc; + + rc = mkdir(path, 0777); + if (rc && errno == EEXIST) + return 0; + return rc; +} + +/* + * This is to avoid interfering with existing cgroups. Unfortunately, + * most people don't have cgroupv2 enabled at this point in time. + * It's easier to create our own mount namespace and manage it + * ourselves. This function drops you into the top of that cgroup2 + * mount point, so make sure you call load_bpf before calling this. + */ +int setup_cgroups(void) +{ + if (unshare(CLONE_NEWNS)) { + log_err("unshare"); + return 1; + } + + if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) { + log_err("mount fakeroot"); + return 1; + } + + if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) { + log_err("mount cgroup2"); + return 1; + } + + if (chdir(CGROUP_MOUNT_PATH)) { + log_err("chdir"); + return 1; + } + + return 0; +} + +int join_cgroup(char *path) +{ + char cgroup_path[1024]; + pid_t pid = getpid(); + int fd, rc = 0; + + snprintf(cgroup_path, sizeof(cgroup_path), "%s/cgroup.procs", path); + + fd = open(cgroup_path, O_WRONLY); + if (fd < 0) { + log_err("Opening Cgroup"); + return 1; + } + + if (dprintf(fd, "%d\n", pid) < 0) { + log_err("Joining Cgroup"); + rc = 1; + } + close(fd); + return rc; +} + +int reset_bpf_hook(int fd) +{ + if (dprintf(fd, "0\n") < 0) { + log_err("Unable to reset BPF hook"); + return 1; + } + return 0; +} diff --git a/samples/bpf/cgroup_helpers.h b/samples/bpf/cgroup_helpers.h new file mode 100644 index 0000000..f9f1bdf --- /dev/null +++ b/samples/bpf/cgroup_helpers.h @@ -0,0 +1,15 @@ +#ifndef __CGROUP_HELPERS_H +#define __CGROUP_HELPERS_H +#include + +#define clean_errno() (errno == 0 ? "None" : strerror(errno)) +#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \ + __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) + +int mkdirp(char *path); +int setup_cgroups(void); +int join_cgroup(char *path); +int reset_bpf_hook(int fd); +int add_controller(char *controller); + +#endif diff --git a/samples/bpf/test_current_task_under_cgroup_user.c b/samples/bpf/test_current_task_under_cgroup_user.c index 30b0bce..752a254 100644 --- a/samples/bpf/test_current_task_under_cgroup_user.c +++ b/samples/bpf/test_current_task_under_cgroup_user.c @@ -11,44 +11,12 @@ #include #include "libbpf.h" #include "bpf_load.h" -#include #include #include #include -#include -#include -#include -#include -#include +#include "cgroup_helpers.h" -#define CGROUP_MOUNT_PATH "/mnt" -#define CGROUP_PATH "/mnt/my-cgroup" - -#define clean_errno() (errno == 0 ? "None" : strerror(errno)) -#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \ - __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) - -static int join_cgroup(char *path) -{ - int fd, rc = 0; - pid_t pid = getpid(); - char cgroup_path[PATH_MAX + 1]; - - snprintf(cgroup_path, sizeof(cgroup_path), "%s/cgroup.procs", path); - - fd = open(cgroup_path, O_WRONLY); - if (fd < 0) { - log_err("Opening Cgroup"); - return 1; - } - - if (dprintf(fd, "%d\n", pid) < 0) { - log_err("Joining Cgroup"); - rc = 1; - } - close(fd); - return rc; -} +#define CGROUP_NAME "test_current_task_under" int main(int argc, char **argv) { @@ -62,33 +30,13 @@ int main(int argc, char **argv) return 1; } - /* - * This is to avoid interfering with existing cgroups. Unfortunately, - * most people don't have cgroupv2 enabled at this point in time. - * It's easier to create our own mount namespace and manage it - * ourselves. - */ - if (unshare(CLONE_NEWNS)) { - log_err("unshare"); - return 1; - } - - if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) { - log_err("mount fakeroot"); + if (setup_cgroups()) return 1; - } - if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) { - log_err("mount cgroup2"); + if (mkdirp(CGROUP_NAME)) return 1; - } - - if (mkdir(CGROUP_PATH, 0777) && errno != EEXIST) { - log_err("mkdir cgroup"); - return 1; - } - cg2 = open(CGROUP_PATH, O_RDONLY); + cg2 = open(CGROUP_NAME, O_RDONLY); if (cg2 < 0) { log_err("opening target cgroup"); goto cleanup_cgroup_err; @@ -98,7 +46,7 @@ int main(int argc, char **argv) log_err("Adding target cgroup to map"); goto cleanup_cgroup_err; } - if (join_cgroup("/mnt/my-cgroup")) { + if (join_cgroup(CGROUP_NAME)) { log_err("Leaving target cgroup"); goto cleanup_cgroup_err; } @@ -119,7 +67,7 @@ int main(int argc, char **argv) } /* Verify the negative scenario; leave the cgroup */ - if (join_cgroup(CGROUP_MOUNT_PATH)) + if (join_cgroup(".")) goto leave_cgroup_err; remote_pid = 0; @@ -133,13 +81,13 @@ int main(int argc, char **argv) goto cleanup_cgroup_err; } - rmdir(CGROUP_PATH); + rmdir(CGROUP_NAME); return 0; /* Error condition, cleanup */ leave_cgroup_err: - join_cgroup(CGROUP_MOUNT_PATH); + join_cgroup("."); cleanup_cgroup_err: - rmdir(CGROUP_PATH); + rmdir(CGROUP_NAME); return 1; }