From patchwork Wed Dec 19 04:21:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154229 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4501008ljp; Tue, 18 Dec 2018 20:26:47 -0800 (PST) X-Google-Smtp-Source: AFSGD/WoxC+zrZltrwRAGNzPfMXqsoi6NHekBPoin759n9eIHnrT8yfQlNUpI3haAuJldIpy+z0Q X-Received: by 2002:a0c:d268:: with SMTP id o37mr20097041qvh.136.1545193607203; Tue, 18 Dec 2018 20:26:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193607; cv=none; d=google.com; s=arc-20160816; b=B2D0nBxOwyjd8MVenboCbFQrC6c1XtpPlJPl/STUydOUwtACZQUms7/jFGYYzn/ahB S9r/1WILQF2YykUlaofnZ43rwk24HmOL9x4YqaAVucFHEguTwUruZ69NNlG8uRE7Tye6 7nhmv3uzfwEWXCElG0UnalhNGwiLk/8Cs7NXdafLVvS/lyfzbSee1Z5jh8EQa7GMYlWf SRjQdf65Lm0xYtli5WneynqtrfMXDv/5uEz0NMrsfbq8pp58T+OgO20VZAxbDgGfNuyd V0/tfMk5zuafGoh6tKzglsD8DlKs88do7TixF4xtMCE42yaEdl1N+HWSNIjXsXvb6r2U CBwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=OfmTfGXkwBCLR/dEJXtfzODTTIjvv42AjrKEtbmcqsE=; b=QZIbGE3DlFx+/lyQDO7r64OCjeWG1nloN6i8hCidxfix7gUWW/dLWl73FC2dKTNBwt RM+ED+Yi0/TlG85IBWsK/U/PuGjnYPDJ7TfLtLLjG9g6FPcbLsAudL/6/IcDYWv5tXTd W4PoPUCxoVxXpLjCroQPKAAgdwsKF8a/2tIX2viNa1d3nx7hA0jhx7UiZI1McgHNoRgN hzpsL1Je9WMoGdo8NrNhVlE5rTe/DPflTJ+7dw8TVL5q+BHVhPVeU+XRyUgnE+nEK7U/ a3Z8xf4wND9fa+2MXS4Bk1w+FIXM1TqOr+/bmklXt7QNfsyQWiiuQTt7aLTmkp/fLUdD 7zdg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=eGhYqlnA; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id m68si747077qkd.120.2018.12.18.20.26.46 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:26:47 -0800 (PST) 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 header.s=google header.b=eGhYqlnA; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57542 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRW-0007qC-Lo for patch@linaro.org; Tue, 18 Dec 2018 23:26:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51193) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRF-0007pt-7T for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMG-0006Ke-Fz for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:25 -0500 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]:46101) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMG-0006J2-4Q for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:20 -0500 Received: by mail-pl1-x643.google.com with SMTP id t13so8839038ply.13 for ; Tue, 18 Dec 2018 20:21:18 -0800 (PST) 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=OfmTfGXkwBCLR/dEJXtfzODTTIjvv42AjrKEtbmcqsE=; b=eGhYqlnAKzoFvjohhdzJl2dJnfmKnf/zmx9NanBX6xcP3loUvKux60icKijhWruIQZ kSsAr6+kL9XUa5EX78/8BtaAKriDRR9GDpgG09I5Nhvy8aJ5QJtyncvKC4LvHxpzW5BB +oOZFWsGmbO37wsH/Gc7PTpX1odkwkwLcm3p8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OfmTfGXkwBCLR/dEJXtfzODTTIjvv42AjrKEtbmcqsE=; b=CyZD132Bw/dDSxSa+SzK0MEeHXtjne/vIxNjFLTkcaEgqWMadaRxtBKSbG7jz5yuQe ZF+aIzVjjlKh6dkxcEc0tmaUYPa7MCxEqCJk1ZLJluLRt2+DvkztsrYTTWKr/rpNfsl4 OmkkxfAkDeibCSejT9qoV3rPHaV5ckfawBVAriP6Ouj3JyweFDJ3fqUuXU1DtNidDhBC mc04evmdtQQiXmzLE5D+7EmVEAdp95iAQO98BJtPrOsqmANIigCUIqpJNnaSfHSwCjVL gzVJm0o1CtQ0Azvi0w+91XB06verJj4MMm/dL4W74gFMWyG6qwjzbZtwSQx1p2kPuCiT V1YA== X-Gm-Message-State: AA+aEWbyXBkN+1RJOlieutsOK25rPaiFvdl3udSWTx9RURaroV1xm0HU MFwGpk8lJyjKQffYKBK65HEKZKTkbfg= X-Received: by 2002:a17:902:7044:: with SMTP id h4mr18718101plt.35.1545193277219; Tue, 18 Dec 2018 20:21:17 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:16 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:06 -0800 Message-Id: <20181219042113.7364-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::643 Subject: [Qemu-devel] [PATCH v5 1/8] linux-user: Setup split syscall infrastructure 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Defines a unified structure for implementation and strace. Signed-off-by: Richard Henderson --- linux-user/syscall.h | 89 ++++++++++ linux-user/strace.c | 388 +++++++++++++++++++++++++++++++------------ linux-user/syscall.c | 107 +++++++++++- 3 files changed, 471 insertions(+), 113 deletions(-) create mode 100644 linux-user/syscall.h -- 2.17.2 diff --git a/linux-user/syscall.h b/linux-user/syscall.h new file mode 100644 index 0000000000..43b5dc0684 --- /dev/null +++ b/linux-user/syscall.h @@ -0,0 +1,89 @@ +/* + * Linux syscalls internals + * Copyright (c) 2018 Linaro, Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef LINUX_USER_SYSCALL_H +#define LINUX_USER_SYSCALL_H 1 + +typedef struct SyscallDef SyscallDef; + +/* + * This hook extracts max 6 arguments from max 8 input registers. + * In the process, register pairs that store 64-bit arguments are merged. + * Finally, syscalls are demultipliexed; e.g. the hook for socketcall will + * return the SyscallDef for bind, listen, etc. In the process the hook + * may need to read from guest memory, or otherwise validate operands. + * On failure, set errno (to a host value) and return NULL; + * the (target adjusted) errno will be returned to the guest. + */ +typedef const SyscallDef *SyscallArgsFn(const SyscallDef *, int64_t out[6], + abi_long in[8]); + +/* This hook implements the syscall. */ +typedef abi_long SyscallImplFn(CPUArchState *, int64_t, int64_t, int64_t, + int64_t, int64_t, int64_t); + +/* This hook prints the arguments to the syscall for strace. */ +typedef void SyscallPrintFn(const SyscallDef *, int64_t arg[6]); + +/* This hook print the return value from the syscall for strace. */ +typedef void SyscallPrintRetFn(const SyscallDef *, abi_long); + +/* + * These flags describe the arguments for the generic fallback to + * SyscallPrintFn. ARG_NONE indicates that the argument is not present. + */ +typedef enum { + ARG_NONE = 0, + + /* These print as numbers of abi_long. */ + ARG_DEC, + ARG_HEX, + ARG_OCT, + + /* These print as sets of flags. */ + ARG_ATDIRFD, + ARG_MODEFLAG, + ARG_OPENFLAG, + + /* These are interpreted as pointers. */ + ARG_PTR, + ARG_STR, + ARG_BUF, + + /* For a 32-bit host, force printing as a 64-bit operand. */ +#if TARGET_ABI_BITS == 32 + ARG_DEC64, +#else + ARG_DEC64 = ARG_DEC, +#endif +} SyscallArgType; + +struct SyscallDef { + const char *name; + SyscallArgsFn *args; + SyscallImplFn *impl; + SyscallPrintFn *print; + SyscallPrintRetFn *print_ret; + SyscallArgType arg_type[6]; +}; + +void print_syscall_def(const SyscallDef *def, int64_t args[6]); +void print_syscall_def_ret(const SyscallDef *def, abi_long ret); +void print_syscall_ptr_ret(const SyscallDef *def, abi_long ret); + +#endif diff --git a/linux-user/strace.c b/linux-user/strace.c index d1d14945f9..0d9e1dc483 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -10,6 +10,7 @@ #include #include #include "qemu.h" +#include "syscall.h" int do_strace=0; @@ -796,7 +797,7 @@ UNUSED static struct flags unlinkat_flags[] = { FLAG_END, }; -UNUSED static struct flags mode_flags[] = { +static struct flags const mode_flags[] = { FLAG_GENERIC(S_IFSOCK), FLAG_GENERIC(S_IFLNK), FLAG_GENERIC(S_IFREG), @@ -807,14 +808,14 @@ UNUSED static struct flags mode_flags[] = { FLAG_END, }; -UNUSED static struct flags open_access_flags[] = { +static struct flags const open_access_flags[] = { FLAG_TARGET(O_RDONLY), FLAG_TARGET(O_WRONLY), FLAG_TARGET(O_RDWR), FLAG_END, }; -UNUSED static struct flags open_flags[] = { +static struct flags const open_flags[] = { FLAG_TARGET(O_APPEND), FLAG_TARGET(O_CREAT), FLAG_TARGET(O_DIRECTORY), @@ -989,84 +990,86 @@ get_comma(int last) return ((last) ? "" : ","); } +static int add_flags(char *buf, int size, const struct flags *f, + int flags, bool octal) +{ + const char *sep = ""; + int off = 0; + + if (flags == 0 && f->f_value == 0) { + return snprintf(buf, size, "%s", f->f_string); + } + + for (; f->f_string != NULL; f++) { + if (f->f_value != 0 && (flags & f->f_value) == f->f_value) { + off += snprintf(buf + off, size - off, "%s%s", sep, f->f_string); + flags &= ~f->f_value; + sep = "|"; + } + } + + /* Print rest of the flags as numeric. */ + if (flags) { + if (octal) { + off += snprintf(buf + off, size - off, "%s%#o", sep, flags); + } else { + off += snprintf(buf + off, size - off, "%s%#x", sep, flags); + } + } + return off; +} + static void print_flags(const struct flags *f, abi_long flags, int last) { - const char *sep = ""; - int n; + char buf[256]; + add_flags(buf, sizeof(buf), f, flags, false); + gemu_log("%s%s", buf, get_comma(last)); +} - if ((flags == 0) && (f->f_value == 0)) { - gemu_log("%s%s", f->f_string, get_comma(last)); - return; - } - for (n = 0; f->f_string != NULL; f++) { - if ((f->f_value != 0) && ((flags & f->f_value) == f->f_value)) { - gemu_log("%s%s", sep, f->f_string); - flags &= ~f->f_value; - sep = "|"; - n++; - } - } - - if (n > 0) { - /* print rest of the flags as numeric */ - if (flags != 0) { - gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last)); - } else { - gemu_log("%s", get_comma(last)); - } +static int add_atdirfd(char *buf, int size, int fd) +{ + if (fd == AT_FDCWD) { + return snprintf(buf, size, "AT_FDCWD"); } else { - /* no string version of flags found, print them in hex then */ - gemu_log("%#x%s", (unsigned int)flags, get_comma(last)); + return snprintf(buf, size, "%d", fd); } } static void print_at_dirfd(abi_long dirfd, int last) { -#ifdef AT_FDCWD - if (dirfd == AT_FDCWD) { - gemu_log("AT_FDCWD%s", get_comma(last)); - return; - } -#endif - gemu_log("%d%s", (int)dirfd, get_comma(last)); + char buf[16]; + add_atdirfd(buf, sizeof(buf), dirfd); + gemu_log("%s%s", buf, get_comma(last)); } static void print_file_mode(abi_long mode, int last) { - const char *sep = ""; - const struct flags *m; + char buf[256]; + add_flags(buf, sizeof(buf), mode_flags, mode, true); + gemu_log("%s%s", buf, get_comma(last)); +} - for (m = &mode_flags[0]; m->f_string != NULL; m++) { - if ((m->f_value & mode) == m->f_value) { - gemu_log("%s%s", m->f_string, sep); - sep = "|"; - mode &= ~m->f_value; - break; - } +static int add_open_flags(char *buf, int size, int flags) +{ + int off = add_flags(buf, size, open_access_flags, + flags & TARGET_O_ACCMODE, false); + flags &= ~TARGET_O_ACCMODE; + if (flags == 0 || off + 2 >= size) { + return off; } - - mode &= ~S_IFMT; - /* print rest of the mode as octal */ - if (mode != 0) - gemu_log("%s%#o", sep, (unsigned int)mode); - - gemu_log("%s", get_comma(last)); + buf[off++] = '|'; + return off + add_flags(buf + off, size - off, open_flags, flags, true); } static void print_open_flags(abi_long flags, int last) { - print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1); - flags &= ~TARGET_O_ACCMODE; - if (flags == 0) { - gemu_log("%s", get_comma(last)); - return; - } - gemu_log("|"); - print_flags(open_flags, flags, last); + char buf[256]; + add_open_flags(buf, sizeof(buf), flags); + gemu_log("%s%s", buf, get_comma(last)); } static void @@ -1083,48 +1086,86 @@ print_syscall_epilogue(const struct syscallname *sc) gemu_log(")"); } -static void -print_string(abi_long addr, int last) +static int add_pointer(char *buf, int size, abi_ulong addr) { - char *s; - - if ((s = lock_user_string(addr)) != NULL) { - gemu_log("\"%s\"%s", s, get_comma(last)); - unlock_user(s, addr, 0); + if (addr) { + return snprintf(buf, size, "0x" TARGET_ABI_FMT_lx, addr); } else { - /* can't get string out of it, so print it as pointer */ - print_pointer(addr, last); + return snprintf(buf, size, "NULL"); } } +static int add_string(char *buf, int size, abi_ulong addr) +{ + char *s = lock_user_string(addr); + if (s) { + /* TODO: Escape special characters within the string. */ + /* TODO: Limit the string length for logging. */ + int len = snprintf(buf, size, "\"%s\"", s); + unlock_user(s, addr, 0); + return len; + } + return add_pointer(buf, size, addr); +} + +static void +print_string(abi_long addr, int last) +{ + char buf[256]; + add_string(buf, sizeof(buf), addr); + gemu_log("%s%s", buf, get_comma(last)); +} + #define MAX_PRINT_BUF 40 + +static int add_buffer(char *buf, int size, abi_long addr, abi_ulong len) +{ + unsigned char *p; + int off = 0; + abi_ulong i; + + p = lock_user(VERIFY_READ, addr, MIN(len, MAX_PRINT_BUF), 1); + if (!p) { + return add_pointer(buf, size, addr); + } + + buf[0] = '"'; + off = 1; + + for (i = 0; i < MAX_PRINT_BUF; ++i) { + int len; + + if (isprint(p[i])) { + buf[off] = p[i]; + len = 1; + } else { + len = snprintf(buf + off, size - off, "\\%o", p[i]); + } + off += len; + if (off + 2 >= size) { + goto overflow; + } + } + unlock_user(p, addr, 0); + + if (i == len && off + 2 < size) { + buf[off] = '"'; + buf[off + 1] = 0; + return off + 1; + } + + overflow: + off = MIN(off, size - 5); + strcpy(buf + off, "...\""); + return off + 4; +} + static void print_buf(abi_long addr, abi_long len, int last) { - uint8_t *s; - int i; - - s = lock_user(VERIFY_READ, addr, len, 1); - if (s) { - gemu_log("\""); - for (i = 0; i < MAX_PRINT_BUF && i < len; i++) { - if (isprint(s[i])) { - gemu_log("%c", s[i]); - } else { - gemu_log("\\%o", s[i]); - } - } - gemu_log("\""); - if (i != len) { - gemu_log("..."); - } - if (!last) { - gemu_log(","); - } - unlock_user(s, addr, 0); - } else { - print_pointer(addr, last); - } + char buf[256]; + add_buffer(buf, sizeof(buf), addr, len); + gemu_log("%s%s", buf, get_comma(last)); } /* @@ -1143,10 +1184,9 @@ print_raw_param(const char *fmt, abi_long param, int last) static void print_pointer(abi_long p, int last) { - if (p == 0) - gemu_log("NULL%s", get_comma(last)); - else - gemu_log("0x" TARGET_ABI_FMT_lx "%s", p, get_comma(last)); + char buf[24]; + add_pointer(buf, sizeof(buf), p); + gemu_log("%s%s", buf, get_comma(last)); } /* @@ -2638,32 +2678,170 @@ print_syscall(int num, gemu_log("Unknown syscall %d\n", num); } +static void print_syscall_def1(const SyscallDef *def, int64_t args[6]) +{ + char buf[1024], *b = buf; + int i, rest = sizeof(buf); + + /* + * Render the argument list into BUF. This allows us to log the + * entire syscall in one write statement at the end. + * While this is still not quite as good as separate files, a-la + * strace -ff, it can minimize confusion with a multithreaded guest. + */ + buf[0] = 0; + for (i = 0; i < 6; ++i) { + SyscallArgType type = def->arg_type[i]; + int64_t arg = args[i]; + int len; + + if (type == ARG_NONE) { + break; + } + + /* Validate remaining space. */ + if (rest < 4) { + goto overflow; + } + + /* Add separator. */ + if (i > 0) { + b[0] = ','; + b[1] = ' '; + b += 2; + rest -= 2; + } + + switch (type) { +#if TARGET_ABI_BITS == 32 + /* + * ??? We don't have TARGET_ABI_FMT_* macros for exactly + * what we want here. For this case it probably makes + * most sense to just special case. + */ + case ARG_DEC: + len = snprintf(b, rest, "%d", (int32_t)arg); + break; + case ARG_HEX: + len = snprintf(b, rest, "%#x", (uint32_t)arg); + break; + case ARG_OCT: + len = snprintf(b, rest, "%#o", (uint32_t)arg); + break; + case ARG_DEC64: + len = snprintf(b, rest, "%" PRId64, arg); + break; +#else + case ARG_DEC: + len = snprintf(b, rest, "%" PRId64, arg); + break; + case ARG_OCT: + len = snprintf(b, rest, "%" PRIo64, arg); + break; + case ARG_HEX: + len = snprintf(b, rest, "%" PRIx64, arg); + break; +#endif + case ARG_ATDIRFD: + len = add_atdirfd(b, rest, arg); + break; + case ARG_MODEFLAG: + len = add_flags(b, rest, mode_flags, arg, true); + break; + case ARG_OPENFLAG: + len = add_open_flags(b, rest, arg); + break; + case ARG_PTR: + len = add_pointer(b, rest, arg); + break; + case ARG_STR: + len = add_string(b, rest, arg); + break; + case ARG_BUF: + len = add_buffer(b, rest, arg, MAX_PRINT_BUF); + break; + default: + g_assert_not_reached(); + } + + b += len; + rest -= len; + if (rest == 0) { + goto overflow; + } + } + goto done; + + overflow: + strcpy(buf + sizeof(buf) - 4, "..."); + done: + gemu_log("%d %s(%s)", getpid(), def->name, buf); +} + +void print_syscall_def(const SyscallDef *def, int64_t args[6]) +{ + SyscallPrintFn *print = def->print; + if (!print) { + print = print_syscall_def1; + } + print(def, args); +} + +static void print_syscall_def_ret1(const SyscallDef *def, abi_long ret) +{ + if (is_error(ret)) { + const char *errstr = target_strerror(-ret); + if (errstr) { + gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", + -ret, errstr); + } else { + gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld "\n", -ret); + } + } else { + gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); + } +} void print_syscall_ret(int num, abi_long ret) { int i; - const char *errstr = NULL; for(i=0;iprint_ret; + if (!print) { + print = print_syscall_def_ret1; + } + print(def, ret); +} + void print_taken_signal(int target_signum, const target_siginfo_t *tinfo) { /* Print the strace output for a signal being taken: diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 280137da8c..5d388ffd62 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -111,6 +111,7 @@ #include "qemu.h" #include "fd-trans.h" +#include "syscall.h" #ifndef CLONE_IO #define CLONE_IO 0x80000000 /* Clone io context */ @@ -11480,12 +11481,74 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } +/* Emit the signature for a SyscallArgsFn. */ +#define SYSCALL_ARGS(NAME) \ + static const SyscallDef *args_##NAME(const SyscallDef *def, \ + int64_t out[6], abi_long in[8]) + +/* Emit the signature for a SyscallImplFn. */ +#define SYSCALL_IMPL(NAME) \ + static abi_long impl_##NAME(CPUArchState *cpu_env, int64_t arg1, \ + int64_t arg2, int64_t arg3, int64_t arg4, \ + int64_t arg5, int64_t arg6) + + +#undef SYSCALL_IMPL +#undef SYSCALL_ARGS + +/* + * Emit the definition for a "simple" syscall. Such does not use + * SyscallArgsFn and only uses arg_type for strace. + */ +#define SYSCALL_DEF(NAME, ...) \ + static const SyscallDef def_##NAME = { \ + .name = #NAME, .impl = impl_##NAME, .arg_type = { __VA_ARGS__ } \ + } + +/* + * Emit the definition for a syscall that also has an args hook, + * and uses arg_type for strace. + */ +#define SYSCALL_DEF_ARGS(NAME, ...) \ + static const SyscallDef def_##NAME = { \ + .name = #NAME, .args = args_##NAME, .impl = impl_##NAME, \ + .arg_type = { __VA_ARGS__ } \ + } + +/* + * Emit a complete SyscallDef structure. + */ +#define SYSCALL_DEF_FULL(NAME, ...) \ + static const SyscallDef def_##NAME = { .name = #NAME, __VA_ARGS__ } + +#undef SYSCALL_DEF +#undef SYSCALL_DEF_ARGS +#undef SYSCALL_DEF_FULL + +static const SyscallDef *syscall_table(int num) +{ +#define SYSCALL_DEF(NAME, ...) case TARGET_NR_##NAME: return &def_##NAME +#define SYSCALL_DEF_ARGS(NAME, ...) SYSCALL_DEF(NAME) +#define SYSCALL_DEF_FULL(NAME, ...) SYSCALL_DEF(NAME) + + switch (num) { + } + return NULL; + +#undef SYSCALL_DEF +#undef SYSCALL_DEF_ARGS +#undef SYSCALL_DEF_FULL +} + abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { CPUState *cpu = ENV_GET_CPU(cpu_env); + const SyscallDef *def, *orig_def; + abi_long raw_args[8] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }; + int64_t out_args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 }; abi_long ret; #ifdef DEBUG_ERESTARTSYS @@ -11505,16 +11568,44 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - if (unlikely(do_strace)) { - print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); - ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8); - print_syscall_ret(num, ret); - } else { - ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8); + orig_def = def = syscall_table(num); + if (def == NULL) { + /* Unconverted. */ + if (unlikely(do_strace)) { + print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8); + print_syscall_ret(num, ret); + } else { + ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8); + } + goto fini; } + if (def->args) { + def = def->args(def, out_args, raw_args); + if (unlikely(def == NULL)) { + ret = -host_to_target_errno(errno); + if (unlikely(do_strace)) { + print_syscall_def(orig_def, out_args); + print_syscall_def_ret(orig_def, ret); + } + goto fini; + } + } + + if (unlikely(do_strace)) { + print_syscall_def(def, out_args); + ret = def->impl(cpu_env, out_args[0], out_args[1], out_args[2], + out_args[3], out_args[4], out_args[5]); + print_syscall_def_ret(def, ret); + } else { + ret = def->impl(cpu_env, out_args[0], out_args[1], out_args[2], + out_args[3], out_args[4], out_args[5]); + } + + fini: trace_guest_user_syscall_ret(cpu, num, ret); return ret; } From patchwork Wed Dec 19 04:21:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154236 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4506121ljp; Tue, 18 Dec 2018 20:34:34 -0800 (PST) X-Google-Smtp-Source: AFSGD/UUjGcng19pu1zZplVQgZUg/wH32vU9D7PUcTI3Y+VAOnJ5fGFq7tYN8Q39Kba6J5YltXMn X-Received: by 2002:ac8:2a81:: with SMTP id b1mr20658598qta.110.1545194074627; Tue, 18 Dec 2018 20:34:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545194074; cv=none; d=google.com; s=arc-20160816; b=q/T6jHIMQUdvgOJyDwOC/v1v5IozTdaeYaZXSyeftKNwg/n7zuEft3+Xq0pPLLMWs2 zjPK0z8mGDytMlu1Ht9jqJezCEuiqZOx+ymUkp+XXkP3JoSPNRiMmHJ1IdfEdV2AWdRZ N1301UQ3t4yRrZHZjFx6kS4B7RA8ID2HMn/gbcbIZSXaNYhAsGm5iHJaI68fFfPXD7ZI BfX6RgC06VsThJ/K6NJRtPd3k3NmBQRbhnG2RH5kay5qKXCRJ+aGz8pOjewEmfOAORYI m6Zxof7MtwYsOPOzHMrlLv44kBTKOUnqBXMLE9B8Uhr29JCVqe/M7yAsb0Zyb8m3qz7B I65Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=XGjyX9NLTs3IjPa45jI1L2yDtds3NxRJcixX2lTa96E=; b=zOCFCpsK41iPx7KWx2LpSh/SE95pHUsJEoIIb8+vrZODiDWw3QDqplpT/IL06vVMGh JQL3gIymZEPi0Xym/D6OILnIMhkB7D8WzvrSRshU9cLSFKySOLXaiG3GocJ+a1tVxpVc Rb5fKmEmoAxh6tjOxTSjOrUU2PPf3PCr0ovwcHzv3wWt6pU1TLV02QJezjoJjuQVs4C8 ELLaAh9AMaJ2lI7jCOOS5xzw14CkM6LjHsBGJnaoYGCD2tl04U1ikQlxTHf7NvdYZH5T LE5UWNFfpytO7ZBXbXTPN8Fz465qTwdJaQsIzNhEJ1yNdzVuKoHF8f+LmI0UpWYEbE36 MgeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=GmIO0YbR; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id j35si1289688qtc.137.2018.12.18.20.34.34 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:34:34 -0800 (PST) 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 header.s=google header.b=GmIO0YbR; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57574 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTZ4-00059n-1P for patch@linaro.org; Tue, 18 Dec 2018 23:34:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51214) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRd-0007vI-Ke for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMK-0006MT-3h for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:28 -0500 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]:33085) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMH-0006Jj-T6 for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:23 -0500 Received: by mail-pf1-x444.google.com with SMTP id c123so9213988pfb.0 for ; Tue, 18 Dec 2018 20:21:20 -0800 (PST) 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=XGjyX9NLTs3IjPa45jI1L2yDtds3NxRJcixX2lTa96E=; b=GmIO0YbRksI9G5Lww2rn5KpGqvzAI7cbA9QA3bDXQpN7yXmIq8h156dC8SvxXqwMSY D68CTgo+o7cJlPW3pRWEh1bxviGllF0VJcdQhAkAgp3sW8znCk42yqu1XZnPIpk7Clia zVGNttN5XCVlSVeRxqddiq6jBCYYcRmGqjsMg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XGjyX9NLTs3IjPa45jI1L2yDtds3NxRJcixX2lTa96E=; b=b7BCaAtry3EiRU9LgFd2W/u5UMya0FqeI0oSCkFdRxW05HI1Dd8l5+H7Xszb2iVYKH jH6MoI9RLBG2h3IkcedGwia9WnMEnqkL7IOfw+7Kqh0SXnp2L3gUwZOrBfwhslIdhZ9a ISmBbJJixPESAJJnlnfsF0yBRw1Y/dXp+WNjRzrsfR7vURy2hWZaPIkZMMwvStkW/Tsa RivlvA1tTz0Z+wEfnXo3Msc4s7v7AN0tEh4FvHjL6cMllqcMyVfJqCAYoXbHu87q4DTr e7t3bZtQaOZ58b8/jfq6WH9ppIuBPOZQ5aVBgB7Tm2wNXbwL67MXT0N6pPbofTdh4qXX 5oYQ== X-Gm-Message-State: AA+aEWY6WQZC2vaC75fJWKaboGSP1S/XSrUoJIKfdlO9Xld1WfdMexKJ PX9MfniOnBpp2vIdWF0G86ASQmV+kug= X-Received: by 2002:a62:59c9:: with SMTP id k70mr18991506pfj.243.1545193278703; Tue, 18 Dec 2018 20:21:18 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.17 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:17 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:07 -0800 Message-Id: <20181219042113.7364-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::444 Subject: [Qemu-devel] [PATCH v5 2/8] linux-user: Split out some simple file syscalls 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" This includes close, open, openat, read, readlink, readlinkat, write. Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 31 +++ linux-user/syscall-file.inc.c | 433 ++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 376 +---------------------------- 3 files changed, 468 insertions(+), 372 deletions(-) create mode 100644 linux-user/syscall-defs.h create mode 100644 linux-user/syscall-file.inc.c -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h new file mode 100644 index 0000000000..b031de1375 --- /dev/null +++ b/linux-user/syscall-defs.h @@ -0,0 +1,31 @@ +/* + * Linux syscall definitions + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +SYSCALL_DEF(close, ARG_DEC); +#ifdef TARGET_NR_open +SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); +#endif +SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); +SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC); +#ifdef TARGET_NR_readlink +SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC); +#endif +#ifdef TARGET_NR_readlinkat +SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC); +#endif +SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC); diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c new file mode 100644 index 0000000000..11e75044c1 --- /dev/null +++ b/linux-user/syscall-file.inc.c @@ -0,0 +1,433 @@ +/* + * Linux file-related syscall implementations + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Helpers for do_openat, manipulating /proc/self/foo. + */ + +static int open_self_cmdline(void *cpu_env, int fd) +{ + CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); + struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm; + int i; + + for (i = 0; i < bprm->argc; i++) { + size_t len = strlen(bprm->argv[i]) + 1; + + if (write(fd, bprm->argv[i], len) != len) { + return -1; + } + } + + return 0; +} + +static int open_self_maps(void *cpu_env, int fd) +{ + CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); + TaskState *ts = cpu->opaque; + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t read; + + fp = fopen("/proc/self/maps", "r"); + if (fp == NULL) { + return -1; + } + + while ((read = getline(&line, &len, fp)) != -1) { + int fields, dev_maj, dev_min, inode; + uint64_t min, max, offset; + char flag_r, flag_w, flag_x, flag_p; + char path[512] = ""; + fields = sscanf(line, "%" PRIx64 "-%" PRIx64 " %c%c%c%c %" + PRIx64" %x:%x %d %512s", + &min, &max, &flag_r, &flag_w, &flag_x, + &flag_p, &offset, &dev_maj, &dev_min, &inode, path); + + if ((fields < 10) || (fields > 11)) { + continue; + } + if (h2g_valid(min)) { + int flags = page_get_flags(h2g(min)); + if (!h2g_valid(max - 1)) { + max = (uintptr_t)g2h(GUEST_ADDR_MAX) + 1; + } + if (page_check_range(h2g(min), max - min, flags) == -1) { + continue; + } + if (h2g(min) == ts->info->stack_limit) { + pstrcpy(path, sizeof(path), " [stack]"); + } + dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr + " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", + h2g(min), h2g(max - 1) + 1, flag_r, flag_w, + flag_x, flag_p, offset, dev_maj, dev_min, inode, + path[0] ? " " : "", path); + } + } + + free(line); + fclose(fp); + + return 0; +} + +static int open_self_stat(void *cpu_env, int fd) +{ + CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); + TaskState *ts = cpu->opaque; + abi_ulong start_stack = ts->info->start_stack; + int i; + + for (i = 0; i < 44; i++) { + char buf[128]; + int len; + uint64_t val = 0; + + if (i == 0) { + /* pid */ + val = getpid(); + snprintf(buf, sizeof(buf), "%"PRId64 " ", val); + } else if (i == 1) { + /* app name */ + snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]); + } else if (i == 27) { + /* stack bottom */ + val = start_stack; + snprintf(buf, sizeof(buf), "%"PRId64 " ", val); + } else { + /* for the rest, there is MasterCard */ + snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' '); + } + + len = strlen(buf); + if (write(fd, buf, len) != len) { + return -1; + } + } + + return 0; +} + +static int open_self_auxv(void *cpu_env, int fd) +{ + CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); + TaskState *ts = cpu->opaque; + abi_ulong auxv = ts->info->saved_auxv; + abi_ulong len = ts->info->auxv_len; + char *ptr; + + /* + * Auxiliary vector is stored in target process stack. + * read in whole auxv vector and copy it to file + */ + ptr = lock_user(VERIFY_READ, auxv, len, 0); + if (ptr != NULL) { + while (len > 0) { + ssize_t r; + r = write(fd, ptr, len); + if (r <= 0) { + break; + } + len -= r; + ptr += r; + } + lseek(fd, 0, SEEK_SET); + unlock_user(ptr, auxv, len); + } + + return 0; +} + +static int is_proc_myself(const char *filename, const char *entry) +{ + if (!strncmp(filename, "/proc/", strlen("/proc/"))) { + filename += strlen("/proc/"); + if (!strncmp(filename, "self/", strlen("self/"))) { + filename += strlen("self/"); + } else if (*filename >= '1' && *filename <= '9') { + char myself[80]; + snprintf(myself, sizeof(myself), "%d/", getpid()); + if (!strncmp(filename, myself, strlen(myself))) { + filename += strlen(myself); + } else { + return 0; + } + } else { + return 0; + } + if (!strcmp(filename, entry)) { + return 1; + } + } + return 0; +} + +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +static int is_proc(const char *filename, const char *entry) +{ + return strcmp(filename, entry) == 0; +} + +static int open_net_route(void *cpu_env, int fd) +{ + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t read; + + fp = fopen("/proc/net/route", "r"); + if (fp == NULL) { + return -1; + } + + /* read header */ + + read = getline(&line, &len, fp); + dprintf(fd, "%s", line); + + /* read routes */ + + while ((read = getline(&line, &len, fp)) != -1) { + char iface[16]; + uint32_t dest, gw, mask; + unsigned int flags, refcnt, use, metric, mtu, window, irtt; + sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", + iface, &dest, &gw, &flags, &refcnt, &use, &metric, + &mask, &mtu, &window, &irtt); + dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", + iface, tswap32(dest), tswap32(gw), flags, refcnt, use, + metric, tswap32(mask), mtu, window, irtt); + } + + free(line); + fclose(fp); + + return 0; +} +#endif + +static abi_long do_openat(void *cpu_env, int dirfd, abi_ulong target_path, + int target_flags, int mode) +{ + struct fake_open { + const char *filename; + int (*fill)(void *cpu_env, int fd); + int (*cmp)(const char *s1, const char *s2); + }; + static const struct fake_open fakes[] = { + { "maps", open_self_maps, is_proc_myself }, + { "stat", open_self_stat, is_proc_myself }, + { "auxv", open_self_auxv, is_proc_myself }, + { "cmdline", open_self_cmdline, is_proc_myself }, +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) + { "/proc/net/route", open_net_route, is_proc }, +#endif + }; + + char *pathname = lock_user_string(target_path); + int flags = target_to_host_bitmask(target_flags, fcntl_flags_tbl); + abi_long ret; + size_t i; + + if (!pathname) { + return -TARGET_EFAULT; + } + + if (is_proc_myself(pathname, "exe")) { + ret = qemu_getauxval(AT_EXECFD); + if (ret == 0) { + ret = get_errno(safe_openat(dirfd, exec_path, flags, mode)); + } + goto done; + } + + for (i = 0; i < ARRAY_SIZE(fakes); ++i) { + if (fakes[i].cmp(pathname, fakes[i].filename)) { + const char *tmpdir; + char filename[PATH_MAX]; + + /* Create temporary file. */ + tmpdir = getenv("TMPDIR"); + if (!tmpdir) { + tmpdir = "/tmp"; + } + snprintf(filename, sizeof(filename), + "%s/qemu-open.XXXXXX", tmpdir); + ret = mkstemp(filename); + if (ret < 0) { + ret = -TARGET_ENOENT; + goto done; + } + unlink(filename); + + /* Add contents to the temporary file. */ + if (fakes[i].fill(cpu_env, ret)) { + close(ret); + ret = -TARGET_ENOENT; + goto done; + } + + lseek(ret, 0, SEEK_SET); + goto done; + } + } + + ret = get_errno(safe_openat(dirfd, path(pathname), flags, mode)); + done: + fd_trans_unregister(ret); + unlock_user(pathname, target_path, 0); + return ret; +} + +SYSCALL_IMPL(close) +{ + fd_trans_unregister(arg1); + return get_errno(close(arg1)); +} + +#ifdef TARGET_NR_open +SYSCALL_IMPL(open) +{ + return do_openat(cpu_env, AT_FDCWD, arg1, arg2, arg3); +} +#endif + +SYSCALL_IMPL(openat) +{ + return do_openat(cpu_env, arg1, arg2, arg3, arg4); +} + +SYSCALL_IMPL(read) +{ + abi_long ret; + void *p; + + if (arg3 == 0) { + return 0; + } + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_read(arg1, p, arg3)); + + if (!is_error(ret)) { + TargetFdDataFunc trans = fd_trans_host_to_target_data(arg1); + if (trans) { + ret = trans(p, ret); + } + } + unlock_user(p, arg2, ret); + return ret; +} + +static abi_long do_readlink_proc_exe(char *buf, abi_ulong bufsiz) +{ + char real[PATH_MAX]; + char *temp = realpath(exec_path, real); + abi_long ret; + + /* Return value is # of bytes that we wrote to the buffer. */ + if (temp == NULL) { + return -host_to_target_errno(errno); + } + ret = MIN(strlen(real), bufsiz); + /* We cannot NUL terminate the string. */ + memcpy(buf, real, ret); + return ret; +} + +#ifdef TARGET_NR_readlink +SYSCALL_IMPL(readlink) +{ + char *p = lock_user_string(arg1); + abi_ulong bufsiz = arg3; + void *buf = lock_user(VERIFY_WRITE, arg2, bufsiz, 0); + abi_long ret; + + if (!p || !buf) { + ret = -TARGET_EFAULT; + } else if (!bufsiz) { + /* Short circuit this for the magic exe check. */ + ret = -TARGET_EINVAL; + } else if (is_proc_myself(p, "exe")) { + ret = do_readlink_proc_exe(buf, bufsiz); + } else { + ret = get_errno(readlink(path(p), buf, bufsiz)); + } + unlock_user(buf, arg2, ret); + unlock_user(p, arg1, 0); + return ret; +} +#endif + +#ifdef TARGET_NR_readlinkat +SYSCALL_IMPL(readlinkat) +{ + char *p = lock_user_string(arg2); + abi_ulong bufsiz = arg4; + void *buf = lock_user(VERIFY_WRITE, arg3, bufsiz, 0); + abi_long ret; + + if (!p || !buf) { + ret = -TARGET_EFAULT; + } else if (!bufsiz) { + /* Short circuit this for the magic exe check. */ + ret = -TARGET_EINVAL; + } else if (is_proc_myself(p, "exe")) { + ret = do_readlink_proc_exe(buf, bufsiz); + } else { + ret = get_errno(readlinkat(arg1, path(p), buf, bufsiz)); + } + unlock_user(buf, arg3, ret); + unlock_user(p, arg2, 0); + return ret; +} +#endif + +SYSCALL_IMPL(write) +{ + TargetFdDataFunc trans; + abi_long ret; + void *p; + + if (arg2 == 0 && arg3 == 0) { + return get_errno(safe_write(arg1, 0, 0)); + } + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (!p) { + return -TARGET_EFAULT; + } + trans = fd_trans_target_to_host_data(arg1); + if (trans) { + void *copy = g_malloc(arg3); + memcpy(copy, p, arg3); + ret = trans(copy, arg3); + if (ret >= 0) { + ret = get_errno(safe_write(arg1, copy, ret)); + } + g_free(copy); + } else { + ret = get_errno(safe_write(arg1, p, arg3)); + } + unlock_user(p, arg2, 0); + return ret; +} diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5d388ffd62..7118f07441 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6538,267 +6538,6 @@ int host_to_target_waitstatus(int status) return status; } -static int open_self_cmdline(void *cpu_env, int fd) -{ - CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); - struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm; - int i; - - for (i = 0; i < bprm->argc; i++) { - size_t len = strlen(bprm->argv[i]) + 1; - - if (write(fd, bprm->argv[i], len) != len) { - return -1; - } - } - - return 0; -} - -static int open_self_maps(void *cpu_env, int fd) -{ - CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); - TaskState *ts = cpu->opaque; - FILE *fp; - char *line = NULL; - size_t len = 0; - ssize_t read; - - fp = fopen("/proc/self/maps", "r"); - if (fp == NULL) { - return -1; - } - - while ((read = getline(&line, &len, fp)) != -1) { - int fields, dev_maj, dev_min, inode; - uint64_t min, max, offset; - char flag_r, flag_w, flag_x, flag_p; - char path[512] = ""; - fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d" - " %512s", &min, &max, &flag_r, &flag_w, &flag_x, - &flag_p, &offset, &dev_maj, &dev_min, &inode, path); - - if ((fields < 10) || (fields > 11)) { - continue; - } - if (h2g_valid(min)) { - int flags = page_get_flags(h2g(min)); - max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1; - if (page_check_range(h2g(min), max - min, flags) == -1) { - continue; - } - if (h2g(min) == ts->info->stack_limit) { - pstrcpy(path, sizeof(path), " [stack]"); - } - dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr - " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", - h2g(min), h2g(max - 1) + 1, flag_r, flag_w, - flag_x, flag_p, offset, dev_maj, dev_min, inode, - path[0] ? " " : "", path); - } - } - - free(line); - fclose(fp); - - return 0; -} - -static int open_self_stat(void *cpu_env, int fd) -{ - CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); - TaskState *ts = cpu->opaque; - abi_ulong start_stack = ts->info->start_stack; - int i; - - for (i = 0; i < 44; i++) { - char buf[128]; - int len; - uint64_t val = 0; - - if (i == 0) { - /* pid */ - val = getpid(); - snprintf(buf, sizeof(buf), "%"PRId64 " ", val); - } else if (i == 1) { - /* app name */ - snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]); - } else if (i == 27) { - /* stack bottom */ - val = start_stack; - snprintf(buf, sizeof(buf), "%"PRId64 " ", val); - } else { - /* for the rest, there is MasterCard */ - snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' '); - } - - len = strlen(buf); - if (write(fd, buf, len) != len) { - return -1; - } - } - - return 0; -} - -static int open_self_auxv(void *cpu_env, int fd) -{ - CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); - TaskState *ts = cpu->opaque; - abi_ulong auxv = ts->info->saved_auxv; - abi_ulong len = ts->info->auxv_len; - char *ptr; - - /* - * Auxiliary vector is stored in target process stack. - * read in whole auxv vector and copy it to file - */ - ptr = lock_user(VERIFY_READ, auxv, len, 0); - if (ptr != NULL) { - while (len > 0) { - ssize_t r; - r = write(fd, ptr, len); - if (r <= 0) { - break; - } - len -= r; - ptr += r; - } - lseek(fd, 0, SEEK_SET); - unlock_user(ptr, auxv, len); - } - - return 0; -} - -static int is_proc_myself(const char *filename, const char *entry) -{ - if (!strncmp(filename, "/proc/", strlen("/proc/"))) { - filename += strlen("/proc/"); - if (!strncmp(filename, "self/", strlen("self/"))) { - filename += strlen("self/"); - } else if (*filename >= '1' && *filename <= '9') { - char myself[80]; - snprintf(myself, sizeof(myself), "%d/", getpid()); - if (!strncmp(filename, myself, strlen(myself))) { - filename += strlen(myself); - } else { - return 0; - } - } else { - return 0; - } - if (!strcmp(filename, entry)) { - return 1; - } - } - return 0; -} - -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) -static int is_proc(const char *filename, const char *entry) -{ - return strcmp(filename, entry) == 0; -} - -static int open_net_route(void *cpu_env, int fd) -{ - FILE *fp; - char *line = NULL; - size_t len = 0; - ssize_t read; - - fp = fopen("/proc/net/route", "r"); - if (fp == NULL) { - return -1; - } - - /* read header */ - - read = getline(&line, &len, fp); - dprintf(fd, "%s", line); - - /* read routes */ - - while ((read = getline(&line, &len, fp)) != -1) { - char iface[16]; - uint32_t dest, gw, mask; - unsigned int flags, refcnt, use, metric, mtu, window, irtt; - sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", - iface, &dest, &gw, &flags, &refcnt, &use, &metric, - &mask, &mtu, &window, &irtt); - dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", - iface, tswap32(dest), tswap32(gw), flags, refcnt, use, - metric, tswap32(mask), mtu, window, irtt); - } - - free(line); - fclose(fp); - - return 0; -} -#endif - -static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode) -{ - struct fake_open { - const char *filename; - int (*fill)(void *cpu_env, int fd); - int (*cmp)(const char *s1, const char *s2); - }; - const struct fake_open *fake_open; - static const struct fake_open fakes[] = { - { "maps", open_self_maps, is_proc_myself }, - { "stat", open_self_stat, is_proc_myself }, - { "auxv", open_self_auxv, is_proc_myself }, - { "cmdline", open_self_cmdline, is_proc_myself }, -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) - { "/proc/net/route", open_net_route, is_proc }, -#endif - { NULL, NULL, NULL } - }; - - if (is_proc_myself(pathname, "exe")) { - int execfd = qemu_getauxval(AT_EXECFD); - return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode); - } - - for (fake_open = fakes; fake_open->filename; fake_open++) { - if (fake_open->cmp(pathname, fake_open->filename)) { - break; - } - } - - if (fake_open->filename) { - const char *tmpdir; - char filename[PATH_MAX]; - int fd, r; - - /* create temporary file to map stat to */ - tmpdir = getenv("TMPDIR"); - if (!tmpdir) - tmpdir = "/tmp"; - snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir); - fd = mkstemp(filename); - if (fd < 0) { - return fd; - } - unlink(filename); - - if ((r = fake_open->fill(cpu_env, fd))) { - int e = errno; - close(fd); - errno = e; - return r; - } - lseek(fd, 0, SEEK_SET); - - return fd; - } - - return safe_openat(dirfd, path(pathname), flags, mode); -} - #define TIMER_MAGIC 0x0caf0000 #define TIMER_MAGIC_MASK 0xffff0000 @@ -6948,60 +6687,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, preexit_cleanup(cpu_env, arg1); _exit(arg1); return 0; /* avoid warning */ - case TARGET_NR_read: - if (arg3 == 0) { - return 0; - } else { - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - return -TARGET_EFAULT; - ret = get_errno(safe_read(arg1, p, arg3)); - if (ret >= 0 && - fd_trans_host_to_target_data(arg1)) { - ret = fd_trans_host_to_target_data(arg1)(p, ret); - } - unlock_user(p, arg2, ret); - } - return ret; - case TARGET_NR_write: - if (arg2 == 0 && arg3 == 0) { - return get_errno(safe_write(arg1, 0, 0)); - } - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - return -TARGET_EFAULT; - if (fd_trans_target_to_host_data(arg1)) { - void *copy = g_malloc(arg3); - memcpy(copy, p, arg3); - ret = fd_trans_target_to_host_data(arg1)(copy, arg3); - if (ret >= 0) { - ret = get_errno(safe_write(arg1, copy, ret)); - } - g_free(copy); - } else { - ret = get_errno(safe_write(arg1, p, arg3)); - } - unlock_user(p, arg2, 0); - return ret; - -#ifdef TARGET_NR_open - case TARGET_NR_open: - if (!(p = lock_user_string(arg1))) - return -TARGET_EFAULT; - ret = get_errno(do_openat(cpu_env, AT_FDCWD, p, - target_to_host_bitmask(arg2, fcntl_flags_tbl), - arg3)); - fd_trans_unregister(ret); - unlock_user(p, arg1, 0); - return ret; -#endif - case TARGET_NR_openat: - if (!(p = lock_user_string(arg2))) - return -TARGET_EFAULT; - ret = get_errno(do_openat(cpu_env, arg1, p, - target_to_host_bitmask(arg3, fcntl_flags_tbl), - arg4)); - fd_trans_unregister(ret); - unlock_user(p, arg2, 0); - return ret; #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) case TARGET_NR_name_to_handle_at: ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5); @@ -7013,10 +6698,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, fd_trans_unregister(ret); return ret; #endif - case TARGET_NR_close: - fd_trans_unregister(arg1); - return get_errno(close(arg1)); - case TARGET_NR_brk: return do_brk(arg1); #ifdef TARGET_NR_fork @@ -8292,59 +7973,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif -#ifdef TARGET_NR_readlink - case TARGET_NR_readlink: - { - void *p2; - p = lock_user_string(arg1); - p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); - if (!p || !p2) { - ret = -TARGET_EFAULT; - } else if (!arg3) { - /* Short circuit this for the magic exe check. */ - ret = -TARGET_EINVAL; - } else if (is_proc_myself((const char *)p, "exe")) { - char real[PATH_MAX], *temp; - temp = realpath(exec_path, real); - /* Return value is # of bytes that we wrote to the buffer. */ - if (temp == NULL) { - ret = get_errno(-1); - } else { - /* Don't worry about sign mismatch as earlier mapping - * logic would have thrown a bad address error. */ - ret = MIN(strlen(real), arg3); - /* We cannot NUL terminate the string. */ - memcpy(p2, real, ret); - } - } else { - ret = get_errno(readlink(path(p), p2, arg3)); - } - unlock_user(p2, arg2, ret); - unlock_user(p, arg1, 0); - } - return ret; -#endif -#if defined(TARGET_NR_readlinkat) - case TARGET_NR_readlinkat: - { - void *p2; - p = lock_user_string(arg2); - p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); - if (!p || !p2) { - ret = -TARGET_EFAULT; - } else if (is_proc_myself((const char *)p, "exe")) { - char real[PATH_MAX], *temp; - temp = realpath(exec_path, real); - ret = temp == NULL ? get_errno(-1) : strlen(real) ; - snprintf((char *)p2, arg4, "%s", real); - } else { - ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); - } - unlock_user(p2, arg3, ret); - unlock_user(p, arg2, 0); - } - return ret; -#endif #ifdef TARGET_NR_swapon case TARGET_NR_swapon: if (!(p = lock_user_string(arg1))) @@ -11492,6 +11120,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, int64_t arg2, int64_t arg3, int64_t arg4, \ int64_t arg5, int64_t arg6) +#include "syscall-file.inc.c" #undef SYSCALL_IMPL #undef SYSCALL_ARGS @@ -11521,6 +11150,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #define SYSCALL_DEF_FULL(NAME, ...) \ static const SyscallDef def_##NAME = { .name = #NAME, __VA_ARGS__ } +#include "syscall-defs.h" + #undef SYSCALL_DEF #undef SYSCALL_DEF_ARGS #undef SYSCALL_DEF_FULL @@ -11532,6 +11163,7 @@ static const SyscallDef *syscall_table(int num) #define SYSCALL_DEF_FULL(NAME, ...) SYSCALL_DEF(NAME) switch (num) { +#include "syscall-defs.h" } return NULL; From patchwork Wed Dec 19 04:21:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154237 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4506209ljp; Tue, 18 Dec 2018 20:34:45 -0800 (PST) X-Google-Smtp-Source: AFSGD/U4CLAROAqsJrfr+weol3KqILE4KJqn9veelsfRZ7fNAoX46P7h3huixMCnN3r2n2VmgYPk X-Received: by 2002:aed:2803:: with SMTP id r3mr19817347qtd.316.1545194085861; Tue, 18 Dec 2018 20:34:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545194085; cv=none; d=google.com; s=arc-20160816; b=OK5mJZhR49l4HBA8uEEI08bSuJCfq9PPx9ih5G4eNGQwZZcpFxNxY+ZhXWw8A7peZi 53J+ZXJ6zCbCA2PXBbL5H3hz65Xf2YwDHL3E0K0anpn2geUYxXnZomX6a0OTFEUx/slu dAKaV899U2oNA2e4GWdr8xWnMONYBU0jXEXeeImXlOcFLZ+KStcUMjey+kYTkoyqjszp /9yMZl53wKVK+ZKRUxga/eZcFRMUek8bRRUmaM9eCtZ1fQ+qbrC2wBnNbtH77INZnGwd R0QnBTiOHKxlZQzAyDTwr/G1NDbPz0uhhRpIcY92GncuKNJ4p+IbU1ESZtx3ZiOuPQ/u QSVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=jzabKvrmTWISY3KB/ab08L0zuoOLLDdoLb1OMab5kDU=; b=gFp7wQXLe9At9WXIMsbi8uliV0VN4z1TeoXCETDgXXdY20UucEyVc5AKfhyAqC9xUz 0ZbYcG9/rlhyu6LCApApoa0mQ86nmlL9t505PYhukhxk3P7Ikei4Da93gwG3xMo4lysq TjQbCetf/BWFUaDPIhsSHEiPeOHyxfYNIjncVohtPX1t3zXRTp3eolRkG8Tp/0PmU5L5 hB2mrJlBa0tgKNj5RF02Tg+MNF80LHjeNlYpz991q2fSCLP43qt3jDYr4C0wJrH+axGp 170YXpm67qKLgwWYBJF9xYjKieU3QCUmv157gcxSlRkilHImRKqfO1PDhfU/t2FSd1Mk tEaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=WeK7t7C3; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id c29si1252687qte.8.2018.12.18.20.34.45 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:34:45 -0800 (PST) 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 header.s=google header.b=WeK7t7C3; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57575 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTZF-0005IJ-B0 for patch@linaro.org; Tue, 18 Dec 2018 23:34:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51242) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRd-0007wa-Lk for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTML-0006Mz-3E for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:25 -0500 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]:41468) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMJ-0006Km-Iy for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:23 -0500 Received: by mail-pl1-x642.google.com with SMTP id u6so8851156plm.8 for ; Tue, 18 Dec 2018 20:21:21 -0800 (PST) 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=jzabKvrmTWISY3KB/ab08L0zuoOLLDdoLb1OMab5kDU=; b=WeK7t7C30rVzlfptIN9x1dEOq1B1ZU1xEqIWpZl9glKj00kRa7bWTUKvFyJmtdzGDt pacZrMoAdQ6TgYw/2oQ1t4l4NzsjMVaFiavA1yQaX+W3LIpj0go0R5AAiElHs31eCTbm i83HfEjBozV13Aw4A1m8wsZj3QL3387XwG3g4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jzabKvrmTWISY3KB/ab08L0zuoOLLDdoLb1OMab5kDU=; b=H2hEI2sz255Wf26tBt36nM00a6DKEfdgYuiklxziHr5eqaaaHlniClXpOrBrI5BNXa QLhvbwXmAaZ8y7Oq+/wTIoX830KFUncLacihlUyqAEzkpzr0rYDykxXV3k5tRGoTVdOl x3aFSPZpHgVS2ZmV6ABGJnEXSUebVlZgnQvB3gGaBN6aBCjfGdL/3Lm6KC0dfOu6z3c/ yX74uNWqXnAlgtZBnbD0aGSphHdyfgHGoV2NNXEWoAWCkxJ41H4Dpy0IJtc/dDXQevcE cMSqCg0ncz88nPBoSgjjhnUgSURNmd4yrTWwfGWLkvSwbd52VLSW4oPon7wa0lXVT5bM U8aQ== X-Gm-Message-State: AA+aEWZpqjCp+1z37b+z/Jruw3cF2o5sunrsMlRJ8ccpobygLEJia9i1 mz1XxYDB3+KG8ya9Rai5Rnim2esZuUU= X-Received: by 2002:a17:902:66e6:: with SMTP id e93mr18437607plk.92.1545193279831; Tue, 18 Dec 2018 20:21:19 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:19 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:08 -0800 Message-Id: <20181219042113.7364-4-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::642 Subject: [Qemu-devel] [PATCH v5 3/8] linux-user: Reduce regpairs_aligned & target_offset64 ifdefs 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- linux-user/syscall.c | 54 ++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 29 deletions(-) -- 2.17.2 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7118f07441..d4c11c3e93 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -474,37 +474,38 @@ static inline int next_free_host_timer(void) } #endif -/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +/* + * Returns true if syscall NUM expects 64bit types aligned even + * on pairs of registers. + */ +static inline bool regpairs_aligned(void *cpu_env, int num) +{ #ifdef TARGET_ARM -static inline int regpairs_aligned(void *cpu_env, int num) -{ - return ((((CPUARMState *)cpu_env)->eabi) == 1) ; -} -#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } + return ((CPUARMState *)cpu_env)->eabi; +#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32 + return true; #elif defined(TARGET_PPC) && !defined(TARGET_PPC64) -/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs - * of registers which translates to the same as ARM/MIPS, because we start with - * r3 as arg1 */ -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } + /* + * SysV AVI for PPC32 expects 64bit parameters to be passed on + * odd/even pairs of registers which translates to the same as + * we start with r3 as arg1. + */ + return true; #elif defined(TARGET_SH4) -/* SH4 doesn't align register pairs, except for p{read,write}64 */ -static inline int regpairs_aligned(void *cpu_env, int num) -{ + /* SH4 doesn't align register pairs, except for p{read,write}64. */ switch (num) { case TARGET_NR_pread64: case TARGET_NR_pwrite64: - return 1; - + return true; default: - return 0; + return false; } -} #elif defined(TARGET_XTENSA) -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } + return true; #else -static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } + return false; #endif +} #define ERRNO_TABLE_SIZE 1200 @@ -6066,21 +6067,16 @@ void syscall_init(void) } } -#if TARGET_ABI_BITS == 32 -static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) +static inline uint64_t target_offset64(abi_ulong word0, abi_ulong word1) { -#ifdef TARGET_WORDS_BIGENDIAN +#if TARGET_ABI_BITS == 64 + return word0; +#elif defined(TARGET_WORDS_BIGENDIAN) return ((uint64_t)word0 << 32) | word1; #else return ((uint64_t)word1 << 32) | word0; #endif } -#else /* TARGET_ABI_BITS == 32 */ -static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) -{ - return word0; -} -#endif /* TARGET_ABI_BITS != 32 */ #ifdef TARGET_NR_truncate64 static inline abi_long target_truncate64(void *cpu_env, const char *arg1, From patchwork Wed Dec 19 04:21:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154234 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4503231ljp; Tue, 18 Dec 2018 20:30:23 -0800 (PST) X-Google-Smtp-Source: AFSGD/W8Wjh89ZCx1g3f3walm384IjlRdJHjsJaZg4L5v0yiAvzeNTIhzunkwkLOsQrq1Ne7As90 X-Received: by 2002:a37:5189:: with SMTP id f131mr3759539qkb.309.1545193823060; Tue, 18 Dec 2018 20:30:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193823; cv=none; d=google.com; s=arc-20160816; b=jf/n3YD9pmcWvR4GfvQ6Oie8fiAuyBHJK2nJio3mjtWt4AUVRNWrtxZPg9opKw3oAc WIjlwlyy/MtuHfA+YeZ9z73mGpvnHHDuOw2pmoXiRWRWOq+YICdrj4CFWwj+p034pLvs 13UifQjFieI6YUsQHufB/t1CXyxJd5BrVlSWu12oW1EnEUMub3qQhc0O+DpJRZBON+xv iEZX354C8GKUQ7KD1jxDWHjScQJVgv+Dq7lSsdLg4JpTvaAm2L0d4JSwwY8S/pGpensj oqAWKpXyqPnAHqj3xVO54CbkOV8oRL7JpKTUmzMJpbhkdrUwhjtzKPwkPa79wfop8++g 4t7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=a9DSFdR7AYYRCK7akqnANM9Ri/qYpVRaqeI+N+gswSE=; b=PfVgfPHh6Arvrp1aWBsVUXgQ0Itl+7Zd1DDwQKpLdmSpl/OKwbLTtLa0CVcGAdbR8a I3BKyqaVeG0ypYMaU+gERSyPpICEy7ZRWpGhl2McPry3FWZ5JB+jB3TCEQrwmikFlxBR Gj/nw7AICLhY1TTjEx1pfrxB4AlSlGC3fLXOFBvV2JX6P+jUa5i0jN2jRy8Lw2BPL0aB Ofn8UJs8yOenq/oWUor6PGbgAEYXjxImFPSYkY+If38V5HSg8dFUKFk1PzgH0bVYLaZ4 xZPyKexaVbRmkm0on/ZvXAkKS9eLLU/OY32L3KgnqOxMAT81Kt51wyQNl/kG5QqjMKWh jJvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=TyUKkirh; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 10si1299926qto.215.2018.12.18.20.30.22 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:30:23 -0800 (PST) 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 header.s=google header.b=TyUKkirh; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57558 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTV0-0002NT-Ea for patch@linaro.org; Tue, 18 Dec 2018 23:30:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51221) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRa-0007vd-3t for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMM-0006Nk-1J for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:28 -0500 Received: from mail-pf1-x443.google.com ([2607:f8b0:4864:20::443]:39124) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMJ-0006L5-ST for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:24 -0500 Received: by mail-pf1-x443.google.com with SMTP id r136so2142561pfc.6 for ; Tue, 18 Dec 2018 20:21:22 -0800 (PST) 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=a9DSFdR7AYYRCK7akqnANM9Ri/qYpVRaqeI+N+gswSE=; b=TyUKkirha1CXt0IFWLA95h9OK6svcqejfNSzr3G1LEDSho1F4YnHcOlQBug9chIE1q NE/YR+sflrlhGmK0ApMqTR4oadXADLlD68H/W6yuse3fTaEFXuCspd76VuTBNEwcvHk6 dlbDozH7Xshurweqtz+nS0gUw9pDOaXTaK5ig= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=a9DSFdR7AYYRCK7akqnANM9Ri/qYpVRaqeI+N+gswSE=; b=XZFmXpxu9PrEegKQCZjJof2lfKi47FqN2uAi3PQVkaJvKxaO8nzNv3vAFY4Zguwibv AzXyDYqqlXOtwk9f8TAFE+b9HdxkU1k5P/B0CnZsKGs85NfsjXsebOlpDL4zBMHbL8gq 9DZSEW+egNb0l0gUEbWOgd11YEfc6/uf1xRHevWsI15MqShnzwc2oVTflkUq2IhQXMtq DAKgJN5KBlxqGLLQ5Qys/knCmAZ/SHAb78SbUjB1c7d/qRcOkFFhUXPbZloeH4SM235r POUMP5qnpKWjuL/BQ7obsDHH8E6qD/PL2hVRQALcMSThpoAXxNYBbiLxCNwhhbhrBldO OGQw== X-Gm-Message-State: AA+aEWZWPlvcBVoV+McSUT2eEdayQd9EjY1VL+yXo8Vx709ewb/NXa4s SIshOSht4UZCEJZPfldd33ugIokJok4= X-Received: by 2002:a63:3507:: with SMTP id c7mr18324739pga.315.1545193280917; Tue, 18 Dec 2018 20:21:20 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.19 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:20 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:09 -0800 Message-Id: <20181219042113.7364-5-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::443 Subject: [Qemu-devel] [PATCH v5 4/8] linux-user: Split out preadv, pwritev, readv, writev, pread64, pwrite64 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 14 ++++ linux-user/syscall-file.inc.c | 124 ++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 93 ------------------------- linux-user/strace.list | 18 ----- 4 files changed, 138 insertions(+), 111 deletions(-) -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index b031de1375..ae89be0e87 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -21,6 +21,18 @@ SYSCALL_DEF(close, ARG_DEC); SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); #endif SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); +SYSCALL_DEF_FULL(pread64, .impl = impl_pread64, + .args = args_pread64_pwrite64, + .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); +SYSCALL_DEF_FULL(pwrite64, .impl = impl_pwrite64, + .args = args_pread64_pwrite64, + .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); +SYSCALL_DEF_FULL(preadv, .impl = impl_preadv, + .args = args_preadv_pwritev, + .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); +SYSCALL_DEF_FULL(pwritev, .impl = impl_pwritev, + .args = args_preadv_pwritev, + .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); SYSCALL_DEF(read, ARG_DEC, ARG_PTR, ARG_DEC); #ifdef TARGET_NR_readlink SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC); @@ -28,4 +40,6 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC); #ifdef TARGET_NR_readlinkat SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC); #endif +SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC); SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC); +SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC); diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c index 11e75044c1..410a763eee 100644 --- a/linux-user/syscall-file.inc.c +++ b/linux-user/syscall-file.inc.c @@ -315,6 +315,104 @@ SYSCALL_IMPL(openat) return do_openat(cpu_env, arg1, arg2, arg3, arg4); } +/* + * Both pread64 and pwrite64 merge args into a 64-bit offset, + * but the input registers and ordering are target specific. + */ +#if TARGET_ABI_BITS == 32 +SYSCALL_ARGS(pread64_pwrite64) +{ + /* We have already assigned out[0-2]. */ + int off = regpairs_aligned(cpu_env, TARGET_NR_pread64); + out[3] = target_offset64(in[3 + off], in[4 + off]); + return def; +} +#else +#define args_pread64_pwrite64 NULL +#endif + +SYSCALL_IMPL(pread64) +{ + void *p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + abi_long ret; + + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(pread64(arg1, p, arg3, arg4)); + unlock_user(p, arg2, ret); + return ret; +} + +SYSCALL_IMPL(pwrite64) +{ + void *p = lock_user(VERIFY_READ, arg2, arg3, 0); + abi_long ret; + + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(pwrite64(arg1, p, arg3, arg4)); + unlock_user(p, arg2, 0); + return ret; +} + +/* + * Both preadv and pwritev merge args 4/5 into a 64-bit offset. + * Moreover, the parts are *always* in little-endian order. + */ +#if TARGET_ABI_BITS == 32 +SYSCALL_ARGS(preadv_pwritev) +{ + /* We have already assigned out[0-2]. */ + abi_ulong lo = in[3], hi = in[4]; + out[3] = ((hi << (TARGET_ABI_BITS - 1)) << 1) | lo; + return def; +} +#else +#define args_preadv_pwritev NULL +#endif + +/* Perform the inverse operation for the host. */ +static inline void host_offset64_low_high(unsigned long *l, unsigned long *h, + uint64_t off) +{ + *l = off; + *h = (off >> (HOST_LONG_BITS - 1)) >> 1; +} + +SYSCALL_IMPL(preadv) +{ + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); + unsigned long lo, hi; + abi_long ret; + + if (vec == NULL) { + return -host_to_target_errno(errno); + } + + host_offset64_low_high(&lo, &hi, arg4); + ret = get_errno(safe_preadv(arg1, vec, arg3, lo, hi)); + unlock_iovec(vec, arg2, arg3, 1); + return ret; +} + +SYSCALL_IMPL(pwritev) +{ + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + unsigned long lo, hi; + abi_long ret; + + if (vec == NULL) { + ret = -host_to_target_errno(errno); + } + + host_offset64_low_high(&lo, &hi, arg4); + ret = get_errno(safe_pwritev(arg1, vec, arg3, lo, hi)); + unlock_iovec(vec, arg2, arg3, 0); + return ret; +} + SYSCALL_IMPL(read) { abi_long ret; @@ -403,6 +501,19 @@ SYSCALL_IMPL(readlinkat) } #endif +SYSCALL_IMPL(readv) +{ + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); + abi_long ret; + + if (vec == NULL) { + return -host_to_target_errno(errno); + } + ret = get_errno(safe_readv(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 1); + return ret; +} + SYSCALL_IMPL(write) { TargetFdDataFunc trans; @@ -431,3 +542,16 @@ SYSCALL_IMPL(write) unlock_user(p, arg2, 0); return ret; } + +SYSCALL_IMPL(writev) +{ + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + abi_long ret; + + if (vec == NULL) { + return -host_to_target_errno(errno); + } + ret = get_errno(safe_writev(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 0); + return ret; +} diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d4c11c3e93..9a9b6c543c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2364,23 +2364,6 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, return ret; } -/* Convert target low/high pair representing file offset into the host - * low/high pair. This function doesn't handle offsets bigger than 64 bits - * as the kernel doesn't handle them either. - */ -static void target_to_host_low_high(abi_ulong tlow, - abi_ulong thigh, - unsigned long *hlow, - unsigned long *hhigh) -{ - uint64_t off = tlow | - ((unsigned long long)thigh << TARGET_LONG_BITS / 2) << - TARGET_LONG_BITS / 2; - - *hlow = off; - *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2; -} - static struct iovec *lock_iovec(int type, abi_ulong target_addr, abi_ulong count, int copy) { @@ -8910,60 +8893,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, /* NOTE: the flock constant seems to be the same for every Linux platform */ return get_errno(safe_flock(arg1, arg2)); - case TARGET_NR_readv: - { - struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); - if (vec != NULL) { - ret = get_errno(safe_readv(arg1, vec, arg3)); - unlock_iovec(vec, arg2, arg3, 1); - } else { - ret = -host_to_target_errno(errno); - } - } - return ret; - case TARGET_NR_writev: - { - struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); - if (vec != NULL) { - ret = get_errno(safe_writev(arg1, vec, arg3)); - unlock_iovec(vec, arg2, arg3, 0); - } else { - ret = -host_to_target_errno(errno); - } - } - return ret; -#if defined(TARGET_NR_preadv) - case TARGET_NR_preadv: - { - struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); - if (vec != NULL) { - unsigned long low, high; - - target_to_host_low_high(arg4, arg5, &low, &high); - ret = get_errno(safe_preadv(arg1, vec, arg3, low, high)); - unlock_iovec(vec, arg2, arg3, 1); - } else { - ret = -host_to_target_errno(errno); - } - } - return ret; -#endif -#if defined(TARGET_NR_pwritev) - case TARGET_NR_pwritev: - { - struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); - if (vec != NULL) { - unsigned long low, high; - - target_to_host_low_high(arg4, arg5, &low, &high); - ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high)); - unlock_iovec(vec, arg2, arg3, 0); - } else { - ret = -host_to_target_errno(errno); - } - } - return ret; -#endif case TARGET_NR_getsid: return get_errno(getsid(arg1)); #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ @@ -9295,28 +9224,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #else #error unreachable #endif -#endif -#ifdef TARGET_NR_pread64 - case TARGET_NR_pread64: - if (regpairs_aligned(cpu_env, num)) { - arg4 = arg5; - arg5 = arg6; - } - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - return -TARGET_EFAULT; - ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); - unlock_user(p, arg2, ret); - return ret; - case TARGET_NR_pwrite64: - if (regpairs_aligned(cpu_env, num)) { - arg4 = arg5; - arg5 = arg6; - } - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - return -TARGET_EFAULT; - ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); - unlock_user(p, arg2, 0); - return ret; #endif case TARGET_NR_getcwd: if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0))) diff --git a/linux-user/strace.list b/linux-user/strace.list index ff8bb19f5f..8f96b7a105 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1034,12 +1034,6 @@ #ifdef TARGET_NR_prctl { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_pread64 -{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_preadv -{ TARGET_NR_preadv, "preadv" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_prlimit64 { TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL }, #endif @@ -1064,12 +1058,6 @@ #ifdef TARGET_NR_putpmsg { TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_pwrite64 -{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_pwritev -{ TARGET_NR_pwritev, "pwritev" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_query_module { TARGET_NR_query_module, "query_module" , NULL, NULL, NULL }, #endif @@ -1091,9 +1079,6 @@ #ifdef TARGET_NR_readlinkat { TARGET_NR_readlinkat, "readlinkat" , NULL, print_readlinkat, NULL }, #endif -#ifdef TARGET_NR_readv -{ TARGET_NR_readv, "readv" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_reboot { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL }, #endif @@ -1629,9 +1614,6 @@ #ifdef TARGET_NR_write { TARGET_NR_write, "write" , "%s(%d,%#x,%d)", NULL, NULL }, #endif -#ifdef TARGET_NR_writev -{ TARGET_NR_writev, "writev" , "%s(%d,%p,%#x)", NULL, NULL }, -#endif #ifdef TARGET_NR_utimensat { TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL }, #endif From patchwork Wed Dec 19 04:21:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154233 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4502942ljp; Tue, 18 Dec 2018 20:29:56 -0800 (PST) X-Google-Smtp-Source: AFSGD/V/Tgr2XQnrXYusu4zPvhKKHVQ6IEKjuhli7Rtsc1IhZT2RhKeyNZqWhlthA7jPzZcPiXrW X-Received: by 2002:a37:ccc2:: with SMTP id n63mr18472887qkl.82.1545193796094; Tue, 18 Dec 2018 20:29:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193796; cv=none; d=google.com; s=arc-20160816; b=QkShcEBqKWhQqhy1cg+6g8fu4Tm3XPzUz/GXlUozYieSoYgJXxLfqldI1qBrg84IMO 7vzyghnsOMqRM/sjmPYIyKemN+WhwmYWIe9UP5dwYI87q7ZII2cz2ZRdfKa3Q+xa+R/y HHjL6uXJr0TP4++UPyQlvPjFBiiJXZOPWHkhqVxknRlqAPYkces8o671lQoAFCCjolB9 n1jWcmdX3rjhb8+eECbZoVlvtF7HQJ9SYhDZlY3ICFdp1q3ldd6iFmX2rtX4IxvgpTAa EyNvwZ+JcfKoMnVfQgQRoza44vZq+V0E6j8vOJrFenCeJo7+Jk9G3cbb1mtJn6CihPBa pnNQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=cI8r8fgHxTtQjNJx7bm22wVY3Dvh3yyiVQzQMsjkClI=; b=CbhXwxgyp5i5zWrJg8KKY5oSHcPiYhSsx3m2pkUWu2QExcLqII7M/oElUpoalMyHCd m8rW3Vg170gRUMfz20Up/XybvG/29n/fMSU9o/cQAhPAdY6RbDwtMPlHqRHJICkBIu9F fl3bTbRF0c6cYTKANViCfjLhDToo6iXwGbdOe6JqXZ6CQReLma5pDBa3x/iD+7Yd0YH0 CDH2mAQk2Nnn1ypun1+9W7B9jDvJSWiBt3f94V7/0erWFp0Qqdiyzq0RIc0iiMYQ/n7b p0rl+yi0JcNl+tZNF2A8dB6M3SUq3/8LMWzkTWz6aWgucVZk9m0XgG/KNWWkj/qmpcoL wT3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=RgJEf6r+; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w5si1217251qvi.223.2018.12.18.20.29.55 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:29:56 -0800 (PST) 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 header.s=google header.b=RgJEf6r+; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57549 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTUZ-0000xZ-9x for patch@linaro.org; Tue, 18 Dec 2018 23:29:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51242) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRY-0007wa-Vd for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMM-0006O1-3q for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:28 -0500 Received: from mail-pg1-x542.google.com ([2607:f8b0:4864:20::542]:46383) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMK-0006Ld-7w for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:25 -0500 Received: by mail-pg1-x542.google.com with SMTP id w7so8831408pgp.13 for ; Tue, 18 Dec 2018 20:21:23 -0800 (PST) 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=cI8r8fgHxTtQjNJx7bm22wVY3Dvh3yyiVQzQMsjkClI=; b=RgJEf6r+v3tHEjV7Lm7lvASIorHl20akGPpKZk+QiLWmtRVYqIn71s6TXoz/cYo30t NdwFxVJOrx7GFhWx/lS/cl2LInQjcModpYfl8TG3Te6dI1kiWxXakQI7Lt5kZIUnf8KG rKzAdhyBlaVvoZA0yPRv77ciTt75HBwnPAuyE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cI8r8fgHxTtQjNJx7bm22wVY3Dvh3yyiVQzQMsjkClI=; b=VXvrrixfyJ98OWSyOIUiyejcEPkKy9jBDM8W3FuvheUksIMNMYYEcMMjc1RXBz2XHK 2hpCEqL6LcpF+Y4i2XzVJ6L7/VeMW/9KunA3gprksv3GEMzMIgwOAnViO9vYsAiMJdih BEZEuDB9F9tkf3Z3JxMw3jBBwetjhkU2WVEIHW7ixA7GEhgdAW8HNkDckvUbC0/5Z46t yH/9LbAtqdZu8/yNnTlAB7BsKHTgu5SXbth7s++oU9tel/b5zoCOODExIc91WVXESnTk yDAuyxruT7OsJ4YhxUxJO9/WEyGHfB+jyVaMAB50YffR4MsFuoXAV8cygvGdri+005gb B3nw== X-Gm-Message-State: AA+aEWaN8C+UNnPmggCqtlfQoCREd+ZZZOzks6STkuOdAIcEdsiwy3OD 3SWd/5omh/Shnbj67XeTe+P3E9SMHpg= X-Received: by 2002:a63:3204:: with SMTP id y4mr18025786pgy.41.1545193282084; Tue, 18 Dec 2018 20:21:22 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:21 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:10 -0800 Message-Id: <20181219042113.7364-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::542 Subject: [Qemu-devel] [PATCH v5 5/8] linux-user: Split out name_to_handle_at, open_by_handle_at 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 3 + linux-user/syscall.h | 1 + linux-user/strace.c | 5 +- linux-user/syscall-file.inc.c | 81 +++++++++++++++++++++++++++ linux-user/syscall.c | 102 ++-------------------------------- linux-user/strace.list | 3 - 6 files changed, 93 insertions(+), 102 deletions(-) -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index ae89be0e87..3d52835216 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -21,6 +21,9 @@ SYSCALL_DEF(close, ARG_DEC); SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); #endif SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); +SYSCALL_DEF(name_to_handle_at, + ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG); +SYSCALL_DEF(open_by_handle_at, ARG_DEC, ARG_PTR, ARG_OPENFLAG); SYSCALL_DEF_FULL(pread64, .impl = impl_pread64, .args = args_pread64_pwrite64, .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }); diff --git a/linux-user/syscall.h b/linux-user/syscall.h index 43b5dc0684..83f602f8e7 100644 --- a/linux-user/syscall.h +++ b/linux-user/syscall.h @@ -57,6 +57,7 @@ typedef enum { /* These print as sets of flags. */ ARG_ATDIRFD, + ARG_ATFLAG, ARG_MODEFLAG, ARG_OPENFLAG, diff --git a/linux-user/strace.c b/linux-user/strace.c index 0d9e1dc483..661e5de7f7 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -780,7 +780,7 @@ UNUSED static struct flags access_flags[] = { FLAG_END, }; -UNUSED static struct flags at_file_flags[] = { +static struct flags const at_file_flags[] = { #ifdef AT_EACCESS FLAG_GENERIC(AT_EACCESS), #endif @@ -2745,6 +2745,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6]) case ARG_ATDIRFD: len = add_atdirfd(b, rest, arg); break; + case ARG_ATFLAG: + len = add_flags(b, rest, at_file_flags, arg, false); + break; case ARG_MODEFLAG: len = add_flags(b, rest, mode_flags, arg, true); break; diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c index 410a763eee..e7b8068a46 100644 --- a/linux-user/syscall-file.inc.c +++ b/linux-user/syscall-file.inc.c @@ -315,6 +315,87 @@ SYSCALL_IMPL(openat) return do_openat(cpu_env, arg1, arg2, arg3, arg4); } +SYSCALL_IMPL(name_to_handle_at) +{ + struct file_handle *target_fh; + struct file_handle *fh; + int mid = 0; + abi_long ret; + char *name; + uint32_t size, total_size; + + if (get_user_s32(size, arg3)) { + return -TARGET_EFAULT; + } + total_size = sizeof(struct file_handle) + size; + target_fh = lock_user(VERIFY_WRITE, arg3, total_size, 0); + if (!target_fh) { + return -TARGET_EFAULT; + } + + name = lock_user_string(arg2); + if (!name) { + unlock_user(target_fh, arg3, 0); + return -TARGET_EFAULT; + } + + fh = g_malloc0(total_size); + fh->handle_bytes = size; + + ret = get_errno(safe_name_to_handle_at(arg1, path(name), fh, &mid, arg5)); + unlock_user(name, arg2, 0); + + /* + * man name_to_handle_at(2): + * Other than the use of the handle_bytes field, the caller should treat + * the file_handle structure as an opaque data type + */ + if (!is_error(ret)) { + memcpy(target_fh, fh, total_size); + target_fh->handle_bytes = tswap32(fh->handle_bytes); + target_fh->handle_type = tswap32(fh->handle_type); + g_free(fh); + unlock_user(target_fh, arg3, total_size); + + if (put_user_s32(mid, arg4)) { + return -TARGET_EFAULT; + } + } + return ret; +} + +SYSCALL_IMPL(open_by_handle_at) +{ + abi_long mount_fd = arg1; + abi_long handle = arg2; + int host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl); + struct file_handle *target_fh; + struct file_handle *fh; + unsigned int size, total_size; + abi_long ret; + + if (get_user_s32(size, handle)) { + return -TARGET_EFAULT; + } + total_size = sizeof(struct file_handle) + size; + target_fh = lock_user(VERIFY_READ, handle, total_size, 1); + if (!target_fh) { + return -TARGET_EFAULT; + } + + fh = g_memdup(target_fh, total_size); + fh->handle_bytes = size; + fh->handle_type = tswap32(target_fh->handle_type); + + ret = get_errno(safe_open_by_handle_at(mount_fd, fh, host_flags)); + + g_free(fh); + unlock_user(target_fh, handle, total_size); + + fd_trans_unregister(ret); + return ret; +} + /* * Both pread64 and pwrite64 merge args into a 64-bit offset, * but the input registers and ordering are target specific. diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9a9b6c543c..98eb3a9c94 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -816,6 +816,10 @@ safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr, size_t, len, unsigned *, prio, const struct timespec *, timeout) #endif +safe_syscall5(int, name_to_handle_at, int, dirfd, const char *, pathname, + struct file_handle *, handle, int *, mount_id, int, flags) +safe_syscall3(int, open_by_handle_at, int, mount_fd, + struct file_handle *, handle, int, flags) /* We do ioctl like this rather than via safe_syscall3 to preserve the * "third argument might be integer or pointer or not present" behaviour of * the libc function. @@ -6384,93 +6388,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, return -TARGET_ENOSYS; } } -#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) -static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, - abi_long handle, abi_long mount_id, - abi_long flags) -{ - struct file_handle *target_fh; - struct file_handle *fh; - int mid = 0; - abi_long ret; - char *name; - unsigned int size, total_size; - - if (get_user_s32(size, handle)) { - return -TARGET_EFAULT; - } - - name = lock_user_string(pathname); - if (!name) { - return -TARGET_EFAULT; - } - - total_size = sizeof(struct file_handle) + size; - target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0); - if (!target_fh) { - unlock_user(name, pathname, 0); - return -TARGET_EFAULT; - } - - fh = g_malloc0(total_size); - fh->handle_bytes = size; - - ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags)); - unlock_user(name, pathname, 0); - - /* man name_to_handle_at(2): - * Other than the use of the handle_bytes field, the caller should treat - * the file_handle structure as an opaque data type - */ - - memcpy(target_fh, fh, total_size); - target_fh->handle_bytes = tswap32(fh->handle_bytes); - target_fh->handle_type = tswap32(fh->handle_type); - g_free(fh); - unlock_user(target_fh, handle, total_size); - - if (put_user_s32(mid, mount_id)) { - return -TARGET_EFAULT; - } - - return ret; - -} -#endif - -#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) -static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle, - abi_long flags) -{ - struct file_handle *target_fh; - struct file_handle *fh; - unsigned int size, total_size; - abi_long ret; - - if (get_user_s32(size, handle)) { - return -TARGET_EFAULT; - } - - total_size = sizeof(struct file_handle) + size; - target_fh = lock_user(VERIFY_READ, handle, total_size, 1); - if (!target_fh) { - return -TARGET_EFAULT; - } - - fh = g_memdup(target_fh, total_size); - fh->handle_bytes = size; - fh->handle_type = tswap32(target_fh->handle_type); - - ret = get_errno(open_by_handle_at(mount_fd, fh, - target_to_host_bitmask(flags, fcntl_flags_tbl))); - - g_free(fh); - - unlock_user(target_fh, handle, total_size); - - return ret; -} -#endif #if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4) @@ -6666,17 +6583,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, preexit_cleanup(cpu_env, arg1); _exit(arg1); return 0; /* avoid warning */ -#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) - case TARGET_NR_name_to_handle_at: - ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5); - return ret; -#endif -#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) - case TARGET_NR_open_by_handle_at: - ret = do_open_by_handle_at(arg1, arg2, arg3); - fd_trans_unregister(ret); - return ret; -#endif case TARGET_NR_brk: return do_brk(arg1); #ifdef TARGET_NR_fork diff --git a/linux-user/strace.list b/linux-user/strace.list index 8f96b7a105..c61b3b9d09 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -638,9 +638,6 @@ #ifdef TARGET_NR_munmap { TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL }, #endif -#ifdef TARGET_NR_name_to_handle_at -{ TARGET_NR_name_to_handle_at, "name_to_handle_at" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_nanosleep { TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL }, #endif From patchwork Wed Dec 19 04:21:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154235 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4504977ljp; Tue, 18 Dec 2018 20:32:51 -0800 (PST) X-Google-Smtp-Source: AFSGD/XGbWgFK52OdgJd9v8GGwfKg/0Fh5OlJ4zycJ7145u5jqGvtnsm6ORhnq3oEoSJeaW1VRVn X-Received: by 2002:a0c:878d:: with SMTP id 13mr19923863qvj.8.1545193971659; Tue, 18 Dec 2018 20:32:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193971; cv=none; d=google.com; s=arc-20160816; b=eFrT2Arljf22X4ICgRFjFKI1r/8NzZMxl5PLcO+qXF4oix6PVlkeI4YL4wlLTMo2PP F+P58nw2DcbLa8CWLuMWjhnL54+O8qkJ6aAly7mS5z0Tbk0Cd0yzzykR5r+SJ/L5co2D UR3sVfOMr+CZlxeGPXS9cFAh2Kl60SavFyW3bkMfHZdJhJQwePRO8AzzMI3iWk0rsJpB KV/vvLCXaloxVZ+Vs4RbzDnLJEu58t1vBwYwYOMGK6HxFy8m6TDvwxkcA52/FsaUNG8c PfDBFrtWkHp/e1WsSk5RBW/wP8Ra1Bn5z7q3s0EoDmzXBz0Gq+z0cE7ntMKoLv9oImO5 mumQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=Tm5wYsouPN/qwtk5Smb6Qz6bmgSyVF3qEeBDB3FcG9U=; b=rrdVQsPsG8kU8KDjGdgBwC4VWb4zIlxWgjinD3b8qV/fC+/VEBB6lTD4Qig98/wolH jn3cRrl0bmh+qSWCtOhrYmJBEWFzTN34FRbPzIn44W0lHW1lNQeWDNRe+ou5GjW6TXUz BXO0RGLbwFtw0JIPCrvu0kJYuVXnkVJ0jJGEynIj9vKiVvT/SEJtriDGY8S2IcztYFD0 mLbWW3B4PurosPY46BLeBEA7KutW2pAfvx/z7wtEXmGbj07PBfUyLkJQaTewjfwFOPSm 3TAsf3YPQHouserpSObK6GKrNs0cdRjooBxTYAuy8TwE3vaosFe1/p2IB+EP3wiFAs1c CHdQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=BF3DIyHV; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id h2si1281292qkc.249.2018.12.18.20.32.51 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:32:51 -0800 (PST) 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 header.s=google header.b=BF3DIyHV; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57568 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTXO-0003YK-7J for patch@linaro.org; Tue, 18 Dec 2018 23:32:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51193) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRX-0007pt-NW for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMO-0006Q5-Du for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:34 -0500 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]:41470) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMM-0006N7-0e for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:26 -0500 Received: by mail-pl1-x644.google.com with SMTP id u6so8851246plm.8 for ; Tue, 18 Dec 2018 20:21:25 -0800 (PST) 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=Tm5wYsouPN/qwtk5Smb6Qz6bmgSyVF3qEeBDB3FcG9U=; b=BF3DIyHVMGAPbqml3Qt8UkEP3zDnozGz1Fhp4f5lZLAZAbF8cgXPxNoyI5QLRRT6ZQ PLjdTNjx2+X1Fq2gKUcFlrDGbI4p6QU3AAZol+O3dF1yOTwPEAO3Sey/jWa3Z5ifPzn2 T+7Re6u8tUr7M5WDvXrUZvlYm9ysALE82vKCs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Tm5wYsouPN/qwtk5Smb6Qz6bmgSyVF3qEeBDB3FcG9U=; b=h5Q25Bk/vDD32DO4rxF3a/MHKShomvjgjS+JNR6A7L4lO7jItiFQqtYPUWmhOG4vJC xYva37LBXg/K7+e9W33zTJvQG/srUhmdmGvTyG/zSC8ravEbnodnYlAk+K+3WDlrEMIE pr9Zu4sWWDAHBegZZN3Nm4HvIRd0jB31AM//DG73LWPcJAB246JJWzDZPRH/ISyu21/1 p1uz4WXlzdV9JAh0Zsdo0dHFveDZ9Zpnn3QAihbIBYCAnqdeJ0gEVPBeU/6Vgfj6TpQS fRN4ovwWiq++iFWwIprn7vTvqYOIm0soWH9awhvpWLL2aDfvFYVMwj1G7yb3/ZhH81UE LMtA== X-Gm-Message-State: AA+aEWYh+XptZYuL89E6r0SuFoHGO1434NKopQqaFdmKvGQIG7BHxUlk AaC8KZjqwKj/68xbc1iZX073hz4Ycos= X-Received: by 2002:a17:902:a98c:: with SMTP id bh12mr19092804plb.31.1545193283581; Tue, 18 Dec 2018 20:21:23 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:22 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:11 -0800 Message-Id: <20181219042113.7364-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::644 Subject: [Qemu-devel] [PATCH v5 6/8] linux-user: Split out ipc syscalls 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 38 ++ linux-user/strace.c | 83 --- linux-user/syscall-ipc.inc.c | 1086 ++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 972 +----------------------------- linux-user/strace.list | 42 -- 5 files changed, 1127 insertions(+), 1094 deletions(-) create mode 100644 linux-user/syscall-ipc.inc.c -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index 3d52835216..2712867228 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -17,6 +17,21 @@ */ SYSCALL_DEF(close, ARG_DEC); +#ifdef TARGET_NR_ipc +SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgctl) +SYSCALL_DEF(msgctl, ARG_DEC, ARG_DEC, ARG_PTR); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgget) +SYSCALL_DEF(msgget, ARG_DEC, ARG_DEC); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgrcv) +SYSCALL_DEF(msgrcv, ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgsnd) +SYSCALL_DEF(msgsnd, ARG_DEC, ARG_PTR, ARG_DEC, ARG_HEX); +#endif #ifdef TARGET_NR_open SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); #endif @@ -44,5 +59,28 @@ SYSCALL_DEF(readlink, ARG_STR, ARG_PTR, ARG_DEC); SYSCALL_DEF(readlinkat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_DEC); #endif SYSCALL_DEF(readv, ARG_DEC, ARG_PTR, ARG_DEC); +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl) +SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semget) +SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop) +SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmat) +SYSCALL_DEF_FULL(shmat, .impl = impl_shmat, + .print_ret = print_syscall_ptr_ret, + .arg_type = { ARG_DEC, ARG_PTR, ARG_HEX }); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmctl) +SYSCALL_DEF(shmctl, ARG_DEC, ARG_DEC, ARG_PTR); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmdt) +SYSCALL_DEF(shmdt, ARG_PTR); +#endif +#if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmget) +SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX); +#endif SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC); SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC); diff --git a/linux-user/strace.c b/linux-user/strace.c index 661e5de7f7..95cf9837cf 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1,8 +1,4 @@ #include "qemu/osdep.h" -#include -#include -#include -#include #include #include #include @@ -74,54 +70,6 @@ UNUSED static void print_socket_protocol(int domain, int type, int protocol); /* * Utility functions */ -static void -print_ipc_cmd(int cmd) -{ -#define output_cmd(val) \ -if( cmd == val ) { \ - gemu_log(#val); \ - return; \ -} - - cmd &= 0xff; - - /* General IPC commands */ - output_cmd( IPC_RMID ); - output_cmd( IPC_SET ); - output_cmd( IPC_STAT ); - output_cmd( IPC_INFO ); - /* msgctl() commands */ - output_cmd( MSG_STAT ); - output_cmd( MSG_INFO ); - /* shmctl() commands */ - output_cmd( SHM_LOCK ); - output_cmd( SHM_UNLOCK ); - output_cmd( SHM_STAT ); - output_cmd( SHM_INFO ); - /* semctl() commands */ - output_cmd( GETPID ); - output_cmd( GETVAL ); - output_cmd( GETALL ); - output_cmd( GETNCNT ); - output_cmd( GETZCNT ); - output_cmd( SETVAL ); - output_cmd( SETALL ); - output_cmd( SEM_STAT ); - output_cmd( SEM_INFO ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - output_cmd( IPC_RMID ); - - /* Some value we don't recognize */ - gemu_log("%d",cmd); -} - static void print_signal(abi_ulong arg, int last) { @@ -620,18 +568,6 @@ print_newselect(const struct syscallname *name, } #endif -#ifdef TARGET_NR_semctl -static void -print_semctl(const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) -{ - gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); - print_ipc_cmd(arg3); - gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); -} -#endif - static void print_execve(const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, @@ -664,25 +600,6 @@ print_execve(const struct syscallname *name, gemu_log("NULL})"); } -#ifdef TARGET_NR_ipc -static void -print_ipc(const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) -{ - switch(arg1) { - case IPCOP_semctl: - gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2); - print_ipc_cmd(arg3); - gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); - break; - default: - gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", - name->name, arg1, arg2, arg3, arg4); - } -} -#endif - /* * Variants for the return value output function */ diff --git a/linux-user/syscall-ipc.inc.c b/linux-user/syscall-ipc.inc.c new file mode 100644 index 0000000000..18076017b8 --- /dev/null +++ b/linux-user/syscall-ipc.inc.c @@ -0,0 +1,1086 @@ +/* + * Linux ipc-related syscalls + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +#ifdef __NR_msgsnd +safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, + int, flags) +safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, + long, msgtype, int, flags) +safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, + unsigned, nsops, const struct timespec *, timeout) +#else +/* + * This host kernel architecture uses a single ipc syscall; fake up + * wrappers for the sub-operations to hide this implementation detail. + * Annoyingly we can't include linux/ipc.h to get the constant definitions + * for the call parameter because some structs in there conflict with the + * sys/ipc.h ones. So we just define them here, and rely on them being + * the same for all host architectures. + */ +#define Q_SEMTIMEDOP 4 +#define Q_MSGSND 11 +#define Q_MSGRCV 12 +#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP)) + +safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, + void *, ptr, long, fifth) + +static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags) +{ + return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0); +} + +static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags) +{ + return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type); +} + +static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops, + const struct timespec *timeout) +{ + return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops, + (long)timeout); +} +#endif + +/* See comment above. */ +#define SEMOPM 500 + +#define N_SHM_REGIONS 32 + +static struct shm_region { + abi_ulong start; + abi_ulong size; + bool in_use; +} shm_regions[N_SHM_REGIONS]; + +#ifndef TARGET_SEMID64_DS +/* asm-generic version of this struct */ +struct target_semid64_ds { + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong sem_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong sem_nsems; + abi_ulong __unused3; + abi_ulong __unused4; +}; +#endif + +static abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, + abi_ulong target_addr) +{ + struct target_ipc_perm *target_ip; + struct target_semid64_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + target_ip = &target_sd->sem_perm; + host_ip->__key = tswap32(target_ip->__key); + host_ip->uid = tswap32(target_ip->uid); + host_ip->gid = tswap32(target_ip->gid); + host_ip->cuid = tswap32(target_ip->cuid); + host_ip->cgid = tswap32(target_ip->cgid); +#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) + host_ip->mode = tswap32(target_ip->mode); +#else + host_ip->mode = tswap16(target_ip->mode); +#endif +#if defined(TARGET_PPC) + host_ip->__seq = tswap32(target_ip->__seq); +#else + host_ip->__seq = tswap16(target_ip->__seq); +#endif + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +static abi_long host_to_target_ipc_perm(abi_ulong target_addr, + struct ipc_perm *host_ip) +{ + struct target_ipc_perm *target_ip; + struct target_semid64_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + target_ip = &target_sd->sem_perm; + target_ip->__key = tswap32(host_ip->__key); + target_ip->uid = tswap32(host_ip->uid); + target_ip->gid = tswap32(host_ip->gid); + target_ip->cuid = tswap32(host_ip->cuid); + target_ip->cgid = tswap32(host_ip->cgid); +#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) + target_ip->mode = tswap32(host_ip->mode); +#else + target_ip->mode = tswap16(host_ip->mode); +#endif +#if defined(TARGET_PPC) + target_ip->__seq = tswap32(host_ip->__seq); +#else + target_ip->__seq = tswap16(host_ip->__seq); +#endif + unlock_user_struct(target_sd, target_addr, 1); + return 0; +} + +static abi_long target_to_host_semid_ds(struct semid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_semid64_ds *target_sd; + + if (target_to_host_ipc_perm(&host_sd->sem_perm, target_addr)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + host_sd->sem_nsems = tswapal(target_sd->sem_nsems); + host_sd->sem_otime = tswapal(target_sd->sem_otime); + host_sd->sem_ctime = tswapal(target_sd->sem_ctime); + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +static abi_long host_to_target_semid_ds(abi_ulong target_addr, + struct semid_ds *host_sd) +{ + struct target_semid64_ds *target_sd; + + if (host_to_target_ipc_perm(target_addr, &host_sd->sem_perm)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + target_sd->sem_nsems = tswapal(host_sd->sem_nsems); + target_sd->sem_otime = tswapal(host_sd->sem_otime); + target_sd->sem_ctime = tswapal(host_sd->sem_ctime); + unlock_user_struct(target_sd, target_addr, 1); + return 0; +} + +struct target_seminfo { + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +static abi_long host_to_target_seminfo(abi_ulong target_addr, + struct seminfo *host_seminfo) +{ + struct target_seminfo *target_seminfo; + + if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_seminfo->semmap, &target_seminfo->semmap); + __put_user(host_seminfo->semmni, &target_seminfo->semmni); + __put_user(host_seminfo->semmns, &target_seminfo->semmns); + __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); + __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); + __put_user(host_seminfo->semopm, &target_seminfo->semopm); + __put_user(host_seminfo->semume, &target_seminfo->semume); + __put_user(host_seminfo->semusz, &target_seminfo->semusz); + __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); + __put_user(host_seminfo->semaem, &target_seminfo->semaem); + unlock_user_struct(target_seminfo, target_addr, 1); + return 0; +} + +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; +}; + +union target_semun { + int val; + abi_ulong buf; + abi_ulong array; + abi_ulong __buf; +}; + +static abi_long target_to_host_semarray(int semid, + unsigned short **host_array, + abi_ulong target_addr) +{ + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) { + return get_errno(ret); + } + + nsems = semid_ds.sem_nsems; + + *host_array = g_try_new(unsigned short, nsems); + if (!*host_array) { + return -TARGET_ENOMEM; + } + array = lock_user(VERIFY_READ, target_addr, + nsems * sizeof(unsigned short), 1); + if (!array) { + g_free(*host_array); + return -TARGET_EFAULT; + } + for (i = 0; i < nsems; i++) { + __get_user((*host_array)[i], &array[i]); + } + unlock_user(array, target_addr, 0); + + return 0; +} + +static abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array) +{ + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) { + return get_errno(ret); + } + + nsems = semid_ds.sem_nsems; + + array = lock_user(VERIFY_WRITE, target_addr, + nsems * sizeof(unsigned short), 0); + if (!array) { + return -TARGET_EFAULT; + } + for (i = 0; i < nsems; i++) { + __put_user((*host_array)[i], &array[i]); + } + g_free(*host_array); + unlock_user(array, target_addr, 1); + + return 0; +} + +struct target_sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; +}; + +static abi_long target_to_host_sembuf(struct sembuf *host_sembuf, + abi_ulong target_addr, + unsigned nsops) +{ + struct target_sembuf *target_sembuf; + int i; + + target_sembuf = lock_user(VERIFY_READ, target_addr, + nsops * sizeof(struct target_sembuf), 1); + if (!target_sembuf) { + return -TARGET_EFAULT; + } + for (i = 0; i < nsops; i++) { + __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num); + __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op); + __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg); + } + unlock_user(target_sembuf, target_addr, 0); + return 0; +} + +struct target_msqid_ds { + struct target_ipc_perm msg_perm; + abi_ulong msg_stime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong msg_rtime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong msg_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + abi_ulong __msg_cbytes; + abi_ulong msg_qnum; + abi_ulong msg_qbytes; + abi_ulong msg_lspid; + abi_ulong msg_lrpid; + abi_ulong __unused4; + abi_ulong __unused5; +}; + +static abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, + abi_ulong target_addr) +{ + struct target_msqid_ds *target_md; + + if (target_to_host_ipc_perm(&host_md->msg_perm, target_addr)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) { + return -TARGET_EFAULT; + } + host_md->msg_stime = tswapal(target_md->msg_stime); + host_md->msg_rtime = tswapal(target_md->msg_rtime); + host_md->msg_ctime = tswapal(target_md->msg_ctime); + host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes); + host_md->msg_qnum = tswapal(target_md->msg_qnum); + host_md->msg_qbytes = tswapal(target_md->msg_qbytes); + host_md->msg_lspid = tswapal(target_md->msg_lspid); + host_md->msg_lrpid = tswapal(target_md->msg_lrpid); + unlock_user_struct(target_md, target_addr, 0); + return 0; +} + +static abi_long host_to_target_msqid_ds(abi_ulong target_addr, + struct msqid_ds *host_md) +{ + struct target_msqid_ds *target_md; + + if (host_to_target_ipc_perm(target_addr, &host_md->msg_perm)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) { + return -TARGET_EFAULT; + } + target_md->msg_stime = tswapal(host_md->msg_stime); + target_md->msg_rtime = tswapal(host_md->msg_rtime); + target_md->msg_ctime = tswapal(host_md->msg_ctime); + target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes); + target_md->msg_qnum = tswapal(host_md->msg_qnum); + target_md->msg_qbytes = tswapal(host_md->msg_qbytes); + target_md->msg_lspid = tswapal(host_md->msg_lspid); + target_md->msg_lrpid = tswapal(host_md->msg_lrpid); + unlock_user_struct(target_md, target_addr, 1); + return 0; +} + +struct target_msginfo { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; +}; + +static abi_long host_to_target_msginfo(abi_ulong target_addr, + struct msginfo *host_msginfo) +{ + struct target_msginfo *target_msginfo; + + if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); + __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); + __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); + __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); + __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); + __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); + __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); + __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); + unlock_user_struct(target_msginfo, target_addr, 1); + return 0; +} + +struct target_msgbuf { + abi_long mtype; + char mtext[1]; +}; + +static abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_shmid_ds *target_sd; + + if (target_to_host_ipc_perm(&host_sd->shm_perm, target_addr)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __get_user(host_sd->shm_atime, &target_sd->shm_atime); + __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); + __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +static abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd) +{ + struct target_shmid_ds *target_sd; + + if (host_to_target_ipc_perm(target_addr, &host_sd->shm_perm)) { + return -TARGET_EFAULT; + } + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __put_user(host_sd->shm_atime, &target_sd->shm_atime); + __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); + __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 1); + return 0; +} + +struct target_shminfo { + abi_ulong shmmax; + abi_ulong shmmin; + abi_ulong shmmni; + abi_ulong shmseg; + abi_ulong shmall; +}; + +static abi_long host_to_target_shminfo(abi_ulong target_addr, + struct shminfo *host_shminfo) +{ + struct target_shminfo *target_shminfo; + + if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); + __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); + __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); + __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); + __put_user(host_shminfo->shmall, &target_shminfo->shmall); + unlock_user_struct(target_shminfo, target_addr, 1); + return 0; +} + +struct target_shm_info { + int used_ids; + abi_ulong shm_tot; + abi_ulong shm_rss; + abi_ulong shm_swp; + abi_ulong swap_attempts; + abi_ulong swap_successes; +}; + +static abi_long host_to_target_shm_info(abi_ulong target_addr, + struct shm_info *host_shm_info) +{ + struct target_shm_info *target_shm_info; + + if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); + __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); + __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); + __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); + __put_user(host_shm_info->swap_attempts, + &target_shm_info->swap_attempts); + __put_user(host_shm_info->swap_successes, + &target_shm_info->swap_successes); + unlock_user_struct(target_shm_info, target_addr, 1); + return 0; +} + +#ifndef TARGET_FORCE_SHMLBA +/* + * For most architectures, SHMLBA is the same as the page size; + * some architectures have larger values, in which case they should + * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function. + * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA + * and defining its own value for SHMLBA. + * + * The kernel also permits SHMLBA to be set by the architecture to a + * value larger than the page size without setting __ARCH_FORCE_SHMLBA; + * this means that addresses are rounded to the large size if + * SHM_RND is set but addresses not aligned to that size are not rejected + * as long as they are at least page-aligned. Since the only architecture + * which uses this is ia64 this code doesn't provide for that oddity. + */ +static abi_ulong target_shmlba(CPUArchState *cpu_env) +{ + return TARGET_PAGE_SIZE; +} +#endif + + +SYSCALL_IMPL(msgctl) +{ + abi_long msgid = arg1; + int cmd = arg2 & 0xff; + abi_ulong ptr = arg3; + struct msqid_ds dsarg; + struct msginfo msginfo; + abi_long ret; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + case MSG_STAT: + if (target_to_host_msqid_ds(&dsarg, ptr)) { + return -TARGET_EFAULT; + } + ret = get_errno(msgctl(msgid, cmd, &dsarg)); + if (!is_error(ret) && host_to_target_msqid_ds(ptr, &dsarg)) { + return -TARGET_EFAULT; + } + return ret; + + case IPC_RMID: + return get_errno(msgctl(msgid, cmd, NULL)); + + case IPC_INFO: + case MSG_INFO: + ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); + if (host_to_target_msginfo(ptr, &msginfo)) { + return -TARGET_EFAULT; + } + return ret; + + default: + return -TARGET_EINVAL; + } +} + +SYSCALL_IMPL(msgget) +{ + return get_errno(msgget(arg1, arg2)); +} + +SYSCALL_IMPL(msgrcv) +{ + int msqid = arg1; + abi_ulong msgp = arg2; + abi_long msgsz = arg3; + abi_long msgtyp = arg4; + int msgflg = arg5; + struct target_msgbuf *target_mb; + char *target_mtext; + struct msgbuf *host_mb; + abi_long ret = 0; + + if (msgsz < 0) { + return -TARGET_EINVAL; + } + if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) { + return -TARGET_EFAULT; + } + + host_mb = g_try_malloc(msgsz + sizeof(long)); + if (!host_mb) { + ret = -TARGET_ENOMEM; + goto end; + } + ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg)); + + if (ret > 0) { + abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); + target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); + if (!target_mtext) { + ret = -TARGET_EFAULT; + goto end; + } + memcpy(target_mb->mtext, host_mb->mtext, ret); + unlock_user(target_mtext, target_mtext_addr, ret); + } + target_mb->mtype = tswapal(host_mb->mtype); + + end: + unlock_user_struct(target_mb, msgp, 1); + g_free(host_mb); + return ret; +} + +SYSCALL_IMPL(msgsnd) +{ + int msqid = arg1; + abi_ulong msgp = arg2; + abi_long msgsz = arg3; + int msgflg = arg4; + struct target_msgbuf *target_mb; + struct msgbuf *host_mb; + abi_long ret = 0; + + if (msgsz < 0) { + return -TARGET_EINVAL; + } + if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) { + return -TARGET_EFAULT; + } + host_mb = g_try_malloc(msgsz + sizeof(long)); + if (!host_mb) { + unlock_user_struct(target_mb, msgp, 0); + return -TARGET_ENOMEM; + } + + host_mb->mtype = (abi_long)tswapal(target_mb->mtype); + memcpy(host_mb->mtext, target_mb->mtext, msgsz); + ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg)); + + g_free(host_mb); + unlock_user_struct(target_mb, msgp, 0); + return ret; +} + +SYSCALL_IMPL(semctl) +{ + abi_long semid = arg1; + abi_long semnum = arg2; + int cmd = arg3 & 0xff; + abi_ulong target_arg = arg4; + union target_semun target_su = { .buf = target_arg }; + union semun arg; + struct semid_ds dsarg; + unsigned short *array = NULL; + struct seminfo seminfo; + abi_long ret, err; + + switch (cmd) { + case GETVAL: + case SETVAL: + /* + * In 64 bit cross-endian situations, we will erroneously pick up + * the wrong half of the union for the "val" element. To rectify + * this, the entire 8-byte structure is byteswapped, followed by + * a swap of the 4 byte val field. In other cases, the data is + * already in proper host byte order. + */ + if (sizeof(target_su.val) != sizeof(target_su.buf)) { + target_su.buf = tswapal(target_su.buf); + arg.val = tswap32(target_su.val); + } else { + arg.val = target_su.val; + } + return get_errno(semctl(semid, semnum, cmd, arg)); + + case GETALL: + case SETALL: + err = target_to_host_semarray(semid, &array, target_su.array); + if (err) { + return err; + } + arg.array = array; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + if (!is_error(ret)) { + err = host_to_target_semarray(semid, target_su.array, &array); + if (err) { + return err; + } + } + return ret; + + case IPC_STAT: + case IPC_SET: + case SEM_STAT: + err = target_to_host_semid_ds(&dsarg, target_su.buf); + if (err) { + return err; + } + arg.buf = &dsarg; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + if (!is_error(ret)) { + err = host_to_target_semid_ds(target_su.buf, &dsarg); + if (err) { + return err; + } + } + return ret; + + case IPC_INFO: + case SEM_INFO: + arg.__buf = &seminfo; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + if (!is_error(ret)) { + err = host_to_target_seminfo(target_su.__buf, &seminfo); + if (err) { + return err; + } + } + return ret; + + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + return get_errno(semctl(semid, semnum, cmd, NULL)); + + default: + return -TARGET_EINVAL; + } +} + +SYSCALL_IMPL(semget) +{ + return get_errno(semget(arg1, arg2, arg3)); +} + +SYSCALL_IMPL(semop) +{ + abi_long semid = arg1; + abi_ulong ptr = arg2; + abi_ulong nsops = arg3; + struct sembuf sops[SEMOPM]; + + if (nsops > SEMOPM) { + return -TARGET_E2BIG; + } + if (target_to_host_sembuf(sops, ptr, nsops)) { + return -TARGET_EFAULT; + } + return get_errno(safe_semtimedop(semid, sops, nsops, NULL)); +} + +SYSCALL_IMPL(shmat) +{ + int shmid = arg1; + abi_ulong shmaddr = arg2; + int shmflg = arg3; + abi_ulong raddr; + void *host_raddr; + struct shmid_ds shm_info; + int i, ret; + abi_ulong shmlba; + + /* Find out the length of the shared memory segment. */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* can't get length, bail out */ + return ret; + } + + /* Validate memory placement and alignment for the guest. */ + shmlba = target_shmlba(cpu_env); + if (shmaddr & (shmlba - 1)) { + if (shmflg & SHM_RND) { + shmaddr &= ~(shmlba - 1); + } else { + return -TARGET_EINVAL; + } + } + if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) { + return -TARGET_EINVAL; + } + + mmap_lock(); + + if (shmaddr) { + host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg); + } else { + abi_ulong mmap_start = mmap_find_vma(0, shm_info.shm_segsz); + if (mmap_start == -1) { + errno = ENOMEM; + host_raddr = (void *)-1; + } else { + host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP); + } + } + if (host_raddr == (void *)-1) { + mmap_unlock(); + return get_errno((intptr_t)host_raddr); + } + + raddr = h2g((uintptr_t)host_raddr); + page_set_flags(raddr, raddr + shm_info.shm_segsz, + PAGE_VALID | PAGE_READ | + (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE)); + + for (i = 0; i < N_SHM_REGIONS; i++) { + if (!shm_regions[i].in_use) { + shm_regions[i].in_use = true; + shm_regions[i].start = raddr; + shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + mmap_unlock(); + return raddr; +} + +SYSCALL_IMPL(shmctl) +{ + int shmid = arg1; + int cmd = arg2 & 0xff; + abi_ulong buf = arg3; + struct shmid_ds dsarg; + struct shminfo shminfo; + struct shm_info shm_info; + abi_long ret; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + case SHM_STAT: + if (target_to_host_shmid_ds(&dsarg, buf)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (!is_error(ret) && host_to_target_shmid_ds(buf, &dsarg)) { + return -TARGET_EFAULT; + } + return ret; + + case IPC_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); + if (!is_error(ret) && host_to_target_shminfo(buf, &shminfo)) { + return -TARGET_EFAULT; + } + return ret; + + case SHM_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); + if (!is_error(ret) && host_to_target_shm_info(buf, &shm_info)) { + return -TARGET_EFAULT; + } + return ret; + + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: + return get_errno(shmctl(shmid, cmd, NULL)); + + default: + return -TARGET_EINVAL; + } +} + +SYSCALL_IMPL(shmdt) +{ + abi_ulong shmaddr = arg1; + abi_long ret; + int i; + + mmap_lock(); + + for (i = 0; i < N_SHM_REGIONS; ++i) { + if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) { + shm_regions[i].in_use = false; + page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0); + break; + } + } + ret = get_errno(shmdt(g2h(shmaddr))); + + mmap_unlock(); + + return ret; +} + +SYSCALL_IMPL(shmget) +{ + return get_errno(shmget(arg1, arg2, arg3)); +} + +#ifdef TARGET_NR_ipc +/* + * This differs from normal shmat in returning the result via a pointer. + * Here we have shifted that pointer to arg4. + */ +SYSCALL_IMPL(ipc_shmat) +{ + abi_long ret = impl_shmat(cpu_env, arg1, arg2, arg3, 0, 0, 0); + + if (is_error(ret)) { + return ret; + } + if (put_user_ual(ret, arg4)) { + return -TARGET_EFAULT; + } + return 0; +} + +static const SyscallDef def_ipc_shmat = { + .name = "shmat", + .impl = impl_ipc_shmat, + .arg_type = { ARG_DEC, ARG_PTR, ARG_HEX, ARG_PTR }, +}; + +/* These get defined later via syscall-defs.h. */ +static const SyscallDef def_semop; +static const SyscallDef def_semget; +static const SyscallDef def_semctl; +static const SyscallDef def_msgget; +static const SyscallDef def_msgsnd; +static const SyscallDef def_msgctl; +static const SyscallDef def_msgrcv; +static const SyscallDef def_shmdt; +static const SyscallDef def_shmget; +static const SyscallDef def_shmctl; + +/* + * Demultiplex the IPC syscall and shuffle the arguments around + * into the "normal" ordering. + */ +SYSCALL_ARGS(ipc) +{ + int call = extract32(in[0], 0, 16); + int version = extract32(in[0], 16, 16); + abi_long first = in[1]; + abi_long second = in[2]; + abi_long third = in[3]; + abi_ulong ptr = in[4]; + abi_long fifth = in[5]; + abi_ulong atptr; + + /* IPC_* and SHM_* command values are the same on all linux platforms */ + switch (call) { + case IPCOP_semop: + out[0] = first; + out[1] = ptr; + out[2] = second; + return &def_semop; + + case IPCOP_semget: + out[0] = first; + out[1] = second; + out[2] = third; + return &def_semget; + + case IPCOP_semctl: + /* + * The semun argument to semctl is passed by value, + * so dereference the ptr argument. + */ + if (get_user_ual(atptr, ptr)) { + errno = EFAULT; + return NULL; + } + out[0] = first; + out[1] = second; + out[2] = third; + out[3] = atptr; + return &def_semctl; + + case IPCOP_msgget: + out[0] = first; + out[1] = second; + return &def_msgget; + + case IPCOP_msgsnd: + out[0] = first; + out[1] = ptr; + out[2] = second; + out[3] = third; + return &def_msgsnd; + + case IPCOP_msgctl: + out[0] = first; + out[1] = second; + out[2] = ptr; + return &def_msgctl; + + case IPCOP_msgrcv: + if (version == 0) { + struct target_ipc_kludge { + abi_long msgp; + abi_long msgtyp; + } *tmp; + + if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { + errno = EFAULT; + return NULL; + } + out[0] = first; + out[1] = tswapal(tmp->msgp); + out[2] = second; + out[3] = tswapal(tmp->msgtyp); + out[4] = third; + unlock_user_struct(tmp, ptr, 0); + } else { + out[0] = first; + out[1] = ptr; + out[2] = second; + out[3] = fifth; + out[4] = third; + } + return &def_msgrcv; + + case IPCOP_shmat: + if (version == 1) { + errno = EINVAL; + return NULL; + } + out[0] = first; + out[1] = ptr; + out[2] = second; + out[3] = third; + return &def_ipc_shmat; + + case IPCOP_shmdt: + out[0] = ptr; + return &def_shmdt; + + case IPCOP_shmget: + out[0] = first; + out[1] = second; + out[2] = third; + return &def_shmget; + + case IPCOP_shmctl: + out[0] = first; + out[1] = second; + out[2] = ptr; + return &def_shmctl; + + default: + /* Invalid syscall. Continue to impl_ipc for logging. */ + return def; + } +} + +SYSCALL_IMPL(ipc) +{ + int call = extract32(arg1, 0, 16); + int version = extract32(arg1, 16, 16); + + gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); + return -TARGET_ENOSYS; +} +#endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 98eb3a9c94..249eb85d4a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -773,43 +773,6 @@ safe_syscall2(int, nanosleep, const struct timespec *, req, safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef __NR_msgsnd -safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, - int, flags) -safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, - long, msgtype, int, flags) -safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, - unsigned, nsops, const struct timespec *, timeout) -#else -/* This host kernel architecture uses a single ipc syscall; fake up - * wrappers for the sub-operations to hide this implementation detail. - * Annoyingly we can't include linux/ipc.h to get the constant definitions - * for the call parameter because some structs in there conflict with the - * sys/ipc.h ones. So we just define them here, and rely on them being - * the same for all host architectures. - */ -#define Q_SEMTIMEDOP 4 -#define Q_MSGSND 11 -#define Q_MSGRCV 12 -#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP)) - -safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, - void *, ptr, long, fifth) -static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags) -{ - return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0); -} -static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags) -{ - return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type); -} -static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops, - const struct timespec *timeout) -{ - return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops, - (long)timeout); -} -#endif #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, size_t, len, unsigned, prio, const struct timespec *, timeout) @@ -3095,890 +3058,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr) } #endif -#define N_SHM_REGIONS 32 - -static struct shm_region { - abi_ulong start; - abi_ulong size; - bool in_use; -} shm_regions[N_SHM_REGIONS]; - -#ifndef TARGET_SEMID64_DS -/* asm-generic version of this struct */ -struct target_semid64_ds -{ - struct target_ipc_perm sem_perm; - abi_ulong sem_otime; -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong sem_ctime; -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong sem_nsems; - abi_ulong __unused3; - abi_ulong __unused4; -}; -#endif - -static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, - abi_ulong target_addr) -{ - struct target_ipc_perm *target_ip; - struct target_semid64_ds *target_sd; - - if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) - return -TARGET_EFAULT; - target_ip = &(target_sd->sem_perm); - host_ip->__key = tswap32(target_ip->__key); - host_ip->uid = tswap32(target_ip->uid); - host_ip->gid = tswap32(target_ip->gid); - host_ip->cuid = tswap32(target_ip->cuid); - host_ip->cgid = tswap32(target_ip->cgid); -#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) - host_ip->mode = tswap32(target_ip->mode); -#else - host_ip->mode = tswap16(target_ip->mode); -#endif -#if defined(TARGET_PPC) - host_ip->__seq = tswap32(target_ip->__seq); -#else - host_ip->__seq = tswap16(target_ip->__seq); -#endif - unlock_user_struct(target_sd, target_addr, 0); - return 0; -} - -static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr, - struct ipc_perm *host_ip) -{ - struct target_ipc_perm *target_ip; - struct target_semid64_ds *target_sd; - - if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) - return -TARGET_EFAULT; - target_ip = &(target_sd->sem_perm); - target_ip->__key = tswap32(host_ip->__key); - target_ip->uid = tswap32(host_ip->uid); - target_ip->gid = tswap32(host_ip->gid); - target_ip->cuid = tswap32(host_ip->cuid); - target_ip->cgid = tswap32(host_ip->cgid); -#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) - target_ip->mode = tswap32(host_ip->mode); -#else - target_ip->mode = tswap16(host_ip->mode); -#endif -#if defined(TARGET_PPC) - target_ip->__seq = tswap32(host_ip->__seq); -#else - target_ip->__seq = tswap16(host_ip->__seq); -#endif - unlock_user_struct(target_sd, target_addr, 1); - return 0; -} - -static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, - abi_ulong target_addr) -{ - struct target_semid64_ds *target_sd; - - if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) - return -TARGET_EFAULT; - if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) - return -TARGET_EFAULT; - host_sd->sem_nsems = tswapal(target_sd->sem_nsems); - host_sd->sem_otime = tswapal(target_sd->sem_otime); - host_sd->sem_ctime = tswapal(target_sd->sem_ctime); - unlock_user_struct(target_sd, target_addr, 0); - return 0; -} - -static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, - struct semid_ds *host_sd) -{ - struct target_semid64_ds *target_sd; - - if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) - return -TARGET_EFAULT; - if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) - return -TARGET_EFAULT; - target_sd->sem_nsems = tswapal(host_sd->sem_nsems); - target_sd->sem_otime = tswapal(host_sd->sem_otime); - target_sd->sem_ctime = tswapal(host_sd->sem_ctime); - unlock_user_struct(target_sd, target_addr, 1); - return 0; -} - -struct target_seminfo { - int semmap; - int semmni; - int semmns; - int semmnu; - int semmsl; - int semopm; - int semume; - int semusz; - int semvmx; - int semaem; -}; - -static inline abi_long host_to_target_seminfo(abi_ulong target_addr, - struct seminfo *host_seminfo) -{ - struct target_seminfo *target_seminfo; - if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) - return -TARGET_EFAULT; - __put_user(host_seminfo->semmap, &target_seminfo->semmap); - __put_user(host_seminfo->semmni, &target_seminfo->semmni); - __put_user(host_seminfo->semmns, &target_seminfo->semmns); - __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); - __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); - __put_user(host_seminfo->semopm, &target_seminfo->semopm); - __put_user(host_seminfo->semume, &target_seminfo->semume); - __put_user(host_seminfo->semusz, &target_seminfo->semusz); - __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); - __put_user(host_seminfo->semaem, &target_seminfo->semaem); - unlock_user_struct(target_seminfo, target_addr, 1); - return 0; -} - -union semun { - int val; - struct semid_ds *buf; - unsigned short *array; - struct seminfo *__buf; -}; - -union target_semun { - int val; - abi_ulong buf; - abi_ulong array; - abi_ulong __buf; -}; - -static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, - abi_ulong target_addr) -{ - int nsems; - unsigned short *array; - union semun semun; - struct semid_ds semid_ds; - int i, ret; - - semun.buf = &semid_ds; - - ret = semctl(semid, 0, IPC_STAT, semun); - if (ret == -1) - return get_errno(ret); - - nsems = semid_ds.sem_nsems; - - *host_array = g_try_new(unsigned short, nsems); - if (!*host_array) { - return -TARGET_ENOMEM; - } - array = lock_user(VERIFY_READ, target_addr, - nsems*sizeof(unsigned short), 1); - if (!array) { - g_free(*host_array); - return -TARGET_EFAULT; - } - - for(i=0; imsg_perm),target_addr)) - return -TARGET_EFAULT; - host_md->msg_stime = tswapal(target_md->msg_stime); - host_md->msg_rtime = tswapal(target_md->msg_rtime); - host_md->msg_ctime = tswapal(target_md->msg_ctime); - host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes); - host_md->msg_qnum = tswapal(target_md->msg_qnum); - host_md->msg_qbytes = tswapal(target_md->msg_qbytes); - host_md->msg_lspid = tswapal(target_md->msg_lspid); - host_md->msg_lrpid = tswapal(target_md->msg_lrpid); - unlock_user_struct(target_md, target_addr, 0); - return 0; -} - -static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, - struct msqid_ds *host_md) -{ - struct target_msqid_ds *target_md; - - if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) - return -TARGET_EFAULT; - if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm))) - return -TARGET_EFAULT; - target_md->msg_stime = tswapal(host_md->msg_stime); - target_md->msg_rtime = tswapal(host_md->msg_rtime); - target_md->msg_ctime = tswapal(host_md->msg_ctime); - target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes); - target_md->msg_qnum = tswapal(host_md->msg_qnum); - target_md->msg_qbytes = tswapal(host_md->msg_qbytes); - target_md->msg_lspid = tswapal(host_md->msg_lspid); - target_md->msg_lrpid = tswapal(host_md->msg_lrpid); - unlock_user_struct(target_md, target_addr, 1); - return 0; -} - -struct target_msginfo { - int msgpool; - int msgmap; - int msgmax; - int msgmnb; - int msgmni; - int msgssz; - int msgtql; - unsigned short int msgseg; -}; - -static inline abi_long host_to_target_msginfo(abi_ulong target_addr, - struct msginfo *host_msginfo) -{ - struct target_msginfo *target_msginfo; - if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) - return -TARGET_EFAULT; - __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); - __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); - __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); - __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); - __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); - __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); - __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); - __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); - unlock_user_struct(target_msginfo, target_addr, 1); - return 0; -} - -static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr) -{ - struct msqid_ds dsarg; - struct msginfo msginfo; - abi_long ret = -TARGET_EINVAL; - - cmd &= 0xff; - - switch (cmd) { - case IPC_STAT: - case IPC_SET: - case MSG_STAT: - if (target_to_host_msqid_ds(&dsarg,ptr)) - return -TARGET_EFAULT; - ret = get_errno(msgctl(msgid, cmd, &dsarg)); - if (host_to_target_msqid_ds(ptr,&dsarg)) - return -TARGET_EFAULT; - break; - case IPC_RMID: - ret = get_errno(msgctl(msgid, cmd, NULL)); - break; - case IPC_INFO: - case MSG_INFO: - ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); - if (host_to_target_msginfo(ptr, &msginfo)) - return -TARGET_EFAULT; - break; - } - - return ret; -} - -struct target_msgbuf { - abi_long mtype; - char mtext[1]; -}; - -static inline abi_long do_msgsnd(int msqid, abi_long msgp, - ssize_t msgsz, int msgflg) -{ - struct target_msgbuf *target_mb; - struct msgbuf *host_mb; - abi_long ret = 0; - - if (msgsz < 0) { - return -TARGET_EINVAL; - } - - if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) - return -TARGET_EFAULT; - host_mb = g_try_malloc(msgsz + sizeof(long)); - if (!host_mb) { - unlock_user_struct(target_mb, msgp, 0); - return -TARGET_ENOMEM; - } - host_mb->mtype = (abi_long) tswapal(target_mb->mtype); - memcpy(host_mb->mtext, target_mb->mtext, msgsz); - ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg)); - g_free(host_mb); - unlock_user_struct(target_mb, msgp, 0); - - return ret; -} - -static inline abi_long do_msgrcv(int msqid, abi_long msgp, - ssize_t msgsz, abi_long msgtyp, - int msgflg) -{ - struct target_msgbuf *target_mb; - char *target_mtext; - struct msgbuf *host_mb; - abi_long ret = 0; - - if (msgsz < 0) { - return -TARGET_EINVAL; - } - - if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) - return -TARGET_EFAULT; - - host_mb = g_try_malloc(msgsz + sizeof(long)); - if (!host_mb) { - ret = -TARGET_ENOMEM; - goto end; - } - ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg)); - - if (ret > 0) { - abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); - target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); - if (!target_mtext) { - ret = -TARGET_EFAULT; - goto end; - } - memcpy(target_mb->mtext, host_mb->mtext, ret); - unlock_user(target_mtext, target_mtext_addr, ret); - } - - target_mb->mtype = tswapal(host_mb->mtype); - -end: - if (target_mb) - unlock_user_struct(target_mb, msgp, 1); - g_free(host_mb); - return ret; -} - -static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, - abi_ulong target_addr) -{ - struct target_shmid_ds *target_sd; - - if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) - return -TARGET_EFAULT; - if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) - return -TARGET_EFAULT; - __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); - __get_user(host_sd->shm_atime, &target_sd->shm_atime); - __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); - __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); - __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); - __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); - __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); - unlock_user_struct(target_sd, target_addr, 0); - return 0; -} - -static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr, - struct shmid_ds *host_sd) -{ - struct target_shmid_ds *target_sd; - - if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) - return -TARGET_EFAULT; - if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) - return -TARGET_EFAULT; - __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); - __put_user(host_sd->shm_atime, &target_sd->shm_atime); - __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); - __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); - __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); - __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); - __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); - unlock_user_struct(target_sd, target_addr, 1); - return 0; -} - -struct target_shminfo { - abi_ulong shmmax; - abi_ulong shmmin; - abi_ulong shmmni; - abi_ulong shmseg; - abi_ulong shmall; -}; - -static inline abi_long host_to_target_shminfo(abi_ulong target_addr, - struct shminfo *host_shminfo) -{ - struct target_shminfo *target_shminfo; - if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) - return -TARGET_EFAULT; - __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); - __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); - __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); - __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); - __put_user(host_shminfo->shmall, &target_shminfo->shmall); - unlock_user_struct(target_shminfo, target_addr, 1); - return 0; -} - -struct target_shm_info { - int used_ids; - abi_ulong shm_tot; - abi_ulong shm_rss; - abi_ulong shm_swp; - abi_ulong swap_attempts; - abi_ulong swap_successes; -}; - -static inline abi_long host_to_target_shm_info(abi_ulong target_addr, - struct shm_info *host_shm_info) -{ - struct target_shm_info *target_shm_info; - if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) - return -TARGET_EFAULT; - __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); - __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); - __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); - __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); - __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts); - __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes); - unlock_user_struct(target_shm_info, target_addr, 1); - return 0; -} - -static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf) -{ - struct shmid_ds dsarg; - struct shminfo shminfo; - struct shm_info shm_info; - abi_long ret = -TARGET_EINVAL; - - cmd &= 0xff; - - switch(cmd) { - case IPC_STAT: - case IPC_SET: - case SHM_STAT: - if (target_to_host_shmid_ds(&dsarg, buf)) - return -TARGET_EFAULT; - ret = get_errno(shmctl(shmid, cmd, &dsarg)); - if (host_to_target_shmid_ds(buf, &dsarg)) - return -TARGET_EFAULT; - break; - case IPC_INFO: - ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); - if (host_to_target_shminfo(buf, &shminfo)) - return -TARGET_EFAULT; - break; - case SHM_INFO: - ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); - if (host_to_target_shm_info(buf, &shm_info)) - return -TARGET_EFAULT; - break; - case IPC_RMID: - case SHM_LOCK: - case SHM_UNLOCK: - ret = get_errno(shmctl(shmid, cmd, NULL)); - break; - } - - return ret; -} - -#ifndef TARGET_FORCE_SHMLBA -/* For most architectures, SHMLBA is the same as the page size; - * some architectures have larger values, in which case they should - * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function. - * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA - * and defining its own value for SHMLBA. - * - * The kernel also permits SHMLBA to be set by the architecture to a - * value larger than the page size without setting __ARCH_FORCE_SHMLBA; - * this means that addresses are rounded to the large size if - * SHM_RND is set but addresses not aligned to that size are not rejected - * as long as they are at least page-aligned. Since the only architecture - * which uses this is ia64 this code doesn't provide for that oddity. - */ -static inline abi_ulong target_shmlba(CPUArchState *cpu_env) -{ - return TARGET_PAGE_SIZE; -} -#endif - -static inline abi_ulong do_shmat(CPUArchState *cpu_env, - int shmid, abi_ulong shmaddr, int shmflg) -{ - abi_long raddr; - void *host_raddr; - struct shmid_ds shm_info; - int i,ret; - abi_ulong shmlba; - - /* find out the length of the shared memory segment */ - ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); - if (is_error(ret)) { - /* can't get length, bail out */ - return ret; - } - - shmlba = target_shmlba(cpu_env); - - if (shmaddr & (shmlba - 1)) { - if (shmflg & SHM_RND) { - shmaddr &= ~(shmlba - 1); - } else { - return -TARGET_EINVAL; - } - } - if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) { - return -TARGET_EINVAL; - } - - mmap_lock(); - - if (shmaddr) - host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg); - else { - abi_ulong mmap_start; - - mmap_start = mmap_find_vma(0, shm_info.shm_segsz); - - if (mmap_start == -1) { - errno = ENOMEM; - host_raddr = (void *)-1; - } else - host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP); - } - - if (host_raddr == (void *)-1) { - mmap_unlock(); - return get_errno((long)host_raddr); - } - raddr=h2g((unsigned long)host_raddr); - - page_set_flags(raddr, raddr + shm_info.shm_segsz, - PAGE_VALID | PAGE_READ | - ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE)); - - for (i = 0; i < N_SHM_REGIONS; i++) { - if (!shm_regions[i].in_use) { - shm_regions[i].in_use = true; - shm_regions[i].start = raddr; - shm_regions[i].size = shm_info.shm_segsz; - break; - } - } - - mmap_unlock(); - return raddr; - -} - -static inline abi_long do_shmdt(abi_ulong shmaddr) -{ - int i; - abi_long rv; - - mmap_lock(); - - for (i = 0; i < N_SHM_REGIONS; ++i) { - if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) { - shm_regions[i].in_use = false; - page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0); - break; - } - } - rv = get_errno(shmdt(g2h(shmaddr))); - - mmap_unlock(); - - return rv; -} - -#ifdef TARGET_NR_ipc -/* ??? This only works with linear mappings. */ -/* do_ipc() must return target values and target errnos. */ -static abi_long do_ipc(CPUArchState *cpu_env, - unsigned int call, abi_long first, - abi_long second, abi_long third, - abi_long ptr, abi_long fifth) -{ - int version; - abi_long ret = 0; - - version = call >> 16; - call &= 0xffff; - - switch (call) { - case IPCOP_semop: - ret = do_semop(first, ptr, second); - break; - - case IPCOP_semget: - ret = get_errno(semget(first, second, third)); - break; - - case IPCOP_semctl: { - /* The semun argument to semctl is passed by value, so dereference the - * ptr argument. */ - abi_ulong atptr; - get_user_ual(atptr, ptr); - ret = do_semctl(first, second, third, atptr); - break; - } - - case IPCOP_msgget: - ret = get_errno(msgget(first, second)); - break; - - case IPCOP_msgsnd: - ret = do_msgsnd(first, ptr, second, third); - break; - - case IPCOP_msgctl: - ret = do_msgctl(first, second, ptr); - break; - - case IPCOP_msgrcv: - switch (version) { - case 0: - { - struct target_ipc_kludge { - abi_long msgp; - abi_long msgtyp; - } *tmp; - - if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { - ret = -TARGET_EFAULT; - break; - } - - ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third); - - unlock_user_struct(tmp, ptr, 0); - break; - } - default: - ret = do_msgrcv(first, ptr, second, fifth, third); - } - break; - - case IPCOP_shmat: - switch (version) { - default: - { - abi_ulong raddr; - raddr = do_shmat(cpu_env, first, ptr, second); - if (is_error(raddr)) - return get_errno(raddr); - if (put_user_ual(raddr, third)) - return -TARGET_EFAULT; - break; - } - case 1: - ret = -TARGET_EINVAL; - break; - } - break; - case IPCOP_shmdt: - ret = do_shmdt(ptr); - break; - - case IPCOP_shmget: - /* IPC_* flag values are the same on all linux platforms */ - ret = get_errno(shmget(first, second, third)); - break; - - /* IPC_* and SHM_* command values are the same on all linux platforms */ - case IPCOP_shmctl: - ret = do_shmctl(first, second, ptr); - break; - default: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; - break; - } - return ret; -} -#endif - /* kernel structure types definitions */ #define STRUCT(name, ...) STRUCT_ ## name, @@ -8356,54 +7435,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; -#ifdef TARGET_NR_ipc - case TARGET_NR_ipc: - return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); -#endif -#ifdef TARGET_NR_semget - case TARGET_NR_semget: - return get_errno(semget(arg1, arg2, arg3)); -#endif -#ifdef TARGET_NR_semop - case TARGET_NR_semop: - return do_semop(arg1, arg2, arg3); -#endif -#ifdef TARGET_NR_semctl - case TARGET_NR_semctl: - return do_semctl(arg1, arg2, arg3, arg4); -#endif -#ifdef TARGET_NR_msgctl - case TARGET_NR_msgctl: - return do_msgctl(arg1, arg2, arg3); -#endif -#ifdef TARGET_NR_msgget - case TARGET_NR_msgget: - return get_errno(msgget(arg1, arg2)); -#endif -#ifdef TARGET_NR_msgrcv - case TARGET_NR_msgrcv: - return do_msgrcv(arg1, arg2, arg3, arg4, arg5); -#endif -#ifdef TARGET_NR_msgsnd - case TARGET_NR_msgsnd: - return do_msgsnd(arg1, arg2, arg3, arg4); -#endif -#ifdef TARGET_NR_shmget - case TARGET_NR_shmget: - return get_errno(shmget(arg1, arg2, arg3)); -#endif -#ifdef TARGET_NR_shmctl - case TARGET_NR_shmctl: - return do_shmctl(arg1, arg2, arg3); -#endif -#ifdef TARGET_NR_shmat - case TARGET_NR_shmat: - return do_shmat(cpu_env, arg1, arg2, arg3); -#endif -#ifdef TARGET_NR_shmdt - case TARGET_NR_shmdt: - return do_shmdt(arg1); -#endif case TARGET_NR_fsync: return get_errno(fsync(arg1)); case TARGET_NR_clone: @@ -10930,6 +9961,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, int64_t arg5, int64_t arg6) #include "syscall-file.inc.c" +#include "syscall-ipc.inc.c" #undef SYSCALL_IMPL #undef SYSCALL_ARGS @@ -10970,6 +10002,7 @@ static const SyscallDef *syscall_table(int num) #define SYSCALL_DEF(NAME, ...) case TARGET_NR_##NAME: return &def_##NAME #define SYSCALL_DEF_ARGS(NAME, ...) SYSCALL_DEF(NAME) #define SYSCALL_DEF_FULL(NAME, ...) SYSCALL_DEF(NAME) +#define SYSCALL_TABLE switch (num) { #include "syscall-defs.h" @@ -10979,6 +10012,7 @@ static const SyscallDef *syscall_table(int num) #undef SYSCALL_DEF #undef SYSCALL_DEF_ARGS #undef SYSCALL_DEF_FULL +#undef SYSCALL_TABLE } abi_long do_syscall(void *cpu_env, int num, abi_long arg1, diff --git a/linux-user/strace.list b/linux-user/strace.list index c61b3b9d09..9385ea3dd1 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -455,9 +455,6 @@ #ifdef TARGET_NR_io_submit { TARGET_NR_io_submit, "io_submit" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_ipc -{ TARGET_NR_ipc, "ipc" , NULL, print_ipc, NULL }, -#endif #ifdef TARGET_NR_kcmp { TARGET_NR_kcmp, "kcmp" , NULL, NULL, NULL }, #endif @@ -611,18 +608,6 @@ #ifdef TARGET_NR_mremap { TARGET_NR_mremap, "mremap" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_msgctl -{ TARGET_NR_msgctl, "msgctl" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_msgget -{ TARGET_NR_msgget, "msgget" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_msgrcv -{ TARGET_NR_msgrcv, "msgrcv" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_msgsnd -{ TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_msync { TARGET_NR_msync, "msync" , NULL, NULL, NULL }, #endif @@ -926,9 +911,6 @@ #ifdef TARGET_NR_osf_settimeofday { TARGET_NR_osf_settimeofday, "osf_settimeofday" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_osf_shmat -{ TARGET_NR_osf_shmat, "osf_shmat" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_osf_signal { TARGET_NR_osf_signal, "osf_signal" , NULL, NULL, NULL }, #endif @@ -1202,18 +1184,6 @@ #ifdef TARGET_NR_select { TARGET_NR_select, "select" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_semctl -{ TARGET_NR_semctl, "semctl" , NULL, print_semctl, NULL }, -#endif -#ifdef TARGET_NR_semget -{ TARGET_NR_semget, "semget" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_semop -{ TARGET_NR_semop, "semop" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_semtimedop -{ TARGET_NR_semtimedop, "semtimedop" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_send { TARGET_NR_send, "send" , NULL, NULL, NULL }, #endif @@ -1341,18 +1311,6 @@ #ifdef TARGET_NR_sgetmask { TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_shmat -{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr }, -#endif -#ifdef TARGET_NR_shmctl -{ TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_shmdt -{ TARGET_NR_shmdt, "shmdt" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_shmget -{ TARGET_NR_shmget, "shmget" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_shutdown { TARGET_NR_shutdown, "shutdown" , NULL, NULL, NULL }, #endif From patchwork Wed Dec 19 04:21:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154230 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4501392ljp; Tue, 18 Dec 2018 20:27:23 -0800 (PST) X-Google-Smtp-Source: AFSGD/VhzAv8IEPDX/ASdkyvfuopGWGqzJJLmQOA1lgDnlDCIg9FhfgcREC8KnuOCkAhL5AE2Bvq X-Received: by 2002:ac8:67da:: with SMTP id r26mr20587312qtp.350.1545193643060; Tue, 18 Dec 2018 20:27:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193643; cv=none; d=google.com; s=arc-20160816; b=mzJfhMkZ3ahuzsOnwV9bm2ZxCTwe+x+PjWjpSNcUiiemdzKSd/pvs08QC0wAkAw9Q2 aMiaYz/SyweaUuBr1VKmcRg3Q0ba4saytBRLewakkhbBXAekuREJ8k7f9h1hpQ6BxNNU hmCcqyULMgShD+AYo1v6sF2qWXGfrKtx9gxhS6xFL3hDxwn1s06f1MZ/IwW/euD7Qjde ALVhsL/1ejf4nj1RLx9AWaqjvr47jmT/BtxyaKKFAw9UBuSZTMcGqTsit24CS2YFQcLk N4zWXyq0vldElTHvOBpZYuriRtiV2Sxwy+C2qbrpXoj4smd7d6eHAjkZfjyjsbmL+j3a IQ8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=HCD/nBzAuB7ZbyQ4yDm35FfatvAb1AXFeU5pfuMaHsg=; b=c20dJYpMd6yeYNDU8Qf5zN+xMbN5OZ6lmifDWHTFILGydULJrPQ4YBFLMCqgCeaUfL FCvqj2gGm2JJxSxbfv1lWgta80B3c+Tzg9Vx4J2KHUspPJ4pE1dgy/ILtvVL2afeTB4D q/69MdDH1Fai1lxYtF3AiHgE2kj2BQTBTGyyWQ/Qz249mIt5zaeG5fyUYdjkxc7JPtRI /EjqozkUoguGdOPHdvPFdLUj4DToAisIx5ZG8ketFg48q8yJYdJj/WNnM/V/JrLDpnfS sFHZ2Nv/vn2CM15CHeb0gxdSCWTAezrzqnnvQ90YT2i2kFKf1gC6hi86M3KfuS77Ehjw wLzQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=T0xPg0hl; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id o14si1291869qtr.110.2018.12.18.20.27.22 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:27:23 -0800 (PST) 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 header.s=google header.b=T0xPg0hl; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57543 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTS6-00081X-BJ for patch@linaro.org; Tue, 18 Dec 2018 23:27:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51221) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRV-0007vd-WA for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMS-0006Rb-62 for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:36 -0500 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]:43814) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMO-0006NQ-CB for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:29 -0500 Received: by mail-pg1-x544.google.com with SMTP id v28so8839632pgk.10 for ; Tue, 18 Dec 2018 20:21:26 -0800 (PST) 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=HCD/nBzAuB7ZbyQ4yDm35FfatvAb1AXFeU5pfuMaHsg=; b=T0xPg0hlXeLPEJu0sADhoWQCeIlmgaTMakR33FrQQ7Ld2hjJBZLldoHSyEACciRBNe ESHQ4F/ASyO3v1JIgBW2Tfkjvk328EbCb9IZ65YDSrSclqrMGY3dOLynJlgu7MppW25p d6a1q0XCGzucOgYm2HJruBQOUM9eia1mkGjyg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HCD/nBzAuB7ZbyQ4yDm35FfatvAb1AXFeU5pfuMaHsg=; b=SY+wmpHVOn5zAhLEBCKYA9ZdKMOtq8AB3ratJd3dCZ3pUBr1uiF1Qg4l5KZe4j2CoX AKrGNbgmHQFB/QjTMtziclDF3TKYKC6arnZ84cbarzNy1q4iykHeMOoAy4H+VbVDuwNh 439Dt+iOV8XgYhJuunA56+WZOkmjEcuJxoCgxd9uOCa1+lSrYFgomwhNfhitGntDDude 8Yh0T7tEFJtjXBPyuS8sFR3kdmlJm7q7rfuIh4TO6VcW5fl6UBH4VVlnD/0iZcXIip+U 0I3HhlgHChPjtF/1MNlWOFJsuQdgf8ngYtoBHw/B0WhoOnPWlO/nzozqip2OjuASoZCC FrqA== X-Gm-Message-State: AA+aEWYc9SIs1JBi1Ex0wUQ9daWEMCjXfRJzFIDfOI6gdBCJ1+6jpF4g IUUnruK3I6miUz44dIJ1rJAiPhAhYQM= X-Received: by 2002:a63:194f:: with SMTP id 15mr18303162pgz.192.1545193284896; Tue, 18 Dec 2018 20:21:24 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:24 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:12 -0800 Message-Id: <20181219042113.7364-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::544 Subject: [Qemu-devel] [PATCH v5 7/8] linux-user: Split out memory syscalls 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" This includes mmap, mmap2, munmap, mlock, mlockall, munlock, munlockall, mprotect, mremap, msync. Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 24 ++++++ linux-user/syscall.h | 2 + linux-user/strace.c | 55 ++----------- linux-user/syscall-mem.inc.c | 154 +++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 119 +-------------------------- linux-user/strace.list | 33 -------- 6 files changed, 189 insertions(+), 198 deletions(-) create mode 100644 linux-user/syscall-mem.inc.c -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index 2712867228..a057aa9150 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -20,6 +20,26 @@ SYSCALL_DEF(close, ARG_DEC); #ifdef TARGET_NR_ipc SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX); #endif +SYSCALL_DEF(mlock, ARG_PTR, ARG_DEC); +SYSCALL_DEF(mlockall, ARG_HEX); +#ifdef TARGET_NR_mmap +SYSCALL_DEF_FULL(mmap, .impl = impl_mmap, + .args = args_mmap, + .print_ret = print_syscall_ptr_ret, + .arg_type = { ARG_PTR, ARG_DEC, ARG_MMAPPROT, + ARG_MMAPFLAG, ARG_DEC, ARG_DEC }); +#endif +#ifdef TARGET_NR_mmap2 +SYSCALL_DEF_FULL(mmap2, .impl = impl_mmap, + .args = args_mmap2, + .print_ret = print_syscall_ptr_ret, + .arg_type = { ARG_PTR, ARG_DEC, ARG_MMAPPROT, + ARG_MMAPFLAG, ARG_DEC, ARG_DEC64 }); +#endif +SYSCALL_DEF(mprotect, ARG_PTR, ARG_DEC, ARG_MMAPPROT); +SYSCALL_DEF_FULL(mremap, .impl = impl_mremap, + .print_ret = print_syscall_ptr_ret, + .arg_type = { ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR }); #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgctl) SYSCALL_DEF(msgctl, ARG_DEC, ARG_DEC, ARG_PTR); #endif @@ -32,6 +52,10 @@ SYSCALL_DEF(msgrcv, ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC, ARG_HEX); #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_msgsnd) SYSCALL_DEF(msgsnd, ARG_DEC, ARG_PTR, ARG_DEC, ARG_HEX); #endif +SYSCALL_DEF(msync, ARG_PTR, ARG_DEC, ARG_HEX); +SYSCALL_DEF(munlock, ARG_PTR, ARG_DEC); +SYSCALL_DEF(munlockall); +SYSCALL_DEF(munmap, ARG_PTR, ARG_DEC); #ifdef TARGET_NR_open SYSCALL_DEF(open, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG); #endif diff --git a/linux-user/syscall.h b/linux-user/syscall.h index 83f602f8e7..8175de4c31 100644 --- a/linux-user/syscall.h +++ b/linux-user/syscall.h @@ -58,6 +58,8 @@ typedef enum { /* These print as sets of flags. */ ARG_ATDIRFD, ARG_ATFLAG, + ARG_MMAPFLAG, + ARG_MMAPPROT, ARG_MODEFLAG, ARG_OPENFLAG, diff --git a/linux-user/strace.c b/linux-user/strace.c index 95cf9837cf..8bc7338af8 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -801,7 +801,7 @@ UNUSED static struct flags umount2_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_prot_flags[] = { +static struct flags const mmap_prot_flags[] = { FLAG_GENERIC(PROT_NONE), FLAG_GENERIC(PROT_EXEC), FLAG_GENERIC(PROT_READ), @@ -812,7 +812,7 @@ UNUSED static struct flags mmap_prot_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_flags[] = { +static struct flags const mmap_flags[] = { FLAG_TARGET(MAP_SHARED), FLAG_TARGET(MAP_PRIVATE), FLAG_TARGET(MAP_ANONYMOUS), @@ -2414,51 +2414,6 @@ print_utimensat(const struct syscallname *name, } #endif -#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2) -static void -print_mmap(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) -{ - print_syscall_prologue(name); - print_pointer(arg0, 0); - print_raw_param("%d", arg1, 0); - print_flags(mmap_prot_flags, arg2, 0); - print_flags(mmap_flags, arg3, 0); - print_raw_param("%d", arg4, 0); - print_raw_param("%#x", arg5, 1); - print_syscall_epilogue(name); -} -#define print_mmap2 print_mmap -#endif - -#ifdef TARGET_NR_mprotect -static void -print_mprotect(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) -{ - print_syscall_prologue(name); - print_pointer(arg0, 0); - print_raw_param("%d", arg1, 0); - print_flags(mmap_prot_flags, arg2, 1); - print_syscall_epilogue(name); -} -#endif - -#ifdef TARGET_NR_munmap -static void -print_munmap(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) -{ - print_syscall_prologue(name); - print_pointer(arg0, 0); - print_raw_param("%d", arg1, 1); - print_syscall_epilogue(name); -} -#endif - #ifdef TARGET_NR_futex static void print_futex_op(abi_long tflag, int last) { @@ -2665,6 +2620,12 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6]) case ARG_ATFLAG: len = add_flags(b, rest, at_file_flags, arg, false); break; + case ARG_MMAPFLAG: + len = add_flags(b, rest, mmap_flags, arg, false); + break; + case ARG_MMAPPROT: + len = add_flags(b, rest, mmap_prot_flags, arg, false); + break; case ARG_MODEFLAG: len = add_flags(b, rest, mode_flags, arg, true); break; diff --git a/linux-user/syscall-mem.inc.c b/linux-user/syscall-mem.inc.c new file mode 100644 index 0000000000..d2ce0cb8cc --- /dev/null +++ b/linux-user/syscall-mem.inc.c @@ -0,0 +1,154 @@ +/* + * Linux memory-related syscalls + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +static bitmask_transtbl const mmap_flags_tbl[] = { + { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, + { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, + { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, + { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, + MAP_ANONYMOUS, MAP_ANONYMOUS }, + { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, + MAP_GROWSDOWN, MAP_GROWSDOWN }, + { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, + MAP_DENYWRITE, MAP_DENYWRITE }, + { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, + MAP_EXECUTABLE, MAP_EXECUTABLE }, + { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, + { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, + MAP_NORESERVE, MAP_NORESERVE }, + { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB }, + /* + * MAP_STACK had been ignored by the kernel for quite some time. + * Recognize it for the target insofar as we do not want to pass + * it through to the host. + */ + { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 }, + { 0, 0, 0, 0 } +}; + + +SYSCALL_IMPL(mlock) +{ + return get_errno(mlock(g2h(arg1), arg2)); +} + +SYSCALL_IMPL(mlockall) +{ + int host_flag = 0; + if (arg1 & TARGET_MLOCKALL_MCL_CURRENT) { + host_flag |= MCL_CURRENT; + } + if (arg1 & TARGET_MLOCKALL_MCL_FUTURE) { + host_flag |= MCL_FUTURE; + } + return get_errno(mlockall(host_flag)); +} + +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ + (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ + defined(TARGET_M68K) || defined(TARGET_CRIS) || \ + defined(TARGET_MICROBLAZE) || defined(TARGET_S390X) +SYSCALL_ARGS(mmap) +{ + abi_ulong ptr = in[0]; + abi_long *v = lock_user(VERIFY_READ, ptr, 6 * sizeof(abi_long), 1); + if (v == NULL) { + errno = EFAULT; + return NULL; + } + out[0] = tswapal(v[0]); + out[1] = tswapal(v[1]); + out[2] = tswapal(v[2]); + out[3] = tswapal(v[3]); + out[4] = tswapal(v[4]); + out[5] = tswapal(v[5]); + unlock_user(v, ptr, 0); + return def; +} +#else +# define args_mmap NULL +#endif + +SYSCALL_IMPL(mmap) +{ + int host_flags = target_to_host_bitmask(arg4, mmap_flags_tbl); + return get_errno(target_mmap(arg1, arg2, arg3, host_flags, arg5, arg6)); +} + +#ifdef TARGET_NR_mmap2 +/* + * Define mmap2 in terms of mmap. + * !!! Note that there is a fundamental problem here in that + * target_mmap has an offset parameter that is abi_ulong + * and not off_t. This means that we cannot actually pass + * through a 64-bit file offset as intended. + */ + +#ifndef MMAP_SHIFT +# define MMAP_SHIFT 12 +#endif + +SYSCALL_ARGS(mmap2) +{ + /* We have already assigned out[0-4]. */ + out[5] = (uint64_t)(abi_ulong)in[5] << MMAP_SHIFT; + return def; +} +#endif + +SYSCALL_IMPL(mprotect) +{ + CPUState *cpu = ENV_GET_CPU(cpu_env); + TaskState *ts = cpu->opaque; + + /* Special hack to detect libc making the stack executable. */ + if ((arg3 & PROT_GROWSDOWN) + && arg1 >= ts->info->stack_limit + && arg1 <= ts->info->start_stack) { + arg3 &= ~PROT_GROWSDOWN; + arg2 = arg2 + arg1 - ts->info->stack_limit; + arg1 = ts->info->stack_limit; + } + return get_errno(target_mprotect(arg1, arg2, arg3)); +} + +SYSCALL_IMPL(mremap) +{ + return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); +} + +SYSCALL_IMPL(msync) +{ + return get_errno(msync(g2h(arg1), arg2, arg3)); +} + +SYSCALL_IMPL(munlock) +{ + return get_errno(munlock(g2h(arg1), arg2)); +} + +SYSCALL_IMPL(munlockall) +{ + return get_errno(munlockall()); +} + +SYSCALL_IMPL(munmap) +{ + return get_errno(target_munmap(arg1, arg2)); +} diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 249eb85d4a..fda7376e58 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4091,29 +4091,6 @@ static const StructEntry struct_termios_def = { .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) }, }; -static bitmask_transtbl mmap_flags_tbl[] = { - { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, - { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, - { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, - { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, - MAP_ANONYMOUS, MAP_ANONYMOUS }, - { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, - MAP_GROWSDOWN, MAP_GROWSDOWN }, - { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, - MAP_DENYWRITE, MAP_DENYWRITE }, - { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, - MAP_EXECUTABLE, MAP_EXECUTABLE }, - { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, - { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, - MAP_NORESERVE, MAP_NORESERVE }, - { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB }, - /* MAP_STACK had been ignored by the kernel for quite some time. - Recognize it for the target insofar as we do not want to pass - it through to the host. */ - { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 }, - { 0, 0, 0, 0 } -}; - #if defined(TARGET_I386) /* NOTE: there is really one LDT for all the threads */ @@ -5334,21 +5311,6 @@ static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp, return 0; } -#if defined(TARGET_NR_mlockall) -static inline int target_to_host_mlockall_arg(int arg) -{ - int result = 0; - - if (arg & TARGET_MLOCKALL_MCL_CURRENT) { - result |= MCL_CURRENT; - } - if (arg & TARGET_MLOCKALL_MCL_FUTURE) { - result |= MCL_FUTURE; - } - return result; -} -#endif - #if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \ defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \ defined(TARGET_NR_newfstatat)) @@ -6958,86 +6920,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, ret = get_errno(reboot(arg1, arg2, arg3, NULL)); } return ret; -#ifdef TARGET_NR_mmap - case TARGET_NR_mmap: -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ - (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ - defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \ - || defined(TARGET_S390X) - { - abi_ulong *v; - abi_ulong v1, v2, v3, v4, v5, v6; - if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1))) - return -TARGET_EFAULT; - v1 = tswapal(v[0]); - v2 = tswapal(v[1]); - v3 = tswapal(v[2]); - v4 = tswapal(v[3]); - v5 = tswapal(v[4]); - v6 = tswapal(v[5]); - unlock_user(v, arg1, 0); - ret = get_errno(target_mmap(v1, v2, v3, - target_to_host_bitmask(v4, mmap_flags_tbl), - v5, v6)); - } -#else - ret = get_errno(target_mmap(arg1, arg2, arg3, - target_to_host_bitmask(arg4, mmap_flags_tbl), - arg5, - arg6)); -#endif - return ret; -#endif -#ifdef TARGET_NR_mmap2 - case TARGET_NR_mmap2: -#ifndef MMAP_SHIFT -#define MMAP_SHIFT 12 -#endif - ret = target_mmap(arg1, arg2, arg3, - target_to_host_bitmask(arg4, mmap_flags_tbl), - arg5, arg6 << MMAP_SHIFT); - return get_errno(ret); -#endif - case TARGET_NR_munmap: - return get_errno(target_munmap(arg1, arg2)); - case TARGET_NR_mprotect: - { - TaskState *ts = cpu->opaque; - /* Special hack to detect libc making the stack executable. */ - if ((arg3 & PROT_GROWSDOWN) - && arg1 >= ts->info->stack_limit - && arg1 <= ts->info->start_stack) { - arg3 &= ~PROT_GROWSDOWN; - arg2 = arg2 + arg1 - ts->info->stack_limit; - arg1 = ts->info->stack_limit; - } - } - return get_errno(target_mprotect(arg1, arg2, arg3)); -#ifdef TARGET_NR_mremap - case TARGET_NR_mremap: - return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); -#endif - /* ??? msync/mlock/munlock are broken for softmmu. */ -#ifdef TARGET_NR_msync - case TARGET_NR_msync: - return get_errno(msync(g2h(arg1), arg2, arg3)); -#endif -#ifdef TARGET_NR_mlock - case TARGET_NR_mlock: - return get_errno(mlock(g2h(arg1), arg2)); -#endif -#ifdef TARGET_NR_munlock - case TARGET_NR_munlock: - return get_errno(munlock(g2h(arg1), arg2)); -#endif -#ifdef TARGET_NR_mlockall - case TARGET_NR_mlockall: - return get_errno(mlockall(target_to_host_mlockall_arg(arg1))); -#endif -#ifdef TARGET_NR_munlockall - case TARGET_NR_munlockall: - return get_errno(munlockall()); -#endif #ifdef TARGET_NR_truncate case TARGET_NR_truncate: if (!(p = lock_user_string(arg1))) @@ -9962,6 +9844,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #include "syscall-file.inc.c" #include "syscall-ipc.inc.c" +#include "syscall-mem.inc.c" #undef SYSCALL_IMPL #undef SYSCALL_ARGS diff --git a/linux-user/strace.list b/linux-user/strace.list index 9385ea3dd1..ac7cf77021 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -557,21 +557,6 @@ #ifdef TARGET_NR_mknodat { TARGET_NR_mknodat, "mknodat" , NULL, print_mknodat, NULL }, #endif -#ifdef TARGET_NR_mlock -{ TARGET_NR_mlock, "mlock" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_mlock2 -{ TARGET_NR_mlock2, "mlock2" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_mlockall -{ TARGET_NR_mlockall, "mlockall" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_mmap -{ TARGET_NR_mmap, "mmap" , NULL, print_mmap, print_syscall_ret_addr }, -#endif -#ifdef TARGET_NR_mmap2 -{ TARGET_NR_mmap2, "mmap2" , NULL, print_mmap2, print_syscall_ret_addr }, -#endif #ifdef TARGET_NR_modify_ldt { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL }, #endif @@ -581,9 +566,6 @@ #ifdef TARGET_NR_move_pages { TARGET_NR_move_pages, "move_pages" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_mprotect -{ TARGET_NR_mprotect, "mprotect" , NULL, print_mprotect, NULL }, -#endif #ifdef TARGET_NR_mpx { TARGET_NR_mpx, "mpx" , NULL, NULL, NULL }, #endif @@ -605,24 +587,9 @@ #ifdef TARGET_NR_mq_unlink { TARGET_NR_mq_unlink, "mq_unlink" , NULL, print_mq_unlink, NULL }, #endif -#ifdef TARGET_NR_mremap -{ TARGET_NR_mremap, "mremap" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_msync -{ TARGET_NR_msync, "msync" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_multiplexer { TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_munlock -{ TARGET_NR_munlock, "munlock" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_munlockall -{ TARGET_NR_munlockall, "munlockall" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_munmap -{ TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL }, -#endif #ifdef TARGET_NR_nanosleep { TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL }, #endif From patchwork Wed Dec 19 04:21:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 154232 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4502903ljp; Tue, 18 Dec 2018 20:29:52 -0800 (PST) X-Google-Smtp-Source: AFSGD/XZXHCXek1tccDfUeJZKdq3Ksru4ddjNgqkMNnSOOm+EoxXrU98faEVCs/79i8PS4c8pTJl X-Received: by 2002:a05:6214:1087:: with SMTP id o7mr20245292qvr.115.1545193792772; Tue, 18 Dec 2018 20:29:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545193792; cv=none; d=google.com; s=arc-20160816; b=W9h0UpSAAJ3adx8L1ynKbu6NMmm9r/V8H7X6cFRLZhDk1m7YaTYiTQEKZJnYQB1mjw BgwaqW7bZnOO/0o2Eblp/nOJO+4yoxPLfDRIvXjCwdd3fhP+QQkqJAQKnNqu0d49tz1+ 6Wi01B6ess2UkSqaI2c9vZVde9FDQN6wrrjzUSo3tW9XJm4N+iaRANRn+UHATN7wHk+e NPcDArUOGvkDf7Njje3LB5QDhl98/qPryDHB5g2Sec+AVhtghy+kElRA7voWrz0EZs7Y Tsyk/RR64R1SJD9dztbvzG6dVO2hCL/CJlu0QUikRhovF57r0S3BNAvO0nmU9YFLt+tD TGaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=pUhyKy1kUFhDIv3AgsDpkwpM37KaUZyg4MPBbA09fWQ=; b=UgixQ/aZAxNzWPXyspiAB1tcH3gUTqWu6A9P3g4cBAipHG7abxeNcGF9v3+gGIZZk4 eoCKis7+gR8jgNKBcG8NyMF6lG6qj9EELzrHYD6KQEZ4iCLXjB9kR1wF74KXf2YPS8bP o0k5h73b6CmdBbRg73Lti/MXIt0VRp30pOyLkMivLeQb8SB6y6Ov+fq/dVL91t/GhstE BlTKlSTO9+r2mcUOdEktfUG45o+4aJDqPNxYjsDxvZTylRCv0wT4VMFewEWRmN4sAgwo /X07RhsYOl/SXQffL4hpTiZkp24kkM2SxiG21VGpjSFSjh6sfrLoPv0dCXwkOdsoY7iQ hSfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=c4YPSpZS; 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 sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id k8si1271280qtj.365.2018.12.18.20.29.52 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 18 Dec 2018 20:29:52 -0800 (PST) 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 header.s=google header.b=c4YPSpZS; 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 sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:57553 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTUW-0001pb-3E for patch@linaro.org; Tue, 18 Dec 2018 23:29:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51214) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZTRV-0007vI-Vh for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:26:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZTMS-0006TD-HR for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:38 -0500 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]:34625) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gZTMQ-0006Pb-AX for qemu-devel@nongnu.org; Tue, 18 Dec 2018 23:21:32 -0500 Received: by mail-pl1-x642.google.com with SMTP id w4so8868779plz.1 for ; Tue, 18 Dec 2018 20:21:28 -0800 (PST) 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=pUhyKy1kUFhDIv3AgsDpkwpM37KaUZyg4MPBbA09fWQ=; b=c4YPSpZSFp6tNB9bVkDdQqygJsnpow+0RCT9UinQ++IM4FdKaDKDgkpuseaOyRAZ/i 2E17LVGOzD6OF5qvIeDF4jPHTeqvipllv9kVEOkyvgDzJEAj9936OxFgD2OY1noInYMK a4ktGDp9RgvSmvTMUyygByRlavLJyZEkBtGFo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=pUhyKy1kUFhDIv3AgsDpkwpM37KaUZyg4MPBbA09fWQ=; b=n+nUX0X8KfToupw8bhRzREtc5IZBcyK8Vzi6qsVDKP5x1Jm8PdozMyR4ZCc1TShBGz eEW6jbj/flVPnzJncyPlB7KFtP5EmLfXw2okhUcqZmFwSDe5viwFLQKTg4azjHwFWtpD mdHhk/9ZJLoKR18PA5+BDIBJq6Y68IDrvcRrVkAIQk3a8fO23G/sEp1yLM4VOq71mcdI KinpLJkKAUbNiO1oNNQkTw/l8jm+4BkuDJB+lne6gCaWXe1CZ3OwZL/1X4gWEaMaIAU7 1/RzY+o9BHjr3f655DYoavujio9cdIl/Y2HmeLqtBqlnETzUR+gPxnk5qpUSWOyCJL1E qJxQ== X-Gm-Message-State: AA+aEWYVEhcvnf5EfNLfmw+Sxx3AP9iISPDPOWcekK6lPx3VTnn0dOnh lbfo30eakKv6U9KjDXBgGsz4N23ZYMU= X-Received: by 2002:a17:902:9006:: with SMTP id a6mr18737491plp.334.1545193286371; Tue, 18 Dec 2018 20:21:26 -0800 (PST) Received: from cloudburst.twiddle.net (97-126-115-157.tukw.qwest.net. [97.126.115.157]) by smtp.gmail.com with ESMTPSA id f64sm47287228pfh.0.2018.12.18.20.21.25 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 20:21:25 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 20:21:13 -0800 Message-Id: <20181219042113.7364-9-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181219042113.7364-1-richard.henderson@linaro.org> References: <20181219042113.7364-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::642 Subject: [Qemu-devel] [PATCH v5 8/8] linux-user: Split out some process syscalls 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: laurent@vivier.eu Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" This includes clone, getgroups, gettid, setfsgid, setfsuid, setgroups, setsid, setuid, fork, getegid, getegid32, geteuid, geteuid32, getgid, getgid32, getgroups32, getpgrp, getpid, getppid, getresgid, getresgid32, getresuid, getresuid32, getuid, getuid32, getxgid, getxpid, getxuid, setfsgid32, setgsuid32, setgid32, setgroups32, setregid, setregid32, setresgid, setresgid32, setresuid, setresuid32, setreuid, setreuid32, setuid32, vfork. Signed-off-by: Richard Henderson --- linux-user/syscall-defs.h | 121 +++++ linux-user/syscall.h | 1 + linux-user/strace.c | 36 +- linux-user/syscall-proc.inc.c | 861 ++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 677 +------------------------- linux-user/strace.list | 147 ------ 6 files changed, 988 insertions(+), 855 deletions(-) create mode 100644 linux-user/syscall-proc.inc.c -- 2.17.2 diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h index a057aa9150..a7f78793fd 100644 --- a/linux-user/syscall-defs.h +++ b/linux-user/syscall-defs.h @@ -16,7 +16,80 @@ * along with this program; if not, see . */ +SYSCALL_DEF_ARGS(clone, ARG_CLONEFLAG, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR); SYSCALL_DEF(close, ARG_DEC); +#ifdef TARGET_NR_fork +SYSCALL_DEF(fork); +#endif +#ifdef TARGET_NR_getegid +SYSCALL_DEF(getegid); +#endif +#ifdef TARGET_NR_getegid32 +SYSCALL_DEF(getegid32); +#endif +#ifdef TARGET_NR_geteuid +SYSCALL_DEF(geteuid); +#endif +#ifdef TARGET_NR_geteuid32 +SYSCALL_DEF(geteuid32); +#endif +#ifdef TARGET_NR_getgid +SYSCALL_DEF(getgid); +#endif +#ifdef TARGET_NR_getgid32 +SYSCALL_DEF(getgid32); +#endif +SYSCALL_DEF(getgroups, ARG_DEC, ARG_PTR); +#ifdef TARGET_NR_getgroups32 +SYSCALL_DEF(getgroups32, ARG_DEC, ARG_PTR); +#endif +#ifdef TARGET_NR_getresgid +SYSCALL_DEF(getresgid, ARG_PTR, ARG_PTR, ARG_PTR); +#endif +#ifdef TARGET_NR_getresgid32 +SYSCALL_DEF(getresgid32, ARG_PTR, ARG_PTR, ARG_PTR); +#endif +#ifdef TARGET_NR_getresuid +SYSCALL_DEF(getresuid, ARG_PTR, ARG_PTR, ARG_PTR); +#endif +#ifdef TARGET_NR_getresuid32 +SYSCALL_DEF(getresuid32, ARG_PTR, ARG_PTR, ARG_PTR); +#endif +#ifdef TARGET_NR_getpgrp +SYSCALL_DEF(getpgrp); +#endif +#ifdef TARGET_NR_getpid +SYSCALL_DEF(getpid); +#endif +#ifdef TARGET_NR_getppid +SYSCALL_DEF(getppid); +#endif +SYSCALL_DEF(gettid); +#ifdef TARGET_NR_getuid +SYSCALL_DEF(getuid); +#endif +#ifdef TARGET_NR_getuid32 +SYSCALL_DEF(getuid32); +#endif +#ifdef TARGET_NR_getxgid +SYSCALL_DEF(getxgid); +#endif +#ifdef TARGET_NR_getxpid +SYSCALL_DEF(getxpid); +#endif +#ifdef TARGET_NR_getxuid +SYSCALL_DEF(getxuid); +#endif +#ifdef TARGET_NR_get_thread_area +# if defined(TARGET_I386) && defined(TARGET_ABI32) +SYSCALL_DEF_FULL(get_thread_area, .impl = impl_get_thread_area, + .print_ret = print_syscall_ptr_ret, + .arg_type = { ARG_PTR }); +# else +SYSCALL_DEF_FULL(get_thread_area, .impl = impl_get_thread_area, + .print_ret = print_syscall_ptr_ret); +# endif +#endif #ifdef TARGET_NR_ipc SYSCALL_DEF_ARGS(ipc, ARG_HEX, ARG_DEC, ARG_DEC, ARG_HEX, ARG_PTR, ARG_HEX); #endif @@ -92,6 +165,51 @@ SYSCALL_DEF(semget, ARG_DEC, ARG_DEC, ARG_HEX); #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semop) SYSCALL_DEF(semop, ARG_DEC, ARG_PTR, ARG_DEC); #endif +SYSCALL_DEF(setfsgid, ARG_DEC); +#ifdef TARGET_NR_setfsgid32 +SYSCALL_DEF(setfsgid32, ARG_DEC); +#endif +SYSCALL_DEF(setfsuid, ARG_DEC); +#ifdef TARGET_NR_setfsuid32 +SYSCALL_DEF(setfsuid32, ARG_DEC); +#endif +SYSCALL_DEF(setgid, ARG_DEC); +#ifdef TARGET_NR_setgid32 +SYSCALL_DEF(setgid32, ARG_DEC); +#endif +SYSCALL_DEF(setgroups, ARG_DEC, ARG_PTR); +#ifdef TARGET_NR_setgroups32 +SYSCALL_DEF(setgroups32, ARG_DEC, ARG_PTR); +#endif +SYSCALL_DEF(setregid, ARG_DEC, ARG_DEC); +#ifdef TARGET_NR_setregid32 +SYSCALL_DEF(setregid32, ARG_DEC, ARG_DEC); +#endif +#ifdef TARGET_NR_setresgid +SYSCALL_DEF(setresgid, ARG_DEC, ARG_DEC, ARG_DEC); +#endif +#ifdef TARGET_NR_setresgid32 +SYSCALL_DEF(setresgid32, ARG_DEC, ARG_DEC, ARG_DEC); +#endif +#ifdef TARGET_NR_setresuid +SYSCALL_DEF(setresuid, ARG_DEC, ARG_DEC, ARG_DEC); +#endif +#ifdef TARGET_NR_setresuid32 +SYSCALL_DEF(setresuid32, ARG_DEC, ARG_DEC, ARG_DEC); +#endif +SYSCALL_DEF(setreuid, ARG_DEC, ARG_DEC); +#ifdef TARGET_NR_setreuid32 +SYSCALL_DEF(setreuid32, ARG_DEC, ARG_DEC); +#endif +SYSCALL_DEF(setsid); +SYSCALL_DEF(setuid, ARG_DEC); +#ifdef TARGET_NR_setuid32 +SYSCALL_DEF(setuid32, ARG_DEC); +#endif +#ifdef TARGET_NR_set_thread_area +SYSCALL_DEF(set_thread_area, ARG_PTR); +#endif +SYSCALL_DEF(set_tid_address, ARG_PTR); #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_shmat) SYSCALL_DEF_FULL(shmat, .impl = impl_shmat, .print_ret = print_syscall_ptr_ret, @@ -108,3 +226,6 @@ SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX); #endif SYSCALL_DEF(write, ARG_DEC, ARG_PTR, ARG_DEC); SYSCALL_DEF(writev, ARG_DEC, ARG_PTR, ARG_DEC); +#ifdef TARGET_NR_vfork +SYSCALL_DEF(vfork); +#endif diff --git a/linux-user/syscall.h b/linux-user/syscall.h index 8175de4c31..f75cd3ddd0 100644 --- a/linux-user/syscall.h +++ b/linux-user/syscall.h @@ -58,6 +58,7 @@ typedef enum { /* These print as sets of flags. */ ARG_ATDIRFD, ARG_ATFLAG, + ARG_CLONEFLAG, ARG_MMAPFLAG, ARG_MMAPPROT, ARG_MODEFLAG, diff --git a/linux-user/strace.c b/linux-user/strace.c index 8bc7338af8..19b0403d74 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -836,7 +836,7 @@ static struct flags const mmap_flags[] = { FLAG_END, }; -UNUSED static struct flags clone_flags[] = { +static struct flags const clone_flags[] = { FLAG_GENERIC(CLONE_VM), FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FILES), @@ -1218,37 +1218,6 @@ print_clock_adjtime(const struct syscallname *name, } #endif -#ifdef TARGET_NR_clone -static void do_print_clone(unsigned int flags, abi_ulong newsp, - abi_ulong parent_tidptr, target_ulong newtls, - abi_ulong child_tidptr) -{ - print_flags(clone_flags, flags, 0); - print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, newsp, 0); - print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, parent_tidptr, 0); - print_raw_param("tls=0x" TARGET_ABI_FMT_lx, newtls, 0); - print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, child_tidptr, 1); -} - -static void -print_clone(const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) -{ - print_syscall_prologue(name); -#if defined(TARGET_MICROBLAZE) - do_print_clone(arg1, arg2, arg4, arg6, arg5); -#elif defined(TARGET_CLONE_BACKWARDS) - do_print_clone(arg1, arg2, arg3, arg4, arg5); -#elif defined(TARGET_CLONE_BACKWARDS2) - do_print_clone(arg2, arg1, arg3, arg5, arg4); -#else - do_print_clone(arg1, arg2, arg3, arg5, arg4); -#endif - print_syscall_epilogue(name); -} -#endif - #ifdef TARGET_NR_creat static void print_creat(const struct syscallname *name, @@ -2620,6 +2589,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6]) case ARG_ATFLAG: len = add_flags(b, rest, at_file_flags, arg, false); break; + case ARG_CLONEFLAG: + len = add_flags(b, rest, clone_flags, arg, false); + break; case ARG_MMAPFLAG: len = add_flags(b, rest, mmap_flags, arg, false); break; diff --git a/linux-user/syscall-proc.inc.c b/linux-user/syscall-proc.inc.c new file mode 100644 index 0000000000..dee441b4ff --- /dev/null +++ b/linux-user/syscall-proc.inc.c @@ -0,0 +1,861 @@ +/* + * Linux process related syscalls + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +/* + * 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) + +#ifndef __NR_gettid +#define __NR_gettid -1 +#endif +_syscall0(int, gettid) + +#ifndef __NR_set_tid_address +#define __NR_set_tid_address -1 +#endif +_syscall1(int, set_tid_address, int *, tidptr) + + +/* + * CLONE_VFORK is special cased early in do_fork(). The other flag bits + * have almost all been allocated. We cannot support any of + * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC, + * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED. + * The checks against the invalid thread masks above will catch these. + * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.) + */ + +#ifndef CLONE_IO +#define CLONE_IO 0x80000000 /* Clone io context */ +#endif + +/* + * We can't directly call the host clone syscall, because this will + * badly confuse libc (breaking mutexes, for example). So we must + * divide clone flags into: + * * flag combinations that look like pthread_create() + * * flag combinations that look like fork() + * * flags we can implement within QEMU itself + * * flags we can't support and will return an error for + * + * For thread creation, all these flags must be present; for + * fork, none must be present. + */ +#define CLONE_THREAD_FLAGS \ + (CLONE_VM | CLONE_FS | CLONE_FILES | \ + CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM) + +/* + * These flags are ignored: + * CLONE_DETACHED is now ignored by the kernel; + * CLONE_IO is just an optimisation hint to the I/O scheduler + */ +#define CLONE_IGNORED_FLAGS \ + (CLONE_DETACHED | CLONE_IO) + +/* Flags for fork which we can implement within QEMU itself */ +#define CLONE_OPTIONAL_FORK_FLAGS \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) + +/* Flags for thread creation which we can implement within QEMU itself */ +#define CLONE_OPTIONAL_THREAD_FLAGS \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT) + +#define CLONE_INVALID_FORK_FLAGS \ + (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS)) + +#define CLONE_INVALID_THREAD_FLAGS \ + (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \ + CLONE_IGNORED_FLAGS)) + +#define NEW_STACK_SIZE 0x40000 + +static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; +typedef struct { + CPUArchState *env; + pthread_mutex_t mutex; + pthread_cond_t cond; + pthread_t thread; + uint32_t tid; + abi_ulong child_tidptr; + abi_ulong parent_tidptr; + sigset_t sigmask; +} new_thread_info; + +static void *clone_func(void *arg) +{ + new_thread_info *info = arg; + CPUArchState *env = info->env; + CPUState *cpu = ENV_GET_CPU(env); + TaskState *ts = (TaskState *)cpu->opaque; + + rcu_register_thread(); + tcg_register_thread(); + thread_cpu = cpu; + info->tid = gettid(); + task_settid(ts); + if (info->child_tidptr) { + put_user_u32(info->tid, info->child_tidptr); + } + if (info->parent_tidptr) { + put_user_u32(info->tid, info->parent_tidptr); + } + /* Enable signals. */ + sigprocmask(SIG_SETMASK, &info->sigmask, NULL); + /* Signal to the parent that we're ready. */ + pthread_mutex_lock(&info->mutex); + pthread_cond_broadcast(&info->cond); + pthread_mutex_unlock(&info->mutex); + /* Wait until the parent has finished initializing the tls state. */ + pthread_mutex_lock(&clone_lock); + pthread_mutex_unlock(&clone_lock); + cpu_loop(env); + /* never exits */ + return NULL; +} + +static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, + abi_ulong parent_tidptr, abi_ulong child_tidptr, + target_ulong newtls) +{ + CPUState *cpu = ENV_GET_CPU(env); + int ret; + TaskState *ts; + CPUState *new_cpu; + CPUArchState *new_env; + sigset_t sigmask; + + flags &= ~CLONE_IGNORED_FLAGS; + + /* Emulate vfork() with fork() */ + if (flags & CLONE_VFORK) { + flags &= ~(CLONE_VFORK | CLONE_VM); + } + + if (flags & CLONE_VM) { + TaskState *parent_ts = (TaskState *)cpu->opaque; + new_thread_info info; + pthread_attr_t attr; + + if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) || + (flags & CLONE_INVALID_THREAD_FLAGS)) { + return -TARGET_EINVAL; + } + + ts = g_new0(TaskState, 1); + init_task_state(ts); + + /* Grab a mutex so that thread setup appears atomic. */ + pthread_mutex_lock(&clone_lock); + + /* we create a new CPU instance. */ + new_env = cpu_copy(env); + /* Init regs that differ from the parent. */ + cpu_clone_regs(new_env, newsp); + new_cpu = ENV_GET_CPU(new_env); + new_cpu->opaque = ts; + ts->bprm = parent_ts->bprm; + ts->info = parent_ts->info; + ts->signal_mask = parent_ts->signal_mask; + + if (flags & CLONE_CHILD_CLEARTID) { + ts->child_tidptr = child_tidptr; + } + + if (flags & CLONE_SETTLS) { + cpu_set_tls(new_env, newtls); + } + + memset(&info, 0, sizeof(info)); + pthread_mutex_init(&info.mutex, NULL); + pthread_mutex_lock(&info.mutex); + pthread_cond_init(&info.cond, NULL); + info.env = new_env; + if (flags & CLONE_CHILD_SETTID) { + info.child_tidptr = child_tidptr; + } + if (flags & CLONE_PARENT_SETTID) { + info.parent_tidptr = parent_tidptr; + } + + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + /* + * It is not safe to deliver signals until the child has finished + * initializing, so temporarily block all signals. + */ + sigfillset(&sigmask); + sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask); + + /* + * If this is our first additional thread, we need to ensure we + * generate code for parallel execution and flush old translations. + */ + if (!parallel_cpus) { + parallel_cpus = true; + tb_flush(cpu); + } + + ret = pthread_create(&info.thread, &attr, clone_func, &info); + + /* TODO: Free new CPU state if thread creation failed. */ + + sigprocmask(SIG_SETMASK, &info.sigmask, NULL); + pthread_attr_destroy(&attr); + if (ret == 0) { + /* Wait for the child to initialize. */ + pthread_cond_wait(&info.cond, &info.mutex); + ret = info.tid; + } else { + ret = -host_to_target_errno(ret); + } + pthread_mutex_unlock(&info.mutex); + pthread_cond_destroy(&info.cond); + pthread_mutex_destroy(&info.mutex); + pthread_mutex_unlock(&clone_lock); + } else { + /* if no CLONE_VM, we consider it is a fork */ + if (flags & CLONE_INVALID_FORK_FLAGS) { + return -TARGET_EINVAL; + } + + /* We can't support custom termination signals */ + if ((flags & CSIGNAL) != TARGET_SIGCHLD) { + return -TARGET_EINVAL; + } + + if (block_signals()) { + return -TARGET_ERESTARTSYS; + } + + fork_start(); + ret = fork(); + if (ret < 0) { + return get_errno(-1); + } + if (ret == 0) { + /* Child Process. */ + cpu_clone_regs(env, newsp); + fork_end(1); + /* + * There is a race condition here. The parent process could + * theoretically read the TID in the child process before the + * child tid is set. This would require using either ptrace + * (not implemented) or having *_tidptr to point at a shared + * memory mapping. We can't repeat the spinlock hack used + * above because the child process gets its own copy of the lock. + */ + if (flags & CLONE_CHILD_SETTID) { + put_user_u32(gettid(), child_tidptr); + } + if (flags & CLONE_PARENT_SETTID) { + put_user_u32(gettid(), parent_tidptr); + } + ts = (TaskState *)cpu->opaque; + if (flags & CLONE_SETTLS) { + cpu_set_tls(env, newtls); + } + if (flags & CLONE_CHILD_CLEARTID) { + ts->child_tidptr = child_tidptr; + } + } else { + fork_end(0); + } + } + return ret; +} + +SYSCALL_ARGS(clone) +{ + abi_ulong fl, sp, ptid, ctid, tls; + + /* + * Linux manages to have three different orderings for its + * arguments to clone(); the BACKWARDS and BACKWARDS2 defines + * match the kernel's CONFIG_CLONE_* settings. + * Microblaze is further special in that it uses a sixth + * implicit argument to clone for the TLS pointer. + */ +#if defined(TARGET_MICROBLAZE) + fl = in[0], sp = in[1], ptid = in[3], ctid = in[4], tls = in[5]; +#elif defined(TARGET_CLONE_BACKWARDS) + fl = in[0], sp = in[1], ptid = in[2], tls = in[3], ctid = in[4]; +#elif defined(TARGET_CLONE_BACKWARDS2) + sp = in[0], fl = in[1], ptid = in[2], ctid = in[3], tls = in[4]; +#else + fl = in[0], sp = in[1], ptid = in[2], ctid = in[3], tls = in[4]; +#endif + out[0] = fl, out[1] = sp, out[2] = ptid, out[3] = ctid, out[4] = tls; + return def; +} + +SYSCALL_IMPL(clone) +{ + /* We've done all of the odd ABI adjustment above. */ + return do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5); +} + +#ifdef TARGET_NR_fork +SYSCALL_IMPL(fork) +{ + return do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0); +} +#endif + +#ifdef TARGET_NR_vfork +SYSCALL_IMPL(vfork) +{ + return do_fork(cpu_env, CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD, + 0, 0, 0, 0); +} +#endif + +#ifdef TARGET_NR_getegid +SYSCALL_IMPL(getegid) +{ + return get_errno(high2lowgid(getegid())); +} +#endif + +#ifdef TARGET_NR_getegid32 +SYSCALL_IMPL(getegid32) +{ + return get_errno(getegid()); +} +#endif + +#ifdef TARGET_NR_geteuid +SYSCALL_IMPL(geteuid) +{ + return get_errno(high2lowuid(geteuid())); +} +#endif + +#ifdef TARGET_NR_geteuid32 +SYSCALL_IMPL(geteuid32) +{ + return get_errno(geteuid()); +} +#endif + +#ifdef TARGET_NR_getgid +SYSCALL_IMPL(getgid) +{ + return get_errno(high2lowgid(getgid())); +} +#endif + +#ifdef TARGET_NR_getgid32 +SYSCALL_IMPL(getgid32) +{ + return get_errno(getgid()); +} +#endif + +SYSCALL_IMPL(getgroups) +{ + int gidsetsize = arg1; + gid_t *grouplist; + abi_long ret; + + grouplist = g_try_new(gid_t, gidsetsize); + if (!grouplist) { + return -TARGET_ENOMEM; + } + ret = get_errno(getgroups(gidsetsize, grouplist)); + + if (!is_error(ret) && gidsetsize != 0) { + size_t target_grouplist_size = gidsetsize * sizeof(target_id); + target_id *target_grouplist + = lock_user(VERIFY_WRITE, arg2, target_grouplist_size, 0); + if (target_grouplist) { + int i; + for (i = 0; i < ret; i++) { + target_grouplist[i] = tswapid(high2lowgid(grouplist[i])); + } + unlock_user(target_grouplist, arg2, target_grouplist_size); + } else { + ret = -TARGET_EFAULT; + } + } + g_free(grouplist); + return ret; +} + +#ifdef TARGET_NR_getgroups32 +SYSCALL_IMPL(getgroups32) +{ + int gidsetsize = arg1; + gid_t *grouplist; + abi_long ret; + + grouplist = g_try_new(gid_t, gidsetsize); + if (!grouplist) { + return -TARGET_ENOMEM; + } + ret = get_errno(getgroups(gidsetsize, grouplist)); + + if (!is_error(ret) && gidsetsize != 0) { + uint32_t *target_grouplist + = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0); + if (target_grouplist) { + int i; + for (i = 0; i < ret; i++) { + target_grouplist[i] = tswap32(grouplist[i]); + } + unlock_user(target_grouplist, arg2, gidsetsize * 4); + } else { + ret = -TARGET_EFAULT; + } + } + return ret; +} +#endif + +#ifdef TARGET_NR_getresgid +SYSCALL_IMPL(getresgid) +{ + gid_t rgid, egid, sgid; + abi_long ret = get_errno(getresgid(&rgid, &egid, &sgid)); + + if (!is_error(ret) && + (put_user_id(high2lowgid(rgid), arg1) || + put_user_id(high2lowgid(egid), arg2) || + put_user_id(high2lowgid(sgid), arg3))) { + return -TARGET_EFAULT; + } + return ret; +} +#endif + +#ifdef TARGET_NR_getresgid32 +SYSCALL_IMPL(getresgid32) +{ + gid_t rgid, egid, sgid; + abi_long ret = get_errno(getresgid(&rgid, &egid, &sgid)); + + if (!is_error(ret) && + (put_user_u32(rgid, arg1) || + put_user_u32(egid, arg2) || + put_user_u32(sgid, arg3))) { + return -TARGET_EFAULT; + } + return ret; +} +#endif + +#ifdef TARGET_NR_getresuid +SYSCALL_IMPL(getresuid) +{ + uid_t ruid, euid, suid; + abi_long ret = get_errno(getresuid(&ruid, &euid, &suid)); + + if (!is_error(ret) && + (put_user_id(high2lowuid(ruid), arg1) || + put_user_id(high2lowuid(euid), arg2) || + put_user_id(high2lowuid(suid), arg3))) { + return -TARGET_EFAULT; + } + return ret; +} +#endif + +#ifdef TARGET_NR_getresuid32 +SYSCALL_IMPL(getresuid32) +{ + uid_t ruid, euid, suid; + abi_long ret = get_errno(getresuid(&ruid, &euid, &suid)); + + if (!is_error(ret) && + (put_user_u32(ruid, arg1) || + put_user_u32(euid, arg2) || + put_user_u32(suid, arg3))) { + return -TARGET_EFAULT; + } + return ret; +} +#endif + +#ifdef TARGET_NR_getpgrp +SYSCALL_IMPL(getpgrp) +{ + return get_errno(getpgrp()); +} +#endif + +#ifdef TARGET_NR_getpid +SYSCALL_IMPL(getpid) +{ + return get_errno(getpid()); +} +#endif + +#ifdef TARGET_NR_getppid +SYSCALL_IMPL(getppid) +{ + return get_errno(getppid()); +} +#endif + +SYSCALL_IMPL(gettid) +{ + return get_errno(gettid()); +} + +#ifdef TARGET_NR_getuid +SYSCALL_IMPL(getuid) +{ + return get_errno(high2lowuid(getuid())); +} +#endif + +#ifdef TARGET_NR_getuid32 +SYSCALL_IMPL(getuid32) +{ + return get_errno(getuid()); +} +#endif + +#ifdef TARGET_NR_getxgid +SYSCALL_IMPL(getxgid) +{ + /* Alpha specific */ + cpu_env->ir[IR_A4] = getegid(); + return get_errno(getgid()); +} +#endif + +#ifdef TARGET_NR_getxpid +SYSCALL_IMPL(getxpid) +{ + /* Alpha specific */ + cpu_env->ir[IR_A4] = getppid(); + return get_errno(getpid()); +} +#endif + +#ifdef TARGET_NR_getxuid +SYSCALL_IMPL(getxuid) +{ + /* Alpha specific */ + cpu_env->ir[IR_A4] = geteuid(); + return get_errno(getuid()); +} +#endif + +SYSCALL_IMPL(setfsgid) +{ + return get_errno(setfsgid(arg1)); +} + +#ifdef TARGET_NR_setfsgid32 +SYSCALL_IMPL(setfsgid32) +{ + return get_errno(setfsgid(arg1)); +} +#endif + +SYSCALL_IMPL(setfsuid) +{ + return get_errno(setfsuid(arg1)); +} + +#ifdef TARGET_NR_setfsuid32 +SYSCALL_IMPL(setfsuid32) +{ + return get_errno(setfsuid(arg1)); +} +#endif + +SYSCALL_IMPL(setgid) +{ + return get_errno(sys_setgid(low2highgid(arg1))); +} + +#ifdef TARGET_NR_setgid32 +SYSCALL_IMPL(setgid32) +{ + return get_errno(sys_setgid(arg1)); +} +#endif + +SYSCALL_IMPL(setgroups) +{ + int gidsetsize = arg1; + gid_t *grouplist = NULL; + abi_long ret; + + if (gidsetsize != 0) { + size_t target_grouplist_size = gidsetsize * sizeof(target_id); + target_id *target_grouplist + = lock_user(VERIFY_READ, arg2, target_grouplist_size, 1); + int i; + + if (!target_grouplist) { + return -TARGET_EFAULT; + } + grouplist = g_try_new(gid_t, gidsetsize); + if (!grouplist) { + unlock_user(target_grouplist, arg2, 0); + return -TARGET_ENOMEM; + } + + for (i = 0; i < gidsetsize; i++) { + grouplist[i] = low2highgid(tswapid(target_grouplist[i])); + } + unlock_user(target_grouplist, arg2, 0); + } + ret = get_errno(setgroups(gidsetsize, grouplist)); + g_free(grouplist); + return ret; +} + +#ifdef TARGET_NR_setgroups32 +SYSCALL_IMPL(setgroups32) +{ + int gidsetsize = arg1; + gid_t *grouplist = NULL; + abi_long ret; + + if (gidsetsize != 0) { + uint32_t *target_grouplist + = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1); + int i; + + if (!target_grouplist) { + return -TARGET_EFAULT; + } + grouplist = g_try_new(gid_t, gidsetsize); + if (!grouplist) { + unlock_user(target_grouplist, arg2, 0); + return -TARGET_ENOMEM; + } + + for (i = 0; i < gidsetsize; i++) { + grouplist[i] = tswap32(target_grouplist[i]); + } + unlock_user(target_grouplist, arg2, 0); + } + ret = get_errno(setgroups(gidsetsize, grouplist)); + g_free(grouplist); + return ret; +} +#endif + +SYSCALL_IMPL(setregid) +{ + return get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); +} + +#ifdef TARGET_NR_setregid32 +SYSCALL_IMPL(setregid32) +{ + return get_errno(setregid(arg1, arg2)); +} +#endif + +#ifdef TARGET_NR_setresgid +SYSCALL_IMPL(setresgid) +{ + return get_errno(sys_setresgid(low2highgid(arg1), + low2highgid(arg2), + low2highgid(arg3))); +} +#endif + +#ifdef TARGET_NR_setresgid32 +SYSCALL_IMPL(setresgid32) +{ + return get_errno(sys_setresgid(arg1, arg2, arg3)); +} +#endif + +#ifdef TARGET_NR_setresuid +SYSCALL_IMPL(setresuid) +{ + return get_errno(sys_setresuid(low2highuid(arg1), + low2highuid(arg2), + low2highuid(arg3))); +} +#endif + +#ifdef TARGET_NR_setresuid32 +SYSCALL_IMPL(setresuid32) +{ + return get_errno(sys_setresuid(arg1, arg2, arg3)); +} +#endif + +SYSCALL_IMPL(setreuid) +{ + return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); +} + +#ifdef TARGET_NR_setreuid32 +SYSCALL_IMPL(setreuid32) +{ + return get_errno(setreuid(arg1, arg2)); +} +#endif + +SYSCALL_IMPL(setsid) +{ + return get_errno(setsid()); +} + +SYSCALL_IMPL(setuid) +{ + return get_errno(sys_setuid(low2highuid(arg1))); +} + +#ifdef TARGET_NR_setuid32 +SYSCALL_IMPL(setuid32) +{ + return get_errno(sys_setuid(arg1)); +} +#endif + +#ifdef TARGET_NR_get_thread_area +#if defined(TARGET_I386) && defined(TARGET_ABI32) +static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) +{ + struct target_modify_ldt_ldt_s *target_ldt_info; + uint64_t *gdt_table = g2h(env->gdt.base); + uint32_t base_addr, limit, flags; + int seg_32bit, contents, read_exec_only, limit_in_pages, idx; + int seg_not_present, useable, lm; + uint32_t *lp, entry_1, entry_2; + + lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); + if (!target_ldt_info) { + return -TARGET_EFAULT; + } + idx = tswap32(target_ldt_info->entry_number); + if (idx < TARGET_GDT_ENTRY_TLS_MIN || + idx > TARGET_GDT_ENTRY_TLS_MAX) { + unlock_user_struct(target_ldt_info, ptr, 1); + return -TARGET_EINVAL; + } + lp = (uint32_t *)(gdt_table + idx); + entry_1 = tswap32(lp[0]); + entry_2 = tswap32(lp[1]); + + read_exec_only = ((entry_2 >> 9) & 1) ^ 1; + contents = (entry_2 >> 10) & 3; + seg_not_present = ((entry_2 >> 15) & 1) ^ 1; + seg_32bit = (entry_2 >> 22) & 1; + limit_in_pages = (entry_2 >> 23) & 1; + useable = (entry_2 >> 20) & 1; +#ifdef TARGET_ABI32 + lm = 0; +#else + lm = (entry_2 >> 21) & 1; +#endif + flags = (seg_32bit << 0) | (contents << 1) | + (read_exec_only << 3) | (limit_in_pages << 4) | + (seg_not_present << 5) | (useable << 6) | (lm << 7); + limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000); + base_addr = (entry_1 >> 16) | + (entry_2 & 0xff000000) | + ((entry_2 & 0xff) << 16); + target_ldt_info->base_addr = tswapal(base_addr); + target_ldt_info->limit = tswap32(limit); + target_ldt_info->flags = tswap32(flags); + unlock_user_struct(target_ldt_info, ptr, 1); + return 0; +} +#endif + +SYSCALL_IMPL(get_thread_area) +{ +#if defined(TARGET_I386) && defined(TARGET_ABI32) + return do_get_thread_area(cpu_env, arg1); +#elif defined(TARGET_M68K) + CPUState *cpu = ENV_GET_CPU(cpu_env); + TaskState *ts = cpu->opaque; + return ts->tp_value; +#else + return -TARGET_ENOSYS; +#endif +} +#endif + +#ifdef TARGET_NR_set_thread_area +SYSCALL_IMPL(set_thread_area) +{ +#if defined(TARGET_MIPS) + cpu_env->active_tc.CP0_UserLocal = arg1; + return 0; +#elif defined(TARGET_CRIS) + if (arg1 & 0xff) { + return -TARGET_EINVAL; + } + cpu_env->pregs[PR_PID] = arg1; + return 0; +#elif defined(TARGET_I386) && defined(TARGET_ABI32) + return do_set_thread_area(cpu_env, arg1); +#elif defined(TARGET_M68K) + CPUState *cpu = ENV_GET_CPU(cpu_env); + TaskState *ts = cpu->opaque; + ts->tp_value = arg1; + return 0; +#else + return -TARGET_ENOSYS; +#endif +} +#endif + +SYSCALL_IMPL(set_tid_address) +{ + return get_errno(set_tid_address((int *)g2h(arg1))); +} diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fda7376e58..73d8ec3283 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -113,57 +113,6 @@ #include "fd-trans.h" #include "syscall.h" -#ifndef CLONE_IO -#define CLONE_IO 0x80000000 /* Clone io context */ -#endif - -/* We can't directly call the host clone syscall, because this will - * badly confuse libc (breaking mutexes, for example). So we must - * divide clone flags into: - * * flag combinations that look like pthread_create() - * * flag combinations that look like fork() - * * flags we can implement within QEMU itself - * * flags we can't support and will return an error for - */ -/* For thread creation, all these flags must be present; for - * fork, none must be present. - */ -#define CLONE_THREAD_FLAGS \ - (CLONE_VM | CLONE_FS | CLONE_FILES | \ - CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM) - -/* These flags are ignored: - * CLONE_DETACHED is now ignored by the kernel; - * CLONE_IO is just an optimisation hint to the I/O scheduler - */ -#define CLONE_IGNORED_FLAGS \ - (CLONE_DETACHED | CLONE_IO) - -/* Flags for fork which we can implement within QEMU itself */ -#define CLONE_OPTIONAL_FORK_FLAGS \ - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ - CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) - -/* Flags for thread creation which we can implement within QEMU itself */ -#define CLONE_OPTIONAL_THREAD_FLAGS \ - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ - CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT) - -#define CLONE_INVALID_FORK_FLAGS \ - (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS)) - -#define CLONE_INVALID_THREAD_FLAGS \ - (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \ - CLONE_IGNORED_FLAGS)) - -/* CLONE_VFORK is special cased early in do_fork(). The other flag bits - * have almost all been allocated. We cannot support any of - * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC, - * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED. - * The checks against the invalid thread masks above will catch these. - * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.) - */ - /* Define DEBUG_ERESTARTSYS to force every syscall to be restarted * once. This exercises the codepaths for restart. */ @@ -250,16 +199,6 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define TARGET_NR__llseek TARGET_NR_llseek #endif -#ifdef __NR_gettid -_syscall0(int, gettid) -#else -/* This is a replacement for the host gettid() and must return a host - errno. */ -static int gettid(void) { - return -ENOSYS; -} -#endif - /* For the 64-bit guest on 32-bit host case we must emulate * getdents using getdents64, because otherwise the host * might hand us back more dirent records than we can fit @@ -289,9 +228,6 @@ _syscall3(int,sys_syslog,int,type,char*,bufp,int,len) #ifdef __NR_exit_group _syscall1(int,exit_group,int,error_code) #endif -#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) -_syscall1(int,set_tid_address,int *,tidptr) -#endif #if defined(TARGET_NR_futex) && defined(__NR_futex) _syscall6(int,sys_futex,int *,uaddr,int,op,int,val, const struct timespec *,timeout,int *,uaddr2,int,val3) @@ -4315,53 +4251,6 @@ install: lp[1] = tswap32(entry_2); return 0; } - -static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) -{ - struct target_modify_ldt_ldt_s *target_ldt_info; - uint64_t *gdt_table = g2h(env->gdt.base); - uint32_t base_addr, limit, flags; - int seg_32bit, contents, read_exec_only, limit_in_pages, idx; - int seg_not_present, useable, lm; - uint32_t *lp, entry_1, entry_2; - - lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); - if (!target_ldt_info) - return -TARGET_EFAULT; - idx = tswap32(target_ldt_info->entry_number); - if (idx < TARGET_GDT_ENTRY_TLS_MIN || - idx > TARGET_GDT_ENTRY_TLS_MAX) { - unlock_user_struct(target_ldt_info, ptr, 1); - return -TARGET_EINVAL; - } - lp = (uint32_t *)(gdt_table + idx); - entry_1 = tswap32(lp[0]); - entry_2 = tswap32(lp[1]); - - read_exec_only = ((entry_2 >> 9) & 1) ^ 1; - contents = (entry_2 >> 10) & 3; - seg_not_present = ((entry_2 >> 15) & 1) ^ 1; - seg_32bit = (entry_2 >> 22) & 1; - limit_in_pages = (entry_2 >> 23) & 1; - useable = (entry_2 >> 20) & 1; -#ifdef TARGET_ABI32 - lm = 0; -#else - lm = (entry_2 >> 21) & 1; -#endif - flags = (seg_32bit << 0) | (contents << 1) | - (read_exec_only << 3) | (limit_in_pages << 4) | - (seg_not_present << 5) | (useable << 6) | (lm << 7); - limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000); - base_addr = (entry_1 >> 16) | - (entry_2 & 0xff000000) | - ((entry_2 & 0xff) << 16); - target_ldt_info->base_addr = tswapal(base_addr); - target_ldt_info->limit = tswap32(limit); - target_ldt_info->flags = tswap32(flags); - unlock_user_struct(target_ldt_info, ptr, 1); - return 0; -} #endif /* TARGET_I386 && TARGET_ABI32 */ #ifndef TARGET_ABI32 @@ -4401,194 +4290,6 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) #endif /* defined(TARGET_I386) */ -#define NEW_STACK_SIZE 0x40000 - - -static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; -typedef struct { - CPUArchState *env; - pthread_mutex_t mutex; - pthread_cond_t cond; - pthread_t thread; - uint32_t tid; - abi_ulong child_tidptr; - abi_ulong parent_tidptr; - sigset_t sigmask; -} new_thread_info; - -static void *clone_func(void *arg) -{ - new_thread_info *info = arg; - CPUArchState *env; - CPUState *cpu; - TaskState *ts; - - rcu_register_thread(); - tcg_register_thread(); - env = info->env; - cpu = ENV_GET_CPU(env); - thread_cpu = cpu; - ts = (TaskState *)cpu->opaque; - info->tid = gettid(); - task_settid(ts); - if (info->child_tidptr) - put_user_u32(info->tid, info->child_tidptr); - if (info->parent_tidptr) - put_user_u32(info->tid, info->parent_tidptr); - /* Enable signals. */ - sigprocmask(SIG_SETMASK, &info->sigmask, NULL); - /* Signal to the parent that we're ready. */ - pthread_mutex_lock(&info->mutex); - pthread_cond_broadcast(&info->cond); - pthread_mutex_unlock(&info->mutex); - /* Wait until the parent has finished initializing the tls state. */ - pthread_mutex_lock(&clone_lock); - pthread_mutex_unlock(&clone_lock); - cpu_loop(env); - /* never exits */ - return NULL; -} - -/* do_fork() Must return host values and target errnos (unlike most - do_*() functions). */ -static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, - abi_ulong parent_tidptr, target_ulong newtls, - abi_ulong child_tidptr) -{ - CPUState *cpu = ENV_GET_CPU(env); - int ret; - TaskState *ts; - CPUState *new_cpu; - CPUArchState *new_env; - sigset_t sigmask; - - flags &= ~CLONE_IGNORED_FLAGS; - - /* Emulate vfork() with fork() */ - if (flags & CLONE_VFORK) - flags &= ~(CLONE_VFORK | CLONE_VM); - - if (flags & CLONE_VM) { - TaskState *parent_ts = (TaskState *)cpu->opaque; - new_thread_info info; - pthread_attr_t attr; - - if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) || - (flags & CLONE_INVALID_THREAD_FLAGS)) { - return -TARGET_EINVAL; - } - - ts = g_new0(TaskState, 1); - init_task_state(ts); - - /* Grab a mutex so that thread setup appears atomic. */ - pthread_mutex_lock(&clone_lock); - - /* we create a new CPU instance. */ - new_env = cpu_copy(env); - /* Init regs that differ from the parent. */ - cpu_clone_regs(new_env, newsp); - new_cpu = ENV_GET_CPU(new_env); - new_cpu->opaque = ts; - ts->bprm = parent_ts->bprm; - ts->info = parent_ts->info; - ts->signal_mask = parent_ts->signal_mask; - - if (flags & CLONE_CHILD_CLEARTID) { - ts->child_tidptr = child_tidptr; - } - - if (flags & CLONE_SETTLS) { - cpu_set_tls (new_env, newtls); - } - - memset(&info, 0, sizeof(info)); - pthread_mutex_init(&info.mutex, NULL); - pthread_mutex_lock(&info.mutex); - pthread_cond_init(&info.cond, NULL); - info.env = new_env; - if (flags & CLONE_CHILD_SETTID) { - info.child_tidptr = child_tidptr; - } - if (flags & CLONE_PARENT_SETTID) { - info.parent_tidptr = parent_tidptr; - } - - ret = pthread_attr_init(&attr); - ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); - ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - /* It is not safe to deliver signals until the child has finished - initializing, so temporarily block all signals. */ - sigfillset(&sigmask); - sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask); - - /* If this is our first additional thread, we need to ensure we - * generate code for parallel execution and flush old translations. - */ - if (!parallel_cpus) { - parallel_cpus = true; - tb_flush(cpu); - } - - ret = pthread_create(&info.thread, &attr, clone_func, &info); - /* TODO: Free new CPU state if thread creation failed. */ - - sigprocmask(SIG_SETMASK, &info.sigmask, NULL); - pthread_attr_destroy(&attr); - if (ret == 0) { - /* Wait for the child to initialize. */ - pthread_cond_wait(&info.cond, &info.mutex); - ret = info.tid; - } else { - ret = -1; - } - pthread_mutex_unlock(&info.mutex); - pthread_cond_destroy(&info.cond); - pthread_mutex_destroy(&info.mutex); - pthread_mutex_unlock(&clone_lock); - } else { - /* if no CLONE_VM, we consider it is a fork */ - if (flags & CLONE_INVALID_FORK_FLAGS) { - return -TARGET_EINVAL; - } - - /* We can't support custom termination signals */ - if ((flags & CSIGNAL) != TARGET_SIGCHLD) { - return -TARGET_EINVAL; - } - - if (block_signals()) { - return -TARGET_ERESTARTSYS; - } - - fork_start(); - ret = fork(); - if (ret == 0) { - /* Child Process. */ - cpu_clone_regs(env, newsp); - fork_end(1); - /* There is a race condition here. The parent process could - theoretically read the TID in the child process before the child - tid is set. This would require using either ptrace - (not implemented) or having *_tidptr to point at a shared memory - mapping. We can't repeat the spinlock hack used above because - the child process gets its own copy of the lock. */ - if (flags & CLONE_CHILD_SETTID) - put_user_u32(gettid(), child_tidptr); - if (flags & CLONE_PARENT_SETTID) - put_user_u32(gettid(), parent_tidptr); - ts = (TaskState *)cpu->opaque; - if (flags & CLONE_SETTLS) - cpu_set_tls (env, newtls); - if (flags & CLONE_CHILD_CLEARTID) - ts->child_tidptr = child_tidptr; - } else { - fork_end(0); - } - } - return ret; -} - /* warning : doesn't handle linux specific flags... */ static int target_to_host_fcntl_cmd(int cmd) { @@ -5024,40 +4725,6 @@ 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; @@ -5626,10 +5293,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return 0; /* avoid warning */ case TARGET_NR_brk: return do_brk(arg1); -#ifdef TARGET_NR_fork - case TARGET_NR_fork: - return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0)); -#endif #ifdef TARGET_NR_waitpid case TARGET_NR_waitpid: { @@ -5855,16 +5518,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_lseek case TARGET_NR_lseek: return get_errno(lseek(arg1, arg2, arg3)); -#endif -#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) - /* Alpha specific */ - case TARGET_NR_getxpid: - ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid(); - return get_errno(getpid()); -#endif -#ifdef TARGET_NR_getpid - case TARGET_NR_getpid: - return get_errno(getpid()); #endif case TARGET_NR_mount: { @@ -6205,16 +5858,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } #endif -#ifdef TARGET_NR_getppid /* not on alpha */ - case TARGET_NR_getppid: - return get_errno(getppid()); -#endif -#ifdef TARGET_NR_getpgrp - case TARGET_NR_getpgrp: - return get_errno(getpgrp()); -#endif - case TARGET_NR_setsid: - return get_errno(setsid()); #ifdef TARGET_NR_sigaction case TARGET_NR_sigaction: { @@ -7319,23 +6962,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; case TARGET_NR_fsync: return get_errno(fsync(arg1)); - case TARGET_NR_clone: - /* Linux manages to have three different orderings for its - * arguments to clone(); the BACKWARDS and BACKWARDS2 defines - * match the kernel's CONFIG_CLONE_* settings. - * Microblaze is further special in that it uses a sixth - * implicit argument to clone for the TLS pointer. - */ -#if defined(TARGET_MICROBLAZE) - ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); -#elif defined(TARGET_CLONE_BACKWARDS) - ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); -#elif defined(TARGET_CLONE_BACKWARDS2) - ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); -#else - ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); -#endif - return ret; #ifdef __NR_exit_group /* new thread calls */ case TARGET_NR_exit_group: @@ -8170,12 +7796,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } #endif #endif -#ifdef TARGET_NR_vfork - case TARGET_NR_vfork: - return get_errno(do_fork(cpu_env, - CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD, - 0, 0, 0, 0)); -#endif #ifdef TARGET_NR_ugetrlimit case TARGET_NR_ugetrlimit: { @@ -8258,66 +7878,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); return ret; #endif -#ifdef TARGET_NR_getuid - case TARGET_NR_getuid: - return get_errno(high2lowuid(getuid())); -#endif -#ifdef TARGET_NR_getgid - case TARGET_NR_getgid: - return get_errno(high2lowgid(getgid())); -#endif -#ifdef TARGET_NR_geteuid - case TARGET_NR_geteuid: - return get_errno(high2lowuid(geteuid())); -#endif -#ifdef TARGET_NR_getegid - case TARGET_NR_getegid: - return get_errno(high2lowgid(getegid())); -#endif - case TARGET_NR_setreuid: - return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); - case TARGET_NR_setregid: - return get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); - case TARGET_NR_getgroups: - { - int gidsetsize = arg1; - target_id *target_grouplist; - gid_t *grouplist; - int i; - - grouplist = alloca(gidsetsize * sizeof(gid_t)); - ret = get_errno(getgroups(gidsetsize, grouplist)); - if (gidsetsize == 0) - return ret; - if (!is_error(ret)) { - target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0); - if (!target_grouplist) - return -TARGET_EFAULT; - for(i = 0;i < ret; i++) - target_grouplist[i] = tswapid(high2lowgid(grouplist[i])); - unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id)); - } - } - return ret; - case TARGET_NR_setgroups: - { - int gidsetsize = arg1; - target_id *target_grouplist; - gid_t *grouplist = NULL; - int i; - if (gidsetsize) { - grouplist = alloca(gidsetsize * sizeof(gid_t)); - target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1); - if (!target_grouplist) { - return -TARGET_EFAULT; - } - for (i = 0; i < gidsetsize; i++) { - grouplist[i] = low2highgid(tswapid(target_grouplist[i])); - } - unlock_user(target_grouplist, arg2, 0); - } - return get_errno(setgroups(gidsetsize, grouplist)); - } case TARGET_NR_fchown: return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3))); #if defined(TARGET_NR_fchownat) @@ -8329,46 +7889,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, 0); return ret; #endif -#ifdef TARGET_NR_setresuid - case TARGET_NR_setresuid: - return get_errno(sys_setresuid(low2highuid(arg1), - low2highuid(arg2), - low2highuid(arg3))); -#endif -#ifdef TARGET_NR_getresuid - case TARGET_NR_getresuid: - { - uid_t ruid, euid, suid; - ret = get_errno(getresuid(&ruid, &euid, &suid)); - if (!is_error(ret)) { - if (put_user_id(high2lowuid(ruid), arg1) - || put_user_id(high2lowuid(euid), arg2) - || put_user_id(high2lowuid(suid), arg3)) - return -TARGET_EFAULT; - } - } - return ret; -#endif -#ifdef TARGET_NR_getresgid - case TARGET_NR_setresgid: - return get_errno(sys_setresgid(low2highgid(arg1), - low2highgid(arg2), - low2highgid(arg3))); -#endif -#ifdef TARGET_NR_getresgid - case TARGET_NR_getresgid: - { - gid_t rgid, egid, sgid; - ret = get_errno(getresgid(&rgid, &egid, &sgid)); - if (!is_error(ret)) { - if (put_user_id(high2lowgid(rgid), arg1) - || put_user_id(high2lowgid(egid), arg2) - || put_user_id(high2lowgid(sgid), arg3)) - return -TARGET_EFAULT; - } - } - return ret; -#endif #ifdef TARGET_NR_chown case TARGET_NR_chown: if (!(p = lock_user_string(arg1))) @@ -8377,15 +7897,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); return ret; #endif - case TARGET_NR_setuid: - return get_errno(sys_setuid(low2highuid(arg1))); - case TARGET_NR_setgid: - return get_errno(sys_setgid(low2highgid(arg1))); - case TARGET_NR_setfsuid: - return get_errno(setfsuid(arg1)); - case TARGET_NR_setfsgid: - return get_errno(setfsgid(arg1)); - #ifdef TARGET_NR_lchown32 case TARGET_NR_lchown32: if (!(p = lock_user_string(arg1))) @@ -8394,31 +7905,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); return ret; #endif -#ifdef TARGET_NR_getuid32 - case TARGET_NR_getuid32: - return get_errno(getuid()); -#endif - -#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA) - /* Alpha specific */ - case TARGET_NR_getxuid: - { - uid_t euid; - euid=geteuid(); - ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid; - } - return get_errno(getuid()); -#endif -#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA) - /* Alpha specific */ - case TARGET_NR_getxgid: - { - uid_t egid; - egid=getegid(); - ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid; - } - return get_errno(getgid()); -#endif #if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA) /* Alpha specific */ case TARGET_NR_osf_getsysinfo: @@ -8579,110 +8065,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif - -#ifdef TARGET_NR_getgid32 - case TARGET_NR_getgid32: - return get_errno(getgid()); -#endif -#ifdef TARGET_NR_geteuid32 - case TARGET_NR_geteuid32: - return get_errno(geteuid()); -#endif -#ifdef TARGET_NR_getegid32 - case TARGET_NR_getegid32: - return get_errno(getegid()); -#endif -#ifdef TARGET_NR_setreuid32 - case TARGET_NR_setreuid32: - return get_errno(setreuid(arg1, arg2)); -#endif -#ifdef TARGET_NR_setregid32 - case TARGET_NR_setregid32: - return get_errno(setregid(arg1, arg2)); -#endif -#ifdef TARGET_NR_getgroups32 - case TARGET_NR_getgroups32: - { - int gidsetsize = arg1; - uint32_t *target_grouplist; - gid_t *grouplist; - int i; - - grouplist = alloca(gidsetsize * sizeof(gid_t)); - ret = get_errno(getgroups(gidsetsize, grouplist)); - if (gidsetsize == 0) - return ret; - if (!is_error(ret)) { - target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0); - if (!target_grouplist) { - return -TARGET_EFAULT; - } - for(i = 0;i < ret; i++) - target_grouplist[i] = tswap32(grouplist[i]); - unlock_user(target_grouplist, arg2, gidsetsize * 4); - } - } - return ret; -#endif -#ifdef TARGET_NR_setgroups32 - case TARGET_NR_setgroups32: - { - int gidsetsize = arg1; - uint32_t *target_grouplist; - gid_t *grouplist; - int i; - - grouplist = alloca(gidsetsize * sizeof(gid_t)); - target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1); - if (!target_grouplist) { - return -TARGET_EFAULT; - } - for(i = 0;i < gidsetsize; i++) - grouplist[i] = tswap32(target_grouplist[i]); - unlock_user(target_grouplist, arg2, 0); - return get_errno(setgroups(gidsetsize, grouplist)); - } -#endif #ifdef TARGET_NR_fchown32 case TARGET_NR_fchown32: return get_errno(fchown(arg1, arg2, arg3)); #endif -#ifdef TARGET_NR_setresuid32 - case TARGET_NR_setresuid32: - return get_errno(sys_setresuid(arg1, arg2, arg3)); -#endif -#ifdef TARGET_NR_getresuid32 - case TARGET_NR_getresuid32: - { - uid_t ruid, euid, suid; - ret = get_errno(getresuid(&ruid, &euid, &suid)); - if (!is_error(ret)) { - if (put_user_u32(ruid, arg1) - || put_user_u32(euid, arg2) - || put_user_u32(suid, arg3)) - return -TARGET_EFAULT; - } - } - return ret; -#endif -#ifdef TARGET_NR_setresgid32 - case TARGET_NR_setresgid32: - return get_errno(sys_setresgid(arg1, arg2, arg3)); -#endif -#ifdef TARGET_NR_getresgid32 - case TARGET_NR_getresgid32: - { - gid_t rgid, egid, sgid; - ret = get_errno(getresgid(&rgid, &egid, &sgid)); - if (!is_error(ret)) { - if (put_user_u32(rgid, arg1) - || put_user_u32(egid, arg2) - || put_user_u32(sgid, arg3)) - return -TARGET_EFAULT; - } - } - return ret; -#endif #ifdef TARGET_NR_chown32 case TARGET_NR_chown32: if (!(p = lock_user_string(arg1))) @@ -8691,22 +8077,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); return ret; #endif -#ifdef TARGET_NR_setuid32 - case TARGET_NR_setuid32: - return get_errno(sys_setuid(arg1)); -#endif -#ifdef TARGET_NR_setgid32 - case TARGET_NR_setgid32: - return get_errno(sys_setgid(arg1)); -#endif -#ifdef TARGET_NR_setfsuid32 - case TARGET_NR_setfsuid32: - return get_errno(setfsuid(arg1)); -#endif -#ifdef TARGET_NR_setfsgid32 - case TARGET_NR_setfsgid32: - return get_errno(setfsgid(arg1)); -#endif #ifdef TARGET_NR_mincore case TARGET_NR_mincore: { @@ -8865,8 +8235,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, case TARGET_NR_getpagesize: return TARGET_PAGE_SIZE; #endif - case TARGET_NR_gettid: - return get_errno(gettid()); #ifdef TARGET_NR_readahead case TARGET_NR_readahead: #if TARGET_ABI_BITS == 32 @@ -9043,44 +8411,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; #endif #endif /* CONFIG_ATTR */ -#ifdef TARGET_NR_set_thread_area - case TARGET_NR_set_thread_area: -#if defined(TARGET_MIPS) - ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1; - return 0; -#elif defined(TARGET_CRIS) - if (arg1 & 0xff) - ret = -TARGET_EINVAL; - else { - ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1; - ret = 0; - } - return ret; -#elif defined(TARGET_I386) && defined(TARGET_ABI32) - return do_set_thread_area(cpu_env, arg1); -#elif defined(TARGET_M68K) - { - TaskState *ts = cpu->opaque; - ts->tp_value = arg1; - return 0; - } -#else - return -TARGET_ENOSYS; -#endif -#endif -#ifdef TARGET_NR_get_thread_area - case TARGET_NR_get_thread_area: -#if defined(TARGET_I386) && defined(TARGET_ABI32) - return do_get_thread_area(cpu_env, arg1); -#elif defined(TARGET_M68K) - { - TaskState *ts = cpu->opaque; - return ts->tp_value; - } -#else - return -TARGET_ENOSYS; -#endif -#endif #ifdef TARGET_NR_getdomainname case TARGET_NR_getdomainname: return -TARGET_ENOSYS; @@ -9140,12 +8470,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } #endif - -#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) - case TARGET_NR_set_tid_address: - return get_errno(set_tid_address((int *)g2h(arg1))); -#endif - case TARGET_NR_tkill: return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2))); @@ -9845,6 +9169,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #include "syscall-file.inc.c" #include "syscall-ipc.inc.c" #include "syscall-mem.inc.c" +#include "syscall-proc.inc.c" #undef SYSCALL_IMPL #undef SYSCALL_ARGS diff --git a/linux-user/strace.list b/linux-user/strace.list index ac7cf77021..58704fcb07 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -94,12 +94,6 @@ #ifdef TARGET_NR_clock_settime { TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_clone -{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL }, -#endif -#ifdef TARGET_NR_close -{ TARGET_NR_close, "close" , "%s(%d)", NULL, NULL }, -#endif #ifdef TARGET_NR_connect { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL }, #endif @@ -226,9 +220,6 @@ #ifdef TARGET_NR_flock { TARGET_NR_flock, "flock" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_fork -{ TARGET_NR_fork, "fork" , "%s()", NULL, NULL }, -#endif #ifdef TARGET_NR_fremovexattr { TARGET_NR_fremovexattr, "fremovexattr" , NULL, NULL, NULL }, #endif @@ -283,30 +274,6 @@ #ifdef TARGET_NR_getdtablesize { TARGET_NR_getdtablesize, "getdtablesize" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getegid -{ TARGET_NR_getegid, "getegid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getegid32 -{ TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_geteuid -{ TARGET_NR_geteuid, "geteuid" , "%s()", NULL, NULL }, -#endif -#ifdef TARGET_NR_geteuid32 -{ TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getgid -{ TARGET_NR_getgid, "getgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getgid32 -{ TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getgroups -{ TARGET_NR_getgroups, "getgroups" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getgroups32 -{ TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_gethostname { TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL }, #endif @@ -325,39 +292,15 @@ #ifdef TARGET_NR_getpeername { TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getpgid -{ TARGET_NR_getpgid, "getpgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getpgrp -{ TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getpid -{ TARGET_NR_getpid, "getpid" , "%s()", NULL, NULL }, -#endif #ifdef TARGET_NR_getpmsg { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getppid -{ TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL }, -#endif #ifdef TARGET_NR_getpriority { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL }, #endif #ifdef TARGET_NR_getrandom { TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getresgid -{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getresgid32 -{ TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getresuid -{ TARGET_NR_getresuid, "getresuid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getresuid32 -{ TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_getrlimit { TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL }, #endif @@ -367,9 +310,6 @@ #ifdef TARGET_NR_getrusage { TARGET_NR_getrusage, "getrusage" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getsid -{ TARGET_NR_getsid, "getsid" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_getsockname { TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL }, #endif @@ -380,30 +320,12 @@ { TARGET_NR_get_thread_area, "get_thread_area", "%s(0x"TARGET_ABI_FMT_lx")", NULL, NULL }, #endif -#ifdef TARGET_NR_gettid -{ TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL }, -#endif #ifdef TARGET_NR_gettimeofday { TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getuid -{ TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL }, -#endif -#ifdef TARGET_NR_getuid32 -{ TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_getxattr { TARGET_NR_getxattr, "getxattr" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_getxgid -{ TARGET_NR_getxgid, "getxgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getxpid -{ TARGET_NR_getxpid, "getxpid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_getxuid -{ TARGET_NR_getxuid, "getxuid" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_gtty { TARGET_NR_gtty, "gtty" , NULL, NULL, NULL }, #endif @@ -641,9 +563,6 @@ #ifdef TARGET_NR_osf_alt_plock { TARGET_NR_osf_alt_plock, "osf_alt_plock" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_osf_alt_setsid -{ TARGET_NR_osf_alt_setsid, "osf_alt_setsid" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_osf_alt_sigpending { TARGET_NR_osf_alt_sigpending, "osf_alt_sigpending" , NULL, NULL, NULL }, #endif @@ -1172,30 +1091,6 @@ #ifdef TARGET_NR_setdomainname { TARGET_NR_setdomainname, "setdomainname" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_setfsgid -{ TARGET_NR_setfsgid, "setfsgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setfsgid32 -{ TARGET_NR_setfsgid32, "setfsgid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setfsuid -{ TARGET_NR_setfsuid, "setfsuid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setfsuid32 -{ TARGET_NR_setfsuid32, "setfsuid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setgid -{ TARGET_NR_setgid, "setgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setgid32 -{ TARGET_NR_setgid32, "setgid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setgroups -{ TARGET_NR_setgroups, "setgroups" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setgroups32 -{ TARGET_NR_setgroups32, "setgroups32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_sethae { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL }, #endif @@ -1211,48 +1106,15 @@ #ifdef TARGET_NR_setns { TARGET_NR_setns, "setns" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_setpgid -{ TARGET_NR_setpgid, "setpgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setpgrp -{ TARGET_NR_setpgrp, "setpgrp" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_setpriority { TARGET_NR_setpriority, "setpriority" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_setregid -{ TARGET_NR_setregid, "setregid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setregid32 -{ TARGET_NR_setregid32, "setregid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setresgid -{ TARGET_NR_setresgid, "setresgid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setresgid32 -{ TARGET_NR_setresgid32, "setresgid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setresuid -{ TARGET_NR_setresuid, "setresuid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setresuid32 -{ TARGET_NR_setresuid32, "setresuid32" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setreuid -{ TARGET_NR_setreuid, "setreuid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setreuid32 -{ TARGET_NR_setreuid32, "setreuid32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_setrlimit { TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_set_robust_list { TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_setsid -{ TARGET_NR_setsid, "setsid" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_setsockopt { TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL }, #endif @@ -1266,12 +1128,6 @@ #ifdef TARGET_NR_settimeofday { TARGET_NR_settimeofday, "settimeofday" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_setuid -{ TARGET_NR_setuid, "setuid" , NULL, NULL, NULL }, -#endif -#ifdef TARGET_NR_setuid32 -{ TARGET_NR_setuid32, "setuid32" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_setxattr { TARGET_NR_setxattr, "setxattr" , NULL, NULL, NULL }, #endif @@ -1506,9 +1362,6 @@ #ifdef TARGET_NR_utrap_install { TARGET_NR_utrap_install, "utrap_install" , NULL, NULL, NULL }, #endif -#ifdef TARGET_NR_vfork -{ TARGET_NR_vfork, "vfork" , NULL, NULL, NULL }, -#endif #ifdef TARGET_NR_vhangup { TARGET_NR_vhangup, "vhangup" , NULL, NULL, NULL }, #endif