nsjail/config.c

275 lines
8.0 KiB
C
Raw Normal View History

2017-05-26 08:24:56 +08:00
/*
nsjail - config parsing
-----------------------------------------
Copyright 2017 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 "common.h"
2017-05-26 23:50:28 +08:00
#include <stdio.h>
2017-05-27 07:16:12 +08:00
#include <sys/mount.h>
2017-05-26 23:50:28 +08:00
#include <sys/personality.h>
2017-05-26 08:24:56 +08:00
#include "config.h"
#include "log.h"
2017-05-27 07:16:12 +08:00
#include "mount.h"
2017-05-27 05:26:07 +08:00
#include "user.h"
2017-05-26 08:24:56 +08:00
#include "util.h"
2017-05-26 10:15:45 +08:00
#if !defined(NSJAIL_WITH_PROTOBUF)
2017-05-26 08:24:56 +08:00
bool configParse(struct nsjconf_t * nsjconf UNUSED, const char *file UNUSED)
{
LOG_W("nsjail was not compiled with the protobuf-c library");
return false;
}
2017-05-26 10:15:45 +08:00
#else /* !defined(NSJAIL_WITH_PROTOBUF) */
2017-05-26 08:24:56 +08:00
#include "config.pb-c.h"
#include "protobuf-c-text.h"
2017-05-26 08:24:56 +08:00
static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig * njc)
{
2017-05-26 11:01:22 +08:00
switch (njc->mode) {
case NSJAIL__MODE__LISTEN:
nsjconf->mode = MODE_LISTEN_TCP;
break;
case NSJAIL__MODE__ONCE:
nsjconf->mode = MODE_STANDALONE_ONCE;
break;
case NSJAIL__MODE__RERUN:
nsjconf->mode = MODE_STANDALONE_RERUN;
break;
case NSJAIL__MODE__EXECVE:
nsjconf->mode = MODE_STANDALONE_EXECVE;
break;
default:
LOG_E("Uknown running mode: %d", njc->mode);
return false;
2017-05-26 10:37:50 +08:00
}
nsjconf->chroot = utilStrDup(njc->chroot_dir);
nsjconf->hostname = utilStrDup(njc->hostname);
nsjconf->cwd = utilStrDup(njc->cwd);
nsjconf->bindhost = utilStrDup(njc->bindhost);
2017-05-26 11:01:22 +08:00
nsjconf->max_conns_per_ip = njc->max_conns_per_ip;
2017-05-26 11:12:01 +08:00
nsjconf->tlimit = njc->time_limit;
nsjconf->daemonize = njc->daemon;
2017-05-26 21:22:59 +08:00
nsjconf->log_fd = njc->log_fd;
nsjconf->logfile = utilStrDup(njc->log_file);
2017-05-26 21:22:59 +08:00
if (njc->has_log_level) {
switch (njc->log_level) {
case NSJAIL__LOG_LEVEL__DEBUG:
nsjconf->loglevel = DEBUG;
break;
case NSJAIL__LOG_LEVEL__INFO:
nsjconf->loglevel = INFO;
break;
case NSJAIL__LOG_LEVEL__WARNING:
nsjconf->loglevel = WARNING;
break;
case NSJAIL__LOG_LEVEL__ERROR:
nsjconf->loglevel = ERROR;
break;
case NSJAIL__LOG_LEVEL__FATAL:
nsjconf->loglevel = FATAL;
break;
default:
LOG_E("Unknown log_level: %d", njc->log_level);
return false;
}
2017-05-26 20:08:09 +08:00
}
if (njc->log_file || njc->has_log_level) {
2017-05-26 21:22:59 +08:00
if (logInitLogFile(nsjconf) == false) {
return false;
}
}
nsjconf->keep_env = njc->keep_env;
2017-05-27 10:06:28 +08:00
for (size_t i = 0; i < njc->n_envar; i++) {
struct charptr_t *p = utilMalloc(sizeof(struct charptr_t));
p->val = utilStrDup(njc->envar[i]);
TAILQ_INSERT_TAIL(&nsjconf->envs, p, pointers);
}
2017-05-29 01:17:48 +08:00
nsjconf->keep_caps = njc->keep_caps;
2017-05-26 21:22:59 +08:00
nsjconf->is_silent = njc->silent;
nsjconf->skip_setsid = njc->skip_setsid;
for (size_t i = 0; i < njc->n_pass_fd; i++) {
struct fds_t *f = utilMalloc(sizeof(struct fds_t));
f->fd = njc->pass_fd[i];
TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
}
nsjconf->disable_no_new_privs = njc->disable_no_new_privs;
2017-05-26 20:08:09 +08:00
nsjconf->rl_as = njc->rlimit_as * 1024ULL * 1024ULL;
nsjconf->rl_core = njc->rlimit_core * 1024ULL * 1024ULL;
nsjconf->rl_cpu = njc->rlimit_cpu;
nsjconf->rl_fsize = njc->rlimit_fsize * 1024ULL * 1024ULL;
nsjconf->rl_nofile = njc->rlimit_nofile;
if (njc->has_rlimit_nproc) {
nsjconf->rl_nproc = njc->rlimit_nproc;
}
if (njc->has_rlimit_stack) {
nsjconf->rl_stack = njc->rlimit_stack * 1024ULL * 1024ULL;
}
2017-05-26 08:24:56 +08:00
2017-05-26 23:50:28 +08:00
if (njc->persona_addr_compat_layout) {
nsjconf->personality |= ADDR_COMPAT_LAYOUT;
}
if (njc->persona_mmap_page_zero) {
nsjconf->personality |= MMAP_PAGE_ZERO;
}
if (njc->persona_read_implies_exec) {
nsjconf->personality |= READ_IMPLIES_EXEC;
}
if (njc->persona_addr_limit_3gb) {
nsjconf->personality |= ADDR_LIMIT_3GB;
}
if (njc->persona_addr_no_randomize) {
nsjconf->personality |= ADDR_NO_RANDOMIZE;
}
nsjconf->clone_newnet = njc->clone_newnet;
nsjconf->clone_newuser = njc->clone_newuser;
nsjconf->clone_newns = njc->clone_newns;
nsjconf->clone_newpid = njc->clone_newpid;
nsjconf->clone_newipc = njc->clone_newipc;
nsjconf->clone_newuts = njc->clone_newuts;
nsjconf->clone_newcgroup = njc->clone_newcgroup;
2017-05-27 05:26:07 +08:00
for (size_t i = 0; i < njc->n_uidmap; i++) {
2017-05-28 07:05:27 +08:00
if (userParseId
(nsjconf, njc->uidmap[i]->inside_id, njc->uidmap[i]->outside_id,
njc->uidmap[i]->count, false /* is_gid */ ,
njc->uidmap[i]->use_newidmap) == false) {
2017-05-27 05:26:07 +08:00
return false;
}
}
for (size_t i = 0; i < njc->n_gidmap; i++) {
2017-05-28 07:05:27 +08:00
if (userParseId
(nsjconf, njc->gidmap[i]->inside_id, njc->gidmap[i]->outside_id,
njc->gidmap[i]->count, true /* is_gid */ ,
njc->gidmap[i]->use_newidmap) == false) {
2017-05-27 05:26:07 +08:00
return false;
}
}
2017-05-26 23:50:28 +08:00
2017-05-27 21:17:11 +08:00
nsjconf->mount_proc = njc->mount_proc;
2017-05-27 07:16:12 +08:00
for (size_t i = 0; i < njc->n_mount; i++) {
const char *src = njc->mount[i]->src;
const char *src_env = njc->mount[i]->prefix_src_env;
const char *dst = njc->mount[i]->dst;
const char *dst_env = njc->mount[i]->prefix_dst_env;
const char *fstype = njc->mount[i]->fstype;
const char *options = njc->mount[i]->options;
2017-05-28 07:24:55 +08:00
uintptr_t flags = (njc->mount[i]->rw == false) ? MS_RDONLY : 0;
flags |= njc->mount[i]->is_bind ? (MS_BIND | MS_REC) : 0;
bool mandatory = njc->mount[i]->mandatory;
const bool *isDir =
(njc->mount[i]->has_is_dir) ? (const bool *)&njc->mount[i]->is_dir : NULL;
uint8_t *src_content = NULL;
size_t src_content_len = 0;
if (njc->mount[i]->has_src_content) {
src_content = njc->mount[i]->src_content.data;
src_content_len = njc->mount[i]->src_content.len;
}
if (mountAddMountPt
(nsjconf, src, dst, fstype, options, flags, isDir, mandatory, src_env,
dst_env, src_content, src_content_len) == false) {
LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
return false;
2017-05-27 07:16:12 +08:00
}
}
2017-05-27 07:35:00 +08:00
if (njc->seccomp_policy_file) {
if ((nsjconf->kafel_file = fopen(njc->seccomp_policy_file, "rb")) == NULL) {
PLOG_W("Couldn't open file with seccomp policy '%s'",
njc->seccomp_policy_file);
return false;
}
}
nsjconf->kafel_string = utilStrDup(njc->seccomp_string);
2017-05-27 07:35:00 +08:00
2017-05-27 08:09:21 +08:00
nsjconf->cgroup_mem_max = njc->cgroup_mem_max;
nsjconf->cgroup_mem_mount = utilStrDup(njc->cgroup_mem_mount);
nsjconf->cgroup_mem_parent = utilStrDup(njc->cgroup_mem_parent);
nsjconf->cgroup_pids_max = njc->cgroup_pids_max;
nsjconf->cgroup_pids_mount = utilStrDup(njc->cgroup_pids_mount);
nsjconf->cgroup_pids_parent = utilStrDup(njc->cgroup_pids_parent);
nsjconf->iface_no_lo = njc->iface_no_lo;
nsjconf->iface = utilStrDup(njc->macvlan_iface);
2017-05-27 08:09:21 +08:00
nsjconf->iface_vs_ip = utilStrDup(njc->macvlan_vs_ip);
nsjconf->iface_vs_nm = utilStrDup(njc->macvlan_vs_nm);
nsjconf->iface_vs_gw = utilStrDup(njc->macvlan_vs_gw);
2017-05-27 08:24:41 +08:00
if (njc->exec_bin) {
char **argv = utilCalloc(sizeof(const char *) * (njc->exec_bin->n_arg + 2));
argv[0] = utilStrDup(njc->exec_bin->path);
for (size_t i = 0; i < njc->exec_bin->n_arg; i++) {
argv[i + 1] = utilStrDup(njc->exec_bin->arg[i]);
}
argv[njc->exec_bin->n_arg + 1] = NULL;
nsjconf->exec_file = argv[0];
2017-05-27 08:24:41 +08:00
nsjconf->argv = argv;
}
2017-05-26 08:24:56 +08:00
return true;
}
bool configParse(struct nsjconf_t * nsjconf, const char *file)
{
2017-05-26 21:22:59 +08:00
LOG_I("Parsing configuration from '%s'", file);
FILE *f = fopen(file, "rb");
if (f == NULL) {
PLOG_W("Couldn't open '%s' for reading", file);
2017-05-26 08:24:56 +08:00
return false;
}
ProtobufCTextError error;
Nsjail__NsJailConfig *njc =
(Nsjail__NsJailConfig *) protobuf_c_text_from_file(&nsjail__ns_jail_config__descriptor,
f, &error, NULL);
2017-05-26 08:24:56 +08:00
if (njc == NULL) {
LOG_W("Couldn't parse config from '%s': %s", file, error.error_txt);
fclose(f);
2017-05-26 08:24:56 +08:00
return false;
}
bool ret = configParseInternal(nsjconf, njc);
2017-05-26 21:22:59 +08:00
char *config_str = protobuf_c_text_to_string((ProtobufCMessage *) njc, NULL);
if (config_str) {
LOG_D("Parsed config:\n%s", config_str);
free(config_str);
}
fclose(f);
2017-05-26 08:24:56 +08:00
return ret;
}
2017-05-26 10:15:45 +08:00
#endif /* !defined(NSJAIL_WITH_PROTOBUF) */