| 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());
|
| +}
|
|
|