get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1707775/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1707775,
    "url": "http://patchwork.ozlabs.org/api/patches/1707775/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-um/patch/20221122100759.208290-28-benjamin@sipsolutions.net/",
    "project": {
        "id": 60,
        "url": "http://patchwork.ozlabs.org/api/projects/60/?format=api",
        "name": "User-mode Linux Development",
        "link_name": "linux-um",
        "list_id": "linux-um.lists.infradead.org",
        "list_email": "linux-um@lists.infradead.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20221122100759.208290-28-benjamin@sipsolutions.net>",
    "list_archive_url": null,
    "date": "2022-11-22T10:07:58",
    "name": "[v2,27/28] um: Implement kernel side of SECCOMP based process handling",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "70c46ff9cd6b1006171e497ae820f2d2921985a9",
    "submitter": {
        "id": 67525,
        "url": "http://patchwork.ozlabs.org/api/people/67525/?format=api",
        "name": "Benjamin Berg",
        "email": "benjamin@sipsolutions.net"
    },
    "delegate": {
        "id": 54851,
        "url": "http://patchwork.ozlabs.org/api/users/54851/?format=api",
        "username": "rw",
        "first_name": "Richard",
        "last_name": "Weinberger",
        "email": "richard@nod.at"
    },
    "mbox": "http://patchwork.ozlabs.org/project/linux-um/patch/20221122100759.208290-28-benjamin@sipsolutions.net/mbox/",
    "series": [
        {
            "id": 329466,
            "url": "http://patchwork.ozlabs.org/api/series/329466/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-um/list/?series=329466",
            "date": "2022-11-22T10:07:37",
            "name": "Implement SECCOMP based userland",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/329466/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1707775/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1707775/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=<UNKNOWN>)",
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=rSgK088o;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n secure) header.d=infradead.org header.i=@infradead.org header.a=rsa-sha256\n header.s=desiato.20200630 header.b=SGROo6rm;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n secure) header.d=sipsolutions.net header.i=@sipsolutions.net\n header.a=rsa-sha256 header.s=mail header.b=sHza6lQp;\n\tdkim-atps=neutral"
        ],
        "Received": [
            "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4NGgRf6kvVz23nl\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 22 Nov 2022 21:27:10 +1100 (AEDT)",
            "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux))\n\tid 1oxQUZ-007o0R-0W; Tue, 22 Nov 2022 10:27:03 +0000",
            "from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05])\n\tby bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux))\n\tid 1oxQTL-007nKg-OB\n\tfor linux-um@bombadil.infradead.org; Tue, 22 Nov 2022 10:25:48 +0000",
            "from s3.sipsolutions.net ([2a01:4f8:191:4433::2]\n helo=sipsolutions.net)\n\tby desiato.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux))\n\tid 1oxQF1-003P1n-51\n\tfor linux-um@lists.infradead.org; Tue, 22 Nov 2022 10:11:06 +0000",
            "by sipsolutions.net with esmtpsa\n (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256)\n\t(Exim 4.96)\n\t(envelope-from <benjamin@sipsolutions.net>)\n\tid 1oxQEv-006IGn-0s;\n\tTue, 22 Nov 2022 11:10:54 +0100"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=ydHzM4AiqFTVvxj74ppWcGs9NLE+bLcfnM8Ub+5Im2M=; b=rSgK088o3+6bZ4\n\tuLS+Wros/yL//MqYbwfnI+FGLioRe6CW05cMhDGKuhb5WaRhoysAfKyFxGv4lhj0DgTO7GnmVqeYC\n\tS+MzhDBWTy/wxsrbpBH5qRYHrdI3gDXOFhJsBOHEqr8tsvBtPBliItojT19pYVFhGxp4ukWH7cV/G\n\t9/2RATH3yqlr0Wp/bDWTLHIPXTb3l4YIL4EJWrTky5R4CuPT45Hp4zX4VUVwFKkGWvsqLO1pyouRk\n\tvMv5RfmConhh9pC4VJnSbPypSk7bpSPCCYUAXMe9A8v6xSor+xS6z29IUhgg0Rpye/qm7HcnGYQRi\n\t1+Rb1orOLq6CfEK3cD3w==;",
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version\n\t:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:\n\tContent-Type:Content-ID:Content-Description;\n\tbh=inOU+kK11IiDzT1FN7sR69lcT3YP2faBjklKF6PfxC4=; b=SGROo6rmZPl4/3nTTpztm1jIwg\n\tqyvbYnvw5kOhl4PRsLRQTdEnfabLILSsW8F4irfxbzT8rBPFtwd0bKAyNPAdZxtWkJCwo2lbt8cuj\n\t+fqMAKer1sTdSBrEd3qWBa1UcfOkv5wghJhzqj/judO2vrXVnV7/vt5HidFUe/ibhSwSIEeT7JfYO\n\tTCFR2/TTpWXFq2w12gPEw/UA1O/3tH48cbyRD3qt0apH/P/udszoT0Mr3ZZutSHbM5troLJN1EpAf\n\tNZQWzVv3nGHPzdmgYNlH0JSLqW+GyACDgIcW5VGldmfwxfRCwbp4+eY/S4KI/FcQ52Goo310ZfMvS\n\tqpBjw6Xw==;",
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version:\n\tReferences:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender\n\t:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To:\n\tResent-Cc:Resent-Message-ID; bh=inOU+kK11IiDzT1FN7sR69lcT3YP2faBjklKF6PfxC4=;\n\tt=1669111857; x=1670321457; b=sHza6lQpQ5cVm3EL1fpXS0Fyxz30NyODjEfdRTKzk7gY+zr\n\t+CDoOlExke61l9+EycqHeqkP8CKbeBW0dxb0ywWzzhR2KqPyp4GaGoNVgbNgWl6JW1jxhJORWzoxq\n\t0sQCjB7cEhycCSA4Kt6l3eIerNu0hStdc0XiKaxF63eqnWIf62Ko3VNw9nxyNpsgXe/Nm5WUtr/r1\n\t1bQHvuvUd9hW5k1/bGdiOWHh8h9+YUo2SCtSZj/NDkL6C5bDdLAx6XNbkRwQXZ1jCLPEpOLDlD5rR\n\tjFSlQowMHiZFGAXcuUoEOfqXhBYBnWQgLhRu0zfMRHUa5OfXj6iKronybD5JI1XA==;"
        ],
        "From": "benjamin@sipsolutions.net",
        "To": "linux-um@lists.infradead.org",
        "Cc": "Benjamin Berg <benjamin@sipsolutions.net>,\n\tJohannes Berg <johannes@sipsolutions.net>",
        "Subject": "[PATCH v2 27/28] um: Implement kernel side of SECCOMP based process\n handling",
        "Date": "Tue, 22 Nov 2022 11:07:58 +0100",
        "Message-Id": "<20221122100759.208290-28-benjamin@sipsolutions.net>",
        "X-Mailer": "git-send-email 2.38.1",
        "In-Reply-To": "<20221122100759.208290-1-benjamin@sipsolutions.net>",
        "References": "<20221122100759.208290-1-benjamin@sipsolutions.net>",
        "MIME-Version": "1.0",
        "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ",
        "X-CRM114-CacheID": "sfid-20221122_101059_721686_5F152C79 ",
        "X-CRM114-Status": "GOOD (  28.22  )",
        "X-Spam-Score": "-0.2 (/)",
        "X-Spam-Report": "Spam detection software,\n running on the system \"desiato.infradead.org\",\n has NOT identified this incoming email as spam.  The original\n message has been attached to this so you can view it or label\n similar future email.  If you have any questions, see\n the administrator of that system for details.\n Content preview:  From: Benjamin Berg <benjamin@sipsolutions.net> This adds\n   the kernel side of the seccomp based process handling. Co-authored-by:\n Johannes\n    Berg <johannes@sipsolutions.net> Signed-off-by: Benjamin Berg\n <benjamin@sipsolutions.net>\n    --- arch/um/os-Linux/skas/mem.c | 35 +- arch/um/os-Linux/skas/process.c |\n    561 +++++++ [...]\n Content analysis details:   (-0.2 points, 5.0 required)\n  pts rule name              description\n ---- ----------------------\n --------------------------------------------------\n -0.0 SPF_PASS               SPF: sender matches SPF record\n -0.0 SPF_HELO_PASS          SPF: HELO matches SPF record\n -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from\n                             author's domain\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily\n                             valid\n -0.1 DKIM_VALID             Message has at least one valid DKIM or DK\n signature",
        "X-BeenThere": "linux-um@lists.infradead.org",
        "X-Mailman-Version": "2.1.34",
        "Precedence": "list",
        "List-Id": "<linux-um.lists.infradead.org>",
        "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/linux-um>,\n <mailto:linux-um-request@lists.infradead.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.infradead.org/pipermail/linux-um/>",
        "List-Post": "<mailto:linux-um@lists.infradead.org>",
        "List-Help": "<mailto:linux-um-request@lists.infradead.org?subject=help>",
        "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/linux-um>,\n <mailto:linux-um-request@lists.infradead.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Sender": "\"linux-um\" <linux-um-bounces@lists.infradead.org>",
        "Errors-To": "linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"
    },
    "content": "From: Benjamin Berg <benjamin@sipsolutions.net>\n\nThis adds the kernel side of the seccomp based process handling.\n\nCo-authored-by: Johannes Berg <johannes@sipsolutions.net>\nSigned-off-by: Benjamin Berg <benjamin@sipsolutions.net>\n---\n arch/um/os-Linux/skas/mem.c     |  35 +-\n arch/um/os-Linux/skas/process.c | 561 ++++++++++++++++++++++++--------\n arch/um/os-Linux/start_up.c     |   3 -\n 3 files changed, 439 insertions(+), 160 deletions(-)",
    "diff": "diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c\nindex 28e50349ab91..619035151bc6 100644\n--- a/arch/um/os-Linux/skas/mem.c\n+++ b/arch/um/os-Linux/skas/mem.c\n@@ -4,6 +4,7 @@\n  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)\n  */\n \n+#include <linux/kconfig.h>\n #include <stddef.h>\n #include <unistd.h>\n #include <errno.h>\n@@ -22,6 +23,7 @@\n extern char __syscall_stub_start[];\n \n extern void wait_stub_done(int pid);\n+void wait_stub_done_seccomp(int pid, struct stub_data *data, int running);\n \n static inline unsigned long *check_init_stack(struct mm_id *mm_idp,\n \t\t\t\t\t      unsigned long *stack)\n@@ -58,24 +60,29 @@ static inline long do_syscall_stub(struct mm_id *mm_idp)\n \tint n, i;\n \tint err, pid = mm_idp->u.pid;\n \n-\tn = ptrace_setregs(pid, syscall_regs);\n-\tif (n < 0) {\n-\t\tprintk(UM_KERN_ERR \"Registers - \\n\");\n-\t\tfor (i = 0; i < MAX_REG_NR; i++)\n-\t\t\tprintk(UM_KERN_ERR \"\\t%d\\t0x%lx\\n\", i, syscall_regs[i]);\n-\t\tpanic(\"%s : PTRACE_SETREGS failed, errno = %d\\n\",\n-\t\t      __func__, -n);\n-\t}\n-\n \t/* Inform process how much we have filled in. */\n \tproc_data->syscall_data_len = mm_idp->syscall_data_len;\n \n-\terr = ptrace(PTRACE_CONT, pid, 0, 0);\n-\tif (err)\n-\t\tpanic(\"Failed to continue stub, pid = %d, errno = %d\\n\", pid,\n-\t\t      errno);\n+\tif (using_seccomp) {\n+\t\tproc_data->restart_wait = 1;\n+\t\twait_stub_done_seccomp(pid, proc_data, 0);\n+\t} else {\n+\t\tn = ptrace_setregs(pid, syscall_regs);\n+\t\tif (n < 0) {\n+\t\t\tprintk(UM_KERN_ERR \"Registers -\\n\");\n+\t\t\tfor (i = 0; i < MAX_REG_NR; i++)\n+\t\t\t\tprintk(UM_KERN_ERR \"\\t%d\\t0x%lx\\n\", i, syscall_regs[i]);\n+\t\t\tpanic(\"%s : PTRACE_SETREGS failed, errno = %d\\n\",\n+\t\t\t      __func__, -n);\n+\t\t}\n+\n+\t\terr = ptrace(PTRACE_CONT, pid, 0, 0);\n+\t\tif (err)\n+\t\t\tpanic(\"Failed to continue stub, pid = %d, errno = %d\\n\",\n+\t\t\t      pid, errno);\n \n-\twait_stub_done(pid);\n+\t\twait_stub_done(pid);\n+\t}\n \n \t/*\n \t * proc_data->err will be non-zero if there was an (unexpected) error.\ndiff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c\nindex 44a7d49538ce..55868eb35727 100644\n--- a/arch/um/os-Linux/skas/process.c\n+++ b/arch/um/os-Linux/skas/process.c\n@@ -1,9 +1,11 @@\n // SPDX-License-Identifier: GPL-2.0\n /*\n+ * Copyright (C) 2021 Benjamin Berg <benjamin@sipsolutions.net>\n  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)\n  * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)\n  */\n \n+#include <linux/kconfig.h>\n #include <stdlib.h>\n #include <stdbool.h>\n #include <unistd.h>\n@@ -22,7 +24,13 @@\n #include <registers.h>\n #include <skas.h>\n #include <sysdep/stub.h>\n+#include <sysdep/mcontext.h>\n #include <linux/threads.h>\n+#include <sys/resource.h>\n+#include <sys/prctl.h>\n+#include <linux/filter.h>\n+#include <linux/seccomp.h>\n+#include <linux/futex.h>\n \n int is_skas_winch(int pid, int fd, void *data)\n {\n@@ -137,6 +145,58 @@ void wait_stub_done(int pid)\n \tfatal_sigsegv();\n }\n \n+#ifdef CONFIG_UML_SECCOMP\n+void wait_stub_done_seccomp(int pid, struct stub_data *data, int running)\n+{\n+\tint ret;\n+\n+\tdo {\n+\t\tif (!running) {\n+\t\t\tdata->signal = 0;\n+\t\t\tdata->futex = FUTEX_IN_CHILD;\n+\t\t\tCATCH_EINTR(syscall(__NR_futex, &data->futex,\n+\t\t\t\t\t    FUTEX_WAKE, 1, NULL, NULL, 0));\n+\t\t}\n+\n+\t\tdo {\n+\t\t\tret = syscall(__NR_futex, &data->futex,\n+\t\t\t\t      FUTEX_WAIT, FUTEX_IN_CHILD,\n+\t\t\t\t      NULL, NULL, 0);\n+\t\t} while ((ret == -1 && errno == EINTR) || data->futex == FUTEX_IN_CHILD);\n+\n+\t\trunning = 0;\n+\n+\t\t/* We may receive a SIGALRM, if we do, we are not done yet and need to iterate. */\n+\t} while (data->signal == SIGALRM);\n+\n+\tif (ret < 0 && errno != EAGAIN) {\n+\t\tprintk(UM_KERN_ERR \"%s : waiting for child futex failed, errno = %d\\n\",\n+\t\t       __func__, errno);\n+\t\tgoto out_kill;\n+\t}\n+\n+\tif (data->mctx_offset > sizeof(data->sigstack) - sizeof(mcontext_t)) {\n+\t\tprintk(UM_KERN_ERR \"%s : invalid mcontext offset\", __func__);\n+\t\tgoto out_kill;\n+\t}\n+\n+\tif (data->signal != SIGTRAP) {\n+\t\tprintk(UM_KERN_ERR \"%s : expected SIGTRAP but got %d\",\n+\t\t       __func__, data->signal);\n+\t\tgoto out_kill;\n+\t}\n+\n+\treturn;\n+\n+out_kill:\n+\tprintk(UM_KERN_ERR \"%s : failed to wait for SIGTRAP, pid = %d, errno = %d\\n\",\n+\t       __func__, pid, errno);\n+\tfatal_sigsegv();\n+}\n+#else\n+void wait_stub_done_seccomp(int pid, struct stub_data *data, int running);\n+#endif\n+\n extern unsigned long current_stub_stack(void);\n \n static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)\n@@ -198,16 +258,16 @@ extern char __syscall_stub_start[];\n  */\n static int userspace_tramp(void *stack)\n {\n-\tstruct sigaction sa;\n \tstruct stub_data *data;\n \tvoid *addr;\n \tint fd;\n \tunsigned long long offset;\n-\tunsigned long segv_handler = STUB_CODE +\n-\t\t\t\t     (unsigned long) stub_segv_handler -\n-\t\t\t\t     (unsigned long) __syscall_stub_start;\n \n-\tptrace(PTRACE_TRACEME, 0, 0, 0);\n+\tif (!using_seccomp)\n+\t\tptrace(PTRACE_TRACEME, 0, 0, 0);\n+\n+\t/* Needed for seccomp, but this is sane anyway. */\n+\tprctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);\n \n \tsignal(SIGTERM, SIG_DFL);\n \tsignal(SIGWINCH, SIG_IGN);\n@@ -233,17 +293,130 @@ static int userspace_tramp(void *stack)\n \tdata = (void *) addr;\n \n \tset_sigstack((void *) &data->sigstack, sizeof(data->sigstack));\n-\tsigemptyset(&sa.sa_mask);\n-\tsa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;\n-\tsa.sa_sigaction = (void *) segv_handler;\n-\tsa.sa_restorer = NULL;\n-\tif (sigaction(SIGSEGV, &sa, NULL) < 0) {\n-\t\tos_info(\"%s - setting SIGSEGV handler failed - errno = %d\\n\",\n-\t\t\t__func__, errno);\n-\t\texit(1);\n+\n+\tif (using_seccomp) {\n+\t\tstruct rlimit lim;\n+\t\tstruct sock_filter filter[] = {\n+#if __BITS_PER_LONG > 32\n+\t\t\t/* [0] Load upper 32bit of instruction pointer from seccomp_data */\n+\t\t\tBPF_STMT(BPF_LD | BPF_W | BPF_ABS,\n+\t\t\t\t(offsetof(struct seccomp_data, instruction_pointer) + 4)),\n+\n+\t\t\t/* [1] Jump forward 4 instructions if the upper address is not identical */\n+\t\t\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (STUB_CODE) >> 32, 0, 4),\n+#endif\n+\t\t\t/* [2] Load lower 32bit of instruction pointer from seccomp_data */\n+\t\t\tBPF_STMT(BPF_LD | BPF_W | BPF_ABS,\n+\t\t\t\t(offsetof(struct seccomp_data, instruction_pointer))),\n+\n+\t\t\t/* [3] Mask out lower bits */\n+\t\t\tBPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xfffff000),\n+\n+\t\t\t/* [4] Jump to [6] if the lower bits are not on the expected page */\n+\t\t\tBPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (STUB_CODE) & 0xfffff000, 0, 1),\n+\n+\t\t\t/* [5] Permitted call, allow */\n+\t\t\tBPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n+\n+\t\t\t/* [6] Restricted call, replace with SIGSYS */\n+\t\t\tBPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n+\t\t};\n+\t\tstruct sock_fprog prog = {\n+\t\t\t.len = ARRAY_SIZE(filter),\n+\t\t\t.filter = filter,\n+\t\t};\n+\n+\t\t/*\n+\t\t * With seccomp we return normally from the signal handler, so\n+\t\t * avoid setting things up through libc which may do its own\n+\t\t * thing for restoring.\n+\t\t */\n+\t\tstruct sigaction_real {\n+\t\t\tvoid *sa_handler_;\n+\t\t\tunsigned long sa_flags;\n+\t\t\tvoid *sa_restorer;\n+\t\t\tsigset_t sa_mask;\n+\t\t} sa;\n+\n+\t\tunsigned long v = STUB_CODE +\n+\t\t\t\t  (unsigned long) stub_signal_interrupt -\n+\t\t\t\t  (unsigned long) __syscall_stub_start;\n+\t\tunsigned long r = STUB_CODE +\n+\t\t\t\t  (unsigned long) stub_signal_restorer -\n+\t\t\t\t  (unsigned long) __syscall_stub_start;\n+\n+\t\t/* Never coredump */\n+\t\tlim.rlim_cur = 0;\n+\t\tlim.rlim_max = 0;\n+\t\tif (setrlimit(RLIMIT_CORE, &lim) < 0) {\n+\t\t\tos_info(\"Could not set coredump size limit, errno = %d\\n\",\n+\t\t\t\terrno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tsigemptyset(&sa.sa_mask);\n+\t\tsigaddset(&sa.sa_mask, SIGALRM);\n+\t\tsigaddset(&sa.sa_mask, SIGCHLD);\n+\t\tsa.sa_flags = SA_ONSTACK | SA_SIGINFO | 0x04000000; /* SA_RESTORER */\n+\t\tsa.sa_handler_ = (void *)v;\n+\t\tsa.sa_restorer = (void *)r;\n+\t\tif (syscall(__NR_rt_sigaction, SIGSEGV, &sa, NULL, 8) < 0) {\n+\t\t\tos_info(\"%s - setting SIGSEGV handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (syscall(__NR_rt_sigaction, SIGSYS, &sa, NULL, 8) < 0) {\n+\t\t\tos_info(\"%s - setting SIGSYS handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (syscall(__NR_rt_sigaction, SIGALRM, &sa, NULL, 8) < 0) {\n+\t\t\tos_info(\"%s - setting SIGALRM handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (syscall(__NR_rt_sigaction, SIGTRAP, &sa, NULL, 8) < 0) {\n+\t\t\tos_info(\"%s - setting SIGTRAP handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (syscall(__NR_rt_sigaction, SIGFPE, &sa, NULL, 8) < 0) {\n+\t\t\tos_info(\"%s - setting SIGFPE handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,\n+\t\t\t    SECCOMP_FILTER_FLAG_TSYNC, &prog) != 0) {\n+\t\t\tos_info(\"%s - could not install seccomp filter - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(42);\n+\t\t}\n+\n+\t\ttrap_myself();\n+\t} else {\n+\t\tstruct sigaction sa;\n+\t\tunsigned long segv_handler = STUB_CODE +\n+\t\t\t\t\t     (unsigned long) stub_segv_handler -\n+\t\t\t\t\t     (unsigned long) __syscall_stub_start;\n+\n+\t\tsigemptyset(&sa.sa_mask);\n+\t\tsa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;\n+\t\tsa.sa_sigaction = (void *) segv_handler;\n+\t\tsa.sa_restorer = NULL;\n+\t\tif (sigaction(SIGSEGV, &sa, NULL) < 0) {\n+\t\t\tos_info(\"%s - setting SIGSEGV handler failed - errno = %d\\n\",\n+\t\t\t\t__func__, errno);\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tkill(os_getpid(), SIGSTOP);\n \t}\n \n-\tkill(os_getpid(), SIGSTOP);\n \treturn 0;\n }\n \n@@ -269,6 +442,7 @@ int start_userspace(struct mm_id *id)\n \tvoid *stack;\n \tunsigned long sp;\n \tint status, n, flags, err;\n+\tstruct stub_data *proc_data = (void *) id->stack;\n \n \t/* setup a temporary stack page */\n \tstack = mmap(NULL, UM_KERN_PAGE_SIZE,\n@@ -286,6 +460,9 @@ int start_userspace(struct mm_id *id)\n \n \tflags = CLONE_FILES | SIGCHLD;\n \n+\tif (using_seccomp)\n+\t\tproc_data->futex = FUTEX_IN_CHILD;\n+\n \t/* clone into new userspace process */\n \tid->u.pid = clone(userspace_tramp, (void *) sp, flags, (void *) id->stack);\n \tif (id->u.pid < 0) {\n@@ -295,29 +472,33 @@ int start_userspace(struct mm_id *id)\n \t\treturn err;\n \t}\n \n-\tdo {\n-\t\tCATCH_EINTR(n = waitpid(id->u.pid, &status, WUNTRACED | __WALL));\n-\t\tif (n < 0) {\n+\tif (using_seccomp) {\n+\t\twait_stub_done_seccomp(id->u.pid, proc_data, 1);\n+\t} else {\n+\t\tdo {\n+\t\t\tCATCH_EINTR(n = waitpid(id->u.pid, &status, WUNTRACED | __WALL));\n+\t\t\tif (n < 0) {\n+\t\t\t\terr = -errno;\n+\t\t\t\tprintk(UM_KERN_ERR \"%s : wait failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tgoto out_kill;\n+\t\t\t}\n+\t\t} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));\n+\n+\t\tif (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {\n+\t\t\terr = -EINVAL;\n+\t\t\tprintk(UM_KERN_ERR \"%s : expected SIGSTOP, got status = %d\\n\",\n+\t\t\t       __func__, status);\n+\t\t\tgoto out_kill;\n+\t\t}\n+\n+\t\tif (ptrace(PTRACE_SETOPTIONS, id->u.pid, NULL,\n+\t\t\t   (void *) PTRACE_O_TRACESYSGOOD) < 0) {\n \t\t\terr = -errno;\n-\t\t\tprintk(UM_KERN_ERR \"%s : wait failed, errno = %d\\n\",\n+\t\t\tprintk(UM_KERN_ERR \"%s : PTRACE_SETOPTIONS failed, errno = %d\\n\",\n \t\t\t       __func__, errno);\n \t\t\tgoto out_kill;\n \t\t}\n-\t} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));\n-\n-\tif (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {\n-\t\terr = -EINVAL;\n-\t\tprintk(UM_KERN_ERR \"%s : expected SIGSTOP, got status = %d\\n\",\n-\t\t       __func__, status);\n-\t\tgoto out_kill;\n-\t}\n-\n-\tif (ptrace(PTRACE_SETOPTIONS, id->u.pid, NULL,\n-\t\t   (void *) PTRACE_O_TRACESYSGOOD) < 0) {\n-\t\terr = -errno;\n-\t\tprintk(UM_KERN_ERR \"%s : PTRACE_SETOPTIONS failed, errno = %d\\n\",\n-\t\t       __func__, errno);\n-\t\tgoto out_kill;\n \t}\n \n \tif (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {\n@@ -337,7 +518,9 @@ int start_userspace(struct mm_id *id)\n void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)\n {\n \tint err, status, op, pid = userspace_pid[0];\n-\tsiginfo_t si;\n+\tsiginfo_t si_ptrace;\n+\tsiginfo_t *si;\n+\tint sig;\n \n \t/* Handle any immediate reschedules or signals */\n \tinterrupt_end();\n@@ -346,94 +529,166 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)\n \t\tif (kill_userspace_mm[0])\n \t\t\tfatal_sigsegv();\n \n-\t\t/*\n-\t\t * This can legitimately fail if the process loads a\n-\t\t * bogus value into a segment register.  It will\n-\t\t * segfault and PTRACE_GETREGS will read that value\n-\t\t * out of the process.  However, PTRACE_SETREGS will\n-\t\t * fail.  In this case, there is nothing to do but\n-\t\t * just kill the process.\n-\t\t */\n-\t\tif (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) {\n-\t\t\tprintk(UM_KERN_ERR \"%s - ptrace set regs failed, errno = %d\\n\",\n-\t\t\t       __func__, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\tif (using_seccomp) {\n+\t\t\tstruct stub_data *proc_data = (void *)current_stub_stack();\n+\t\t\tint ret;\n \n-\t\tif (put_fp_registers(pid, regs->fp)) {\n-\t\t\tprintk(UM_KERN_ERR \"%s - ptrace set fp regs failed, errno = %d\\n\",\n-\t\t\t       __func__, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\t\tret = set_stub_state(regs, proc_data, singlestepping());\n+\t\t\tif (ret) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - failed to set regs: %d\",\n+\t\t\t\t       __func__, ret);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n \n-\t\tif (singlestepping())\n-\t\t\top = PTRACE_SYSEMU_SINGLESTEP;\n-\t\telse\n-\t\t\top = PTRACE_SYSEMU;\n+\t\t\t/* Must have been reset by the syscall caller */\n+\t\t\tif (proc_data->restart_wait != 0)\n+\t\t\t\tpanic(\"Programming error: Flag to only run syscalls in child was not cleared!\");\n+\n+\t\t\tproc_data->signal = 0;\n+\t\t\tproc_data->futex = FUTEX_IN_CHILD;\n+\t\t\tCATCH_EINTR(syscall(__NR_futex, &proc_data->futex,\n+\t\t\t\t\t    FUTEX_WAKE, 1, NULL, NULL, 0));\n+\t\t\tdo {\n+\t\t\t\tret = syscall(__NR_futex, &proc_data->futex,\n+\t\t\t\t\t      FUTEX_WAIT, FUTEX_IN_CHILD, NULL, NULL, 0);\n+\t\t\t} while ((ret == -1 && errno == EINTR) ||\n+\t\t\t\t proc_data->futex == FUTEX_IN_CHILD);\n+\n+\t\t\tsig = proc_data->signal;\n+\n+\t\t\tret = get_stub_state(regs, proc_data);\n+\t\t\tif (ret) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - failed to get regs: %d\",\n+\t\t\t\t       __func__, ret);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n \n-\t\tif (ptrace(op, pid, 0, 0)) {\n-\t\t\tprintk(UM_KERN_ERR \"%s - ptrace continue failed, op = %d, errno = %d\\n\",\n-\t\t\t       __func__, op, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\t\tif (proc_data->si_offset > sizeof(proc_data->sigstack) - sizeof(*si))\n+\t\t\t\tpanic(\"%s - Invalid siginfo offset from child\",\n+\t\t\t\t      __func__);\n+\t\t\tsi = (void *)&proc_data->sigstack[proc_data->si_offset];\n+\n+\t\t\tif (sig == SIGSEGV && si->si_code == SI_KERNEL) {\n+\t\t\t\t/* This happens if the host is unable to\n+\t\t\t\t * restore the state from the mcontext.\n+\t\t\t\t */\n+\t\t\t\tpanic(\"%s - SEGV with si_code == SI_KERNEL, faulted while returning to userspace (addr: 0x%lx)\",\n+\t\t\t\t      __func__, (unsigned long) si->si_addr);\n+\t\t\t}\n \n-\t\tCATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));\n-\t\tif (err < 0) {\n-\t\t\tprintk(UM_KERN_ERR \"%s - wait failed, errno = %d\\n\",\n-\t\t\t       __func__, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\t\tregs->is_user = 1;\n \n-\t\tregs->is_user = 1;\n-\t\tif (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {\n-\t\t\tprintk(UM_KERN_ERR \"%s - PTRACE_GETREGS failed, errno = %d\\n\",\n-\t\t\t       __func__, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\t\t/* Fill in ORIG_RAX and extract fault information */\n+\t\t\tPT_SYSCALL_NR(regs->gp) = si->si_syscall;\n+\t\t\tif (sig == SIGSEGV) {\n+\t\t\t\tmcontext_t *mcontext = (void *)&proc_data->sigstack[proc_data->mctx_offset];\n \n-\t\tif (get_fp_registers(pid, regs->fp)) {\n-\t\t\tprintk(UM_KERN_ERR \"%s -  get_fp_registers failed, errno = %d\\n\",\n-\t\t\t       __func__, errno);\n-\t\t\tfatal_sigsegv();\n-\t\t}\n+\t\t\t\tGET_FAULTINFO_FROM_MC(regs->faultinfo, mcontext);\n+\t\t\t}\n+\t\t} else {\n+\t\t\t/*\n+\t\t\t * This can legitimately fail if the process loads a\n+\t\t\t * bogus value into a segment register.  It will\n+\t\t\t * segfault and PTRACE_GETREGS will read that value\n+\t\t\t * out of the process.  However, PTRACE_SETREGS will\n+\t\t\t * fail.  In this case, there is nothing to do but\n+\t\t\t * just kill the process.\n+\t\t\t */\n+\t\t\tif (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - ptrace set regs failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n \n-\t\tUPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */\n+\t\t\tif (put_fp_registers(pid, regs->fp)) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - ptrace set fp regs failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n \n-\t\tif (WIFSTOPPED(status)) {\n-\t\t\tint sig = WSTOPSIG(status);\n+\t\t\tif (singlestepping())\n+\t\t\t\top = PTRACE_SYSEMU_SINGLESTEP;\n+\t\t\telse\n+\t\t\t\top = PTRACE_SYSEMU;\n \n-\t\t\t/* These signal handlers need the si argument.\n-\t\t\t * The SIGIO and SIGALARM handlers which constitute the\n-\t\t\t * majority of invocations, do not use it.\n-\t\t\t */\n-\t\t\tswitch (sig) {\n-\t\t\tcase SIGSEGV:\n-\t\t\tcase SIGTRAP:\n-\t\t\tcase SIGILL:\n-\t\t\tcase SIGBUS:\n-\t\t\tcase SIGFPE:\n-\t\t\tcase SIGWINCH:\n-\t\t\t\tptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);\n-\t\t\t\tbreak;\n+\t\t\tif (ptrace(op, pid, 0, 0)) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - ptrace continue failed, op = %d, errno = %d\\n\",\n+\t\t\t\t       __func__, op, errno);\n+\t\t\t\tfatal_sigsegv();\n \t\t\t}\n \n+\t\t\tCATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));\n+\t\t\tif (err < 0) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - wait failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n+\n+\t\t\tregs->is_user = 1;\n+\t\t\tif (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s - PTRACE_GETREGS failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n+\n+\t\t\tif (get_fp_registers(pid, regs->fp)) {\n+\t\t\t\tprintk(UM_KERN_ERR \"%s -  get_fp_registers failed, errno = %d\\n\",\n+\t\t\t\t       __func__, errno);\n+\t\t\t\tfatal_sigsegv();\n+\t\t\t}\n+\n+\t\t\tif (WIFSTOPPED(status)) {\n+\t\t\t\tsig = WSTOPSIG(status);\n+\n+\t\t\t\t/* These signal handlers need the si argument\n+\t\t\t\t * and SIGSEGV needs the faultinfo.\n+\t\t\t\t * The SIGIO and SIGALARM handlers which constitute the\n+\t\t\t\t * majority of invocations, do not use it.\n+\t\t\t\t */\n+\t\t\t\tswitch (sig) {\n+\t\t\t\tcase SIGSEGV:\n+\t\t\t\t\tget_skas_faultinfo(pid,\n+\t\t\t\t\t\t\t   &regs->faultinfo,\n+\t\t\t\t\t\t\t   aux_fp_regs);\n+\t\t\t\t\tfallthrough;\n+\t\t\t\tcase SIGTRAP:\n+\t\t\t\tcase SIGILL:\n+\t\t\t\tcase SIGBUS:\n+\t\t\t\tcase SIGFPE:\n+\t\t\t\tcase SIGWINCH:\n+\t\t\t\t\tptrace(PTRACE_GETSIGINFO, pid, 0,\n+\t\t\t\t\t       (struct siginfo *)&si_ptrace);\n+\t\t\t\t\tsi = &si_ptrace;\n+\t\t\t\t\tbreak;\n+\t\t\t\tdefault:\n+\t\t\t\t\tsi = NULL;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tsig = 0;\n+\t\t\t}\n+\t\t}\n+\n+\t\tUPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */\n+\n+\t\tif (sig) {\n \t\t\tswitch (sig) {\n \t\t\tcase SIGSEGV:\n-\t\t\t\tget_skas_faultinfo(pid,\n-\t\t\t\t\t\t   &regs->faultinfo, aux_fp_regs);\n-\n-\t\t\t\tif (PTRACE_FULL_FAULTINFO)\n-\t\t\t\t\t(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,\n-\t\t\t\t\t\t\t     regs);\n+\t\t\t\tif (using_seccomp || PTRACE_FULL_FAULTINFO)\n+\t\t\t\t\t(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)si,\n+\t\t\t\t\t\t     regs);\n \t\t\t\telse\n \t\t\t\t\tsegv(regs->faultinfo, 0, 1, NULL);\n \n+\t\t\t\tbreak;\n+\t\t\tcase SIGSYS:\n+\t\t\t\thandle_syscall(regs);\n \t\t\t\tbreak;\n \t\t\tcase SIGTRAP + 0x80:\n \t\t\t\thandle_trap(pid, regs);\n \t\t\t\tbreak;\n \t\t\tcase SIGTRAP:\n-\t\t\t\trelay_signal(SIGTRAP, (struct siginfo *)&si, regs);\n+\t\t\t\trelay_signal(SIGTRAP, (struct siginfo *)si, regs);\n \t\t\t\tbreak;\n \t\t\tcase SIGALRM:\n \t\t\t\tbreak;\n@@ -443,7 +698,7 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)\n \t\t\tcase SIGFPE:\n \t\t\tcase SIGWINCH:\n \t\t\t\tblock_signals_trace();\n-\t\t\t\t(*sig_info[sig])(sig, (struct siginfo *)&si, regs);\n+\t\t\t\t(*sig_info[sig])(sig, (struct siginfo *)si, regs);\n \t\t\t\tunblock_signals_trace();\n \t\t\t\tbreak;\n \t\t\tdefault:\n@@ -467,9 +722,14 @@ static int __init init_thread_regs(void)\n {\n \tget_safe_registers(thread_regs.gp, thread_regs.fp);\n \t/* Set parent's instruction pointer to start of clone-stub */\n-\tthread_regs.gp[REGS_IP_INDEX] = STUB_CODE +\n-\t\t\t\t\t(unsigned long)stub_clone_handler -\n-\t\t\t\t\t(unsigned long)__syscall_stub_start;\n+\tif (using_seccomp)\n+\t\tthread_regs.gp[REGS_IP_INDEX] = STUB_CODE +\n+\t\t\t\t(unsigned long)stub_clone_handler_seccomp -\n+\t\t\t\t(unsigned long)__syscall_stub_start;\n+\telse\n+\t\tthread_regs.gp[REGS_IP_INDEX] = STUB_CODE +\n+\t\t\t\t(unsigned long)stub_clone_handler -\n+\t\t\t\t(unsigned long)__syscall_stub_start;\n \n \t/* syscall data as a temporary stack area (top half). */\n \tthread_regs.gp[REGS_SP_INDEX] = STUB_DATA +\n@@ -493,45 +753,55 @@ int copy_context_skas0(struct mm_id *id, struct mm_id *from)\n \t * prepare offset and fd of child's stack as argument for parent's\n \t * and child's mmap2 calls\n \t */\n-\t*data = ((struct stub_data) {\n-\t\t.offset\t= MMAP_OFFSET(new_offset),\n-\t\t.fd     = new_fd,\n-\t\t.err    = -ESRCH,\n-\t\t.child_err = 0,\n-\t});\n-\n-\t*child_data = ((struct stub_data) {\n-\t\t.child_err = -ESRCH,\n-\t});\n-\n-\terr = ptrace_setregs(from->u.pid, thread_regs.gp);\n-\tif (err < 0) {\n-\t\terr = -errno;\n-\t\tprintk(UM_KERN_ERR \"%s : PTRACE_SETREGS failed, pid = %d, errno = %d\\n\",\n-\t\t      __func__, from->u.pid, -err);\n-\t\treturn err;\n-\t}\n+\tdata->offset     = MMAP_OFFSET(new_offset);\n+\tdata->fd         = new_fd;\n+\tdata->err        = -ESRCH;\n+\tdata->child_err  = 0;\n \n-\terr = put_fp_registers(from->u.pid, thread_regs.fp);\n-\tif (err < 0) {\n-\t\tprintk(UM_KERN_ERR \"%s : put_fp_registers failed, pid = %d, err = %d\\n\",\n-\t\t       __func__, from->u.pid, err);\n-\t\treturn err;\n-\t}\n+\tchild_data->child_err = -ESRCH;\n \n-\t/*\n-\t * Wait, until parent has finished its work: read child's pid from\n-\t * parent's stack, and check, if bad result.\n-\t */\n-\terr = ptrace(PTRACE_CONT, from->u.pid, 0, 0);\n-\tif (err) {\n-\t\terr = -errno;\n-\t\tprintk(UM_KERN_ERR \"Failed to continue new process, pid = %d, errno = %d\\n\",\n-\t\t       from->u.pid, errno);\n-\t\treturn err;\n-\t}\n+\tif (using_seccomp) {\n+\t\terr = set_stub_state(&thread_regs, data, 0);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\t/* The architecture dependent state will be identical */\n+\t\tmemcpy(&child_data->arch_data, &data->arch_data, sizeof(data->arch_data));\n+\n+\t\tchild_data->futex = FUTEX_IN_CHILD;\n+\n+\t\tdata->restart_wait = 0;\n+\t\twait_stub_done_seccomp(from->u.pid, data, 0);\n+\t} else {\n+\t\terr = ptrace_setregs(from->u.pid, thread_regs.gp);\n+\t\tif (err < 0) {\n+\t\t\terr = -errno;\n+\t\t\tprintk(UM_KERN_ERR \"%s : PTRACE_SETREGS failed, pid = %d, errno = %d\\n\",\n+\t\t\t      __func__, from->u.pid, -err);\n+\t\t\treturn err;\n+\t\t}\n \n-\twait_stub_done(from->u.pid);\n+\t\terr = put_fp_registers(from->u.pid, thread_regs.fp);\n+\t\tif (err < 0) {\n+\t\t\tprintk(UM_KERN_ERR \"%s : put_fp_registers failed, pid = %d, err = %d\\n\",\n+\t\t\t       __func__, from->u.pid, err);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Wait, until parent has finished its work: read child's pid from\n+\t\t * parent's stack, and check, if bad result.\n+\t\t */\n+\t\terr = ptrace(PTRACE_CONT, from->u.pid, 0, 0);\n+\t\tif (err) {\n+\t\t\terr = -errno;\n+\t\t\tprintk(UM_KERN_ERR \"Failed to continue new process, pid = %d, errno = %d\\n\",\n+\t\t\t       from->u.pid, errno);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\twait_stub_done(from->u.pid);\n+\t}\n \n \tid->u.pid = data->err;\n \tif (id->u.pid < 0) {\n@@ -544,7 +814,11 @@ int copy_context_skas0(struct mm_id *id, struct mm_id *from)\n \t * Wait, until child has finished too: read child's result from\n \t * child's stack and check it.\n \t */\n-\twait_stub_done(id->u.pid);\n+\tif (using_seccomp)\n+\t\twait_stub_done_seccomp(id->u.pid, child_data, 1);\n+\telse\n+\t\twait_stub_done(id->u.pid);\n+\n \tif (child_data->child_err != STUB_DATA) {\n \t\tprintk(UM_KERN_ERR \"%s - stub-child %d reports error %ld\\n\",\n \t\t       __func__, id->u.pid, data->child_err);\n@@ -552,7 +826,8 @@ int copy_context_skas0(struct mm_id *id, struct mm_id *from)\n \t\tgoto out_kill;\n \t}\n \n-\tif (ptrace(PTRACE_SETOPTIONS, id->u.pid, NULL,\n+\tif (!using_seccomp &&\n+\t    ptrace(PTRACE_SETOPTIONS, id->u.pid, NULL,\n \t\t   (void *)PTRACE_O_TRACESYSGOOD) < 0) {\n \t\terr = -errno;\n \t\tprintk(UM_KERN_ERR \"%s : PTRACE_SETOPTIONS failed, errno = %d\\n\",\ndiff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c\nindex f84eb13a0b98..4dd8b959c008 100644\n--- a/arch/um/os-Linux/start_up.c\n+++ b/arch/um/os-Linux/start_up.c\n@@ -413,12 +413,9 @@ void __init os_early_checks(void)\n \tusing_seccomp = 0;\n \n \tif (init_seccomp()) {\n-\t\t/* Not fully implemented */\n-#if 0\n \t\tusing_seccomp = 1;\n \n \t\treturn;\n-#endif\n \t}\n #endif\n \n",
    "prefixes": [
        "v2",
        "27/28"
    ]
}