Index: experimental/webtry/main.cpp |
diff --git a/experimental/webtry/main.cpp b/experimental/webtry/main.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9e7df1484f3516ad5479eb6aab8f92f7f1b4e1ae |
--- /dev/null |
+++ b/experimental/webtry/main.cpp |
@@ -0,0 +1,114 @@ |
+#include <sys/time.h> |
+#include <sys/resource.h> |
+ |
+#include "SkCanvas.h" |
+#include "SkCommandLineFlags.h" |
+#include "SkData.h" |
+#include "SkForceLinking.h" |
+#include "SkGraphics.h" |
+#include "SkImageEncoder.h" |
+#include "SkImageInfo.h" |
+#include "SkStream.h" |
+#include "SkSurface.h" |
+ |
+#include "seccomp_bpf.h" |
+ |
+__SK_FORCE_IMAGE_DECODER_LINKING; |
+ |
+DEFINE_string(out, "", "Filename of the PNG to write to."); |
+ |
+static bool install_syscall_filter() { |
+ struct sock_filter filter[] = { |
+ /* Grab the system call number. */ |
+ EXAMINE_SYSCALL, |
+ /* List allowed syscalls. */ |
+ ALLOW_SYSCALL(exit_group), |
+ ALLOW_SYSCALL(exit), |
+ ALLOW_SYSCALL(fstat), |
+ ALLOW_SYSCALL(read), |
+ ALLOW_SYSCALL(write), |
+ ALLOW_SYSCALL(close), |
+ ALLOW_SYSCALL(mmap), |
+ ALLOW_SYSCALL(munmap), |
+ ALLOW_SYSCALL(brk), |
+ KILL_PROCESS, |
+ }; |
+ struct sock_fprog prog = { |
+ SK_ARRAY_COUNT(filter), |
+ filter, |
+ }; |
+ |
+ // Lock down the app so that it can't get new privs, such as setuid. |
+ // Calling this is a requirement for an unpriviledged process to use mode |
+ // 2 seccomp filters, ala SECCOMP_MODE_FILTER, otherwise we'd have to be |
+ // root. |
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { |
+ perror("prctl(NO_NEW_PRIVS)"); |
+ goto failed; |
+ } |
+ // Now call seccomp and restrict the system calls that can be made to only |
+ // the ones in the provided filter list. |
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { |
+ perror("prctl(SECCOMP)"); |
+ goto failed; |
+ } |
+ return true; |
+ |
+failed: |
+ if (errno == EINVAL) { |
+ fprintf(stderr, "SECCOMP_FILTER is not available. :(\n"); |
+ } |
+ return false; |
+} |
+ |
+static void setLimits() { |
+ struct rlimit n; |
+ |
+ // Limit to 5 seconds of CPU. |
+ n.rlim_cur = 5; |
+ n.rlim_max = 5; |
+ if (setrlimit(RLIMIT_CPU, &n)) { |
+ perror("setrlimit(RLIMIT_CPU)"); |
+ } |
+ |
+ // Limit to 50M of Address space. |
+ n.rlim_cur = 50000000; |
+ n.rlim_max = 50000000; |
+ if (setrlimit(RLIMIT_AS, &n)) { |
+ perror("setrlimit(RLIMIT_CPU)"); |
+ } |
+} |
+ |
+extern void draw(SkCanvas* canvas); |
+ |
+int main(int argc, char** argv) { |
+ SkCommandLineFlags::Parse(argc, argv); |
+ SkAutoGraphics init; |
+ |
+ if (FLAGS_out.count() == 0) { |
+ perror("The --out flag must have an argument."); |
+ return 1; |
+ } |
+ SkFILEWStream stream(FLAGS_out[0]); |
+ |
+ SkImageInfo info = SkImageInfo::MakeN32(300, 300, kPremul_SkAlphaType); |
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); |
+ SkCanvas* canvas = surface->getCanvas(); |
+ |
+ setLimits(); |
+ |
+ if (!install_syscall_filter()) { |
+ return 1; |
+ } |
+ |
+ draw(canvas); |
+ |
+ // Write out the image as a PNG. |
+ SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); |
+ SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100)); |
+ if (NULL == data.get()) { |
+ printf("Failed to encode\n"); |
+ exit(1); |
+ } |
+ stream.write(data->data(), data->size()); |
+} |