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