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