aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2020-06-26 11:41:45 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-06-26 11:41:45 +0100
commit1ef33cf08937783c36613f37e4e909267be60f73 (patch)
tree09b2434f7c5494a21e31dc650ed570011834143b
parented208107abb914d39e9e530472301f9f7a60f4c6 (diff)
downloadpseudo-1ef33cf08937783c36613f37e4e909267be60f73.tar.gz
pseudo-1ef33cf08937783c36613f37e4e909267be60f73.tar.bz2
pseudo-1ef33cf08937783c36613f37e4e909267be60f73.zip
Pseudo changes the syscall access patterns which makes it incompatible with
seccomp. Therefore intercept the seccomp syscall and alter it, pretending that seccomp was setup when in fact we do nothing. If we error as unsupported, utilities like file will exit with errors so we can't just disable it. Also, it fails to compile pseudo-native on centos 7: | ports/linux/pseudo_wrappers.c: In function ‘prctl’: | ports/linux/pseudo_wrappers.c:129:14: error: ‘SECCOMP_SET_MODE_FILTER’ undeclared (first use in this function) | if (cmd == SECCOMP_SET_MODE_FILTER) { | ^ Add macro guard for seccomp to avoid the failure. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-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 */