1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debug.h"
#include "mutex.h"
#include "sandbox_impl.h"
#include "securemem.h"
namespace playground {
void SecureMem::abandonSystemCall(int fd, int err) {
void* rc = reinterpret_cast<void *>(err);
if (err) {
Debug::message("System call failed\n");
}
Sandbox::SysCalls sys;
if (Sandbox::write(sys, fd, &rc, sizeof(rc)) != sizeof(rc)) {
Sandbox::die("Failed to send system call");
}
}
void SecureMem::dieIfParentDied(int parentMapsFd) {
// The syscall_mutex_ should not be contended. If it is, we are either
// experiencing a very unusual load of system calls that the sandbox is not
// optimized for; or, more likely, the sandboxed process terminated while the
// trusted process was in the middle of waiting for the mutex. We detect
// this situation and terminate the trusted process.
int alive = !lseek(parentMapsFd, 0, SEEK_SET);
if (alive) {
char buf;
do {
alive = read(parentMapsFd, &buf, 1);
} while (alive < 0 && errno == EINTR);
}
if (!alive) {
Sandbox::die();
}
}
void SecureMem::lockSystemCall(int parentMapsFd, Args* mem) {
while (!Mutex::lockMutex(&Sandbox::syscall_mutex_, 500)) {
dieIfParentDied(parentMapsFd);
}
asm volatile(
#if defined(__x86_64__)
"lock; incq (%0)\n"
#elif defined(__i386__)
"lock; incl (%0)\n"
#else
#error Unsupported target platform
#endif
:
: "q"(&mem->sequence)
: "memory");
}
void SecureMem::sendSystemCallInternal(int fd, bool locked, int parentMapsFd,
Args* mem, int syscallNum, void* arg1,
void* arg2, void* arg3, void* arg4,
void* arg5, void* arg6) {
if (!locked) {
asm volatile(
#if defined(__x86_64__)
"lock; incq (%0)\n"
#elif defined(__i386__)
"lock; incl (%0)\n"
#else
#error Unsupported target platform
#endif
:
: "q"(&mem->sequence)
: "memory");
}
mem->syscallNum = syscallNum;
mem->arg1 = arg1;
mem->arg2 = arg2;
mem->arg3 = arg3;
mem->arg4 = arg4;
mem->arg5 = arg5;
mem->arg6 = arg6;
asm volatile(
#if defined(__x86_64__)
"lock; incq (%0)\n"
#elif defined(__i386__)
"lock; incl (%0)\n"
#else
#error Unsupported target platform
#endif
:
: "q"(&mem->sequence)
: "memory");
int data = locked ? -2 : -1;
Sandbox::SysCalls sys;
if (Sandbox::write(sys, fd, &data, sizeof(data)) != sizeof(data)) {
Sandbox::die("Failed to send system call");
}
if (parentMapsFd >= 0) {
while (!Mutex::waitForUnlock(&Sandbox::syscall_mutex_, 500)) {
dieIfParentDied(parentMapsFd);
}
}
}
} // namespace
|