1 // Copyright (C) 2012 The SBCELT Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE-file.
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <sys/mman.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <signal.h>
16
17 #include <sys/time.h>
18 #include <sys/syscall.h>
19
20 #include "celt.h"
21 #include "../sbcelt-internal.h"
22
23 #include "pdeath.h"
24 #include "eintr.h"
25 #include "futex.h"
26 #include "sbcelt-sandbox.h"
27
28 #define SAMPLE_RATE 48000
29
30 #ifdef DEBUG
31 # define debugf(fmt, ...) \
32 do { \
33 fprintf(stderr, "sbcelt-helper:%s():%u: " fmt "\n", \
34 __FUNCTION__, __LINE__, ## __VA_ARGS__); \
35 fflush(stderr); \
36 } while (0)
37 #else
38 #define debugf(s, ...) do{} while (0)
39 #endif
40
41 static struct SBCELTWorkPage *workpage = NULL;
42 static struct SBCELTDecoderPage *decpage = NULL;
43 static CELTMode *modes[SBCELT_SLOTS];
44 static CELTDecoder *decoders[SBCELT_SLOTS];
45
SBCELT_DecodeSingleFrame()46 static void SBCELT_DecodeSingleFrame() {
47 unsigned char *src = &workpage->encbuf[0];
48 float *dst = &workpage->decbuf[0];
49
50 int idx = workpage->slot;
51 struct SBCELTDecoderSlot *slot = &decpage->slots[idx];
52 CELTMode *m = modes[idx];
53 CELTDecoder *d = decoders[idx];
54
55 if (slot->dispose && m != NULL && d != NULL) {
56 debugf("disposed of mode & decoder for slot=%i", idx);
57 celt_mode_destroy(m);
58 celt_decoder_destroy(d);
59 m = modes[idx] = celt_mode_create(SAMPLE_RATE, SAMPLE_RATE / 100, NULL);
60 d = decoders[idx] = celt_decoder_create(m, 1, NULL);
61 slot->dispose = 0;
62 }
63
64 if (m == NULL && d == NULL) {
65 debugf("created mode & decoder for slot=%i", idx);
66 m = modes[idx] = celt_mode_create(SAMPLE_RATE, SAMPLE_RATE / 100, NULL);
67 d = decoders[idx] = celt_decoder_create(m, 1, NULL);
68 }
69
70 debugf("got work for slot=%i", idx);
71 unsigned int len = workpage->len;
72 debugf("to decode: %p, %p, %u, %p", d, src, len, dst);
73 if (len == 0) {
74 celt_decode_float(d, NULL, 0, dst);
75 } else {
76 celt_decode_float(d, src, len, dst);
77 }
78
79 debugf("decoded len=%u", len);
80 }
81
SBCELT_FutexHelper()82 static int SBCELT_FutexHelper() {
83 while (1) {
84 // Wait for the lib to signal us.
85 while (workpage->ready == 1) {
86 int err = futex_wait(&workpage->ready, 1, NULL);
87 if (err == 0) {
88 break;
89 }
90 }
91
92 SBCELT_DecodeSingleFrame();
93
94 workpage->ready = 1;
95
96 if (!workpage->busywait) {
97 futex_wake(&workpage->ready);
98 }
99 }
100
101 return -2;
102 }
103
SBCELT_RWHelper()104 static int SBCELT_RWHelper() {
105 while (1) {
106 // Wait for the lib to signal us.
107 if (HANDLE_EINTR(read(0, &workpage->pingpong, 1)) == -1) {
108 return -2;
109 }
110
111 SBCELT_DecodeSingleFrame();
112
113 if (HANDLE_EINTR(write(1, &workpage->pingpong, 1)) == -1) {
114 return -3;
115 }
116 }
117 }
118
main(int argc,char * argv[])119 int main(int argc, char *argv[]) {
120 if (argc >= 2 && !strcmp(argv[1], "detect")) {
121 debugf("in seccomp-detect mode");
122 if (SBCELT_EnterSandbox(SBCELT_SANDBOX_CAPSICUM) == 0) {
123 _exit(SBCELT_SANDBOX_CAPSICUM);
124 }
125 if (SBCELT_EnterSandbox(SBCELT_SANDBOX_SEATBELT) == 0) {
126 _exit(SBCELT_SANDBOX_SEATBELT);
127 }
128 if (SBCELT_EnterSandbox(SBCELT_SANDBOX_SECCOMP_BPF) == 0) {
129 _exit(SBCELT_SANDBOX_SECCOMP_BPF);
130 }
131 if (SBCELT_EnterSandbox(SBCELT_SANDBOX_SECCOMP_STRICT) == 0) {
132 _exit(SBCELT_SANDBOX_SECCOMP_STRICT);
133 }
134 _exit(SBCELT_SANDBOX_NONE);
135 }
136
137 debugf("helper running");
138
139 if (pdeath() == -1) {
140 return 1;
141 }
142
143 char shmfn[50];
144 if (snprintf(&shmfn[0], 50, "/sbcelt-%lu", (unsigned long) getppid()) < 0) {
145 return 2;
146 }
147
148 int fd = shm_open(&shmfn[0], O_RDWR, 0600);
149 if (fd == -1) {
150 debugf("unable to open shm: %s (%i)", strerror(errno), errno);
151 return 3;
152 }
153
154 void *addr = mmap(NULL, SBCELT_PAGES*SBCELT_PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
155 if (addr == MAP_FAILED) {
156 debugf("unable to mmap: %s (%i)", strerror(errno), errno);
157 return 5;
158 }
159 workpage = addr;
160 decpage = addr+SBCELT_PAGE_SIZE;
161
162 debugf("workpage=%p, decpage=%p", workpage, decpage);
163
164 if (SBCELT_EnterSandbox(workpage->sandbox) == -1) {
165 return 6;
166 }
167
168 switch (workpage->mode) {
169 case SBCELT_MODE_FUTEX:
170 return SBCELT_FutexHelper();
171 case SBCELT_MODE_RW:
172 return SBCELT_RWHelper();
173 }
174
175 return 7;
176 }
177