]> git.pld-linux.org Git - packages/openssh.git/blob - libseccomp-sandbox.patch
e701b2c298cbd8966568405f12c1a24a4bbe9e12
[packages/openssh.git] / libseccomp-sandbox.patch
1 https://bugzilla.mindrot.org/show_bug.cgi?id=2142
2
3 --- a/Makefile.in       
4 +++ a/Makefile.in       
5 @@ -112,7 +112,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
6         loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
7         sftp-server.o sftp-common.o \
8         sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
9 -       sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
10 +       sandbox-seccomp-filter.o sandbox-libseccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
11         sandbox-solaris.o
12  
13  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 ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out
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, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge)],
44 +       [  --with-sandbox=style    Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, libseccomp_filter, systrace, pledge)],
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 */
This page took 0.052478 seconds and 2 git commands to generate.