From patchwork Fri May 27 13:00:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 68749 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp96559qge; Fri, 27 May 2016 06:42:10 -0700 (PDT) X-Received: by 10.237.48.73 with SMTP id 67mr13896977qte.57.1464356530264; Fri, 27 May 2016 06:42:10 -0700 (PDT) Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id p129si17605580qkb.49.2016.05.27.06.42.10 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 27 May 2016 06:42:10 -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]:45888 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b6I1h-000521-Ma for patch@linaro.org; Fri, 27 May 2016 09:42:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37608) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b6HOE-0007wF-NL for qemu-devel@nongnu.org; Fri, 27 May 2016 09:01:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b6HO7-0001Lw-Di for qemu-devel@nongnu.org; Fri, 27 May 2016 09:01:21 -0400 Received: from mail-lf0-x22e.google.com ([2a00:1450:4010:c07::22e]:33372) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b6HO7-0001Lf-1N for qemu-devel@nongnu.org; Fri, 27 May 2016 09:01:15 -0400 Received: by mail-lf0-x22e.google.com with SMTP id s64so21625837lfe.0 for ; Fri, 27 May 2016 06:01:14 -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=co4uJbKFwQQ9YOj7PcD8SW/gIpAgCTD2tggQi9ua2/ffOD0zSL4v1GaZbe0hiXSxzl D/fNNW5k5yZRgB+VbnrDXowsE/CJlV7aBMBmKwBpxShFEGaUE/X8liBhEDGexSKDY8WM 8JBaNv29DcqDmOuXlY0Nufr3W8yNI8eK2En3A= 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=RZP2wwTAEI4s7IRMn8GTiuJyzb4B8OQMmpQYWWzE68UsOHNpaDZ0OeF4D75gQZTPDV b7A0BvpwDROoAk91xQb24xcrpGF5zoPyV/wAxESCbP6JfpGlA2I3wykRr4dWTTz4f4Wt P+tqyPq6zmjAYJRFGJ9jNflffY72Oto6nQNCmGbB+po4fEJc/Y53RsX+QTqj9rPqK3Sm R8nWlW4GH0bGkrF7Kymz80eOTru4SpnpbBtUXUU/ojvykPaLc3Mz3yl6KpmKu9mQ/ot3 0rJPzJYU7oQVtOAhLPoW0xVRUdKJY1tOYczTts5Qf5UzzJLq5a9Kvi33/9uIiTepodYa 9xWw== X-Gm-Message-State: ALyK8tKqhwoETmT0fQFQJdT9QznhCvFmoM7qX19r+e0e6KNIXDsB0bo6gusm11axoQ+dvruK X-Received: by 10.25.133.212 with SMTP id h203mr3681337lfd.210.1464354074157; Fri, 27 May 2016 06:01:14 -0700 (PDT) Received: from beaming.home (91-157-168-132.elisa-laajakaista.fi. [91.157.168.132]) by smtp.gmail.com with ESMTPSA id n16sm2281066lfg.31.2016.05.27.06.01.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 27 May 2016 06:01:13 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Fri, 27 May 2016 16:00:24 +0300 Message-Id: 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::22e Subject: [Qemu-devel] [PULL v2 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