OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ |
6 #define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "sandbox/sandbox_export.h" | 11 #include "sandbox/sandbox_export.h" |
12 | 12 |
13 namespace sandbox { | 13 namespace sandbox { |
14 | 14 |
15 // This purely static class can be used to perform system calls with some | 15 // This purely static class can be used to perform system calls with some |
16 // low-level control. | 16 // low-level control. |
17 class SANDBOX_EXPORT Syscall { | 17 class SANDBOX_EXPORT Syscall { |
18 public: | 18 public: |
19 // This performs system call |nr| with the arguments p0 to p5 from a constant | 19 // System calls can take up to six parameters (up to eight on some |
20 // userland address, which is for instance observable by seccomp-bpf filters. | 20 // architectures). Traditionally, glibc |
21 // The constant userland address from which these system calls are made will | |
22 // be returned if |nr| is passed as -1. | |
23 // On error, this function will return a value between -1 and -4095 which | |
24 // should be interpreted as -errno. | |
25 static intptr_t Call(int nr, | |
26 intptr_t p0, | |
27 intptr_t p1, | |
28 intptr_t p2, | |
29 intptr_t p3, | |
30 intptr_t p4, | |
31 intptr_t p5); | |
32 | |
33 // System calls can take up to six parameters. Traditionally, glibc | |
34 // implements this property by using variadic argument lists. This works, but | 21 // implements this property by using variadic argument lists. This works, but |
35 // confuses modern tools such as valgrind, because we are nominally passing | 22 // confuses modern tools such as valgrind, because we are nominally passing |
36 // uninitialized data whenever we call through this function and pass less | 23 // uninitialized data whenever we call through this function and pass less |
37 // than the full six arguments. | 24 // than the full six arguments. |
38 // So, instead, we use C++'s template system to achieve a very similar | 25 // So, instead, we use C++'s template system to achieve a very similar |
39 // effect. C++ automatically sets the unused parameters to zero for us, and | 26 // effect. C++ automatically sets the unused parameters to zero for us, and |
40 // it also does the correct type expansion (e.g. from 32bit to 64bit) where | 27 // it also does the correct type expansion (e.g. from 32bit to 64bit) where |
41 // necessary. | 28 // necessary. |
42 // We have to use C-style cast operators as we want to be able to accept both | 29 // We have to use C-style cast operators as we want to be able to accept both |
43 // integer and pointer types. | 30 // integer and pointer types. |
| 31 template <class T0, |
| 32 class T1, |
| 33 class T2, |
| 34 class T3, |
| 35 class T4, |
| 36 class T5, |
| 37 class T6, |
| 38 class T7> |
| 39 static inline intptr_t |
| 40 Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7) { |
| 41 return Call(nr, |
| 42 (intptr_t)p0, |
| 43 (intptr_t)p1, |
| 44 (intptr_t)p2, |
| 45 (intptr_t)p3, |
| 46 (intptr_t)p4, |
| 47 (intptr_t)p5, |
| 48 (intptr_t)p6, |
| 49 (intptr_t)p7); |
| 50 } |
| 51 |
| 52 template <class T0, |
| 53 class T1, |
| 54 class T2, |
| 55 class T3, |
| 56 class T4, |
| 57 class T5, |
| 58 class T6> |
| 59 static inline intptr_t |
| 60 Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6) { |
| 61 return Call(nr, |
| 62 (intptr_t)p0, |
| 63 (intptr_t)p1, |
| 64 (intptr_t)p2, |
| 65 (intptr_t)p3, |
| 66 (intptr_t)p4, |
| 67 (intptr_t)p5, |
| 68 (intptr_t)p6, |
| 69 0); |
| 70 } |
| 71 |
44 template <class T0, class T1, class T2, class T3, class T4, class T5> | 72 template <class T0, class T1, class T2, class T3, class T4, class T5> |
45 static inline intptr_t | 73 static inline intptr_t |
46 Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) { | 74 Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) { |
47 return Call(nr, | 75 return Call(nr, |
48 (intptr_t)p0, | 76 (intptr_t)p0, |
49 (intptr_t)p1, | 77 (intptr_t)p1, |
50 (intptr_t)p2, | 78 (intptr_t)p2, |
51 (intptr_t)p3, | 79 (intptr_t)p3, |
52 (intptr_t)p4, | 80 (intptr_t)p4, |
53 (intptr_t)p5); | 81 (intptr_t)p5, |
| 82 0, |
| 83 0); |
54 } | 84 } |
55 | 85 |
56 template <class T0, class T1, class T2, class T3, class T4> | 86 template <class T0, class T1, class T2, class T3, class T4> |
57 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) { | 87 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) { |
58 return Call(nr, p0, p1, p2, p3, p4, 0); | 88 return Call(nr, p0, p1, p2, p3, p4, 0, 0, 0); |
59 } | 89 } |
60 | 90 |
61 template <class T0, class T1, class T2, class T3> | 91 template <class T0, class T1, class T2, class T3> |
62 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3) { | 92 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3) { |
63 return Call(nr, p0, p1, p2, p3, 0, 0); | 93 return Call(nr, p0, p1, p2, p3, 0, 0, 0, 0); |
64 } | 94 } |
65 | 95 |
66 template <class T0, class T1, class T2> | 96 template <class T0, class T1, class T2> |
67 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2) { | 97 static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2) { |
68 return Call(nr, p0, p1, p2, 0, 0, 0); | 98 return Call(nr, p0, p1, p2, 0, 0, 0, 0, 0); |
69 } | 99 } |
70 | 100 |
71 template <class T0, class T1> | 101 template <class T0, class T1> |
72 static inline intptr_t Call(int nr, T0 p0, T1 p1) { | 102 static inline intptr_t Call(int nr, T0 p0, T1 p1) { |
73 return Call(nr, p0, p1, 0, 0, 0, 0); | 103 return Call(nr, p0, p1, 0, 0, 0, 0, 0, 0); |
74 } | 104 } |
75 | 105 |
76 template <class T0> | 106 template <class T0> |
77 static inline intptr_t Call(int nr, T0 p0) { | 107 static inline intptr_t Call(int nr, T0 p0) { |
78 return Call(nr, p0, 0, 0, 0, 0, 0); | 108 return Call(nr, p0, 0, 0, 0, 0, 0, 0, 0); |
79 } | 109 } |
80 | 110 |
81 static inline intptr_t Call(int nr) { return Call(nr, 0, 0, 0, 0, 0, 0); } | 111 static inline intptr_t Call(int nr) { |
| 112 return Call(nr, 0, 0, 0, 0, 0, 0, 0, 0); |
| 113 } |
82 | 114 |
83 private: | 115 private: |
| 116 // This performs system call |nr| with the arguments p0 to p7 from a constant |
| 117 // userland address, which is for instance observable by seccomp-bpf filters. |
| 118 // The constant userland address from which these system calls are made will |
| 119 // be returned if |nr| is passed as -1. |
| 120 // On error, this function will return a value between -1 and -4095 which |
| 121 // should be interpreted as -errno. |
| 122 static intptr_t Call(int nr, |
| 123 intptr_t p0, |
| 124 intptr_t p1, |
| 125 intptr_t p2, |
| 126 intptr_t p3, |
| 127 intptr_t p4, |
| 128 intptr_t p5, |
| 129 intptr_t p6, |
| 130 intptr_t p7); |
| 131 |
84 DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall); | 132 DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall); |
85 }; | 133 }; |
86 | 134 |
87 } // namespace sandbox | 135 } // namespace sandbox |
88 | 136 |
89 #endif // SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ | 137 #endif // SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ |
OLD | NEW |