cmdline: implement affinity setting, to limit jailed process to n max cpus
This commit is contained in:
parent
dbdeba6ea4
commit
0e7393cccf
7
Makefile
7
Makefile
@ -28,11 +28,11 @@ CFLAGS += -O2 -c -std=gnu11 \
|
|||||||
-Wall -Wextra -Werror \
|
-Wall -Wextra -Werror \
|
||||||
-Ikafel/include
|
-Ikafel/include
|
||||||
|
|
||||||
LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack
|
LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wl,-z,noexecstack -lpthread
|
||||||
|
|
||||||
BIN = nsjail
|
BIN = nsjail
|
||||||
LIBS = kafel/libkafel.a
|
LIBS = kafel/libkafel.a
|
||||||
SRCS = nsjail.c cmdline.c config.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c
|
SRCS = nsjail.c cmdline.c config.c contain.c log.c cgroup.c mount.c net.c pid.c sandbox.c subproc.c user.c util.c uts.c cpu.c
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
@ -139,7 +139,7 @@ indent:
|
|||||||
nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h
|
nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h
|
||||||
cmdline.o: cmdline.h common.h config.h log.h mount.h util.h user.h
|
cmdline.o: cmdline.h common.h config.h log.h mount.h util.h user.h
|
||||||
config.o: common.h config.h log.h mount.h user.h util.h
|
config.o: common.h config.h log.h mount.h user.h util.h
|
||||||
contain.o: contain.h common.h cgroup.h log.h mount.h net.h pid.h user.h
|
contain.o: contain.h common.h cgroup.h cpu.h log.h mount.h net.h pid.h user.h
|
||||||
contain.o: util.h uts.h
|
contain.o: util.h uts.h
|
||||||
log.o: log.h common.h
|
log.o: log.h common.h
|
||||||
cgroup.o: cgroup.h common.h log.h util.h
|
cgroup.o: cgroup.h common.h log.h util.h
|
||||||
@ -152,3 +152,4 @@ subproc.o: util.h
|
|||||||
user.o: user.h common.h log.h subproc.h util.h
|
user.o: user.h common.h log.h subproc.h util.h
|
||||||
util.o: util.h common.h log.h
|
util.o: util.h common.h log.h
|
||||||
uts.o: uts.h common.h log.h
|
uts.o: uts.h common.h log.h
|
||||||
|
cpu.o: cpu.h common.h log.h util.h
|
||||||
|
@ -79,6 +79,7 @@ struct custom_option custom_opts[] = {
|
|||||||
{{"log", required_argument, NULL, 'l'}, "Log file (default: use log_fd)"},
|
{{"log", required_argument, NULL, 'l'}, "Log file (default: use log_fd)"},
|
||||||
{{"log_fd", required_argument, NULL, 'L'}, "Log FD (default: 2)"},
|
{{"log_fd", required_argument, NULL, 'L'}, "Log FD (default: 2)"},
|
||||||
{{"time_limit", required_argument, NULL, 't'}, "Maximum time that a jail can exist, in seconds (default: 600)"},
|
{{"time_limit", required_argument, NULL, 't'}, "Maximum time that a jail can exist, in seconds (default: 600)"},
|
||||||
|
{{"max_cpu_num", required_argument, NULL, 0x508}, "Maximum number of CPUs a single jailed process can use (default: 0 'no limit')"},
|
||||||
{{"daemon", no_argument, NULL, 'd'}, "Daemonize after start"},
|
{{"daemon", no_argument, NULL, 'd'}, "Daemonize after start"},
|
||||||
{{"verbose", no_argument, NULL, 'v'}, "Verbose output"},
|
{{"verbose", no_argument, NULL, 'v'}, "Verbose output"},
|
||||||
{{"quiet", no_argument, NULL, 'q'}, "Only output warning and more important messages"},
|
{{"quiet", no_argument, NULL, 'q'}, "Only output warning and more important messages"},
|
||||||
@ -314,6 +315,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
.loglevel = INFO,
|
.loglevel = INFO,
|
||||||
.daemonize = false,
|
.daemonize = false,
|
||||||
.tlimit = 0,
|
.tlimit = 0,
|
||||||
|
.max_cpu_num = 0,
|
||||||
.keep_caps = false,
|
.keep_caps = false,
|
||||||
.disable_no_new_privs = false,
|
.disable_no_new_privs = false,
|
||||||
.rl_as = 512 * (1024 * 1024),
|
.rl_as = 512 * (1024 * 1024),
|
||||||
@ -535,6 +537,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
case 0x0507:
|
case 0x0507:
|
||||||
nsjconf->disable_no_new_privs = true;
|
nsjconf->disable_no_new_privs = true;
|
||||||
break;
|
break;
|
||||||
|
case 0x0508:
|
||||||
|
nsjconf->max_cpu_num = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
case 0x0601:
|
case 0x0601:
|
||||||
nsjconf->is_root_rw = true;
|
nsjconf->is_root_rw = true;
|
||||||
break;
|
break;
|
||||||
|
1
common.h
1
common.h
@ -124,6 +124,7 @@ struct nsjconf_t {
|
|||||||
enum llevel_t loglevel;
|
enum llevel_t loglevel;
|
||||||
bool daemonize;
|
bool daemonize;
|
||||||
time_t tlimit;
|
time_t tlimit;
|
||||||
|
size_t max_cpu_num;
|
||||||
bool keep_env;
|
bool keep_env;
|
||||||
bool keep_caps;
|
bool keep_caps;
|
||||||
bool disable_no_new_privs;
|
bool disable_no_new_privs;
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
|
#include "cpu.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mount.h"
|
#include "mount.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
@ -168,6 +169,11 @@ static bool containInitMountNs(struct nsjconf_t *nsjconf)
|
|||||||
return mountInitNs(nsjconf);
|
return mountInitNs(nsjconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool containCPU(struct nsjconf_t *nsjconf)
|
||||||
|
{
|
||||||
|
return cpuInit(nsjconf);
|
||||||
|
}
|
||||||
|
|
||||||
static bool containSetLimits(struct nsjconf_t *nsjconf)
|
static bool containSetLimits(struct nsjconf_t *nsjconf)
|
||||||
{
|
{
|
||||||
struct rlimit64 rl;
|
struct rlimit64 rl;
|
||||||
@ -351,6 +357,9 @@ bool containSetupFD(struct nsjconf_t * nsjconf, int fd_in, int fd_out, int fd_er
|
|||||||
|
|
||||||
bool containContain(struct nsjconf_t * nsjconf)
|
bool containContain(struct nsjconf_t * nsjconf)
|
||||||
{
|
{
|
||||||
|
if (containCPU(nsjconf) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (containUserNs(nsjconf) == false) {
|
if (containUserNs(nsjconf) == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
84
cpu.c
Normal file
84
cpu.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
nsjail - CLONE_NEWUTS routines
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
#include <sched.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void cpuSetRandomCpu(cpu_set_t * mask, size_t mask_size, size_t cpu_num)
|
||||||
|
{
|
||||||
|
if ((size_t) CPU_COUNT_S(mask_size, mask) >= cpu_num) {
|
||||||
|
LOG_F
|
||||||
|
("Number of CPUs in the mask '%d' is bigger than number of available CPUs '%zu'",
|
||||||
|
CPU_COUNT(mask), cpu_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uint64_t n = utilRnd64() % cpu_num;
|
||||||
|
if (!CPU_ISSET_S(n, mask_size, mask)) {
|
||||||
|
CPU_SET_S(n, mask_size, mask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cpuInit(struct nsjconf_t *nsjconf)
|
||||||
|
{
|
||||||
|
long all_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (all_cpus < 0) {
|
||||||
|
PLOG_W("sysconf(_SC_NPROCESSORS_ONLN) returned %ld", all_cpus);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (nsjconf->max_cpu_num >= (size_t) all_cpus) {
|
||||||
|
LOG_D("Requested number of CPUs '%zu' is bigger that CPUs online '%ld'",
|
||||||
|
nsjconf->max_cpu_num, all_cpus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nsjconf->max_cpu_num == 0) {
|
||||||
|
LOG_D("No max_cpu_num limit set");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_set_t *mask = CPU_ALLOC(all_cpus);
|
||||||
|
if (mask == NULL) {
|
||||||
|
PLOG_W("Failure allocating cpu_set_t for %ld CPUs", all_cpus);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mask_size = CPU_ALLOC_SIZE(all_cpus);
|
||||||
|
CPU_ZERO_S(mask_size, mask);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nsjconf->max_cpu_num; i++) {
|
||||||
|
cpuSetRandomCpu(mask, mask_size, all_cpus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sched_setaffinity(0, mask_size, mask) == -1) {
|
||||||
|
PLOG_W("sched_setaffinity(max_cpu_num=%zu) failed", nsjconf->max_cpu_num);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
32
cpu.h
Normal file
32
cpu.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
nsjail - CPU affinity
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NS_CPU_H
|
||||||
|
#define NS_CPU_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
bool cpuInit(struct nsjconf_t *nsjconf);
|
||||||
|
|
||||||
|
#endif /* NS_CPU_H */
|
28
util.c
28
util.c
@ -24,6 +24,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -213,3 +214,30 @@ bool utilIsANumber(const char *s)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __thread pthread_once_t rndThreadOnce = PTHREAD_ONCE_INIT;
|
||||||
|
static __thread uint64_t rndX;
|
||||||
|
|
||||||
|
/* MMIX LCG PRNG */
|
||||||
|
static const uint64_t a = 6364136223846793005ULL;
|
||||||
|
static const uint64_t c = 1442695040888963407ULL;
|
||||||
|
|
||||||
|
static void utilRndInitThread(void)
|
||||||
|
{
|
||||||
|
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd == -1) {
|
||||||
|
PLOG_F("Couldn't open /dev/urandom for reading");
|
||||||
|
}
|
||||||
|
if (utilReadFromFd(fd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
|
||||||
|
PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t utilRnd64(void)
|
||||||
|
{
|
||||||
|
pthread_once(&rndThreadOnce, utilRndInitThread);
|
||||||
|
rndX = a * rndX + c;
|
||||||
|
return rndX;
|
||||||
|
}
|
||||||
|
2
util.h
2
util.h
@ -23,6 +23,7 @@
|
|||||||
#define NS_UTIL_H
|
#define NS_UTIL_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -38,5 +39,6 @@ bool utilWriteBufToFile(const char *filename, const void *buf, size_t len, int o
|
|||||||
bool utilCreateDirRecursively(const char *dir);
|
bool utilCreateDirRecursively(const char *dir);
|
||||||
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
|
int utilSSnPrintf(char *str, size_t size, const char *format, ...);
|
||||||
bool utilIsANumber(const char *s);
|
bool utilIsANumber(const char *s);
|
||||||
|
uint64_t utilRnd64(void);
|
||||||
|
|
||||||
#endif /* NS_UTIL_H */
|
#endif /* NS_UTIL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user