1/* 2 * Copyright (c) 2012 Will Drewry <wad@dataspill.org> 3 * Copyright (c) 2015,2017,2019,2020,2023 Damien Miller <djm@mindrot.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * Uncomment the SANDBOX_SECCOMP_FILTER_DEBUG macro below to help diagnose 20 * filter breakage during development. *Do not* use this in production, 21 * as it relies on making library calls that are unsafe in signal context. 22 * 23 * Instead, live systems the auditctl(8) may be used to monitor failures. 24 * E.g. 25 * auditctl -a task,always -F uid=<privsep uid> 26 */ 27/* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ 28 29#if 0 30/* 31 * For older toolchains, it may be necessary to use the kernel 32 * headers directly. 33 */ 34#ifdef SANDBOX_SECCOMP_FILTER_DEBUG 35# include <asm/siginfo.h> 36# define __have_siginfo_t 1 37# define __have_sigval_t 1 38# define __have_sigevent_t 1 39#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 40#endif 41 42#include "includes.h" 43 44#ifdef SANDBOX_SECCOMP_FILTER 45 46#include <sys/types.h> 47#include <sys/resource.h> 48#include <sys/prctl.h> 49#include <sys/mman.h> 50#include <sys/syscall.h> 51 52#include <linux/futex.h> 53#include <linux/net.h> 54#include <linux/audit.h> 55#include <linux/filter.h> 56#include <linux/seccomp.h> 57#include <elf.h> 58 59#include <asm/unistd.h> 60#ifdef __s390__ 61#include <asm/zcrypt.h> 62#endif 63 64#include <errno.h> 65#include <signal.h> 66#include <stdarg.h> 67#include <stddef.h> /* for offsetof */ 68#include <stdio.h> 69#include <stdlib.h> 70#include <string.h> 71#include <unistd.h> 72 73#include "log.h" 74#include "ssh-sandbox.h" 75#include "xmalloc.h" 76 77/* Linux seccomp_filter sandbox */ 78#define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL 79 80/* Use a signal handler to emit violations when debugging */ 81#ifdef SANDBOX_SECCOMP_FILTER_DEBUG 82# undef SECCOMP_FILTER_FAIL 83# define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP 84#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 85 86#if __BYTE_ORDER == __LITTLE_ENDIAN 87# define ARG_LO_OFFSET 0 88# define ARG_HI_OFFSET sizeof(uint32_t) 89#elif __BYTE_ORDER == __BIG_ENDIAN 90# define ARG_LO_OFFSET sizeof(uint32_t) 91# define ARG_HI_OFFSET 0 92#else 93#error "Unknown endianness" 94#endif 95 96/* Simple helpers to avoid manual errors (but larger BPF programs). */ 97#define SC_DENY(_nr, _errno) \ 98 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \ 99 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)) 100#define SC_ALLOW(_nr) \ 101 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \ 102 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 103#define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \ 104 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 6), \ 105 /* load and test syscall argument, low word */ \ 106 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 107 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ 108 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ 109 ((_arg_val) & 0xFFFFFFFF), 0, 3), \ 110 /* load and test syscall argument, high word */ \ 111 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 112 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ 113 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ 114 (((uint32_t)((uint64_t)(_arg_val) >> 32)) & 0xFFFFFFFF), 0, 1), \ 115 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ 116 /* reload syscall number; all rules expect it in accumulator */ \ 117 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 118 offsetof(struct seccomp_data, nr)) 119/* Allow if syscall argument contains only values in mask */ 120#define SC_ALLOW_ARG_MASK(_nr, _arg_nr, _arg_mask) \ 121 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ 122 /* load, mask and test syscall argument, low word */ \ 123 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 124 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ 125 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~((_arg_mask) & 0xFFFFFFFF)), \ 126 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 4), \ 127 /* load, mask and test syscall argument, high word */ \ 128 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 129 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ 130 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ 131 ~(((uint32_t)((uint64_t)(_arg_mask) >> 32)) & 0xFFFFFFFF)), \ 132 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1), \ 133 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ 134 /* reload syscall number; all rules expect it in accumulator */ \ 135 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 136 offsetof(struct seccomp_data, nr)) 137/* Deny unless syscall argument contains only values in mask */ 138#define SC_DENY_UNLESS_ARG_MASK(_nr, _arg_nr, _arg_mask, _errno) \ 139 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ 140 /* load, mask and test syscall argument, low word */ \ 141 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 142 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ 143 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~((_arg_mask) & 0xFFFFFFFF)), \ 144 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 3), \ 145 /* load, mask and test syscall argument, high word */ \ 146 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 147 offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ 148 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ 149 ~(((uint32_t)((uint64_t)(_arg_mask) >> 32)) & 0xFFFFFFFF)), \ 150 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 1, 0), \ 151 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)), \ 152 /* reload syscall number; all rules expect it in accumulator */ \ 153 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 154 offsetof(struct seccomp_data, nr)) 155#define SC_DENY_UNLESS_MASK(_nr, _arg_nr, _arg_val, _errno) \ 156/* Special handling for futex(2) that combines a bitmap and operation number */ 157#if defined(__NR_futex) || defined(__NR_futex_time64) 158#define SC_FUTEX_MASK (FUTEX_PRIVATE_FLAG|FUTEX_CLOCK_REALTIME) 159#define SC_ALLOW_FUTEX_OP(_nr, _op) \ 160 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ 161 /* load syscall argument, low word */ \ 162 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 163 offsetof(struct seccomp_data, args[1]) + ARG_LO_OFFSET), \ 164 /* mask off allowed bitmap values, low word */ \ 165 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~(SC_FUTEX_MASK & 0xFFFFFFFF)), \ 166 /* test operation number, low word */ \ 167 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((_op) & 0xFFFFFFFF), 0, 4), \ 168 /* load syscall argument, high word */ \ 169 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 170 offsetof(struct seccomp_data, args[1]) + ARG_HI_OFFSET), \ 171 /* mask off allowed bitmap values, high word */ \ 172 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ 173 ~(((uint32_t)((uint64_t)SC_FUTEX_MASK >> 32)) & 0xFFFFFFFF)), \ 174 /* test operation number, high word */ \ 175 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ 176 (((uint32_t)((uint64_t)(_op) >> 32)) & 0xFFFFFFFF), 0, 1), \ 177 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ 178 /* reload syscall number; all rules expect it in accumulator */ \ 179 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)) 180 181/* Use this for both __NR_futex and __NR_futex_time64 */ 182# define SC_FUTEX(_nr) \ 183 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT), \ 184 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT_BITSET), \ 185 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE), \ 186 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE_BITSET), \ 187 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_REQUEUE), \ 188 SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_CMP_REQUEUE) 189#endif /* __NR_futex || __NR_futex_time64 */ 190 191#if defined(__NR_mmap) || defined(__NR_mmap2) 192# ifdef MAP_FIXED_NOREPLACE 193# define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_FIXED_NOREPLACE 194# else 195# define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED 196# endif /* MAP_FIXED_NOREPLACE */ 197/* Use this for both __NR_mmap and __NR_mmap2 variants */ 198# define SC_MMAP(_nr) \ 199 SC_DENY_UNLESS_ARG_MASK(_nr, 3, SC_MMAP_FLAGS, EINVAL), \ 200 SC_ALLOW_ARG_MASK(_nr, 2, PROT_READ|PROT_WRITE|PROT_NONE) 201#endif /* __NR_mmap || __NR_mmap2 */ 202 203/* Syscall filtering set for preauth. */ 204static const struct sock_filter preauth_insns[] = { 205 /* Ensure the syscall arch convention is as expected. */ 206 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 207 offsetof(struct seccomp_data, arch)), 208 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0), 209 BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), 210 /* Load the syscall number for checking. */ 211 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 212 offsetof(struct seccomp_data, nr)), 213 214 /* Syscalls to non-fatally deny */ 215#ifdef __NR_lstat 216 SC_DENY(__NR_lstat, EACCES), 217#endif 218#ifdef __NR_lstat64 219 SC_DENY(__NR_lstat64, EACCES), 220#endif 221#ifdef __NR_fstat 222 SC_DENY(__NR_fstat, EACCES), 223#endif 224#ifdef __NR_fstat64 225 SC_DENY(__NR_fstat64, EACCES), 226#endif 227#ifdef __NR_fstatat64 228 SC_DENY(__NR_fstatat64, EACCES), 229#endif 230#ifdef __NR_open 231 SC_DENY(__NR_open, EACCES), 232#endif 233#ifdef __NR_openat 234 SC_DENY(__NR_openat, EACCES), 235#endif 236#ifdef __NR_newfstatat 237 SC_DENY(__NR_newfstatat, EACCES), 238#endif 239#ifdef __NR_stat 240 SC_DENY(__NR_stat, EACCES), 241#endif 242#ifdef __NR_stat64 243 SC_DENY(__NR_stat64, EACCES), 244#endif 245#ifdef __NR_shmget 246 SC_DENY(__NR_shmget, EACCES), 247#endif 248#ifdef __NR_shmat 249 SC_DENY(__NR_shmat, EACCES), 250#endif 251#ifdef __NR_shmdt 252 SC_DENY(__NR_shmdt, EACCES), 253#endif 254#ifdef __NR_ipc 255 SC_DENY(__NR_ipc, EACCES), 256#endif 257#ifdef __NR_statx 258 SC_DENY(__NR_statx, EACCES), 259#endif 260 261 /* Syscalls to permit */ 262#ifdef __NR_brk 263 SC_ALLOW(__NR_brk), 264#endif 265#ifdef __NR_clock_gettime 266 SC_ALLOW(__NR_clock_gettime), 267#endif 268#ifdef __NR_clock_gettime64 269 SC_ALLOW(__NR_clock_gettime64), 270#endif 271#ifdef __NR_close 272 SC_ALLOW(__NR_close), 273#endif 274#ifdef __NR_exit 275 SC_ALLOW(__NR_exit), 276#endif 277#ifdef __NR_exit_group 278 SC_ALLOW(__NR_exit_group), 279#endif 280#ifdef __NR_futex 281 SC_FUTEX(__NR_futex), 282#endif 283#ifdef __NR_futex_time64 284 SC_FUTEX(__NR_futex_time64), 285#endif 286#ifdef __NR_geteuid 287 SC_ALLOW(__NR_geteuid), 288#endif 289#ifdef __NR_geteuid32 290 SC_ALLOW(__NR_geteuid32), 291#endif 292#ifdef __NR_getpgid 293 SC_ALLOW(__NR_getpgid), 294#endif 295#ifdef __NR_getpid 296 SC_ALLOW(__NR_getpid), 297#endif 298#ifdef __NR_getrandom 299 SC_ALLOW(__NR_getrandom), 300#endif 301#ifdef __NR_gettid 302 SC_ALLOW(__NR_gettid), 303#endif 304#ifdef __NR_gettimeofday 305 SC_ALLOW(__NR_gettimeofday), 306#endif 307#ifdef __NR_getuid 308 SC_ALLOW(__NR_getuid), 309#endif 310#ifdef __NR_getuid32 311 SC_ALLOW(__NR_getuid32), 312#endif 313#ifdef __NR_madvise 314 SC_ALLOW_ARG(__NR_madvise, 2, MADV_NORMAL), 315# ifdef MADV_FREE 316 SC_ALLOW_ARG(__NR_madvise, 2, MADV_FREE), 317# endif 318# ifdef MADV_DONTNEED 319 SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTNEED), 320# endif 321# ifdef MADV_DONTFORK 322 SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTFORK), 323# endif 324# ifdef MADV_DONTDUMP 325 SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTDUMP), 326# endif 327# ifdef MADV_WIPEONFORK 328 SC_ALLOW_ARG(__NR_madvise, 2, MADV_WIPEONFORK), 329# endif 330 SC_DENY(__NR_madvise, EINVAL), 331#endif 332#ifdef __NR_mmap 333 SC_MMAP(__NR_mmap), 334#endif 335#ifdef __NR_mmap2 336 SC_MMAP(__NR_mmap2), 337#endif 338#ifdef __NR_mprotect 339 SC_ALLOW_ARG_MASK(__NR_mprotect, 2, PROT_READ|PROT_WRITE|PROT_NONE), 340#endif 341#ifdef __NR_mremap 342 SC_ALLOW(__NR_mremap), 343#endif 344#ifdef __NR_munmap 345 SC_ALLOW(__NR_munmap), 346#endif 347#ifdef __NR_nanosleep 348 SC_ALLOW(__NR_nanosleep), 349#endif 350#ifdef __NR_clock_nanosleep 351 SC_ALLOW(__NR_clock_nanosleep), 352#endif 353#ifdef __NR_clock_nanosleep_time64 354 SC_ALLOW(__NR_clock_nanosleep_time64), 355#endif 356#ifdef __NR_clock_gettime64 357 SC_ALLOW(__NR_clock_gettime64), 358#endif 359#ifdef __NR__newselect 360 SC_ALLOW(__NR__newselect), 361#endif 362#ifdef __NR_ppoll 363 SC_ALLOW(__NR_ppoll), 364#endif 365#ifdef __NR_ppoll_time64 366 SC_ALLOW(__NR_ppoll_time64), 367#endif 368#ifdef __NR_poll 369 SC_ALLOW(__NR_poll), 370#endif 371#ifdef __NR_pselect6 372 SC_ALLOW(__NR_pselect6), 373#endif 374#ifdef __NR_pselect6_time64 375 SC_ALLOW(__NR_pselect6_time64), 376#endif 377#ifdef __NR_read 378 SC_ALLOW(__NR_read), 379#endif 380#ifdef __NR_rt_sigprocmask 381 SC_ALLOW(__NR_rt_sigprocmask), 382#endif 383#ifdef __NR_select 384 SC_ALLOW(__NR_select), 385#endif 386#ifdef __NR_shutdown 387 SC_ALLOW(__NR_shutdown), 388#endif 389#ifdef __NR_sigprocmask 390 SC_ALLOW(__NR_sigprocmask), 391#endif 392#ifdef __NR_time 393 SC_ALLOW(__NR_time), 394#endif 395#ifdef __NR_write 396 SC_ALLOW(__NR_write), 397#endif 398#ifdef __NR_writev 399 SC_ALLOW(__NR_writev), 400#endif 401#ifdef __NR_socketcall 402 SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), 403 SC_DENY(__NR_socketcall, EACCES), 404#endif 405#if defined(__NR_ioctl) && defined(__s390__) 406 /* Allow ioctls for ICA crypto card on s390 */ 407 SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK), 408 SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO), 409 SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT), 410 SC_ALLOW_ARG(__NR_ioctl, 1, ZSECSENDCPRB), 411 /* Allow ioctls for EP11 crypto card on s390 */ 412 SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB), 413#endif 414#if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT) 415 /* 416 * On Linux x32, the clock_gettime VDSO falls back to the 417 * x86-64 syscall under some circumstances, e.g. 418 * https://bugs.debian.org/849923 419 */ 420 SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT), 421#endif 422 423 /* Default deny */ 424 BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), 425}; 426 427static const struct sock_fprog preauth_program = { 428 .len = (unsigned short)(sizeof(preauth_insns)/sizeof(preauth_insns[0])), 429 .filter = (struct sock_filter *)preauth_insns, 430}; 431 432struct ssh_sandbox { 433 pid_t child_pid; 434}; 435 436struct ssh_sandbox * 437ssh_sandbox_init(struct monitor *monitor) 438{ 439 struct ssh_sandbox *box; 440 441 /* 442 * Strictly, we don't need to maintain any state here but we need 443 * to return non-NULL to satisfy the API. 444 */ 445 debug3("%s: preparing seccomp filter sandbox", __func__); 446 box = xcalloc(1, sizeof(*box)); 447 box->child_pid = 0; 448 449 return box; 450} 451 452#ifdef SANDBOX_SECCOMP_FILTER_DEBUG 453extern struct monitor *pmonitor; 454void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx); 455 456static void 457ssh_sandbox_violation(int signum, siginfo_t *info, void *void_context) 458{ 459 char msg[256]; 460 461 snprintf(msg, sizeof(msg), 462 "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)", 463 __func__, info->si_arch, info->si_syscall, info->si_call_addr); 464 mm_log_handler(SYSLOG_LEVEL_FATAL, 0, msg, pmonitor); 465 _exit(1); 466} 467 468static void 469ssh_sandbox_child_debugging(void) 470{ 471 struct sigaction act; 472 sigset_t mask; 473 474 debug3("%s: installing SIGSYS handler", __func__); 475 memset(&act, 0, sizeof(act)); 476 sigemptyset(&mask); 477 sigaddset(&mask, SIGSYS); 478 479 act.sa_sigaction = &ssh_sandbox_violation; 480 act.sa_flags = SA_SIGINFO; 481 if (sigaction(SIGSYS, &act, NULL) == -1) 482 fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); 483 if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) 484 fatal("%s: sigprocmask(SIGSYS): %s", 485 __func__, strerror(errno)); 486} 487#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 488 489void 490ssh_sandbox_child(struct ssh_sandbox *box) 491{ 492 struct rlimit rl_zero, rl_one = {.rlim_cur = 1, .rlim_max = 1}; 493 int nnp_failed = 0; 494 495 /* Set rlimits for completeness if possible. */ 496 rl_zero.rlim_cur = rl_zero.rlim_max = 0; 497 if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) 498 fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", 499 __func__, strerror(errno)); 500 /* 501 * Cannot use zero for nfds, because poll(2) will fail with 502 * errno=EINVAL if npfds>RLIMIT_NOFILE. 503 */ 504 if (setrlimit(RLIMIT_NOFILE, &rl_one) == -1) 505 fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", 506 __func__, strerror(errno)); 507 if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) 508 fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", 509 __func__, strerror(errno)); 510 511#ifdef SANDBOX_SECCOMP_FILTER_DEBUG 512 ssh_sandbox_child_debugging(); 513#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 514 515 debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); 516 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { 517 debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", 518 __func__, strerror(errno)); 519 nnp_failed = 1; 520 } 521 debug3("%s: attaching seccomp filter program", __func__); 522 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) 523 debug("%s: prctl(PR_SET_SECCOMP): %s", 524 __func__, strerror(errno)); 525 else if (nnp_failed) 526 fatal("%s: SECCOMP_MODE_FILTER activated but " 527 "PR_SET_NO_NEW_PRIVS failed", __func__); 528} 529 530void 531ssh_sandbox_parent_finish(struct ssh_sandbox *box) 532{ 533 free(box); 534 debug3("%s: finished", __func__); 535} 536 537void 538ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) 539{ 540 box->child_pid = child_pid; 541} 542 543#endif /* SANDBOX_SECCOMP_FILTER */ 544