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 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" | 5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <pthread.h> | 9 #include <pthread.h> |
10 #include <sched.h> | 10 #include <sched.h> |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 int* counter = static_cast<int*>(aux); | 106 int* counter = static_cast<int*>(aux); |
107 return (*counter)++; | 107 return (*counter)++; |
108 } | 108 } |
109 | 109 |
110 class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy { | 110 class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy { |
111 public: | 111 public: |
112 explicit VerboseAPITestingPolicy(int* counter_ptr) | 112 explicit VerboseAPITestingPolicy(int* counter_ptr) |
113 : counter_ptr_(counter_ptr) {} | 113 : counter_ptr_(counter_ptr) {} |
114 virtual ~VerboseAPITestingPolicy() {} | 114 virtual ~VerboseAPITestingPolicy() {} |
115 | 115 |
116 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 116 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
117 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 117 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
118 if (sysno == __NR_uname) { | 118 if (sysno == __NR_uname) { |
119 return Trap(IncreaseCounter, counter_ptr_); | 119 return Trap(IncreaseCounter, counter_ptr_); |
120 } | 120 } |
121 return Allow(); | 121 return Allow(); |
122 } | 122 } |
123 | 123 |
124 private: | 124 private: |
125 int* counter_ptr_; | 125 int* counter_ptr_; |
126 | 126 |
(...skipping 17 matching lines...) Expand all Loading... |
144 } | 144 } |
145 } | 145 } |
146 | 146 |
147 // A simple blacklist test | 147 // A simple blacklist test |
148 | 148 |
149 class BlacklistNanosleepPolicy : public SandboxBPFDSLPolicy { | 149 class BlacklistNanosleepPolicy : public SandboxBPFDSLPolicy { |
150 public: | 150 public: |
151 BlacklistNanosleepPolicy() {} | 151 BlacklistNanosleepPolicy() {} |
152 virtual ~BlacklistNanosleepPolicy() {} | 152 virtual ~BlacklistNanosleepPolicy() {} |
153 | 153 |
154 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 154 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
155 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 155 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
156 switch (sysno) { | 156 switch (sysno) { |
157 case __NR_nanosleep: | 157 case __NR_nanosleep: |
158 return Error(EACCES); | 158 return Error(EACCES); |
159 default: | 159 default: |
160 return Allow(); | 160 return Allow(); |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 static void AssertNanosleepFails() { | 164 static void AssertNanosleepFails() { |
(...skipping 11 matching lines...) Expand all Loading... |
176 BlacklistNanosleepPolicy::AssertNanosleepFails(); | 176 BlacklistNanosleepPolicy::AssertNanosleepFails(); |
177 } | 177 } |
178 | 178 |
179 // Now do a simple whitelist test | 179 // Now do a simple whitelist test |
180 | 180 |
181 class WhitelistGetpidPolicy : public SandboxBPFDSLPolicy { | 181 class WhitelistGetpidPolicy : public SandboxBPFDSLPolicy { |
182 public: | 182 public: |
183 WhitelistGetpidPolicy() {} | 183 WhitelistGetpidPolicy() {} |
184 virtual ~WhitelistGetpidPolicy() {} | 184 virtual ~WhitelistGetpidPolicy() {} |
185 | 185 |
186 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 186 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
187 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 187 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
188 switch (sysno) { | 188 switch (sysno) { |
189 case __NR_getpid: | 189 case __NR_getpid: |
190 case __NR_exit_group: | 190 case __NR_exit_group: |
191 return Allow(); | 191 return Allow(); |
192 default: | 192 default: |
193 return Error(ENOMEM); | 193 return Error(ENOMEM); |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
(...skipping 18 matching lines...) Expand all Loading... |
215 SANDBOX_ASSERT(aux); | 215 SANDBOX_ASSERT(aux); |
216 *(static_cast<int*>(aux)) = kExpectedReturnValue; | 216 *(static_cast<int*>(aux)) = kExpectedReturnValue; |
217 return -ENOMEM; | 217 return -ENOMEM; |
218 } | 218 } |
219 | 219 |
220 class BlacklistNanosleepTrapPolicy : public SandboxBPFDSLPolicy { | 220 class BlacklistNanosleepTrapPolicy : public SandboxBPFDSLPolicy { |
221 public: | 221 public: |
222 explicit BlacklistNanosleepTrapPolicy(int* aux) : aux_(aux) {} | 222 explicit BlacklistNanosleepTrapPolicy(int* aux) : aux_(aux) {} |
223 virtual ~BlacklistNanosleepTrapPolicy() {} | 223 virtual ~BlacklistNanosleepTrapPolicy() {} |
224 | 224 |
225 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 225 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
226 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 226 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
227 switch (sysno) { | 227 switch (sysno) { |
228 case __NR_nanosleep: | 228 case __NR_nanosleep: |
229 return Trap(EnomemHandler, aux_); | 229 return Trap(EnomemHandler, aux_); |
230 default: | 230 default: |
231 return Allow(); | 231 return Allow(); |
232 } | 232 } |
233 } | 233 } |
234 | 234 |
235 private: | 235 private: |
(...skipping 21 matching lines...) Expand all Loading... |
257 BPF_ASSERT(*BPF_AUX == kExpectedReturnValue); | 257 BPF_ASSERT(*BPF_AUX == kExpectedReturnValue); |
258 } | 258 } |
259 | 259 |
260 // A simple test that verifies we can return arbitrary errno values. | 260 // A simple test that verifies we can return arbitrary errno values. |
261 | 261 |
262 class ErrnoTestPolicy : public SandboxBPFDSLPolicy { | 262 class ErrnoTestPolicy : public SandboxBPFDSLPolicy { |
263 public: | 263 public: |
264 ErrnoTestPolicy() {} | 264 ErrnoTestPolicy() {} |
265 virtual ~ErrnoTestPolicy() {} | 265 virtual ~ErrnoTestPolicy() {} |
266 | 266 |
267 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 267 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
268 | 268 |
269 private: | 269 private: |
270 DISALLOW_COPY_AND_ASSIGN(ErrnoTestPolicy); | 270 DISALLOW_COPY_AND_ASSIGN(ErrnoTestPolicy); |
271 }; | 271 }; |
272 | 272 |
273 ResultExpr ErrnoTestPolicy::EvaluateSyscall(int sysno) const { | 273 ResultExpr ErrnoTestPolicy::EvaluateSyscall(int sysno) const { |
274 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 274 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
275 switch (sysno) { | 275 switch (sysno) { |
276 case __NR_dup3: // dup2 is a wrapper of dup3 in android | 276 case __NR_dup3: // dup2 is a wrapper of dup3 in android |
277 #if defined(__NR_dup2) | 277 #if defined(__NR_dup2) |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 BPF_ASSERT(errno == 42); | 339 BPF_ASSERT(errno == 42); |
340 } | 340 } |
341 | 341 |
342 // Testing the stacking of two sandboxes | 342 // Testing the stacking of two sandboxes |
343 | 343 |
344 class StackingPolicyPartOne : public SandboxBPFDSLPolicy { | 344 class StackingPolicyPartOne : public SandboxBPFDSLPolicy { |
345 public: | 345 public: |
346 StackingPolicyPartOne() {} | 346 StackingPolicyPartOne() {} |
347 virtual ~StackingPolicyPartOne() {} | 347 virtual ~StackingPolicyPartOne() {} |
348 | 348 |
349 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 349 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
350 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 350 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
351 switch (sysno) { | 351 switch (sysno) { |
352 case __NR_getppid: { | 352 case __NR_getppid: { |
353 const Arg<int> arg(0); | 353 const Arg<int> arg(0); |
354 return If(arg == 0, Allow()).Else(Error(EPERM)); | 354 return If(arg == 0, Allow()).Else(Error(EPERM)); |
355 } | 355 } |
356 default: | 356 default: |
357 return Allow(); | 357 return Allow(); |
358 } | 358 } |
359 } | 359 } |
360 | 360 |
361 private: | 361 private: |
362 DISALLOW_COPY_AND_ASSIGN(StackingPolicyPartOne); | 362 DISALLOW_COPY_AND_ASSIGN(StackingPolicyPartOne); |
363 }; | 363 }; |
364 | 364 |
365 class StackingPolicyPartTwo : public SandboxBPFDSLPolicy { | 365 class StackingPolicyPartTwo : public SandboxBPFDSLPolicy { |
366 public: | 366 public: |
367 StackingPolicyPartTwo() {} | 367 StackingPolicyPartTwo() {} |
368 virtual ~StackingPolicyPartTwo() {} | 368 virtual ~StackingPolicyPartTwo() {} |
369 | 369 |
370 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 370 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
371 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 371 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
372 switch (sysno) { | 372 switch (sysno) { |
373 case __NR_getppid: { | 373 case __NR_getppid: { |
374 const Arg<int> arg(0); | 374 const Arg<int> arg(0); |
375 return If(arg == 0, Error(EINVAL)).Else(Allow()); | 375 return If(arg == 0, Error(EINVAL)).Else(Allow()); |
376 } | 376 } |
377 default: | 377 default: |
378 return Allow(); | 378 return Allow(); |
379 } | 379 } |
380 } | 380 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 // Small contiguous sets of 3 system calls return an errno equal to the | 418 // Small contiguous sets of 3 system calls return an errno equal to the |
419 // index of that set + 1 (so that we never return a NUL errno). | 419 // index of that set + 1 (so that we never return a NUL errno). |
420 return ((sysno & ~3) >> 2) % 29 + 1; | 420 return ((sysno & ~3) >> 2) % 29 + 1; |
421 } | 421 } |
422 | 422 |
423 class SyntheticPolicy : public SandboxBPFDSLPolicy { | 423 class SyntheticPolicy : public SandboxBPFDSLPolicy { |
424 public: | 424 public: |
425 SyntheticPolicy() {} | 425 SyntheticPolicy() {} |
426 virtual ~SyntheticPolicy() {} | 426 virtual ~SyntheticPolicy() {} |
427 | 427 |
428 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 428 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
429 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 429 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
430 if (sysno == __NR_exit_group || sysno == __NR_write) { | 430 if (sysno == __NR_exit_group || sysno == __NR_write) { |
431 // exit_group() is special, we really need it to work. | 431 // exit_group() is special, we really need it to work. |
432 // write() is needed for BPF_ASSERT() to report a useful error message. | 432 // write() is needed for BPF_ASSERT() to report a useful error message. |
433 return Allow(); | 433 return Allow(); |
434 } | 434 } |
435 return Error(SysnoToRandomErrno(sysno)); | 435 return Error(SysnoToRandomErrno(sysno)); |
436 } | 436 } |
437 | 437 |
438 private: | 438 private: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 } else { | 471 } else { |
472 return ENOSYS; | 472 return ENOSYS; |
473 } | 473 } |
474 } | 474 } |
475 | 475 |
476 class ArmPrivatePolicy : public SandboxBPFDSLPolicy { | 476 class ArmPrivatePolicy : public SandboxBPFDSLPolicy { |
477 public: | 477 public: |
478 ArmPrivatePolicy() {} | 478 ArmPrivatePolicy() {} |
479 virtual ~ArmPrivatePolicy() {} | 479 virtual ~ArmPrivatePolicy() {} |
480 | 480 |
481 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 481 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
482 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 482 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
483 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual | 483 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual |
484 // ARM private system calls. | 484 // ARM private system calls. |
485 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && | 485 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && |
486 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | 486 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
487 return Error(ArmPrivateSysnoToErrno(sysno)); | 487 return Error(ArmPrivateSysnoToErrno(sysno)); |
488 } | 488 } |
489 return Allow(); | 489 return Allow(); |
490 } | 490 } |
491 | 491 |
(...skipping 26 matching lines...) Expand all Loading... |
518 } | 518 } |
519 | 519 |
520 class GreyListedPolicy : public SandboxBPFDSLPolicy { | 520 class GreyListedPolicy : public SandboxBPFDSLPolicy { |
521 public: | 521 public: |
522 explicit GreyListedPolicy(int* aux) : aux_(aux) { | 522 explicit GreyListedPolicy(int* aux) : aux_(aux) { |
523 // Set the global environment for unsafe traps once. | 523 // Set the global environment for unsafe traps once. |
524 EnableUnsafeTraps(); | 524 EnableUnsafeTraps(); |
525 } | 525 } |
526 virtual ~GreyListedPolicy() {} | 526 virtual ~GreyListedPolicy() {} |
527 | 527 |
528 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 528 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
529 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 529 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
530 // Some system calls must always be allowed, if our policy wants to make | 530 // Some system calls must always be allowed, if our policy wants to make |
531 // use of UnsafeTrap() | 531 // use of UnsafeTrap() |
532 if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) { | 532 if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) { |
533 return Allow(); | 533 return Allow(); |
534 } else if (sysno == __NR_getpid) { | 534 } else if (sysno == __NR_getpid) { |
535 // Disallow getpid() | 535 // Disallow getpid() |
536 return Error(EPERM); | 536 return Error(EPERM); |
537 } else { | 537 } else { |
538 // Allow (and count) all other system calls. | 538 // Allow (and count) all other system calls. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 } else { | 584 } else { |
585 return SandboxBPF::ForwardSyscall(args); | 585 return SandboxBPF::ForwardSyscall(args); |
586 } | 586 } |
587 } | 587 } |
588 | 588 |
589 class PrctlPolicy : public SandboxBPFDSLPolicy { | 589 class PrctlPolicy : public SandboxBPFDSLPolicy { |
590 public: | 590 public: |
591 PrctlPolicy() {} | 591 PrctlPolicy() {} |
592 virtual ~PrctlPolicy() {} | 592 virtual ~PrctlPolicy() {} |
593 | 593 |
594 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 594 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
595 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 595 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
596 setenv(kSandboxDebuggingEnv, "t", 0); | 596 setenv(kSandboxDebuggingEnv, "t", 0); |
597 Die::SuppressInfoMessages(true); | 597 Die::SuppressInfoMessages(true); |
598 | 598 |
599 if (sysno == __NR_prctl) { | 599 if (sysno == __NR_prctl) { |
600 // Handle prctl() inside an UnsafeTrap() | 600 // Handle prctl() inside an UnsafeTrap() |
601 return UnsafeTrap(PrctlHandler, NULL); | 601 return UnsafeTrap(PrctlHandler, NULL); |
602 } | 602 } |
603 | 603 |
604 // Allow all other system calls. | 604 // Allow all other system calls. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 | 638 |
639 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { | 639 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { |
640 return SandboxBPF::ForwardSyscall(args); | 640 return SandboxBPF::ForwardSyscall(args); |
641 } | 641 } |
642 | 642 |
643 class RedirectAllSyscallsPolicy : public SandboxBPFDSLPolicy { | 643 class RedirectAllSyscallsPolicy : public SandboxBPFDSLPolicy { |
644 public: | 644 public: |
645 RedirectAllSyscallsPolicy() {} | 645 RedirectAllSyscallsPolicy() {} |
646 virtual ~RedirectAllSyscallsPolicy() {} | 646 virtual ~RedirectAllSyscallsPolicy() {} |
647 | 647 |
648 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 648 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
649 | 649 |
650 private: | 650 private: |
651 DISALLOW_COPY_AND_ASSIGN(RedirectAllSyscallsPolicy); | 651 DISALLOW_COPY_AND_ASSIGN(RedirectAllSyscallsPolicy); |
652 }; | 652 }; |
653 | 653 |
654 ResultExpr RedirectAllSyscallsPolicy::EvaluateSyscall(int sysno) const { | 654 ResultExpr RedirectAllSyscallsPolicy::EvaluateSyscall(int sysno) const { |
655 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 655 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
656 setenv(kSandboxDebuggingEnv, "t", 0); | 656 setenv(kSandboxDebuggingEnv, "t", 0); |
657 Die::SuppressInfoMessages(true); | 657 Die::SuppressInfoMessages(true); |
658 | 658 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 BPF_ASSERT(false); | 802 BPF_ASSERT(false); |
803 return -ENOSYS; | 803 return -ENOSYS; |
804 } | 804 } |
805 } | 805 } |
806 | 806 |
807 class DenyOpenPolicy : public SandboxBPFDSLPolicy { | 807 class DenyOpenPolicy : public SandboxBPFDSLPolicy { |
808 public: | 808 public: |
809 explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {} | 809 explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {} |
810 virtual ~DenyOpenPolicy() {} | 810 virtual ~DenyOpenPolicy() {} |
811 | 811 |
812 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 812 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
813 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 813 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
814 | 814 |
815 switch (sysno) { | 815 switch (sysno) { |
816 case __NR_faccessat: | 816 case __NR_faccessat: |
817 #if defined(__NR_access) | 817 #if defined(__NR_access) |
818 case __NR_access: | 818 case __NR_access: |
819 #endif | 819 #endif |
820 #if defined(__NR_open) | 820 #if defined(__NR_open) |
821 case __NR_open: | 821 case __NR_open: |
822 #endif | 822 #endif |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | 882 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); |
883 } | 883 } |
884 | 884 |
885 // Simple test demonstrating how to use SandboxBPF::Cond() | 885 // Simple test demonstrating how to use SandboxBPF::Cond() |
886 | 886 |
887 class SimpleCondTestPolicy : public SandboxBPFDSLPolicy { | 887 class SimpleCondTestPolicy : public SandboxBPFDSLPolicy { |
888 public: | 888 public: |
889 SimpleCondTestPolicy() {} | 889 SimpleCondTestPolicy() {} |
890 virtual ~SimpleCondTestPolicy() {} | 890 virtual ~SimpleCondTestPolicy() {} |
891 | 891 |
892 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 892 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
893 | 893 |
894 private: | 894 private: |
895 DISALLOW_COPY_AND_ASSIGN(SimpleCondTestPolicy); | 895 DISALLOW_COPY_AND_ASSIGN(SimpleCondTestPolicy); |
896 }; | 896 }; |
897 | 897 |
898 ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const { | 898 ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const { |
899 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 899 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
900 | 900 |
901 // We deliberately return unusual errno values upon failure, so that we | 901 // We deliberately return unusual errno values upon failure, so that we |
902 // can uniquely test for these values. In a "real" policy, you would want | 902 // can uniquely test for these values. In a "real" policy, you would want |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1239 #endif | 1239 #endif |
1240 static const int kMaxFanOut = 3; | 1240 static const int kMaxFanOut = 3; |
1241 static const int kMaxArgs = 6; | 1241 static const int kMaxArgs = 6; |
1242 }; | 1242 }; |
1243 | 1243 |
1244 class EqualityStressTestPolicy : public SandboxBPFDSLPolicy { | 1244 class EqualityStressTestPolicy : public SandboxBPFDSLPolicy { |
1245 public: | 1245 public: |
1246 explicit EqualityStressTestPolicy(EqualityStressTest* aux) : aux_(aux) {} | 1246 explicit EqualityStressTestPolicy(EqualityStressTest* aux) : aux_(aux) {} |
1247 virtual ~EqualityStressTestPolicy() {} | 1247 virtual ~EqualityStressTestPolicy() {} |
1248 | 1248 |
1249 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 1249 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
1250 return aux_->Policy(sysno); | 1250 return aux_->Policy(sysno); |
1251 } | 1251 } |
1252 | 1252 |
1253 private: | 1253 private: |
1254 EqualityStressTest* aux_; | 1254 EqualityStressTest* aux_; |
1255 | 1255 |
1256 DISALLOW_COPY_AND_ASSIGN(EqualityStressTestPolicy); | 1256 DISALLOW_COPY_AND_ASSIGN(EqualityStressTestPolicy); |
1257 }; | 1257 }; |
1258 | 1258 |
1259 BPF_TEST(SandboxBPF, | 1259 BPF_TEST(SandboxBPF, |
1260 EqualityTests, | 1260 EqualityTests, |
1261 EqualityStressTestPolicy, | 1261 EqualityStressTestPolicy, |
1262 EqualityStressTest /* (*BPF_AUX) */) { | 1262 EqualityStressTest /* (*BPF_AUX) */) { |
1263 BPF_AUX->VerifyFilter(); | 1263 BPF_AUX->VerifyFilter(); |
1264 } | 1264 } |
1265 | 1265 |
1266 class EqualityArgumentWidthPolicy : public SandboxBPFDSLPolicy { | 1266 class EqualityArgumentWidthPolicy : public SandboxBPFDSLPolicy { |
1267 public: | 1267 public: |
1268 EqualityArgumentWidthPolicy() {} | 1268 EqualityArgumentWidthPolicy() {} |
1269 virtual ~EqualityArgumentWidthPolicy() {} | 1269 virtual ~EqualityArgumentWidthPolicy() {} |
1270 | 1270 |
1271 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1271 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1272 | 1272 |
1273 private: | 1273 private: |
1274 DISALLOW_COPY_AND_ASSIGN(EqualityArgumentWidthPolicy); | 1274 DISALLOW_COPY_AND_ASSIGN(EqualityArgumentWidthPolicy); |
1275 }; | 1275 }; |
1276 | 1276 |
1277 ResultExpr EqualityArgumentWidthPolicy::EvaluateSyscall(int sysno) const { | 1277 ResultExpr EqualityArgumentWidthPolicy::EvaluateSyscall(int sysno) const { |
1278 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 1278 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
1279 if (sysno == __NR_uname) { | 1279 if (sysno == __NR_uname) { |
1280 const Arg<int> option(0); | 1280 const Arg<int> option(0); |
1281 const Arg<uint32_t> arg32(1); | 1281 const Arg<uint32_t> arg32(1); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 EqualityArgumentWidthPolicy) { | 1314 EqualityArgumentWidthPolicy) { |
1315 Syscall::Call(__NR_uname, 0, 0x5555555555555555ULL); | 1315 Syscall::Call(__NR_uname, 0, 0x5555555555555555ULL); |
1316 } | 1316 } |
1317 #endif | 1317 #endif |
1318 | 1318 |
1319 class EqualityWithNegativeArgumentsPolicy : public SandboxBPFDSLPolicy { | 1319 class EqualityWithNegativeArgumentsPolicy : public SandboxBPFDSLPolicy { |
1320 public: | 1320 public: |
1321 EqualityWithNegativeArgumentsPolicy() {} | 1321 EqualityWithNegativeArgumentsPolicy() {} |
1322 virtual ~EqualityWithNegativeArgumentsPolicy() {} | 1322 virtual ~EqualityWithNegativeArgumentsPolicy() {} |
1323 | 1323 |
1324 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 1324 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
1325 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 1325 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
1326 if (sysno == __NR_uname) { | 1326 if (sysno == __NR_uname) { |
1327 // TODO(mdempsky): This currently can't be Arg<int> because then | 1327 // TODO(mdempsky): This currently can't be Arg<int> because then |
1328 // 0xFFFFFFFF will be treated as a (signed) int, and then when | 1328 // 0xFFFFFFFF will be treated as a (signed) int, and then when |
1329 // Arg::EqualTo casts it to uint64_t, it will be sign extended. | 1329 // Arg::EqualTo casts it to uint64_t, it will be sign extended. |
1330 const Arg<unsigned> arg(0); | 1330 const Arg<unsigned> arg(0); |
1331 return If(arg == 0xFFFFFFFF, Error(1)).Else(Error(2)); | 1331 return If(arg == 0xFFFFFFFF, Error(1)).Else(Error(2)); |
1332 } | 1332 } |
1333 return Allow(); | 1333 return Allow(); |
1334 } | 1334 } |
(...skipping 20 matching lines...) Expand all Loading... |
1355 // iff the LSB was negative. So, this death test should error out. | 1355 // iff the LSB was negative. So, this death test should error out. |
1356 BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF00000000LL) == -1); | 1356 BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF00000000LL) == -1); |
1357 } | 1357 } |
1358 #endif | 1358 #endif |
1359 | 1359 |
1360 class AllBitTestPolicy : public SandboxBPFDSLPolicy { | 1360 class AllBitTestPolicy : public SandboxBPFDSLPolicy { |
1361 public: | 1361 public: |
1362 AllBitTestPolicy() {} | 1362 AllBitTestPolicy() {} |
1363 virtual ~AllBitTestPolicy() {} | 1363 virtual ~AllBitTestPolicy() {} |
1364 | 1364 |
1365 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1365 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1366 | 1366 |
1367 private: | 1367 private: |
1368 static ResultExpr HasAllBits32(uint32_t bits); | 1368 static ResultExpr HasAllBits32(uint32_t bits); |
1369 static ResultExpr HasAllBits64(uint64_t bits); | 1369 static ResultExpr HasAllBits64(uint64_t bits); |
1370 | 1370 |
1371 DISALLOW_COPY_AND_ASSIGN(AllBitTestPolicy); | 1371 DISALLOW_COPY_AND_ASSIGN(AllBitTestPolicy); |
1372 }; | 1372 }; |
1373 | 1373 |
1374 ResultExpr AllBitTestPolicy::HasAllBits32(uint32_t bits) { | 1374 ResultExpr AllBitTestPolicy::HasAllBits32(uint32_t bits) { |
1375 if (bits == 0) { | 1375 if (bits == 0) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1541 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1541 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1542 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); | 1542 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
1543 #endif | 1543 #endif |
1544 } | 1544 } |
1545 | 1545 |
1546 class AnyBitTestPolicy : public SandboxBPFDSLPolicy { | 1546 class AnyBitTestPolicy : public SandboxBPFDSLPolicy { |
1547 public: | 1547 public: |
1548 AnyBitTestPolicy() {} | 1548 AnyBitTestPolicy() {} |
1549 virtual ~AnyBitTestPolicy() {} | 1549 virtual ~AnyBitTestPolicy() {} |
1550 | 1550 |
1551 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1551 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1552 | 1552 |
1553 private: | 1553 private: |
1554 static ResultExpr HasAnyBits32(uint32_t); | 1554 static ResultExpr HasAnyBits32(uint32_t); |
1555 static ResultExpr HasAnyBits64(uint64_t); | 1555 static ResultExpr HasAnyBits64(uint64_t); |
1556 | 1556 |
1557 DISALLOW_COPY_AND_ASSIGN(AnyBitTestPolicy); | 1557 DISALLOW_COPY_AND_ASSIGN(AnyBitTestPolicy); |
1558 }; | 1558 }; |
1559 | 1559 |
1560 ResultExpr AnyBitTestPolicy::HasAnyBits32(uint32_t bits) { | 1560 ResultExpr AnyBitTestPolicy::HasAnyBits32(uint32_t bits) { |
1561 if (bits == 0) { | 1561 if (bits == 0) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1705 BITMASK_TEST( 10, 0xFFFFFFFFU, ANYBITS64,0x100000001, EXPECT_SUCCESS); | 1705 BITMASK_TEST( 10, 0xFFFFFFFFU, ANYBITS64,0x100000001, EXPECT_SUCCESS); |
1706 BITMASK_TEST( 10, -1L, ANYBITS64,0x100000001, EXPECT_SUCCESS); | 1706 BITMASK_TEST( 10, -1L, ANYBITS64,0x100000001, EXPECT_SUCCESS); |
1707 #endif | 1707 #endif |
1708 } | 1708 } |
1709 | 1709 |
1710 class MaskedEqualTestPolicy : public SandboxBPFDSLPolicy { | 1710 class MaskedEqualTestPolicy : public SandboxBPFDSLPolicy { |
1711 public: | 1711 public: |
1712 MaskedEqualTestPolicy() {} | 1712 MaskedEqualTestPolicy() {} |
1713 virtual ~MaskedEqualTestPolicy() {} | 1713 virtual ~MaskedEqualTestPolicy() {} |
1714 | 1714 |
1715 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1715 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1716 | 1716 |
1717 private: | 1717 private: |
1718 static ResultExpr MaskedEqual32(uint32_t mask, uint32_t value); | 1718 static ResultExpr MaskedEqual32(uint32_t mask, uint32_t value); |
1719 static ResultExpr MaskedEqual64(uint64_t mask, uint64_t value); | 1719 static ResultExpr MaskedEqual64(uint64_t mask, uint64_t value); |
1720 | 1720 |
1721 DISALLOW_COPY_AND_ASSIGN(MaskedEqualTestPolicy); | 1721 DISALLOW_COPY_AND_ASSIGN(MaskedEqualTestPolicy); |
1722 }; | 1722 }; |
1723 | 1723 |
1724 ResultExpr MaskedEqualTestPolicy::MaskedEqual32(uint32_t mask, uint32_t value) { | 1724 ResultExpr MaskedEqualTestPolicy::MaskedEqual32(uint32_t mask, uint32_t value) { |
1725 const Arg<uint32_t> arg(1); | 1725 const Arg<uint32_t> arg(1); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1832 msg); | 1832 msg); |
1833 } | 1833 } |
1834 return -EPERM; | 1834 return -EPERM; |
1835 } | 1835 } |
1836 | 1836 |
1837 class PthreadPolicyEquality : public SandboxBPFDSLPolicy { | 1837 class PthreadPolicyEquality : public SandboxBPFDSLPolicy { |
1838 public: | 1838 public: |
1839 PthreadPolicyEquality() {} | 1839 PthreadPolicyEquality() {} |
1840 virtual ~PthreadPolicyEquality() {} | 1840 virtual ~PthreadPolicyEquality() {} |
1841 | 1841 |
1842 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1842 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1843 | 1843 |
1844 private: | 1844 private: |
1845 DISALLOW_COPY_AND_ASSIGN(PthreadPolicyEquality); | 1845 DISALLOW_COPY_AND_ASSIGN(PthreadPolicyEquality); |
1846 }; | 1846 }; |
1847 | 1847 |
1848 ResultExpr PthreadPolicyEquality::EvaluateSyscall(int sysno) const { | 1848 ResultExpr PthreadPolicyEquality::EvaluateSyscall(int sysno) const { |
1849 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 1849 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
1850 // This policy allows creating threads with pthread_create(). But it | 1850 // This policy allows creating threads with pthread_create(). But it |
1851 // doesn't allow any other uses of clone(). Most notably, it does not | 1851 // doesn't allow any other uses of clone(). Most notably, it does not |
1852 // allow callers to implement fork() or vfork() by passing suitable flags | 1852 // allow callers to implement fork() or vfork() by passing suitable flags |
(...skipping 23 matching lines...) Expand all Loading... |
1876 } | 1876 } |
1877 | 1877 |
1878 return Allow(); | 1878 return Allow(); |
1879 } | 1879 } |
1880 | 1880 |
1881 class PthreadPolicyBitMask : public SandboxBPFDSLPolicy { | 1881 class PthreadPolicyBitMask : public SandboxBPFDSLPolicy { |
1882 public: | 1882 public: |
1883 PthreadPolicyBitMask() {} | 1883 PthreadPolicyBitMask() {} |
1884 virtual ~PthreadPolicyBitMask() {} | 1884 virtual ~PthreadPolicyBitMask() {} |
1885 | 1885 |
1886 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; | 1886 virtual ResultExpr EvaluateSyscall(int sysno) const override; |
1887 | 1887 |
1888 private: | 1888 private: |
1889 static BoolExpr HasAnyBits(const Arg<unsigned long>& arg, unsigned long bits); | 1889 static BoolExpr HasAnyBits(const Arg<unsigned long>& arg, unsigned long bits); |
1890 static BoolExpr HasAllBits(const Arg<unsigned long>& arg, unsigned long bits); | 1890 static BoolExpr HasAllBits(const Arg<unsigned long>& arg, unsigned long bits); |
1891 | 1891 |
1892 DISALLOW_COPY_AND_ASSIGN(PthreadPolicyBitMask); | 1892 DISALLOW_COPY_AND_ASSIGN(PthreadPolicyBitMask); |
1893 }; | 1893 }; |
1894 | 1894 |
1895 BoolExpr PthreadPolicyBitMask::HasAnyBits(const Arg<unsigned long>& arg, | 1895 BoolExpr PthreadPolicyBitMask::HasAnyBits(const Arg<unsigned long>& arg, |
1896 unsigned long bits) { | 1896 unsigned long bits) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 return 0; | 2047 return 0; |
2048 } | 2048 } |
2049 | 2049 |
2050 const uint16_t kTraceData = 0xcc; | 2050 const uint16_t kTraceData = 0xcc; |
2051 | 2051 |
2052 class TraceAllPolicy : public SandboxBPFDSLPolicy { | 2052 class TraceAllPolicy : public SandboxBPFDSLPolicy { |
2053 public: | 2053 public: |
2054 TraceAllPolicy() {} | 2054 TraceAllPolicy() {} |
2055 virtual ~TraceAllPolicy() {} | 2055 virtual ~TraceAllPolicy() {} |
2056 | 2056 |
2057 virtual ResultExpr EvaluateSyscall(int system_call_number) const OVERRIDE { | 2057 virtual ResultExpr EvaluateSyscall(int system_call_number) const override { |
2058 return Trace(kTraceData); | 2058 return Trace(kTraceData); |
2059 } | 2059 } |
2060 | 2060 |
2061 private: | 2061 private: |
2062 DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy); | 2062 DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy); |
2063 }; | 2063 }; |
2064 | 2064 |
2065 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) { | 2065 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) { |
2066 if (SandboxBPF::SupportsSeccompSandbox(-1) != | 2066 if (SandboxBPF::SupportsSeccompSandbox(-1) != |
2067 sandbox::SandboxBPF::STATUS_AVAILABLE) { | 2067 sandbox::SandboxBPF::STATUS_AVAILABLE) { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2193 return true; | 2193 return true; |
2194 } | 2194 } |
2195 | 2195 |
2196 bool pread_64_was_forwarded = false; | 2196 bool pread_64_was_forwarded = false; |
2197 | 2197 |
2198 class TrapPread64Policy : public SandboxBPFDSLPolicy { | 2198 class TrapPread64Policy : public SandboxBPFDSLPolicy { |
2199 public: | 2199 public: |
2200 TrapPread64Policy() {} | 2200 TrapPread64Policy() {} |
2201 virtual ~TrapPread64Policy() {} | 2201 virtual ~TrapPread64Policy() {} |
2202 | 2202 |
2203 virtual ResultExpr EvaluateSyscall(int system_call_number) const OVERRIDE { | 2203 virtual ResultExpr EvaluateSyscall(int system_call_number) const override { |
2204 // Set the global environment for unsafe traps once. | 2204 // Set the global environment for unsafe traps once. |
2205 if (system_call_number == MIN_SYSCALL) { | 2205 if (system_call_number == MIN_SYSCALL) { |
2206 EnableUnsafeTraps(); | 2206 EnableUnsafeTraps(); |
2207 } | 2207 } |
2208 | 2208 |
2209 if (system_call_number == __NR_pread64) { | 2209 if (system_call_number == __NR_pread64) { |
2210 return UnsafeTrap(ForwardPreadHandler, NULL); | 2210 return UnsafeTrap(ForwardPreadHandler, NULL); |
2211 } | 2211 } |
2212 return Allow(); | 2212 return Allow(); |
2213 } | 2213 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 | 2290 |
2291 // Wait for the thread to finish. | 2291 // Wait for the thread to finish. |
2292 BPF_ASSERT_EQ(0, pthread_join(thread, NULL)); | 2292 BPF_ASSERT_EQ(0, pthread_join(thread, NULL)); |
2293 } | 2293 } |
2294 | 2294 |
2295 class AllowAllPolicy : public SandboxBPFDSLPolicy { | 2295 class AllowAllPolicy : public SandboxBPFDSLPolicy { |
2296 public: | 2296 public: |
2297 AllowAllPolicy() {} | 2297 AllowAllPolicy() {} |
2298 virtual ~AllowAllPolicy() {} | 2298 virtual ~AllowAllPolicy() {} |
2299 | 2299 |
2300 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 2300 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
2301 return Allow(); | 2301 return Allow(); |
2302 } | 2302 } |
2303 | 2303 |
2304 private: | 2304 private: |
2305 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); | 2305 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); |
2306 }; | 2306 }; |
2307 | 2307 |
2308 SANDBOX_DEATH_TEST( | 2308 SANDBOX_DEATH_TEST( |
2309 SandboxBPF, | 2309 SandboxBPF, |
2310 StartMultiThreadedAsSingleThreaded, | 2310 StartMultiThreadedAsSingleThreaded, |
(...skipping 23 matching lines...) Expand all Loading... |
2334 // A stub handler for the UnsafeTrap. Never called. | 2334 // A stub handler for the UnsafeTrap. Never called. |
2335 intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) { | 2335 intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) { |
2336 return -1; | 2336 return -1; |
2337 } | 2337 } |
2338 | 2338 |
2339 class UnsafeTrapWithCondPolicy : public SandboxBPFDSLPolicy { | 2339 class UnsafeTrapWithCondPolicy : public SandboxBPFDSLPolicy { |
2340 public: | 2340 public: |
2341 UnsafeTrapWithCondPolicy() {} | 2341 UnsafeTrapWithCondPolicy() {} |
2342 virtual ~UnsafeTrapWithCondPolicy() {} | 2342 virtual ~UnsafeTrapWithCondPolicy() {} |
2343 | 2343 |
2344 virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { | 2344 virtual ResultExpr EvaluateSyscall(int sysno) const override { |
2345 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 2345 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
2346 setenv(kSandboxDebuggingEnv, "t", 0); | 2346 setenv(kSandboxDebuggingEnv, "t", 0); |
2347 Die::SuppressInfoMessages(true); | 2347 Die::SuppressInfoMessages(true); |
2348 | 2348 |
2349 if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) | 2349 if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) |
2350 return Allow(); | 2350 return Allow(); |
2351 | 2351 |
2352 switch (sysno) { | 2352 switch (sysno) { |
2353 case __NR_uname: { | 2353 case __NR_uname: { |
2354 const Arg<uint32_t> arg(0); | 2354 const Arg<uint32_t> arg(0); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2390 BPF_ASSERT_EQ(ENOSYS, errno); | 2390 BPF_ASSERT_EQ(ENOSYS, errno); |
2391 | 2391 |
2392 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); | 2392 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); |
2393 BPF_ASSERT_EQ(EPERM, errno); | 2393 BPF_ASSERT_EQ(EPERM, errno); |
2394 } | 2394 } |
2395 | 2395 |
2396 } // namespace | 2396 } // namespace |
2397 | 2397 |
2398 } // namespace bpf_dsl | 2398 } // namespace bpf_dsl |
2399 } // namespace sandbox | 2399 } // namespace sandbox |
OLD | NEW |