]>
iEval git - linux-seccomp.git/blob - libseccomp/src/arch-x86.c
2 * Enhanced Seccomp x86 Specific Code
4 * Copyright (c) 2012,2016 Red Hat <pmoore@redhat.com>
5 * Author: Paul Moore <paul@paul-moore.com>
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of version 2.1 of the GNU Lesser General Public License as
11 * published by the Free Software Foundation.
13 * This library is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, see <http://www.gnu.org/licenses>.
25 #include <linux/audit.h>
30 /* x86 syscall numbers */
31 #define __x86_NR_socketcall 102
32 #define __x86_NR_ipc 117
34 const struct arch_def arch_def_x86
= {
35 .token
= SCMP_ARCH_X86
,
36 .token_bpf
= AUDIT_ARCH_I386
,
38 .endian
= ARCH_ENDIAN_LITTLE
,
39 .syscall_resolve_name
= x86_syscall_resolve_name
,
40 .syscall_resolve_num
= x86_syscall_resolve_num
,
41 .syscall_rewrite
= x86_syscall_rewrite
,
42 .rule_add
= x86_rule_add
,
46 * Convert a multiplexed pseudo socket syscall into a direct syscall
47 * @param socketcall the multiplexed pseudo syscall number
49 * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
50 * no related syscall, or __NR_SCMP_ERROR otherwise.
53 int _x86_sock_demux(int socketcall
)
69 /* accept - not defined */
70 return __NR_SCMP_UNDEF
;
81 /* send - not defined */
82 return __NR_SCMP_UNDEF
;
84 /* recv - not defined */
85 return __NR_SCMP_UNDEF
;
118 return __NR_SCMP_ERROR
;
122 * Convert a direct socket syscall into multiplexed pseudo socket syscall
123 * @param syscall the direct syscall
125 * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
126 * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
129 int _x86_sock_mux(int syscall
)
185 return __NR_SCMP_ERROR
;
189 * Rewrite a syscall value to match the architecture
190 * @param syscall the syscall number
192 * Syscalls can vary across different architectures so this function rewrites
193 * the syscall into the correct value for the specified architecture. Returns
194 * zero on success, negative values on failure.
197 int x86_syscall_rewrite(int *syscall
)
201 if (sys
<= -100 && sys
>= -120)
202 *syscall
= __x86_NR_socketcall
;
203 else if (sys
<= -200 && sys
>= -224)
204 *syscall
= __x86_NR_ipc
;
212 * add a new rule to the x86 seccomp filter
213 * @param col the filter collection
214 * @param db the seccomp filter db
215 * @param strict the strict flag
216 * @param rule the filter rule
218 * This function adds a new syscall filter to the seccomp filter db, making any
219 * necessary adjustments for the x86 ABI. Returns zero on success, negative
223 int x86_rule_add(struct db_filter_col
*col
, struct db_filter
*db
, bool strict
,
224 struct db_api_rule_list
*rule
)
229 int sys
= rule
->syscall
;
231 struct db_api_rule_list
*rule_a
, *rule_b
;
233 if ((sys
<= -100 && sys
>= -120) || (sys
>= 359 && sys
<= 373)) {
234 /* (-100 to -120) : multiplexed socket syscalls
235 (359 to 373) : direct socket syscalls, Linux 4.3+ */
237 /* strict check for the multiplexed socket syscalls */
238 for (iter
= 0; iter
< rule
->args_cnt
; iter
++) {
239 if ((rule
->args
[iter
].valid
!= 0) && (strict
))
243 /* determine both the muxed and direct syscall numbers */
245 sys_a
= _x86_sock_mux(sys
);
246 if (sys_a
== __NR_SCMP_ERROR
)
247 return __NR_SCMP_ERROR
;
251 sys_b
= _x86_sock_demux(sys
);
252 if (sys_b
== __NR_SCMP_ERROR
)
253 return __NR_SCMP_ERROR
;
256 /* use rule_a for the multiplexed syscall and use rule_b for
257 * the direct wired syscall */
259 if (sys_a
== __NR_SCMP_UNDEF
) {
262 } else if (sys_b
== __NR_SCMP_UNDEF
) {
266 /* need two rules, dup the first and link together */
268 rule_b
= malloc(sizeof(*rule_b
));
271 args_size
= sizeof(*rule_b
->args
) * rule_a
->args_cnt
;
272 rule_b
->args
= malloc(args_size
);
273 if (rule_b
->args
== NULL
) {
277 rule_b
->action
= rule_a
->action
;
278 rule_b
->syscall
= rule_a
->syscall
;
279 rule_b
->args_cnt
= rule_a
->args_cnt
;
280 memcpy(rule_b
->args
, rule_a
->args
, args_size
);
281 rule_b
->prev
= rule_a
;
283 rule_a
->next
= rule_b
;
286 /* multiplexed socket syscalls */
287 if (rule_a
!= NULL
) {
288 rule_a
->syscall
= __x86_NR_socketcall
;
289 rule_a
->args
[0].arg
= 0;
290 rule_a
->args
[0].op
= SCMP_CMP_EQ
;
291 rule_a
->args
[0].mask
= DATUM_MAX
;
292 rule_a
->args
[0].datum
= (-sys_a
) % 100;
293 rule_a
->args
[0].valid
= 1;
296 /* direct wired socket syscalls */
298 rule_b
->syscall
= sys_b
;
300 /* add the rules as a single transaction */
301 rc
= db_col_transaction_start(col
);
304 if (rule_a
!= NULL
) {
305 rc
= db_rule_add(db
, rule_a
);
307 goto fail_transaction
;
309 if (rule_b
!= NULL
) {
310 rc
= db_rule_add(db
, rule_b
);
312 goto fail_transaction
;
314 db_col_transaction_commit(col
);
315 } else if (sys
<= -200 && sys
>= -224) {
316 /* multiplexed ipc syscalls */
317 for (iter
= 0; iter
< ARG_COUNT_MAX
; iter
++) {
318 if ((rule
->args
[iter
].valid
!= 0) && (strict
))
321 rule
->args
[0].arg
= 0;
322 rule
->args
[0].op
= SCMP_CMP_EQ
;
323 rule
->args
[0].mask
= DATUM_MAX
;
324 rule
->args
[0].datum
= abs(sys
) % 200;
325 rule
->args
[0].valid
= 1;
326 rule
->syscall
= __x86_NR_ipc
;
328 rc
= db_rule_add(db
, rule
);
331 } else if (sys
>= 0) {
332 /* normal syscall processing */
333 rc
= db_rule_add(db
, rule
);
342 db_col_transaction_abort(col
);
This page took 0.072283 seconds and 5 git commands to generate.