| 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 |