Home | History | Annotate | Download | only in webtry
      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