]>
Commit | Line | Data |
---|---|---|
5a5e6771 JR |
1 | https://bugzilla.mindrot.org/show_bug.cgi?id=2142 |
2 | ||
3 | --- a/Makefile.in | |
4 | +++ a/Makefile.in | |
5 | @@ -106,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ | |
6 | sftp-server.o sftp-common.o \ | |
7 | roaming_common.o roaming_serv.o \ | |
8 | sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ | |
9 | - sandbox-seccomp-filter.o sandbox-capsicum.o | |
10 | + sandbox-seccomp-filter.o sandbox-libseccomp-filter.o sandbox-capsicum.o | |
11 | ||
12 | MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out | |
13 | MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 | |
14 | --- a/configure.ac | |
15 | +++ a/configure.ac | |
16 | @@ -2867,11 +2867,22 @@ else | |
17 | fi | |
18 | AC_SUBST([SSH_PRIVSEP_USER]) | |
19 | ||
20 | +AC_CHECK_DECL([SCMP_ARCH_NATIVE], [have_libseccomp_filter=1], , [ | |
21 | + #include <sys/types.h> | |
22 | + #include <seccomp.h> | |
23 | +]) | |
24 | +if test "x$have_libseccomp_filter" = "x1" ; then | |
25 | + AC_CHECK_LIB([seccomp], [seccomp_init], | |
26 | + [LIBS="$LIBS -lseccomp"], | |
27 | + [have_libseccomp_filter=0]) | |
28 | +fi | |
29 | + | |
30 | if test "x$have_linux_no_new_privs" = "x1" ; then | |
31 | AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [ | |
32 | #include <sys/types.h> | |
33 | #include <linux/seccomp.h> | |
34 | ]) | |
35 | + | |
36 | fi | |
37 | if test "x$have_seccomp_filter" = "x1" ; then | |
38 | AC_MSG_CHECKING([kernel for seccomp_filter support]) | |
39 | @@ -2898,7 +2909,7 @@ fi | |
40 | # Decide which sandbox style to use | |
41 | sandbox_arg="" | |
42 | AC_ARG_WITH([sandbox], | |
43 | - [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum)], | |
44 | + [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, libseccomp_filter, capsicum)], | |
45 | [ | |
46 | if test "x$withval" = "xyes" ; then | |
47 | sandbox_arg="" | |
48 | @@ -3008,6 +3019,13 @@ elif test "x$sandbox_arg" = "xdarwin" || \ | |
49 | AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function]) | |
50 | SANDBOX_STYLE="darwin" | |
51 | AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)]) | |
52 | +elif test "x$sandbox_arg" = "xlibseccomp_filter" || \ | |
53 | + ( test -z "$sandbox_arg" && \ | |
54 | + test "x$have_libseccomp_filter" = "x1" ) ; then | |
55 | + test "x$have_libseccomp_filter" != "x1" && \ | |
56 | + AC_MSG_ERROR([libseccomp_filter sandbox not supported on $host]) | |
57 | + SANDBOX_STYLE="libseccomp_filter" | |
58 | + AC_DEFINE([SANDBOX_LIBSECCOMP_FILTER], [1], [Sandbox using libseccomp filter]) | |
59 | elif test "x$sandbox_arg" = "xseccomp_filter" || \ | |
60 | ( test -z "$sandbox_arg" && \ | |
61 | test "x$have_seccomp_filter" = "x1" && \ | |
62 | --- a/sandbox-libseccomp-filter.c | |
63 | +++ a/sandbox-libseccomp-filter.c | |
64 | @@ -0,0 +1,175 @@ | |
65 | +/* | |
66 | + * Copyright (c) 2012 Will Drewry <wad@dataspill.org> | |
67 | + * | |
68 | + * Permission to use, copy, modify, and distribute this software for any | |
69 | + * purpose with or without fee is hereby granted, provided that the above | |
70 | + * copyright notice and this permission notice appear in all copies. | |
71 | + * | |
72 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
73 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
74 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
75 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
76 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
77 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
78 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
79 | + */ | |
80 | + | |
81 | +#include "includes.h" | |
82 | + | |
83 | +#ifdef SANDBOX_LIBSECCOMP_FILTER | |
84 | + | |
85 | +#include <sys/types.h> | |
86 | +#include <sys/resource.h> | |
87 | +#include <seccomp.h> | |
88 | + | |
89 | +#include <errno.h> | |
90 | +#include <signal.h> | |
91 | +#include <stdarg.h> | |
92 | +#include <stddef.h> /* for offsetof */ | |
93 | +#include <stdio.h> | |
94 | +#include <stdlib.h> | |
95 | +#include <string.h> | |
96 | +#include <unistd.h> | |
97 | + | |
98 | +#include "log.h" | |
99 | +#include "ssh-sandbox.h" | |
100 | +#include "xmalloc.h" | |
101 | + | |
102 | +struct ssh_sandbox { | |
103 | + pid_t child_pid; | |
104 | +}; | |
105 | + | |
106 | +struct ssh_sandbox * | |
107 | +ssh_sandbox_init(struct monitor *monitor) | |
108 | +{ | |
109 | + struct ssh_sandbox *box; | |
110 | + | |
111 | + /* | |
112 | + * Strictly, we don't need to maintain any state here but we need | |
113 | + * to return non-NULL to satisfy the API. | |
114 | + */ | |
115 | + debug3("%s: preparing libseccomp filter sandbox", __func__); | |
116 | + box = xcalloc(1, sizeof(*box)); | |
117 | + box->child_pid = 0; | |
118 | + | |
119 | + return box; | |
120 | +} | |
121 | + | |
122 | +static int | |
123 | +seccomp_add_secondary_archs(scmp_filter_ctx *c) | |
124 | +{ | |
125 | +#if defined(__i386__) || defined(__x86_64__) | |
126 | + int r; | |
127 | + r = seccomp_arch_add(c, SCMP_ARCH_X86); | |
128 | + if (r < 0 && r != -EEXIST) | |
129 | + return r; | |
130 | + r = seccomp_arch_add(c, SCMP_ARCH_X86_64); | |
131 | + if (r < 0 && r != -EEXIST) | |
132 | + return r; | |
133 | + r = seccomp_arch_add(c, SCMP_ARCH_X32); | |
134 | + if (r < 0 && r != -EEXIST) | |
135 | + return r; | |
136 | +#endif | |
137 | + return 0; | |
138 | +} | |
139 | + | |
140 | +struct scmp_action_def { | |
141 | + uint32_t action; | |
142 | + int syscall; | |
143 | +}; | |
144 | + | |
145 | +static const struct scmp_action_def preauth_insns[] = { | |
146 | + {SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open)}, | |
147 | + {SCMP_ACT_ERRNO(EACCES), SCMP_SYS(stat)}, | |
148 | + {SCMP_ACT_ALLOW, SCMP_SYS(getpid)}, | |
149 | + {SCMP_ACT_ALLOW, SCMP_SYS(getpid)}, | |
150 | + {SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday)}, | |
151 | + {SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime)}, | |
152 | +#ifdef __NR_time /* not defined on EABI ARM */ | |
153 | + {SCMP_ACT_ALLOW, SCMP_SYS(time)}, | |
154 | +#endif | |
155 | + {SCMP_ACT_ALLOW, SCMP_SYS(read)}, | |
156 | + {SCMP_ACT_ALLOW, SCMP_SYS(write)}, | |
157 | + {SCMP_ACT_ALLOW, SCMP_SYS(close)}, | |
158 | +#ifdef __NR_shutdown /* not defined on archs that go via socketcall(2) */ | |
159 | + {SCMP_ACT_ALLOW, SCMP_SYS(shutdown)}, | |
160 | +#endif | |
161 | + {SCMP_ACT_ALLOW, SCMP_SYS(brk)}, | |
162 | + {SCMP_ACT_ALLOW, SCMP_SYS(poll)}, | |
163 | +#ifdef __NR__newselect | |
164 | + {SCMP_ACT_ALLOW, SCMP_SYS(_newselect)}, | |
165 | +#endif | |
166 | + {SCMP_ACT_ALLOW, SCMP_SYS(select)}, | |
167 | + {SCMP_ACT_ALLOW, SCMP_SYS(madvise)}, | |
168 | +#ifdef __NR_mmap2 /* EABI ARM only has mmap2() */ | |
169 | + {SCMP_ACT_ALLOW, SCMP_SYS(mmap2)}, | |
170 | +#endif | |
171 | +#ifdef __NR_mmap | |
172 | + {SCMP_ACT_ALLOW, SCMP_SYS(mmap)}, | |
173 | +#endif | |
174 | +#ifdef __dietlibc__ | |
175 | + {SCMP_ACT_ALLOW, SCMP_SYS(mremap)}, | |
176 | + {SCMP_ACT_ALLOW, SCMP_SYS(exit)}, | |
177 | +#endif | |
178 | + {SCMP_ACT_ALLOW, SCMP_SYS(munmap)}, | |
179 | + {SCMP_ACT_ALLOW, SCMP_SYS(exit_group)}, | |
180 | +#ifdef __NR_rt_sigprocmask | |
181 | + {SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask)}, | |
182 | +#else | |
183 | + {SCMP_ACT_ALLOW, SCMP_SYS(sigprocmask)}, | |
184 | +#endif | |
185 | + {0, 0} | |
186 | +}; | |
187 | + | |
188 | + | |
189 | +void | |
190 | +ssh_sandbox_child(struct ssh_sandbox *box) | |
191 | +{ | |
192 | + scmp_filter_ctx *seccomp; | |
193 | + struct rlimit rl_zero; | |
194 | + const struct scmp_action_def *insn; | |
195 | + int r; | |
196 | + | |
197 | + /* Set rlimits for completeness if possible. */ | |
198 | + rl_zero.rlim_cur = rl_zero.rlim_max = 0; | |
199 | + if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) | |
200 | + fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", | |
201 | + __func__, strerror(errno)); | |
202 | + if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) | |
203 | + fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", | |
204 | + __func__, strerror(errno)); | |
205 | + if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) | |
206 | + fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", | |
207 | + __func__, strerror(errno)); | |
208 | + | |
209 | + seccomp = seccomp_init(SCMP_ACT_KILL); | |
210 | + if (!seccomp) | |
211 | + fatal("%s:libseccomp activation failed", __func__); | |
212 | + if (seccomp_add_secondary_archs(seccomp)) | |
213 | + fatal("%s:libseccomp secondary arch setup failed", __func__); | |
214 | + | |
215 | + for (insn = preauth_insns; insn->action; insn++) { | |
216 | + if (seccomp_rule_add(seccomp, insn->action, insn->syscall, 0) < 0) | |
217 | + fatal("%s:libseccomp rule failed", __func__); | |
218 | + } | |
219 | + | |
220 | + if ((r = seccomp_load(seccomp)) < 0) | |
221 | + fatal("%s:libseccomp unable to load filter %d", __func__, r); | |
222 | + | |
223 | + seccomp_release(seccomp); | |
224 | +} | |
225 | + | |
226 | +void | |
227 | +ssh_sandbox_parent_finish(struct ssh_sandbox *box) | |
228 | +{ | |
229 | + free(box); | |
230 | + debug3("%s: finished", __func__); | |
231 | +} | |
232 | + | |
233 | +void | |
234 | +ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) | |
235 | +{ | |
236 | + box->child_pid = child_pid; | |
237 | +} | |
238 | + | |
239 | +#endif /* SANDBOX_LIBSECCOMP_FILTER */ |