]>
iEval git - linux-seccomp.git/blob - libseccomp/src/arch.c
2 * Enhanced Seccomp Architecture/Machine Specific Code
4 * Copyright (c) 2012 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>.
26 #include <asm/bitsperlong.h>
27 #include <linux/audit.h>
34 #include "arch-x86_64.h"
37 #include "arch-aarch64.h"
38 #include "arch-mips.h"
39 #include "arch-mips64.h"
40 #include "arch-mips64n32.h"
42 #include "arch-ppc64.h"
43 #include "arch-s390.h"
44 #include "arch-s390x.h"
48 #define default_arg_count_max 6
50 #define default_arg_offset(x) (offsetof(struct seccomp_data, args[x]))
53 const struct arch_def
*arch_def_native
= &arch_def_x86
;
56 const struct arch_def
*arch_def_native
= &arch_def_x32
;
58 const struct arch_def
*arch_def_native
= &arch_def_x86_64
;
59 #endif /* __ILP32__ */
61 const struct arch_def
*arch_def_native
= &arch_def_arm
;
63 const struct arch_def
*arch_def_native
= &arch_def_aarch64
;
64 #elif __mips__ && _MIPS_SIM == _MIPS_SIM_ABI32
66 const struct arch_def
*arch_def_native
= &arch_def_mips
;
68 const struct arch_def
*arch_def_native
= &arch_def_mipsel
;
69 #endif /* _MIPS_SIM_ABI32 */
70 #elif __mips__ && _MIPS_SIM == _MIPS_SIM_ABI64
72 const struct arch_def
*arch_def_native
= &arch_def_mips64
;
74 const struct arch_def
*arch_def_native
= &arch_def_mipsel64
;
75 #endif /* _MIPS_SIM_ABI64 */
76 #elif __mips__ && _MIPS_SIM == _MIPS_SIM_NABI32
78 const struct arch_def
*arch_def_native
= &arch_def_mips64n32
;
80 const struct arch_def
*arch_def_native
= &arch_def_mipsel64n32
;
81 #endif /* _MIPS_SIM_NABI32 */
84 const struct arch_def
*arch_def_native
= &arch_def_ppc64
;
86 const struct arch_def
*arch_def_native
= &arch_def_ppc64le
;
89 const struct arch_def
*arch_def_native
= &arch_def_ppc
;
90 #elif __s390x__ /* s390x must be checked before s390 */
91 const struct arch_def
*arch_def_native
= &arch_def_s390x
;
93 const struct arch_def
*arch_def_native
= &arch_def_s390
;
95 #error the arch code needs to know about your machine type
96 #endif /* machine type guess */
99 * Validate the architecture token
100 * @param arch the architecture token
102 * Verify the given architecture token; return zero if valid, -EINVAL if not.
105 int arch_valid(uint32_t arch
)
107 return (arch_def_lookup(arch
) ? 0 : -EINVAL
);
111 * Lookup the architecture definition
112 * @param token the architecure token
114 * Return the matching architecture definition, returns NULL on failure.
117 const struct arch_def
*arch_def_lookup(uint32_t token
)
121 return &arch_def_x86
;
122 case SCMP_ARCH_X86_64
:
123 return &arch_def_x86_64
;
125 return &arch_def_x32
;
127 return &arch_def_arm
;
128 case SCMP_ARCH_AARCH64
:
129 return &arch_def_aarch64
;
131 return &arch_def_mips
;
132 case SCMP_ARCH_MIPSEL
:
133 return &arch_def_mipsel
;
134 case SCMP_ARCH_MIPS64
:
135 return &arch_def_mips64
;
136 case SCMP_ARCH_MIPSEL64
:
137 return &arch_def_mipsel64
;
138 case SCMP_ARCH_MIPS64N32
:
139 return &arch_def_mips64n32
;
140 case SCMP_ARCH_MIPSEL64N32
:
141 return &arch_def_mipsel64n32
;
143 return &arch_def_ppc
;
144 case SCMP_ARCH_PPC64
:
145 return &arch_def_ppc64
;
146 case SCMP_ARCH_PPC64LE
:
147 return &arch_def_ppc64le
;
149 return &arch_def_s390
;
150 case SCMP_ARCH_S390X
:
151 return &arch_def_s390x
;
158 * Lookup the architecture definition by name
159 * @param arch_name the architecure name
161 * Return the matching architecture definition, returns NULL on failure.
164 const struct arch_def
*arch_def_lookup_name(const char *arch_name
)
166 if (strcmp(arch_name
, "x86") == 0)
167 return &arch_def_x86
;
168 else if (strcmp(arch_name
, "x86_64") == 0)
169 return &arch_def_x86_64
;
170 else if (strcmp(arch_name
, "x32") == 0)
171 return &arch_def_x32
;
172 else if (strcmp(arch_name
, "arm") == 0)
173 return &arch_def_arm
;
174 else if (strcmp(arch_name
, "aarch64") == 0)
175 return &arch_def_aarch64
;
176 else if (strcmp(arch_name
, "mips") == 0)
177 return &arch_def_mips
;
178 else if (strcmp(arch_name
, "mipsel") == 0)
179 return &arch_def_mipsel
;
180 else if (strcmp(arch_name
, "mips64") == 0)
181 return &arch_def_mips64
;
182 else if (strcmp(arch_name
, "mipsel64") == 0)
183 return &arch_def_mipsel64
;
184 else if (strcmp(arch_name
, "mips64n32") == 0)
185 return &arch_def_mips64n32
;
186 else if (strcmp(arch_name
, "mipsel64n32") == 0)
187 return &arch_def_mipsel64n32
;
188 else if (strcmp(arch_name
, "ppc") == 0)
189 return &arch_def_ppc
;
190 else if (strcmp(arch_name
, "ppc64") == 0)
191 return &arch_def_ppc64
;
192 else if (strcmp(arch_name
, "ppc64le") == 0)
193 return &arch_def_ppc64le
;
194 else if (strcmp(arch_name
, "s390") == 0)
195 return &arch_def_s390
;
196 else if (strcmp(arch_name
, "s390x") == 0)
197 return &arch_def_s390x
;
203 * Determine the maximum number of syscall arguments
204 * @param arch the architecture definition
206 * Determine the maximum number of syscall arguments for the given architecture.
207 * Returns the number of arguments on success, negative values on failure.
210 int arch_arg_count_max(const struct arch_def
*arch
)
212 return (arch_valid(arch
->token
) == 0 ? default_arg_count_max
: -EDOM
);
216 * Determine the argument offset for the lower 32 bits
217 * @param arch the architecture definition
218 * @param arg the argument number
220 * Determine the correct offset for the low 32 bits of the given argument based
221 * on the architecture definition. Returns the offset on success, negative
225 int arch_arg_offset_lo(const struct arch_def
*arch
, unsigned int arg
)
227 if (arch_valid(arch
->token
) < 0)
230 switch (arch
->endian
) {
231 case ARCH_ENDIAN_LITTLE
:
232 return default_arg_offset(arg
);
234 case ARCH_ENDIAN_BIG
:
235 return default_arg_offset(arg
) + 4;
243 * Determine the argument offset for the high 32 bits
244 * @param arch the architecture definition
245 * @param arg the argument number
247 * Determine the correct offset for the high 32 bits of the given argument
248 * based on the architecture definition. Returns the offset on success,
249 * negative values on failure.
252 int arch_arg_offset_hi(const struct arch_def
*arch
, unsigned int arg
)
254 if (arch_valid(arch
->token
) < 0 || arch
->size
!= ARCH_SIZE_64
)
257 switch (arch
->endian
) {
258 case ARCH_ENDIAN_LITTLE
:
259 return default_arg_offset(arg
) + 4;
261 case ARCH_ENDIAN_BIG
:
262 return default_arg_offset(arg
);
270 * Determine the argument offset
271 * @param arch the architecture definition
272 * @param arg the argument number
274 * Determine the correct offset for the given argument based on the
275 * architecture definition. Returns the offset on success, negative values on
279 int arch_arg_offset(const struct arch_def
*arch
, unsigned int arg
)
281 return arch_arg_offset_lo(arch
, arg
);
285 * Resolve a syscall name to a number
286 * @param arch the architecture definition
287 * @param name the syscall name
289 * Resolve the given syscall name to the syscall number based on the given
290 * architecture. Returns the syscall number on success, including negative
291 * pseudo syscall numbers; returns __NR_SCMP_ERROR on failure.
294 int arch_syscall_resolve_name(const struct arch_def
*arch
, const char *name
)
296 if (arch
->syscall_resolve_name
)
297 return (*arch
->syscall_resolve_name
)(name
);
299 return __NR_SCMP_ERROR
;
303 * Resolve a syscall number to a name
304 * @param arch the architecture definition
305 * @param num the syscall number
307 * Resolve the given syscall number to the syscall name based on the given
308 * architecture. Returns a pointer to the syscall name string on success,
309 * including pseudo syscall names; returns NULL on failure.
312 const char *arch_syscall_resolve_num(const struct arch_def
*arch
, int num
)
314 if (arch
->syscall_resolve_num
)
315 return (*arch
->syscall_resolve_num
)(num
);
321 * Translate the syscall number
322 * @param arch the architecture definition
323 * @param syscall the syscall number
325 * Translate the syscall number, in the context of the native architecure, to
326 * the provided architecure. Returns zero on success, negative values on
330 int arch_syscall_translate(const struct arch_def
*arch
, int *syscall
)
335 if (arch
->token
!= arch_def_native
->token
) {
336 sc_name
= arch_syscall_resolve_num(arch_def_native
, *syscall
);
340 sc_num
= arch_syscall_resolve_name(arch
, sc_name
);
341 if (sc_num
== __NR_SCMP_ERROR
)
351 * Rewrite a syscall value to match the architecture
352 * @param arch the architecture definition
353 * @param syscall the syscall number
355 * Syscalls can vary across different architectures so this function rewrites
356 * the syscall into the correct value for the specified architecture. Returns
357 * zero on success, -EDOM if the syscall is not defined for @arch, and negative
361 int arch_syscall_rewrite(const struct arch_def
*arch
, int *syscall
)
366 /* we shouldn't be here - no rewrite needed */
368 } else if (sys
< 0 && sys
> -100) {
369 /* reserved values */
371 } else if (sys
<= -100 && sys
> -10000) {
372 /* rewritable syscalls */
373 if (arch
->syscall_rewrite
)
374 (*arch
->syscall_rewrite
)(syscall
);
377 /* syscalls not defined on this architecture */
384 * Add a new rule to the specified filter
385 * @param col the filter collection
386 * @param db the seccomp filter db
387 * @param strict the strict flag
388 * @param action the filter action
389 * @param syscall the syscall number
390 * @param chain_len the number of argument filters in the argument filter chain
391 * @param chain the argument filter chain
393 * This function adds a new argument/comparison/value to the seccomp filter for
394 * a syscall; multiple arguments can be specified and they will be chained
395 * together (essentially AND'd together) in the filter. When the strict flag
396 * is true the function will fail if the exact rule can not be added to the
397 * filter, if the strict flag is false the function will not fail if the
398 * function needs to adjust the rule due to architecture specifics. Returns
399 * zero on success, negative values on failure.
402 int arch_filter_rule_add(struct db_filter_col
*col
, struct db_filter
*db
,
403 bool strict
, uint32_t action
, int syscall
,
404 unsigned int chain_len
, struct db_api_arg
*chain
)
407 size_t chain_size
= sizeof(*chain
) * chain_len
;
408 struct db_api_rule_list
*rule
, *rule_tail
;
410 /* ensure we aren't using any reserved syscall values */
411 if (syscall
< 0 && syscall
> -100)
414 /* translate the syscall */
415 rc
= arch_syscall_translate(db
->arch
, &syscall
);
419 /* copy of the chain for each filter in the collection */
420 rule
= malloc(sizeof(*rule
));
423 rule
->args
= malloc(chain_size
);
424 if (rule
->args
== NULL
) {
428 rule
->action
= action
;
429 rule
->syscall
= syscall
;
430 rule
->args_cnt
= chain_len
;
431 memcpy(rule
->args
, chain
, chain_size
);
435 /* add the new rule to the existing filter */
436 if (db
->arch
->rule_add
== NULL
) {
437 /* negative syscalls require a db->arch->rule_add() function */
438 if (syscall
< 0 && strict
) {
440 goto rule_add_failure
;
442 rc
= db_rule_add(db
, rule
);
444 rc
= (db
->arch
->rule_add
)(col
, db
, strict
, rule
);
446 /* insert the chain to the end of the filter's rule list */
448 while (rule_tail
->next
)
449 rule_tail
= rule_tail
->next
;
450 if (db
->rules
!= NULL
) {
451 rule
->prev
= db
->rules
->prev
;
452 rule_tail
->next
= db
->rules
;
453 db
->rules
->prev
->next
= rule
;
454 db
->rules
->prev
= rule_tail
;
456 rule
->prev
= rule_tail
;
457 rule_tail
->next
= rule
;
461 goto rule_add_failure
;
469 free(rule_tail
->args
);
This page took 0.069912 seconds and 5 git commands to generate.