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