From patchwork Wed May 25 10:32:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 68568 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp1137526qge; Wed, 25 May 2016 03:51:16 -0700 (PDT) X-Received: by 10.55.72.21 with SMTP id v21mr2779614qka.44.1464173476606; Wed, 25 May 2016 03:51:16 -0700 (PDT) Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id k83si7185479qkl.280.2016.05.25.03.51.16 for (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 25 May 2016 03:51:16 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58891 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b5WPE-0000mX-3t for patch@linaro.org; Wed, 25 May 2016 06:51:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42052) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b5W7U-0001Z3-NT for qemu-devel@nongnu.org; Wed, 25 May 2016 06:33:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b5W7I-0003RD-E2 for qemu-devel@nongnu.org; Wed, 25 May 2016 06:32:55 -0400 Received: from mail-lf0-x232.google.com ([2a00:1450:4010:c07::232]:36189) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b5W7I-0003QZ-1g for qemu-devel@nongnu.org; Wed, 25 May 2016 06:32:44 -0400 Received: by mail-lf0-x232.google.com with SMTP id e130so16306361lfe.3 for ; Wed, 25 May 2016 03:32:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zXTtzmOsxmWyDLSk5mzOc1LFrdDKiJUVK+63Aez6ALc=; b=h7uVq6DOFTCB5Td5pyubLQMagsPPXH4jvxXwH5ExwtbR6Fi8BJwpgeylnsJQGUmM2y xXOoS1kKsVUXp80aGS5E5MbNf8vjq4nGbd5lVoh9aHoMIqHPhjSfSWDjF5573xKl3oL2 bvs3TP1DLRq70+nRo5ff3r0CUeOqNflhQddMM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zXTtzmOsxmWyDLSk5mzOc1LFrdDKiJUVK+63Aez6ALc=; b=Fefp8aCthawOGjMS+qIsUJwi0z1Cw9kVetOfJok85avCCzhuuV8iDj6fl6AQgnqR1D 4h1LRuEvgVgwjKdMch2xedlpxtMZhQnZqT+9vJwMqzj9Cj8ATOV+dsxNdMgApD7Y2H4U BLygnyHDxbIAV0aSUjpv76htAmuSjlnQ5iUVzY1SGTmGtonbrITuJ74+CQsQu/PfzXHK Kht2TweUZbrd5nfPj72RxuDc82h+tszjGJP7wFQuBUehPJYzTc23qXhE2pGbf82jhPHb YYdygfVkJkkY5hqq4yTugrMrL6++nZG45e5e6EV2x46z71UVdO6bz5VsOKrup7WzqE/V vMsg== X-Gm-Message-State: ALyK8tLSAfoEcObcRkDiY78QoNnu4VZBfAqXKbgnFSETTvw1nzToS271Jn5gkziG+MOZHShN X-Received: by 10.25.216.106 with SMTP id p103mr780909lfg.16.1464172363282; Wed, 25 May 2016 03:32:43 -0700 (PDT) Received: from beaming.home (91-157-168-132.elisa-laajakaista.fi. [91.157.168.132]) by smtp.gmail.com with ESMTPSA id o75sm1379610lfi.9.2016.05.25.03.32.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 25 May 2016 03:32:42 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Wed, 25 May 2016 13:32:05 +0300 Message-Id: <4c1a8a0c2883726ac717e17468ffa4ced09af4cb.1464153942.git.riku.voipio@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:4010:c07::232 Subject: [Qemu-devel] [PULL 33/38] linux-user: Use direct syscalls for setuid(), etc X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Peter Maydell On Linux the setuid(), setgid(), etc system calls have different semantics from the libc functions. The libc functions follow POSIX and update the credentials for all threads in the process; the system calls update only the thread which makes the call. (This impedance mismatch is worked around in libc by signalling all threads to tell them to do a syscall, in a byzantine and fragile way; see http://ewontfix.com/17/.) Since in linux-user we are trying to emulate the system call semantics, we must implement all these syscalls to directly call the underlying host syscall, rather than calling the host libc function. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 58 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 12 deletions(-) -- 2.1.4 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 40e8742..df70255 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5099,6 +5099,40 @@ static inline int tswapid(int id) #endif /* USE_UID16 */ +/* We must do direct syscalls for setting UID/GID, because we want to + * implement the Linux system call semantics of "change only for this thread", + * not the libc/POSIX semantics of "change for all threads in process". + * (See http://ewontfix.com/17/ for more details.) + * We use the 32-bit version of the syscalls if present; if it is not + * then either the host architecture supports 32-bit UIDs natively with + * the standard syscall, or the 16-bit UID is the best we can do. + */ +#ifdef __NR_setuid32 +#define __NR_sys_setuid __NR_setuid32 +#else +#define __NR_sys_setuid __NR_setuid +#endif +#ifdef __NR_setgid32 +#define __NR_sys_setgid __NR_setgid32 +#else +#define __NR_sys_setgid __NR_setgid +#endif +#ifdef __NR_setresuid32 +#define __NR_sys_setresuid __NR_setresuid32 +#else +#define __NR_sys_setresuid __NR_setresuid +#endif +#ifdef __NR_setresgid32 +#define __NR_sys_setresgid __NR_setresgid32 +#else +#define __NR_sys_setresgid __NR_setresgid +#endif + +_syscall1(int, sys_setuid, uid_t, uid) +_syscall1(int, sys_setgid, gid_t, gid) +_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) +_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) + void syscall_init(void) { IOCTLEntry *ie; @@ -8834,9 +8868,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setresuid case TARGET_NR_setresuid: - ret = get_errno(setresuid(low2highuid(arg1), - low2highuid(arg2), - low2highuid(arg3))); + ret = get_errno(sys_setresuid(low2highuid(arg1), + low2highuid(arg2), + low2highuid(arg3))); break; #endif #ifdef TARGET_NR_getresuid @@ -8855,9 +8889,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_getresgid case TARGET_NR_setresgid: - ret = get_errno(setresgid(low2highgid(arg1), - low2highgid(arg2), - low2highgid(arg3))); + ret = get_errno(sys_setresgid(low2highgid(arg1), + low2highgid(arg2), + low2highgid(arg3))); break; #endif #ifdef TARGET_NR_getresgid @@ -8883,10 +8917,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_setuid: - ret = get_errno(setuid(low2highuid(arg1))); + ret = get_errno(sys_setuid(low2highuid(arg1))); break; case TARGET_NR_setgid: - ret = get_errno(setgid(low2highgid(arg1))); + ret = get_errno(sys_setgid(low2highgid(arg1))); break; case TARGET_NR_setfsuid: ret = get_errno(setfsuid(arg1)); @@ -9168,7 +9202,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setresuid32 case TARGET_NR_setresuid32: - ret = get_errno(setresuid(arg1, arg2, arg3)); + ret = get_errno(sys_setresuid(arg1, arg2, arg3)); break; #endif #ifdef TARGET_NR_getresuid32 @@ -9187,7 +9221,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setresgid32 case TARGET_NR_setresgid32: - ret = get_errno(setresgid(arg1, arg2, arg3)); + ret = get_errno(sys_setresgid(arg1, arg2, arg3)); break; #endif #ifdef TARGET_NR_getresgid32 @@ -9214,12 +9248,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setuid32 case TARGET_NR_setuid32: - ret = get_errno(setuid(arg1)); + ret = get_errno(sys_setuid(arg1)); break; #endif #ifdef TARGET_NR_setgid32 case TARGET_NR_setgid32: - ret = get_errno(setgid(arg1)); + ret = get_errno(sys_setgid(arg1)); break; #endif #ifdef TARGET_NR_setfsuid32