aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ports/linux/portdefs.h2
-rw-r--r--ports/linux/pseudo_wrappers.c56
-rw-r--r--ports/linux/wrapfuncs.in1
3 files changed, 59 insertions, 0 deletions
diff --git a/ports/linux/portdefs.h b/ports/linux/portdefs.h
index d419365..a92e969 100644
--- a/ports/linux/portdefs.h
+++ b/ports/linux/portdefs.h
@@ -32,3 +32,5 @@ GLIBC_COMPAT_SYMBOL(memcpy,2.0);
#include <linux/capability.h>
#include <sys/syscall.h>
+#include <sys/prctl.h>
+#include <linux/seccomp.h>
diff --git a/ports/linux/pseudo_wrappers.c b/ports/linux/pseudo_wrappers.c
index cd7e173..ed34115 100644
--- a/ports/linux/pseudo_wrappers.c
+++ b/ports/linux/pseudo_wrappers.c
@@ -57,6 +57,7 @@ int pseudo_capset(cap_user_header_t hdrp, const cap_user_data_t datap) {
long
syscall(long number, ...) {
long rc = -1;
+ va_list ap;
if (!pseudo_check_wrappers() || !real_syscall) {
/* rc was initialized to the "failure" value */
@@ -77,6 +78,20 @@ syscall(long number, ...) {
(void) number;
#endif
+#ifdef SYS_seccomp
+ /* pseudo and seccomp are incompatible as pseudo uses different syscalls
+ * so pretend to enable seccomp but really do nothing */
+ if (number == SYS_seccomp) {
+ unsigned long cmd;
+ va_start(ap, number);
+ cmd = va_arg(ap, unsigned long);
+ va_end(ap);
+ if (cmd == SECCOMP_SET_MODE_FILTER) {
+ return 0;
+ }
+ }
+#endif
+
/* gcc magic to attempt to just pass these args to syscall. we have to
* guess about the number of args; the docs discuss calling conventions
* up to 7, so let's try that?
@@ -92,3 +107,44 @@ static long wrap_syscall(long nr, va_list ap) {
(void) ap;
return -1;
}
+
+int
+prctl(int option, ...) {
+ int rc = -1;
+ va_list ap;
+
+ if (!pseudo_check_wrappers() || !real_prctl) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("prctl");
+ return rc;
+ }
+
+#ifdef SECCOMP_SET_MODE_FILTER
+ /* pseudo and seccomp are incompatible as pseudo uses different syscalls
+ * so pretend to enable seccomp but really do nothing */
+ if (option == PR_SET_SECCOMP) {
+ unsigned long cmd;
+ va_start(ap, option);
+ cmd = va_arg(ap, unsigned long);
+ va_end(ap);
+ if (cmd == SECCOMP_SET_MODE_FILTER) {
+ return 0;
+ }
+ }
+#endif
+
+ /* gcc magic to attempt to just pass these args to prctl. we have to
+ * guess about the number of args; the docs discuss calling conventions
+ * up to 5, so let's try that?
+ */
+ void *res = __builtin_apply((void (*)()) real_prctl, __builtin_apply_args(), sizeof(long) * 5);
+ __builtin_return(res);
+}
+
+/* unused.
+ */
+static int wrap_prctl(int option, va_list ap) {
+ (void) option;
+ (void) ap;
+ return -1;
+}
diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in
index c5ea7c3..aae0f0d 100644
--- a/ports/linux/wrapfuncs.in
+++ b/ports/linux/wrapfuncs.in
@@ -56,3 +56,4 @@ int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbuf
int capset(cap_user_header_t hdrp, const cap_user_data_t datap); /* real_func=pseudo_capset */
long syscall(long nr, ...); /* hand_wrapped=1 */
int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags); /* flags=AT_SYMLINK_NOFOLLOW */
+int prctl(int option, ...); /* hand_wrapped=1 */