OLD | NEW |
---|---|
(Empty) | |
1 #include <sys/time.h> | |
2 #include <sys/resource.h> | |
3 | |
4 #include "SkCanvas.h" | |
5 #include "SkCommandLineFlags.h" | |
6 #include "SkData.h" | |
7 #include "SkForceLinking.h" | |
8 #include "SkGraphics.h" | |
9 #include "SkImageEncoder.h" | |
10 #include "SkImageInfo.h" | |
11 #include "SkStream.h" | |
12 #include "SkSurface.h" | |
13 | |
14 #include "seccomp_bpf.h" | |
15 | |
16 __SK_FORCE_IMAGE_DECODER_LINKING; | |
17 | |
18 DEFINE_string(out, "", "Filename of the PNG to write to."); | |
19 | |
20 static bool install_syscall_filter(void) { | |
mtklein
2014/04/09 15:03:00
Just FYI, you can legally write () instead of (voi
| |
21 struct sock_filter filter[] = { | |
22 /* Grab the system call number. */ | |
23 EXAMINE_SYSCALL, | |
24 /* List allowed syscalls. */ | |
25 ALLOW_SYSCALL(exit_group), | |
26 ALLOW_SYSCALL(exit), | |
27 ALLOW_SYSCALL(fstat), | |
28 ALLOW_SYSCALL(read), | |
29 ALLOW_SYSCALL(write), | |
30 ALLOW_SYSCALL(close), | |
31 ALLOW_SYSCALL(mmap), | |
32 ALLOW_SYSCALL(munmap), | |
33 ALLOW_SYSCALL(brk), | |
34 KILL_PROCESS, | |
35 }; | |
36 struct sock_fprog prog = { | |
37 SK_ARRAY_COUNT(filter), | |
38 filter, | |
39 }; | |
40 | |
41 // Lock down the app so that it can't get new privs, such as setuid. | |
42 // Calling this is a requirement for an unpriviledged process to use mode | |
43 // 2 seccomp filters, ala SECCOMP_MODE_FILTER, otherwise we'd have to be | |
44 // root. | |
45 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | |
46 perror("prctl(NO_NEW_PRIVS)"); | |
47 goto failed; | |
48 } | |
49 // Now call seccomp and restrict the system calls that can be made to only | |
50 // the ones in the provided filter list. | |
51 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { | |
52 perror("prctl(SECCOMP)"); | |
53 goto failed; | |
54 } | |
55 return true; | |
56 | |
57 failed: | |
58 if (errno == EINVAL) | |
mtklein
2014/04/09 15:03:00
Wrap with {}? I've seen too many
if (errno ==
jcgregorio
2014/04/09 15:23:07
Done.
| |
59 fprintf(stderr, "SECCOMP_FILTER is not available. :(\n"); | |
60 return false; | |
61 } | |
62 | |
63 static void setLimits() { | |
64 struct rlimit n; | |
65 | |
66 // Limit to 5 seconds of CPU. | |
67 n.rlim_cur = 5; | |
68 n.rlim_max = 5; | |
69 if (setrlimit(RLIMIT_CPU, &n)) { | |
70 perror("setrlimit(RLIMIT_CPU)"); | |
71 } | |
72 | |
73 // Limit to 50M of Address space. | |
74 n.rlim_cur = 50000000; | |
75 n.rlim_max = 50000000; | |
76 if (setrlimit(RLIMIT_AS, &n)) { | |
77 perror("setrlimit(RLIMIT_CPU)"); | |
78 } | |
79 } | |
80 | |
81 extern void draw(SkCanvas* canvas); | |
82 | |
83 int main(int argc, char** argv) { | |
84 SkCommandLineFlags::Parse(argc, argv); | |
85 SkAutoGraphics init; | |
86 | |
87 if (FLAGS_out.count() == 0) { | |
88 perror("The --out flag must have an argument."); | |
89 return 1; | |
90 } | |
91 SkFILEWStream stream(FLAGS_out[0]); | |
92 | |
93 SkImageInfo info = SkImageInfo::MakeN32(300, 300, kPremul_SkAlphaType); | |
94 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); | |
95 SkCanvas* canvas = surface->getCanvas(); | |
96 | |
97 setLimits(); | |
98 | |
99 if (!install_syscall_filter()) { | |
100 return 1; | |
101 } | |
102 | |
103 draw(canvas); | |
104 | |
105 // Write out the image as a PNG. | |
106 SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); | |
107 SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100)); | |
108 if (NULL == data.get()) { | |
109 printf("Failed to encode\n"); | |
110 exit(1); | |
111 } | |
112 stream.write(data->data(), data->size()); | |
113 } | |
OLD | NEW |