sandbox-capsicum.c revision 272461
1190815Srmacklem/* 2190815Srmacklem * Copyright (c) 2011 Dag-Erling Smorgrav 3190815Srmacklem * 4190815Srmacklem * Permission to use, copy, modify, and distribute this software for any 5190815Srmacklem * purpose with or without fee is hereby granted, provided that the above 6190815Srmacklem * copyright notice and this permission notice appear in all copies. 7190815Srmacklem * 8190815Srmacklem * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9190815Srmacklem * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10190815Srmacklem * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11190815Srmacklem * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12190815Srmacklem * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13190815Srmacklem * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14190815Srmacklem * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15190815Srmacklem */ 16190815Srmacklem 17190815Srmacklem#include "includes.h" 18190815Srmacklem__RCSID("$FreeBSD$"); 19190815Srmacklem 20190815Srmacklem#ifdef SANDBOX_CAPSICUM 21190815Srmacklem 22190815Srmacklem#include <sys/types.h> 23190815Srmacklem#include <sys/param.h> 24190815Srmacklem#include <sys/time.h> 25190815Srmacklem#include <sys/resource.h> 26190815Srmacklem#include <sys/capability.h> 27190815Srmacklem 28190815Srmacklem#include <errno.h> 29190815Srmacklem#include <stdarg.h> 30190815Srmacklem#include <stdio.h> 31190815Srmacklem#include <stdlib.h> 32190815Srmacklem#include <string.h> 33190815Srmacklem#include <unistd.h> 34190815Srmacklem 35190815Srmacklem#include "log.h" 36190815Srmacklem#include "monitor.h" 37190815Srmacklem#include "ssh-sandbox.h" 38190815Srmacklem#include "xmalloc.h" 39190815Srmacklem 40190815Srmacklem/* 41190815Srmacklem * Capsicum sandbox that sets zero nfiles, nprocs and filesize rlimits, 42190815Srmacklem * limits rights on stdout, stdin, stderr, monitor and switches to 43190815Srmacklem * capability mode. 44190815Srmacklem */ 45190815Srmacklem 46190815Srmacklemstruct ssh_sandbox { 47190815Srmacklem struct monitor *monitor; 48190815Srmacklem pid_t child_pid; 49190815Srmacklem}; 50190815Srmacklem 51190815Srmacklemstruct ssh_sandbox * 52190815Srmacklemssh_sandbox_init(struct monitor *monitor) 53190815Srmacklem{ 54190815Srmacklem struct ssh_sandbox *box; 55190815Srmacklem 56190815Srmacklem /* 57190815Srmacklem * Strictly, we don't need to maintain any state here but we need 58190815Srmacklem * to return non-NULL to satisfy the API. 59190815Srmacklem */ 60190815Srmacklem debug3("%s: preparing capsicum sandbox", __func__); 61190815Srmacklem box = xcalloc(1, sizeof(*box)); 62190815Srmacklem box->monitor = monitor; 63190815Srmacklem box->child_pid = 0; 64190815Srmacklem 65190815Srmacklem return box; 66190815Srmacklem} 67190815Srmacklem 68190815Srmacklemvoid 69190815Srmacklemssh_sandbox_child(struct ssh_sandbox *box) 70190815Srmacklem{ 71190815Srmacklem struct rlimit rl_zero; 72190815Srmacklem cap_rights_t rights; 73190815Srmacklem 74190815Srmacklem rl_zero.rlim_cur = rl_zero.rlim_max = 0; 75190815Srmacklem 76225617Skmacy if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) 77190815Srmacklem fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", 78190815Srmacklem __func__, strerror(errno)); 79190815Srmacklem#ifndef SANDBOX_SKIP_RLIMIT_NOFILE 80190815Srmacklem if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) 81190815Srmacklem fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", 82195104Srwatson __func__, strerror(errno)); 83190815Srmacklem#endif 84221473Srmacklem if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) 85221473Srmacklem fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", 86221473Srmacklem __func__, strerror(errno)); 87221473Srmacklem 88221473Srmacklem cap_rights_init(&rights); 89221473Srmacklem 90190815Srmacklem if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) 91190815Srmacklem fatal("can't limit stdin: %m"); 92190815Srmacklem if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) 93190815Srmacklem fatal("can't limit stdout: %m"); 94190815Srmacklem if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) 95190815Srmacklem fatal("can't limit stderr: %m"); 96190815Srmacklem 97190815Srmacklem cap_rights_init(&rights, CAP_READ, CAP_WRITE); 98190815Srmacklem if (cap_rights_limit(box->monitor->m_recvfd, &rights) < 0 && 99190815Srmacklem errno != ENOSYS) 100190815Srmacklem fatal("%s: failed to limit the network socket", __func__); 101190815Srmacklem cap_rights_init(&rights, CAP_WRITE); 102190815Srmacklem if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) < 0 && 103190815Srmacklem errno != ENOSYS) 104190815Srmacklem fatal("%s: failed to limit the logging socket", __func__); 105241561Srmacklem if (cap_enter() < 0 && errno != ENOSYS) 106241561Srmacklem fatal("%s: failed to enter capability mode", __func__); 107190815Srmacklem 108190815Srmacklem} 109190815Srmacklem 110190815Srmacklemvoid 111190815Srmacklemssh_sandbox_parent_finish(struct ssh_sandbox *box) 112190815Srmacklem{ 113190815Srmacklem free(box); 114190815Srmacklem debug3("%s: finished", __func__); 115190815Srmacklem} 116190815Srmacklem 117190815Srmacklemvoid 118190815Srmacklemssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) 119190815Srmacklem{ 120190815Srmacklem box->child_pid = child_pid; 121190815Srmacklem} 122190815Srmacklem 123190815Srmacklem#endif /* SANDBOX_CAPSICUM */ 124190815Srmacklem