| 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_SANDBOX_BPF_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <sys/types.h> | 9 #include <sys/types.h> |
| 10 #include <sys/wait.h> | 10 #include <sys/wait.h> |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <limits> | 13 #include <limits> |
| 14 #include <map> | 14 #include <map> |
| 15 #include <set> | 15 #include <set> |
| 16 #include <utility> | 16 #include <utility> |
| 17 #include <vector> | 17 #include <vector> |
| 18 | 18 |
| 19 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 20 #include "sandbox/linux/seccomp-bpf/die.h" | 20 #include "sandbox/linux/seccomp-bpf/die.h" |
| 21 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 21 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 22 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | 22 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
| 23 #include "sandbox/linux/seccomp-bpf/port.h" | 23 #include "sandbox/linux/seccomp-bpf/port.h" |
| 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h" | 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h" |
| 25 | 25 |
| 26 namespace playground2 { | 26 namespace playground2 { |
| 27 | 27 |
| 28 struct arch_seccomp_data { | 28 struct arch_seccomp_data { |
| 29 int nr; | 29 int nr; |
| 30 uint32_t arch; | 30 uint32_t arch; |
| 31 uint64_t instruction_pointer; | 31 uint64_t instruction_pointer; |
| 32 uint64_t args[6]; | 32 uint64_t args[6]; |
| 33 }; | 33 }; |
| 34 | 34 |
| 35 struct arch_sigsys { | 35 struct arch_sigsys { |
| 36 void *ip; | 36 void* ip; |
| 37 int nr; | 37 int nr; |
| 38 unsigned int arch; | 38 unsigned int arch; |
| 39 }; | 39 }; |
| 40 | 40 |
| 41 class CodeGen; | 41 class CodeGen; |
| 42 class SandboxUnittestHelper; | 42 class SandboxUnittestHelper; |
| 43 class SandboxBpfPolicy; | 43 class SandboxBpfPolicy; |
| 44 struct Instruction; | 44 struct Instruction; |
| 45 | 45 |
| 46 class Sandbox { | 46 class Sandbox { |
| 47 public: | 47 public: |
| 48 enum SandboxStatus { | 48 enum SandboxStatus { |
| 49 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() | 49 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() |
| 50 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing | 50 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing |
| 51 STATUS_UNAVAILABLE, // Currently unavailable but might work again later | 51 STATUS_UNAVAILABLE, // Currently unavailable but might work again later |
| 52 STATUS_AVAILABLE, // Sandboxing is available but not currently active | 52 STATUS_AVAILABLE, // Sandboxing is available but not currently active |
| 53 STATUS_ENABLED // The sandbox is now active | 53 STATUS_ENABLED // The sandbox is now active |
| 54 }; | 54 }; |
| 55 | 55 |
| 56 // BpfSandboxPolicy is the following type: | 56 // BpfSandboxPolicy is the following type: |
| 57 // ErrorCode (Sandbox *sb, int sysnum, void *aux); | 57 // ErrorCode (Sandbox *sb, int sysnum, void *aux); |
| 58 // When calling setSandboxPolicy(), the caller can provide an arbitrary | 58 // When calling setSandboxPolicy(), the caller can provide an arbitrary |
| 59 // pointer in |aux|. This pointer will then be forwarded to the sandbox | 59 // pointer in |aux|. This pointer will then be forwarded to the sandbox |
| 60 // policy each time a call is made through an EvaluateSyscall function | 60 // policy each time a call is made through an EvaluateSyscall function |
| 61 // pointer. One common use case would be to pass the "aux" pointer as an | 61 // pointer. One common use case would be to pass the "aux" pointer as an |
| 62 // argument to Trap() functions. | 62 // argument to Trap() functions. |
| 63 typedef BpfSandboxPolicy* EvaluateSyscall; | 63 typedef BpfSandboxPolicy* EvaluateSyscall; |
| 64 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; | 64 typedef std::vector<std::pair<EvaluateSyscall, void*> > Evaluators; |
| 65 | 65 |
| 66 // A vector of BPF instructions that need to be installed as a filter | 66 // A vector of BPF instructions that need to be installed as a filter |
| 67 // program in the kernel. | 67 // program in the kernel. |
| 68 typedef std::vector<struct sock_filter> Program; | 68 typedef std::vector<struct sock_filter> Program; |
| 69 | 69 |
| 70 // Constructors and destructors. | 70 // Constructors and destructors. |
| 71 // NOTE: Setting a policy and starting the sandbox is a one-way operation. | 71 // NOTE: Setting a policy and starting the sandbox is a one-way operation. |
| 72 // The kernel does not provide any option for unloading a loaded | 72 // The kernel does not provide any option for unloading a loaded |
| 73 // sandbox. Strictly speaking, that means we should disallow calling | 73 // sandbox. Strictly speaking, that means we should disallow calling |
| 74 // the destructor, if StartSandbox() has ever been called. In practice, | 74 // the destructor, if StartSandbox() has ever been called. In practice, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 104 // by returning ERR_ALLOWED; it can deny the system call unconditionally by | 104 // by returning ERR_ALLOWED; it can deny the system call unconditionally by |
| 105 // returning an appropriate "errno" value; or it can request inspection | 105 // returning an appropriate "errno" value; or it can request inspection |
| 106 // of system call argument(s) by returning a suitable ErrorCode. | 106 // of system call argument(s) by returning a suitable ErrorCode. |
| 107 // The "aux" parameter can be used to pass optional data to the system call | 107 // The "aux" parameter can be used to pass optional data to the system call |
| 108 // evaluator. There are different possible uses for this data, but one of the | 108 // evaluator. There are different possible uses for this data, but one of the |
| 109 // use cases would be for the policy to then forward this pointer to a Trap() | 109 // use cases would be for the policy to then forward this pointer to a Trap() |
| 110 // handler. In this case, of course, the data that is pointed to must remain | 110 // handler. In this case, of course, the data that is pointed to must remain |
| 111 // valid for the entire time that Trap() handlers can be called; typically, | 111 // valid for the entire time that Trap() handlers can be called; typically, |
| 112 // this would be the lifetime of the program. | 112 // this would be the lifetime of the program. |
| 113 // DEPRECATED: use the policy interface below. | 113 // DEPRECATED: use the policy interface below. |
| 114 void SetSandboxPolicyDeprecated(EvaluateSyscall syscallEvaluator, void *aux); | 114 void SetSandboxPolicyDeprecated(EvaluateSyscall syscallEvaluator, void* aux); |
| 115 | 115 |
| 116 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here | 116 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here |
| 117 // to the sandbox object. | 117 // to the sandbox object. |
| 118 void SetSandboxPolicy(SandboxBpfPolicy* policy); | 118 void SetSandboxPolicy(SandboxBpfPolicy* policy); |
| 119 | 119 |
| 120 // We can use ErrorCode to request calling of a trap handler. This method | 120 // We can use ErrorCode to request calling of a trap handler. This method |
| 121 // performs the required wrapping of the callback function into an | 121 // performs the required wrapping of the callback function into an |
| 122 // ErrorCode object. | 122 // ErrorCode object. |
| 123 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall | 123 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall |
| 124 // for a description of how to pass data from SetSandboxPolicy() to a Trap() | 124 // for a description of how to pass data from SetSandboxPolicy() to a Trap() |
| 125 // handler. | 125 // handler. |
| 126 ErrorCode Trap(Trap::TrapFnc fnc, const void *aux); | 126 ErrorCode Trap(Trap::TrapFnc fnc, const void* aux); |
| 127 | 127 |
| 128 // Calls a user-space trap handler and disables all sandboxing for system | 128 // Calls a user-space trap handler and disables all sandboxing for system |
| 129 // calls made from this trap handler. | 129 // calls made from this trap handler. |
| 130 // This feature is available only if explicitly enabled by the user having | 130 // This feature is available only if explicitly enabled by the user having |
| 131 // set the CHROME_SANDBOX_DEBUGGING environment variable. | 131 // set the CHROME_SANDBOX_DEBUGGING environment variable. |
| 132 // Returns an ET_INVALID ErrorCode, if called when not enabled. | 132 // Returns an ET_INVALID ErrorCode, if called when not enabled. |
| 133 // NOTE: This feature, by definition, disables all security features of | 133 // NOTE: This feature, by definition, disables all security features of |
| 134 // the sandbox. It should never be used in production, but it can be | 134 // the sandbox. It should never be used in production, but it can be |
| 135 // very useful to diagnose code that is incompatible with the sandbox. | 135 // very useful to diagnose code that is incompatible with the sandbox. |
| 136 // If even a single system call returns "UnsafeTrap", the security of | 136 // If even a single system call returns "UnsafeTrap", the security of |
| 137 // entire sandbox should be considered compromised. | 137 // entire sandbox should be considered compromised. |
| 138 ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void *aux); | 138 ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void* aux); |
| 139 | 139 |
| 140 // From within an UnsafeTrap() it is often useful to be able to execute | 140 // From within an UnsafeTrap() it is often useful to be able to execute |
| 141 // the system call that triggered the trap. The ForwardSyscall() method | 141 // the system call that triggered the trap. The ForwardSyscall() method |
| 142 // makes this easy. It is more efficient than calling glibc's syscall() | 142 // makes this easy. It is more efficient than calling glibc's syscall() |
| 143 // function, as it avoid the extra round-trip to the signal handler. And | 143 // function, as it avoid the extra round-trip to the signal handler. And |
| 144 // it automatically does the correct thing to report kernel-style error | 144 // it automatically does the correct thing to report kernel-style error |
| 145 // conditions, rather than setting errno. See the comments for TrapFnc for | 145 // conditions, rather than setting errno. See the comments for TrapFnc for |
| 146 // details. In other words, the return value from ForwardSyscall() is | 146 // details. In other words, the return value from ForwardSyscall() is |
| 147 // directly suitable as a return value for a trap handler. | 147 // directly suitable as a return value for a trap handler. |
| 148 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); | 148 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); |
| 149 | 149 |
| 150 // We can also use ErrorCode to request evaluation of a conditional | 150 // We can also use ErrorCode to request evaluation of a conditional |
| 151 // statement based on inspection of system call parameters. | 151 // statement based on inspection of system call parameters. |
| 152 // This method wrap an ErrorCode object around the conditional statement. | 152 // This method wrap an ErrorCode object around the conditional statement. |
| 153 // Argument "argno" (1..6) will be compared to "value" using comparator | 153 // Argument "argno" (1..6) will be compared to "value" using comparator |
| 154 // "op". If the condition is true "passed" will be returned, otherwise | 154 // "op". If the condition is true "passed" will be returned, otherwise |
| 155 // "failed". | 155 // "failed". |
| 156 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) | 156 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) |
| 157 // If it is outside this range, the sandbox treats the system call just | 157 // If it is outside this range, the sandbox treats the system call just |
| 158 // the same as any other ABI violation (i.e. it aborts with an error | 158 // the same as any other ABI violation (i.e. it aborts with an error |
| 159 // message). | 159 // message). |
| 160 ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, | 160 ErrorCode Cond(int argno, |
| 161 ErrorCode::ArgType is_32bit, |
| 161 ErrorCode::Operation op, | 162 ErrorCode::Operation op, |
| 162 uint64_t value, const ErrorCode& passed, | 163 uint64_t value, |
| 164 const ErrorCode& passed, |
| 163 const ErrorCode& failed); | 165 const ErrorCode& failed); |
| 164 | 166 |
| 165 // Kill the program and print an error message. | 167 // Kill the program and print an error message. |
| 166 ErrorCode Kill(const char *msg); | 168 ErrorCode Kill(const char* msg); |
| 167 | 169 |
| 168 // This is the main public entry point. It finds all system calls that | 170 // This is the main public entry point. It finds all system calls that |
| 169 // need rewriting, sets up the resources needed by the sandbox, and | 171 // need rewriting, sets up the resources needed by the sandbox, and |
| 170 // enters Seccomp mode. | 172 // enters Seccomp mode. |
| 171 // It is possible to stack multiple sandboxes by creating separate "Sandbox" | 173 // It is possible to stack multiple sandboxes by creating separate "Sandbox" |
| 172 // objects and calling "StartSandbox()" on each of them. Please note, that | 174 // objects and calling "StartSandbox()" on each of them. Please note, that |
| 173 // this requires special care, though, as newly stacked sandboxes can never | 175 // this requires special care, though, as newly stacked sandboxes can never |
| 174 // relax restrictions imposed by earlier sandboxes. Furthermore, installing | 176 // relax restrictions imposed by earlier sandboxes. Furthermore, installing |
| 175 // a new policy requires making system calls, that might already be | 177 // a new policy requires making system calls, that might already be |
| 176 // disallowed. | 178 // disallowed. |
| 177 // Finally, stacking does add more kernel overhead than having a single | 179 // Finally, stacking does add more kernel overhead than having a single |
| 178 // combined policy. So, it should only be used if there are no alternatives. | 180 // combined policy. So, it should only be used if there are no alternatives. |
| 179 void StartSandbox(); | 181 void StartSandbox(); |
| 180 | 182 |
| 181 // Assembles a BPF filter program from the current policy. After calling this | 183 // Assembles a BPF filter program from the current policy. After calling this |
| 182 // function, you must not call any other sandboxing function. | 184 // function, you must not call any other sandboxing function. |
| 183 // Typically, AssembleFilter() is only used by unit tests and by sandbox | 185 // Typically, AssembleFilter() is only used by unit tests and by sandbox |
| 184 // internals. It should not be used by production code. | 186 // internals. It should not be used by production code. |
| 185 // For performance reasons, we normally only run the assembled BPF program | 187 // For performance reasons, we normally only run the assembled BPF program |
| 186 // through the verifier, iff the program was built in debug mode. | 188 // through the verifier, iff the program was built in debug mode. |
| 187 // But by setting "force_verification", the caller can request that the | 189 // But by setting "force_verification", the caller can request that the |
| 188 // verifier is run unconditionally. This is useful for unittests. | 190 // verifier is run unconditionally. This is useful for unittests. |
| 189 Program *AssembleFilter(bool force_verification); | 191 Program* AssembleFilter(bool force_verification); |
| 190 | 192 |
| 191 // Returns the fatal ErrorCode that is used to indicate that somebody | 193 // Returns the fatal ErrorCode that is used to indicate that somebody |
| 192 // attempted to pass a 64bit value in a 32bit system call argument. | 194 // attempted to pass a 64bit value in a 32bit system call argument. |
| 193 // This method is primarily needed for testing purposes. | 195 // This method is primarily needed for testing purposes. |
| 194 ErrorCode Unexpected64bitArgument(); | 196 ErrorCode Unexpected64bitArgument(); |
| 195 | 197 |
| 196 private: | 198 private: |
| 197 friend class CodeGen; | 199 friend class CodeGen; |
| 198 friend class SandboxUnittestHelper; | 200 friend class SandboxUnittestHelper; |
| 199 friend class ErrorCode; | 201 friend class ErrorCode; |
| 200 | 202 |
| 201 struct Range { | 203 struct Range { |
| 202 Range(uint32_t f, uint32_t t, const ErrorCode& e) | 204 Range(uint32_t f, uint32_t t, const ErrorCode& e) |
| 203 : from(f), | 205 : from(f), to(t), err(e) {} |
| 204 to(t), | 206 uint32_t from, to; |
| 205 err(e) { | |
| 206 } | |
| 207 uint32_t from, to; | |
| 208 ErrorCode err; | 207 ErrorCode err; |
| 209 }; | 208 }; |
| 210 typedef std::vector<Range> Ranges; | 209 typedef std::vector<Range> Ranges; |
| 211 typedef std::map<uint32_t, ErrorCode> ErrMap; | 210 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 212 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; | 211 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; |
| 213 | 212 |
| 214 // Get a file descriptor pointing to "/proc", if currently available. | 213 // Get a file descriptor pointing to "/proc", if currently available. |
| 215 int proc_fd() { return proc_fd_; } | 214 int proc_fd() { return proc_fd_; } |
| 216 | 215 |
| 217 // Creates a subprocess and runs "code_in_sandbox" inside of the specified | 216 // Creates a subprocess and runs "code_in_sandbox" inside of the specified |
| 218 // policy. The caller has to make sure that "this" has not yet been | 217 // policy. The caller has to make sure that "this" has not yet been |
| 219 // initialized with any other policies. | 218 // initialized with any other policies. |
| 220 bool RunFunctionInPolicy(void (*code_in_sandbox)(), | 219 bool RunFunctionInPolicy(void (*code_in_sandbox)(), |
| 221 EvaluateSyscall syscall_evaluator, void *aux); | 220 EvaluateSyscall syscall_evaluator, |
| 221 void* aux); |
| 222 | 222 |
| 223 // Performs a couple of sanity checks to verify that the kernel supports the | 223 // Performs a couple of sanity checks to verify that the kernel supports the |
| 224 // features that we need for successful sandboxing. | 224 // features that we need for successful sandboxing. |
| 225 // The caller has to make sure that "this" has not yet been initialized with | 225 // The caller has to make sure that "this" has not yet been initialized with |
| 226 // any other policies. | 226 // any other policies. |
| 227 bool KernelSupportSeccompBPF(); | 227 bool KernelSupportSeccompBPF(); |
| 228 | 228 |
| 229 // Verify that the current policy passes some basic sanity checks. | 229 // Verify that the current policy passes some basic sanity checks. |
| 230 void PolicySanityChecks(SandboxBpfPolicy* policy); | 230 void PolicySanityChecks(SandboxBpfPolicy* policy); |
| 231 | 231 |
| 232 // Assembles and installs a filter based on the policy that has previously | 232 // Assembles and installs a filter based on the policy that has previously |
| 233 // been configured with SetSandboxPolicy(). | 233 // been configured with SetSandboxPolicy(). |
| 234 void InstallFilter(); | 234 void InstallFilter(); |
| 235 | 235 |
| 236 // Verify the correctness of a compiled program by comparing it against the | 236 // Verify the correctness of a compiled program by comparing it against the |
| 237 // current policy. This function should only ever be called by unit tests and | 237 // current policy. This function should only ever be called by unit tests and |
| 238 // by the sandbox internals. It should not be used by production code. | 238 // by the sandbox internals. It should not be used by production code. |
| 239 void VerifyProgram(const Program& program, bool has_unsafe_traps); | 239 void VerifyProgram(const Program& program, bool has_unsafe_traps); |
| 240 | 240 |
| 241 // Finds all the ranges of system calls that need to be handled. Ranges are | 241 // Finds all the ranges of system calls that need to be handled. Ranges are |
| 242 // sorted in ascending order of system call numbers. There are no gaps in the | 242 // sorted in ascending order of system call numbers. There are no gaps in the |
| 243 // ranges. System calls with identical ErrorCodes are coalesced into a single | 243 // ranges. System calls with identical ErrorCodes are coalesced into a single |
| 244 // range. | 244 // range. |
| 245 void FindRanges(Ranges *ranges); | 245 void FindRanges(Ranges* ranges); |
| 246 | 246 |
| 247 // Returns a BPF program snippet that implements a jump table for the | 247 // Returns a BPF program snippet that implements a jump table for the |
| 248 // given range of system call numbers. This function runs recursively. | 248 // given range of system call numbers. This function runs recursively. |
| 249 Instruction *AssembleJumpTable(CodeGen *gen, | 249 Instruction* AssembleJumpTable(CodeGen* gen, |
| 250 Ranges::const_iterator start, | 250 Ranges::const_iterator start, |
| 251 Ranges::const_iterator stop); | 251 Ranges::const_iterator stop); |
| 252 | 252 |
| 253 // Returns a BPF program snippet that makes the BPF filter program exit | 253 // Returns a BPF program snippet that makes the BPF filter program exit |
| 254 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a | 254 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a |
| 255 // conditional expression; if so, this function will recursively call | 255 // conditional expression; if so, this function will recursively call |
| 256 // CondExpression() and possibly RetExpression() to build a complex set of | 256 // CondExpression() and possibly RetExpression() to build a complex set of |
| 257 // instructions. | 257 // instructions. |
| 258 Instruction *RetExpression(CodeGen *gen, const ErrorCode& err); | 258 Instruction* RetExpression(CodeGen* gen, const ErrorCode& err); |
| 259 | 259 |
| 260 // Returns a BPF program that evaluates the conditional expression in | 260 // Returns a BPF program that evaluates the conditional expression in |
| 261 // "cond" and returns the appropriate value from the BPF filter program. | 261 // "cond" and returns the appropriate value from the BPF filter program. |
| 262 // This function recursively calls RetExpression(); it should only ever be | 262 // This function recursively calls RetExpression(); it should only ever be |
| 263 // called from RetExpression(). | 263 // called from RetExpression(). |
| 264 Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); | 264 Instruction* CondExpression(CodeGen* gen, const ErrorCode& cond); |
| 265 | 265 |
| 266 static SandboxStatus status_; | 266 static SandboxStatus status_; |
| 267 | 267 |
| 268 bool quiet_; | 268 bool quiet_; |
| 269 int proc_fd_; | 269 int proc_fd_; |
| 270 scoped_ptr<const SandboxBpfPolicy> policy_; | 270 scoped_ptr<const SandboxBpfPolicy> policy_; |
| 271 Conds* conds_; | 271 Conds* conds_; |
| 272 bool sandbox_has_started_; | 272 bool sandbox_has_started_; |
| 273 | 273 |
| 274 DISALLOW_COPY_AND_ASSIGN(Sandbox); | 274 DISALLOW_COPY_AND_ASSIGN(Sandbox); |
| 275 }; | 275 }; |
| 276 | 276 |
| 277 } // namespace | 277 } // namespace |
| 278 | 278 |
| 279 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 279 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| OLD | NEW |