OLD | NEW |
| (Empty) |
1 #include <sys/time.h> | |
2 #include <sys/resource.h> | |
3 | |
4 #include "GrContextFactory.h" | |
5 | |
6 #include "SkCanvas.h" | |
7 #include "SkCommandLineFlags.h" | |
8 #include "SkData.h" | |
9 #include "SkForceLinking.h" | |
10 #include "SkGraphics.h" | |
11 #include "SkImageDecoder.h" | |
12 #include "SkImageEncoder.h" | |
13 #include "SkImageInfo.h" | |
14 #include "SkOSFile.h" | |
15 #include "SkStream.h" | |
16 #include "SkSurface.h" | |
17 | |
18 #include "seccomp_bpf.h" | |
19 | |
20 __SK_FORCE_IMAGE_DECODER_LINKING; | |
21 | |
22 DEFINE_string(out, "", "Output basename; fiddle will append the config used and
the appropriate extension"); | |
23 DEFINE_string(source, "", "Filename of the source image."); | |
24 DEFINE_int32(width, 256, "Width of output image."); | |
25 DEFINE_int32(height, 256, "Height of output image."); | |
26 DEFINE_bool(gpu, false, "Use GPU (Mesa) rendering."); | |
27 DEFINE_bool(raster, true, "Use Raster rendering."); | |
28 DEFINE_bool(pdf, false, "Use PDF rendering."); | |
29 | |
30 // Defined in template.cpp. | |
31 extern SkBitmap source; | |
32 | |
33 static bool install_syscall_filter() { | |
34 | |
35 #ifndef SK_UNSAFE_BUILD_DESKTOP_ONLY | |
36 struct sock_filter filter[] = { | |
37 /* Grab the system call number. */ | |
38 EXAMINE_SYSCALL, | |
39 /* List allowed syscalls. */ | |
40 ALLOW_SYSCALL(exit_group), | |
41 ALLOW_SYSCALL(exit), | |
42 ALLOW_SYSCALL(fstat), | |
43 ALLOW_SYSCALL(read), | |
44 ALLOW_SYSCALL(write), | |
45 ALLOW_SYSCALL(close), | |
46 ALLOW_SYSCALL(mmap), | |
47 ALLOW_SYSCALL(munmap), | |
48 ALLOW_SYSCALL(brk), | |
49 ALLOW_SYSCALL(futex), | |
50 KILL_PROCESS, | |
51 }; | |
52 struct sock_fprog prog = { | |
53 SK_ARRAY_COUNT(filter), | |
54 filter, | |
55 }; | |
56 | |
57 // Lock down the app so that it can't get new privs, such as setuid. | |
58 // Calling this is a requirement for an unpriviledged process to use mode | |
59 // 2 seccomp filters, ala SECCOMP_MODE_FILTER, otherwise we'd have to be | |
60 // root. | |
61 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | |
62 perror("prctl(NO_NEW_PRIVS)"); | |
63 goto failed; | |
64 } | |
65 // Now call seccomp and restrict the system calls that can be made to only | |
66 // the ones in the provided filter list. | |
67 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { | |
68 perror("prctl(SECCOMP)"); | |
69 goto failed; | |
70 } | |
71 return true; | |
72 | |
73 failed: | |
74 if (errno == EINVAL) { | |
75 fprintf(stderr, "SECCOMP_FILTER is not available. :(\n"); | |
76 } | |
77 return false; | |
78 #else | |
79 return true; | |
80 #endif /* SK_UNSAFE_BUILD_DESKTOP_ONLY */ | |
81 } | |
82 | |
83 static void setLimits() { | |
84 struct rlimit n; | |
85 | |
86 // Limit to 5 seconds of CPU. | |
87 n.rlim_cur = 5; | |
88 n.rlim_max = 5; | |
89 if (setrlimit(RLIMIT_CPU, &n)) { | |
90 perror("setrlimit(RLIMIT_CPU)"); | |
91 } | |
92 | |
93 // Limit to 150M of Address space. | |
94 n.rlim_cur = 150000000; | |
95 n.rlim_max = 150000000; | |
96 if (setrlimit(RLIMIT_AS, &n)) { | |
97 perror("setrlimit(RLIMIT_CPU)"); | |
98 } | |
99 } | |
100 | |
101 extern void draw(SkCanvas* canvas); | |
102 | |
103 static void drawAndDump(SkSurface* surface, SkWStream* stream) { | |
104 SkCanvas *canvas = surface->getCanvas(); | |
105 draw(canvas); | |
106 | |
107 // Write out the image as a PNG. | |
108 SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); | |
109 SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100)); | |
110 if (NULL == data.get()) { | |
111 printf("Failed to encode\n"); | |
112 exit(1); | |
113 } | |
114 stream->write(data->data(), data->size()); | |
115 } | |
116 | |
117 static void drawRaster(SkWStream* stream, SkImageInfo info) { | |
118 SkAutoTUnref<SkSurface> surface; | |
119 surface.reset(SkSurface::NewRaster(info)); | |
120 drawAndDump(surface, stream); | |
121 } | |
122 | |
123 static void drawGPU(SkWStream* stream, GrContext* gr, SkImageInfo info) { | |
124 SkAutoTUnref<SkSurface> surface; | |
125 surface.reset(SkSurface::NewRenderTarget(gr,info)); | |
126 | |
127 drawAndDump(surface, stream); | |
128 } | |
129 | |
130 static void drawPDF(SkWStream* stream, SkImageInfo info) { | |
131 printf( "Not implemented yet...\n"); | |
132 } | |
133 | |
134 int main(int argc, char** argv) { | |
135 SkCommandLineFlags::Parse(argc, argv); | |
136 SkAutoGraphics init; | |
137 | |
138 if (FLAGS_out.count() == 0) { | |
139 perror("The --out flag must have an argument."); | |
140 return 1; | |
141 } | |
142 | |
143 if (FLAGS_source.count() == 1) { | |
144 const char *sourceDir = getenv("WEBTRY_INOUT"); | |
145 if (NULL == sourceDir) { | |
146 sourceDir = "/skia_build/inout"; | |
147 } | |
148 | |
149 SkString sourcePath = SkOSPath::Join(sourceDir, FLAGS_source[0]); | |
150 if (!SkImageDecoder::DecodeFile(sourcePath.c_str(), &source)) { | |
151 perror("Unable to read the source image."); | |
152 } | |
153 } | |
154 | |
155 // make sure to open any needed output files before we set up the security | |
156 // jail | |
157 | |
158 SkWStream* streams[3] = {NULL, NULL, NULL}; | |
159 | |
160 if (FLAGS_raster) { | |
161 SkString outPath; | |
162 outPath.printf("%s_raster.png", FLAGS_out[0]); | |
163 streams[0] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str())); | |
164 } | |
165 if (FLAGS_gpu) { | |
166 SkString outPath; | |
167 outPath.printf("%s_gpu.png", FLAGS_out[0]); | |
168 streams[1] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str())); | |
169 } | |
170 if (FLAGS_pdf) { | |
171 SkString outPath; | |
172 outPath.printf("%s.pdf", FLAGS_out[0]); | |
173 streams[2] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str())); | |
174 } | |
175 | |
176 SkImageInfo info = SkImageInfo::MakeN32(FLAGS_width, FLAGS_height, kPremul_S
kAlphaType); | |
177 | |
178 GrContext *gr = NULL; | |
179 GrContextFactory* grFactory = NULL; | |
180 | |
181 // need to set up the GPU context before we install system call restrictions | |
182 if (FLAGS_gpu) { | |
183 | |
184 GrContext::Options grContextOpts; | |
185 grFactory = new GrContextFactory(grContextOpts); | |
186 gr = grFactory->get(GrContextFactory::kMESA_GLContextType); | |
187 } | |
188 | |
189 setLimits(); | |
190 | |
191 if (!install_syscall_filter()) { | |
192 return 1; | |
193 } | |
194 | |
195 if (NULL != streams[0]) { | |
196 drawRaster(streams[0], info); | |
197 } | |
198 if (NULL != streams[1]) { | |
199 drawGPU(streams[1], gr, info); | |
200 } | |
201 if (NULL != streams[2]) { | |
202 drawPDF(streams[2], info); | |
203 } | |
204 | |
205 if (gr) { | |
206 delete grFactory; | |
207 } | |
208 } | |
OLD | NEW |