1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li // A binary that tries x86_64 compat syscalls, ptrace and clone untraced.
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <sched.h>
18*ec63e07aSXin Li #include <sys/ptrace.h>
19*ec63e07aSXin Li #include <syscall.h>
20*ec63e07aSXin Li #include <unistd.h>
21*ec63e07aSXin Li
22*ec63e07aSXin Li #include <cerrno>
23*ec63e07aSXin Li #include <cstdint>
24*ec63e07aSXin Li #include <cstdio>
25*ec63e07aSXin Li #include <cstdlib>
26*ec63e07aSXin Li
27*ec63e07aSXin Li #include "absl/base/attributes.h"
28*ec63e07aSXin Li #include "sandboxed_api/config.h"
29*ec63e07aSXin Li
30*ec63e07aSXin Li #ifdef SAPI_X86_64
TestAMD64SyscallMismatch()31*ec63e07aSXin Li void TestAMD64SyscallMismatch() {
32*ec63e07aSXin Li int64_t result;
33*ec63e07aSXin Li
34*ec63e07aSXin Li // exit() is allowed, but not if called via 32-bit syscall.
35*ec63e07aSXin Li asm("movq $1, %%rax\n" // __NR_exit: 1 in 32-bit (60 in 64-bit)
36*ec63e07aSXin Li "movq $42, %%rbx\n" // int error_code: 42
37*ec63e07aSXin Li "int $0x80\n"
38*ec63e07aSXin Li "movq %%rax, %0\n"
39*ec63e07aSXin Li : "=r"(result)
40*ec63e07aSXin Li :
41*ec63e07aSXin Li : "rax", "rbx");
42*ec63e07aSXin Li exit(-result);
43*ec63e07aSXin Li }
44*ec63e07aSXin Li
TestAMD64SyscallMismatchFs()45*ec63e07aSXin Li void TestAMD64SyscallMismatchFs() {
46*ec63e07aSXin Li int64_t result;
47*ec63e07aSXin Li char filename[] = "/etc/passwd";
48*ec63e07aSXin Li
49*ec63e07aSXin Li // access("/etc/passwd") is allowed, but not if called via 32-bit syscall.
50*ec63e07aSXin Li asm("movq $33, %%rax\n" // __NR_access: 33 in 32-bit (21 in 64-bit)
51*ec63e07aSXin Li "movq %1, %%rbx\n" // const char* filename: /etc/passwd
52*ec63e07aSXin Li "movq $0, %%rcx\n" // int mode: F_OK (0), test for existence
53*ec63e07aSXin Li "int $0x80\n"
54*ec63e07aSXin Li "movq %%rax, %0\n"
55*ec63e07aSXin Li : "=r"(result)
56*ec63e07aSXin Li : "g"(filename)
57*ec63e07aSXin Li : "rax", "rbx", "rcx");
58*ec63e07aSXin Li exit(-result);
59*ec63e07aSXin Li }
60*ec63e07aSXin Li #endif
61*ec63e07aSXin Li
TestPtraceDenied()62*ec63e07aSXin Li void TestPtraceDenied() {
63*ec63e07aSXin Li ptrace(PTRACE_SEIZE, getppid(), 0, 0);
64*ec63e07aSXin Li
65*ec63e07aSXin Li printf("Syscall violation should have been discovered by now\n");
66*ec63e07aSXin Li exit(EXIT_FAILURE);
67*ec63e07aSXin Li }
68*ec63e07aSXin Li
TestPtraceBlocked()69*ec63e07aSXin Li void TestPtraceBlocked() {
70*ec63e07aSXin Li int result = ptrace(PTRACE_SEIZE, getppid(), 0, 0);
71*ec63e07aSXin Li
72*ec63e07aSXin Li if (result != -1 || errno != EPERM) {
73*ec63e07aSXin Li printf("System call should have been blocked\n");
74*ec63e07aSXin Li exit(EXIT_FAILURE);
75*ec63e07aSXin Li }
76*ec63e07aSXin Li }
77*ec63e07aSXin Li
TestBpfBlocked()78*ec63e07aSXin Li void TestBpfBlocked() {
79*ec63e07aSXin Li int result = syscall(__NR_bpf, 0, nullptr, 0);
80*ec63e07aSXin Li
81*ec63e07aSXin Li if (result != -1 || errno != EPERM) {
82*ec63e07aSXin Li printf("System call should have been blocked\n");
83*ec63e07aSXin Li exit(EXIT_FAILURE);
84*ec63e07aSXin Li }
85*ec63e07aSXin Li }
86*ec63e07aSXin Li
TestCloneUntraced()87*ec63e07aSXin Li void TestCloneUntraced() {
88*ec63e07aSXin Li syscall(__NR_clone, static_cast<uintptr_t>(CLONE_UNTRACED), nullptr, nullptr,
89*ec63e07aSXin Li nullptr, static_cast<uintptr_t>(0));
90*ec63e07aSXin Li
91*ec63e07aSXin Li printf("Syscall violation should have been discovered by now\n");
92*ec63e07aSXin Li exit(EXIT_FAILURE);
93*ec63e07aSXin Li }
94*ec63e07aSXin Li
TestBpf()95*ec63e07aSXin Li void TestBpf() {
96*ec63e07aSXin Li syscall(__NR_bpf, 0, nullptr, 0);
97*ec63e07aSXin Li
98*ec63e07aSXin Li printf("Syscall violation should have been discovered by now\n");
99*ec63e07aSXin Li exit(EXIT_FAILURE);
100*ec63e07aSXin Li }
101*ec63e07aSXin Li
TestIsatty()102*ec63e07aSXin Li void TestIsatty() { isatty(0); }
103*ec63e07aSXin Li
main(int argc,char * argv[])104*ec63e07aSXin Li int main(int argc, char* argv[]) {
105*ec63e07aSXin Li // Disable buffering.
106*ec63e07aSXin Li setbuf(stdin, nullptr);
107*ec63e07aSXin Li setbuf(stdout, nullptr);
108*ec63e07aSXin Li setbuf(stderr, nullptr);
109*ec63e07aSXin Li
110*ec63e07aSXin Li if (argc < 2) {
111*ec63e07aSXin Li printf("argc < 3\n");
112*ec63e07aSXin Li return EXIT_FAILURE;
113*ec63e07aSXin Li }
114*ec63e07aSXin Li
115*ec63e07aSXin Li int testno = atoi(argv[1]); // NOLINT
116*ec63e07aSXin Li switch (testno) {
117*ec63e07aSXin Li #ifdef SAPI_X86_64
118*ec63e07aSXin Li case 1:
119*ec63e07aSXin Li TestAMD64SyscallMismatch();
120*ec63e07aSXin Li break;
121*ec63e07aSXin Li case 2:
122*ec63e07aSXin Li TestAMD64SyscallMismatchFs();
123*ec63e07aSXin Li break;
124*ec63e07aSXin Li #endif
125*ec63e07aSXin Li case 3:
126*ec63e07aSXin Li TestPtraceDenied();
127*ec63e07aSXin Li break;
128*ec63e07aSXin Li case 4:
129*ec63e07aSXin Li TestCloneUntraced();
130*ec63e07aSXin Li break;
131*ec63e07aSXin Li case 5:
132*ec63e07aSXin Li TestBpf();
133*ec63e07aSXin Li break;
134*ec63e07aSXin Li case 6:
135*ec63e07aSXin Li TestIsatty();
136*ec63e07aSXin Li break;
137*ec63e07aSXin Li case 7:
138*ec63e07aSXin Li TestPtraceBlocked();
139*ec63e07aSXin Li ABSL_FALLTHROUGH_INTENDED;
140*ec63e07aSXin Li case 8:
141*ec63e07aSXin Li TestBpfBlocked();
142*ec63e07aSXin Li break;
143*ec63e07aSXin Li default:
144*ec63e07aSXin Li printf("Unknown test: %d\n", testno);
145*ec63e07aSXin Li return EXIT_FAILURE;
146*ec63e07aSXin Li }
147*ec63e07aSXin Li
148*ec63e07aSXin Li printf("OK: All tests went OK\n");
149*ec63e07aSXin Li return EXIT_SUCCESS;
150*ec63e07aSXin Li }
151