Merge pull request #58 from pandax381/support-cgroup-net-cls

Support cgroup net_cls subsystem
This commit is contained in:
robertswiecki
2017-10-25 15:35:35 +02:00
committed by GitHub
7 changed files with 102 additions and 0 deletions

View File

@@ -462,6 +462,12 @@ Options:
Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')
--cgroup_pids_parent VALUE
Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')
--cgroup_net_cls_classid VALUE
Class identifier of network packets in the group (default: '0' - disabled)
--cgroup_net_cls_mount VALUE
Location of net_cls cgroup FS (default: '/sys/fs/cgroup/net_cls')
--cgroup_net_cls_parent VALUE
Which pre-existing net_cls cgroup to use as a parent (default: 'NSJAIL')
--iface_no_lo
Don't bring up the 'lo' interface
--macvlan_iface|-I VALUE

View File

@@ -123,6 +123,46 @@ static bool cgroupInitNsFromParentPids(struct nsjconf_t* nsjconf, pid_t pid)
return true;
}
static bool cgroupInitNsFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_net_cls_classid == (unsigned int)0) {
return true;
}
char net_cls_cgroup_path[PATH_MAX];
snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
LOG_D("Create '%s' for PID=%d", net_cls_cgroup_path, (int)pid);
if (mkdir(net_cls_cgroup_path, 0700) == -1 && errno != EEXIST) {
PLOG_E("mkdir('%s', 0711) failed", net_cls_cgroup_path);
return false;
}
char fname[PATH_MAX];
if (nsjconf->cgroup_net_cls_classid != (unsigned int)0) {
char net_cls_classid_str[512];
snprintf(net_cls_classid_str, sizeof(net_cls_classid_str), "0x%x", nsjconf->cgroup_net_cls_classid);
snprintf(fname, sizeof(fname), "%s/net_cls.classid", net_cls_cgroup_path);
LOG_D("Setting '%s' to '%s'", fname, net_cls_classid_str);
if (!utilWriteBufToFile(
fname, net_cls_classid_str, strlen(net_cls_classid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update net_cls cgroup classid");
return false;
}
}
char pid_str[512];
snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
snprintf(fname, sizeof(fname), "%s/tasks", net_cls_cgroup_path);
LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
LOG_E("Could not update net_cls cgroup task list");
return false;
}
return true;
}
bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid)
{
if (cgroupInitNsFromParentMem(nsjconf, pid) == false) {
@@ -131,6 +171,9 @@ bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid)
if (cgroupInitNsFromParentPids(nsjconf, pid) == false) {
return false;
}
if (cgroupInitNsFromParentNetCls(nsjconf, pid) == false) {
return false;
}
return true;
}
@@ -164,10 +207,26 @@ void cgroupFinishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid)
return;
}
void cgroupFinishFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid)
{
if (nsjconf->cgroup_net_cls_classid == (size_t)0) {
return;
}
char net_cls_cgroup_path[PATH_MAX];
snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
LOG_D("Remove '%s'", net_cls_cgroup_path);
if (rmdir(net_cls_cgroup_path) == -1) {
PLOG_W("rmdir('%s') failed", net_cls_cgroup_path);
}
return;
}
void cgroupFinishFromParent(struct nsjconf_t* nsjconf, pid_t pid)
{
cgroupFinishFromParentMem(nsjconf, pid);
cgroupFinishFromParentPids(nsjconf, pid);
cgroupFinishFromParentNetCls(nsjconf, pid);
}
bool cgroupInitNs(void) { return true; }

View File

@@ -127,6 +127,9 @@ struct custom_option custom_opts[] = {
{ { "cgroup_pids_max", required_argument, NULL, 0x0811 }, "Maximum number of pids in a cgroup (default: '0' - disabled)" },
{ { "cgroup_pids_mount", required_argument, NULL, 0x0812 }, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')" },
{ { "cgroup_pids_parent", required_argument, NULL, 0x0813 }, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')" },
{ { "cgroup_net_cls_classid", required_argument, NULL, 0x0821 }, "Class identifier of network packets in the group (default: '0' - disabled)" },
{ { "cgroup_net_cls_mount", required_argument, NULL, 0x0822 }, "Location of net_cls cgroup FS (default: '/sys/fs/cgroup/net_cls')" },
{ { "cgroup_net_cls_parent", required_argument, NULL, 0x0823 }, "Which pre-existing net_cls cgroup to use as a parent (default: 'NSJAIL')" },
{ { "iface_no_lo", no_argument, NULL, 0x700 }, "Don't bring the 'lo' interface up" },
{ { "macvlan_iface", required_argument, NULL, 'I' }, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'" },
{ { "macvlan_vs_ip", required_argument, NULL, 0x701 }, "IP of the 'vs' interface (e.g. \"192.168.0.1\")" },
@@ -361,6 +364,9 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
.cgroup_pids_mount = "/sys/fs/cgroup/pids",
.cgroup_pids_parent = "NSJAIL",
.cgroup_pids_max = (size_t)0,
.cgroup_net_cls_mount = "/sys/fs/cgroup/net_cls",
.cgroup_net_cls_parent = "NSJAIL",
.cgroup_net_cls_classid = (unsigned int)0,
.iface_no_lo = false,
.iface_vs = NULL,
.iface_vs_ip = "0.0.0.0",
@@ -732,6 +738,15 @@ bool cmdlineParse(int argc, char* argv[], struct nsjconf_t* nsjconf)
case 0x813:
nsjconf->cgroup_pids_parent = optarg;
break;
case 0x821:
nsjconf->cgroup_net_cls_classid = (unsigned int)strtoul(optarg, NULL, 0);
break;
case 0x822:
nsjconf->cgroup_net_cls_mount = optarg;
break;
case 0x823:
nsjconf->cgroup_net_cls_parent = optarg;
break;
case 'P':
if ((nsjconf->kafel_file = fopen(optarg, "r")) == NULL) {
PLOG_F("Couldn't open '%s'", optarg);

View File

@@ -276,6 +276,9 @@ static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailC
nsjconf->cgroup_pids_max = njc.cgroup_pids_max();
nsjconf->cgroup_pids_mount = njc.cgroup_pids_mount().c_str();
nsjconf->cgroup_pids_parent = njc.cgroup_pids_parent().c_str();
nsjconf->cgroup_net_cls_classid = njc.cgroup_net_cls_classid();
nsjconf->cgroup_net_cls_mount = njc.cgroup_net_cls_mount().c_str();
nsjconf->cgroup_net_cls_parent = njc.cgroup_net_cls_parent().c_str();
nsjconf->iface_no_lo = njc.iface_no_lo();
nsjconf->iface_vs = DUP_IF_SET(njc, macvlan_iface);

View File

@@ -213,4 +213,11 @@ message NsJailConfig
/* Binary path (with arguments) to be executed. If not specified here, it
can be specified with cmd-line as "-- /path/to/command arg1 arg2" */
optional Exe exec_bin = 70;
/* If > 0, Class identifier of network packets inside jail */
optional uint32 cgroup_net_cls_classid = 71 [ default = 0 ];
/* Mount point for cgroups-net-cls in your system */
optional string cgroup_net_cls_mount = 72 [ default = "/sys/fs/cgroup/net_cls" ];
/* Writeable directory (for the nsjail user) under cgroup_net_mount */
optional string cgroup_net_cls_parent = 73 [ default = "NSJAIL" ];
}

View File

@@ -220,6 +220,15 @@ Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')
\fB\-\-cgroup_pids_parent\fR VALUE
Which pre\-existing pids cgroup to use as a parent (default: 'NSJAIL')
.TP
\fB\-\-cgroup_net_cls_classid\fR VALUE
Class identifier of network packets in the group (default: '0' \- disabled)
.TP
\fB\-\-cgroup_net_cls_mount\fR VALUE
Location of net_cls cgroup FS (default: '/sys/fs/cgroup/net_cls')
.TP
\fB\-\-cgroup_net_cls_parent\fR VALUE
Which pre\-existing net_cls cgroup to use as a parent (default: 'NSJAIL')
.TP
\fB\-\-iface_no_lo\fR
Don't bring up the 'lo' interface
.TP

View File

@@ -158,6 +158,9 @@ struct nsjconf_t {
const char* cgroup_pids_mount;
const char* cgroup_pids_parent;
size_t cgroup_pids_max;
const char* cgroup_net_cls_mount;
const char* cgroup_net_cls_parent;
unsigned int cgroup_net_cls_classid;
FILE* kafel_file;
char* kafel_string;
long num_cpus;