From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/12152 Path: news.gmane.org!.POSTED!not-for-mail From: Nicholas Wilson Newsgroups: gmane.linux.lib.musl.general Subject: [PATCH] Wasm support patch 2 (static syscalls) Date: Tue, 28 Nov 2017 12:31:18 +0000 Message-ID: Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1511872293 19701 195.159.176.226 (28 Nov 2017 12:31:33 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 28 Nov 2017 12:31:33 +0000 (UTC) To: "musl@lists.openwall.com" Original-X-From: musl-return-12168-gllmg-musl=m.gmane.org@lists.openwall.com Tue Nov 28 13:31:28 2017 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1eJf2t-0004fh-9a for gllmg-musl@m.gmane.org; Tue, 28 Nov 2017 13:31:27 +0100 Original-Received: (qmail 21962 invoked by uid 550); 28 Nov 2017 12:31:32 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 21924 invoked from network); 28 Nov 2017 12:31:31 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realvnc.onmicrosoft.com; s=selector1-realvnc-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=Xh/vxuBCSAgtcQ+mMfkkp00Tjn7j4Ob0RcL0YTdDeWU=; b=PuBW2PPxuOupkDCb33elRHsbox7q+m/eAb43emxQDlsfYMVA5N7N9am6Pz2vbgsVXClVB+xXVdV7XAEVZn5TE2cT2IzoYqfx2SMrdcZKuZWGplussBV0rGiQOhFkVjhNU6T4uegDcCUOGSEV5Z6tXteIV2VI7ofkhAJIepOIlwo= Thread-Topic: [PATCH] Wasm support patch 2 (static syscalls) Thread-Index: AQHTaEFVgDgYeA7kVEKWz4n1+gEDaA== Accept-Language: en-GB, en-US Content-Language: en-GB X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [2a02:390:a001:192:d6be:d9ff:fe9c:1892] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1;VI1PR0502MB3888;6:ayUREYmu69t65QjY/IkaMUR+c+dL7AKx48bOOKG7tJzCW/M/Mlwfj2xuejXFUJBEfFrHbkzp8PT2PjUQoMJnREAqD6AePg7mn/2wp2PsrLXyT2uyFRV5ByE7G7dPTfqQf562DHg7GQJpg47MsvpqdAcIFl6+RFWrATe5/IyRDFD4jXJIhMztBGHOyR2oIlj2Qk2W4k0V1Eo4h1HK2qRQLZD+wlyr4/yTMjmDXGAaltN9mh0cQ5q3u9+ZxoZ6h+Z1qQnSIR3euzJdVcwpSjxeb370hxNYdE4qywHnGLx7s9CCVcydxnBaRx43PLavFjWDGyvPFlvfmJma559s9R14t5PJ5AeUhbsPeLpSxtg+Zng=;5:Ji/ES2WLKV7tMLzmL5DAgocfKMCsGb4zXAJblzrEelJ50GZUSI5zR8DqNWZy3IicMqYJr1K1KHTAEfnjC0HAiCsjASd5kKfuJ/f9nRS4sG1lqAcczpn8GBuSyoszmPr/a3uTPNR77y38hsWNPwiaLQ/I72ztWdZEntqkTEW1rU4=;24:kksiEii6w/7gwli4t3x4lsUXxt1yWSTq7xkYWeTTMtgE5sk7DBKyehrdGNimRhLoIwLbvmLj5WL8JbPd7bXS6Q2AD5vUquYTVMLZof6505I=;7:Ahy0+AeN0LBIyHWL9oP6mpokgkpOLF48800bYBojgWz71vvvlQllmoYrSjDhbVro59w1CxqzT9llkwqVEM83pux3dBss kUyMWVkp6MF34Janu7KGv1Jqn0KPWUguDcdqAnca/bN6zjFmGqCVgE5icyCs1Au1n7js66Jqba5WiPOFfl6VsBxyLCt3ey9BDN x-ms-exchange-antispam-srfa-diagnostics: SSOS; x-ms-office365-filtering-correlation-id: c891206c-04d1-4561-dfd4-08d5365becb0 x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(4534020)(4602075)(4603075)(4627115)(201702281549075)(5600026)(4604075)(2017052603258);SRVR:VI1PR0502MB3888; x-ms-traffictypediagnostic: VI1PR0502MB3888: authentication-results: spf=none (sender IP is ) smtp.mailfrom=nicholas.wilson@realvnc.com; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6040450)(2401047)(8121501046)(5005006)(10201501046)(93006095)(93001095)(3231022)(3002001)(6041248)(20161123555025)(2016111802025)(20161123562025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123560025)(20161123564025)(6072148)(6043046)(201708071742011);SRVR:VI1PR0502MB3888;BCL:0;PCL:0;RULEID:(100000803101)(100110400095);SRVR:VI1PR0502MB3888; x-forefront-prvs: 0505147DDB x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(6009001)(366004)(346002)(376002)(189002)(199003)(51444003)(86362001)(575784001)(5660300001)(54356999)(3280700002)(50986999)(33656002)(97736004)(45080400002)(2351001)(478600001)(9686003)(53936002)(7696005)(5250100002)(99286004)(2501003)(55016002)(3660700001)(8936002)(14454004)(189998001)(2906002)(25786009)(68736007)(74316002)(6506006)(6916009)(316002)(6116002)(81156014)(5640700003)(81166006)(8676002)(106356001)(6436002)(1730700003)(7736002)(305945005)(105586002)(102836003)(2900100001)(101416001)(21314002);DIR:OUT;SFP:1101;SCL:1;SRVR:VI1PR0502MB3888;H:VI1PR0502MB3885.eurprd05.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; received-spf: None (protection.outlook.com: realvnc.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM X-MS-Exchange-CrossTenant-Network-Message-Id: c891206c-04d1-4561-dfd4-08d5365becb0 X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Nov 2017 12:31:18.2481 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 9ad766d3-c6a5-4458-8c58-244e7c118728 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0502MB3888 X-OriginatorOrg: realvnc.com Xref: news.gmane.org gmane.linux.lib.musl.general:12152 Archived-At: The next patch is more complicated. For WebAssembly, I think we'll want to be able to "statically link" in sysc= alls. Under the hood, Musl is basically a layer that translates calls to t= he libc API into calls to an underlying syscall API - so for Wasm we want t= o exploit that with a twist, by allowing the interpreter environment to pro= vide the syscall definitions. In order for linkage to work nicely, the syscalls need to be split out into= their own functions. I'll give a worked example. Imagine an application that calls "getpid()". This will cause "getpid.o" t= o be linked in, to provide the C API: pid_t getpid(void) { return __syscall(SYS_getpid); } On all of Musl's existing archs, the syscalls are implemented via a seven g= eneric "__syscallN" functions. The assumption is that the kernel provides a= ll syscalls. For Wasm, what I've done is made it so that the interpreter environment ins= tead provides *named* syscall functions, in this case, a "__syscall_getpid"= function. Then, at link-time, when the linker links against libc.a it's ab= le to link in to the application only the syscalls that are actually used. This keeps the changes to Musl down to an absolute minimum. We can compile = all of Musl for the Wasm target, without exclusions, including pthreads, si= gnals, I/O. All that's needed to make it link is for the application develo= per to provide an embedding environment that implements the named syscalls = that the application uses. It might be clearer when I post Patch #3 shortly, which contains my current= stab at a minimal Wasm arch. This patch just contains the code changes nee= ded to accommodate static syscall linkage. There is one wrinkle I've had to work around - by linking in *named* syscal= ls, it means that syscalls can't be called by number. There are only three = places where this is done in Musl currently (ie only three places where the= argument to "__syscall" is not one of the named "SYS_XXX" constants). 1. The "syscall" function itself. We can simply ifdef this out, that's easy= (src/misc/syscall.c) 2. The pthread_cancel() support does some fiddly stuff. For Wasm, I've just= added an ifdef again so that this isn't provided. I think that's reasonabl= y given how messy a feature it is generally, and application developers rea= lly can't expect Wasm to provide it, surely! 3. The generic "__setxid" function that wraps the "set(r)(e)(u|g)id" functi= ons. I've worked around this by tweaking it to use a simple table - a bit = clumsy, but I hope no-one minds too much? Feedback welcome, this is just really to start a dialogue about how the "st= atic syscall" model could be used in Musl. All the best, Nick diff --git a/src/internal/libc.h b/src/internal/libc.h index 5e145183..6265062d 100644 --- a/src/internal/libc.h +++ b/src/internal/libc.h @@ -55,6 +55,10 @@ void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY; #define UNLOCK(x) __unlock(x) =20 void __synccall(void (*)(void *), void *); + +typedef enum __xid { + xid_resuid, xid_resgid, xid_reuid, xid_regid, xid_uid, xid_gid +} xid_t; int __setxid(int, int, int, int); =20 extern char **__environ; diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 6d378a81..92650c45 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -26,7 +26,19 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg= _t, ...), __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t); =20 -#ifdef SYSCALL_NO_INLINE +#define __SYSCALL_CONCAT_X(a,b) a##b +#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) + +#ifdef SYSCALL_STATIC +#define __syscall0(n) __SYSCALL_CONCAT(__,n)(0) +#define __syscall1(n,a) __SYSCALL_CONCAT(__,n)(__scc(a)) +#define __syscall2(n,a,b) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(b)) +#define __syscall3(n,a,b,c) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(b),__scc= (c)) +#define __syscall4(n,a,b,c,d) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(b),__s= cc(c),__scc(d)) +#define __syscall5(n,a,b,c,d,e) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(b),_= _scc(c),__scc(d),__scc(e)) +#define __syscall6(n,a,b,c,d,e,f) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(b)= ,__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __SYSCALL_CONCAT(__,n)(__scc(a),__scc(= b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) +#elif defined SYSCALL_NO_INLINE #define __syscall0(n) (__syscall)(n) #define __syscall1(n,a) (__syscall)(n,__scc(a)) #define __syscall2(n,a,b) (__syscall)(n,__scc(a),__scc(b)) @@ -34,20 +46,20 @@ long __syscall_ret(unsigned long), __syscall(syscall_ar= g_t, ...), #define __syscall4(n,a,b,c,d) (__syscall)(n,__scc(a),__scc(b),__scc(c),__s= cc(d)) #define __syscall5(n,a,b,c,d,e) (__syscall)(n,__scc(a),__scc(b),__scc(c),_= _scc(d),__scc(e)) #define __syscall6(n,a,b,c,d,e,f) (__syscall)(n,__scc(a),__scc(b),__scc(c)= ,__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) (__syscall)(n,__scc(a),__scc(b),__scc(= c),__scc(d),__scc(e),__scc(f),__scc(g)) #else +#define __syscall0(n) __syscall0(n) #define __syscall1(n,a) __syscall1(n,__scc(a)) #define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) #define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) #define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__sc= c(d)) #define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__= scc(d),__scc(e)) #define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),= __scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __syscall7(n,__scc(a),__scc(b),__scc(c= ),__scc(d),__scc(e),__scc(f),__scc(g)) #endif -#define __syscall7(n,a,b,c,d,e,f,g) (__syscall)(n,__scc(a),__scc(b),__scc(= c),__scc(d),__scc(e),__scc(f),__scc(g)) =20 #define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n #define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0= ,) -#define __SYSCALL_CONCAT_X(a,b) a##b -#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) #define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS= __))(__VA_ARGS__) =20 #define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) @@ -56,6 +68,18 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg= _t, ...), #define socketcall __socketcall #define socketcall_cp __socketcall_cp =20 +#ifdef SYSCALL_STATIC +// For archs that define SYSCALL_STATIC (wasm), we basically just don't al= low +// for pthread_cancel(). I don't expect wasm will ever allow for cancella= ble +// waits so that's OK. +#define __syscall_cp0(n) __syscall0(n) +#define __syscall_cp1(n,a) __syscall1(n,a) +#define __syscall_cp2(n,a,b) __syscall2(n,a,b) +#define __syscall_cp3(n,a,b,c) __syscall3(n,a,b,c) +#define __syscall_cp4(n,a,b,c,d) __syscall4(n,a,b,c,d) +#define __syscall_cp5(n,a,b,c,d,e) __syscall5(n,a,b,c,d,e) +#define __syscall_cp6(n,a,b,c,d,e,f) __syscall6(n,a,b,c,d,e,f) +#else #define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0) #define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0) #define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0) @@ -63,6 +87,7 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_= t, ...), #define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(= c),__scc(d),0,0) #define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__sc= c(c),__scc(d),__scc(e),0) #define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__= scc(c),__scc(d),__scc(e),__scc(f)) +#endif =20 #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) diff --git a/src/misc/syscall.c b/src/misc/syscall.c index 9d435a97..013787a4 100644 --- a/src/misc/syscall.c +++ b/src/misc/syscall.c @@ -3,6 +3,7 @@ =20 #undef syscall =20 +#ifndef SYSCALL_STATIC long syscall(long n, ...) { va_list ap; @@ -17,3 +18,4 @@ long syscall(long n, ...) va_end(ap); return __syscall_ret(__syscall(n,a,b,c,d,e,f)); } +#endif diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 3d229223..d14d96ed 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -20,6 +20,7 @@ long __syscall_cp_asm(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t); =20 +#ifndef SYSCALL_STATIC long __syscall_cp_c(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x, syscall_arg_t y, syscall_arg_t z) @@ -38,6 +39,7 @@ long __syscall_cp_c(syscall_arg_t nr, r =3D __cancel(); return r; } +#endif =20 static void _sigaddset(sigset_t *set, int sig) { diff --git a/src/unistd/setegid.c b/src/unistd/setegid.c index e6da2573..dc2702b6 100644 --- a/src/unistd/setegid.c +++ b/src/unistd/setegid.c @@ -1,8 +1,7 @@ #include #include "libc.h" -#include "syscall.h" =20 int setegid(gid_t egid) { - return __setxid(SYS_setresgid, -1, egid, -1); + return __setxid(xid_resgid, -1, egid, -1); } diff --git a/src/unistd/seteuid.c b/src/unistd/seteuid.c index ef8b9df4..d84d6186 100644 --- a/src/unistd/seteuid.c +++ b/src/unistd/seteuid.c @@ -1,8 +1,7 @@ #include -#include "syscall.h" #include "libc.h" =20 int seteuid(uid_t euid) { - return __setxid(SYS_setresuid, -1, euid, -1); + return __setxid(xid_resuid, -1, euid, -1); } diff --git a/src/unistd/setgid.c b/src/unistd/setgid.c index bae4616a..88197ec1 100644 --- a/src/unistd/setgid.c +++ b/src/unistd/setgid.c @@ -1,8 +1,7 @@ #include -#include "syscall.h" #include "libc.h" =20 int setgid(gid_t gid) { - return __setxid(SYS_setgid, gid, 0, 0); + return __setxid(xid_gid, gid, 0, 0); } diff --git a/src/unistd/setregid.c b/src/unistd/setregid.c index f5a8972a..4729c31b 100644 --- a/src/unistd/setregid.c +++ b/src/unistd/setregid.c @@ -1,8 +1,7 @@ #include -#include "syscall.h" #include "libc.h" =20 int setregid(gid_t rgid, gid_t egid) { - return __setxid(SYS_setregid, rgid, egid, 0); + return __setxid(xid_regid, rgid, egid, 0); } diff --git a/src/unistd/setresgid.c b/src/unistd/setresgid.c index b9af540a..929bb72b 100644 --- a/src/unistd/setresgid.c +++ b/src/unistd/setresgid.c @@ -1,9 +1,8 @@ #define _GNU_SOURCE #include -#include "syscall.h" #include "libc.h" =20 int setresgid(gid_t rgid, gid_t egid, gid_t sgid) { - return __setxid(SYS_setresgid, rgid, egid, sgid); + return __setxid(xid_resgid, rgid, egid, sgid); } diff --git a/src/unistd/setresuid.c b/src/unistd/setresuid.c index 83692b4c..74b6ac33 100644 --- a/src/unistd/setresuid.c +++ b/src/unistd/setresuid.c @@ -1,9 +1,8 @@ #define _GNU_SOURCE #include -#include "syscall.h" #include "libc.h" =20 int setresuid(uid_t ruid, uid_t euid, uid_t suid) { - return __setxid(SYS_setresuid, ruid, euid, suid); + return __setxid(xid_resuid, ruid, euid, suid); } diff --git a/src/unistd/setreuid.c b/src/unistd/setreuid.c index 3fcc59e2..9b3efd6a 100644 --- a/src/unistd/setreuid.c +++ b/src/unistd/setreuid.c @@ -1,8 +1,7 @@ #include -#include "syscall.h" #include "libc.h" =20 int setreuid(uid_t ruid, uid_t euid) { - return __setxid(SYS_setreuid, ruid, euid, 0); + return __setxid(xid_reuid, ruid, euid, 0); } diff --git a/src/unistd/setuid.c b/src/unistd/setuid.c index 602ecbbf..de91d0c1 100644 --- a/src/unistd/setuid.c +++ b/src/unistd/setuid.c @@ -1,8 +1,7 @@ #include -#include "syscall.h" #include "libc.h" =20 int setuid(uid_t uid) { - return __setxid(SYS_setuid, uid, 0, 0); + return __setxid(xid_uid, uid, 0, 0); } diff --git a/src/unistd/setxid.c b/src/unistd/setxid.c index 0239f8af..6e11f507 100644 --- a/src/unistd/setxid.c +++ b/src/unistd/setxid.c @@ -6,14 +6,25 @@ =20 struct ctx { int id, eid, sid; - int nr, err; + int xid, err; }; =20 +static int setxid_syscall(int xid, int id, int eid, int sid) +{ + if (xid =3D=3D xid_resuid) return __syscall(SYS_setresuid, id, eid, sid); + if (xid =3D=3D xid_resgid) return __syscall(SYS_setresgid, id, eid, sid); + if (xid =3D=3D xid_reuid) return __syscall(SYS_setreuid, id, eid); + if (xid =3D=3D xid_regid) return __syscall(SYS_setregid, id, eid); + if (xid =3D=3D xid_uid) return __syscall(SYS_setuid, id); + if (xid =3D=3D xid_gid) return __syscall(SYS_setgid, id); + abort(); +} + static void do_setxid(void *p) { struct ctx *c =3D p; if (c->err>0) return; - int ret =3D -__syscall(c->nr, c->id, c->eid, c->sid); + int ret =3D -setxid_syscall(c->xid, c->id, c->eid, c->sid); if (ret && !c->err) { /* If one thread fails to set ids after another has already * succeeded, forcibly killing the process is the only safe @@ -25,11 +36,11 @@ static void do_setxid(void *p) c->err =3D ret; } =20 -int __setxid(int nr, int id, int eid, int sid) +int __setxid(int xid, int id, int eid, int sid) { /* err is initially nonzero so that failure of the first thread does not * trigger the safety kill above. */ - struct ctx c =3D { .nr =3D nr, .id =3D id, .eid =3D eid, .sid =3D sid, .e= rr =3D -1 }; + struct ctx c =3D { .xid =3D xid, .id =3D id, .eid =3D eid, .sid =3D sid, = .err =3D -1 }; __synccall(do_setxid, &c); if (c.err) { if (c.err>0) errno =3D c.err;