From patchwork Wed Sep 14 20:20:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Markovic X-Patchwork-Id: 9332469 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 383986077F for ; Wed, 14 Sep 2016 20:30:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2A53429FF8 for ; Wed, 14 Sep 2016 20:30:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1EEC429FFD; Wed, 14 Sep 2016 20:30:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4E33329FF8 for ; Wed, 14 Sep 2016 20:30:26 +0000 (UTC) Received: from localhost ([::1]:58603 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkGp7-0004Vi-GL for patchwork-qemu-devel@patchwork.kernel.org; Wed, 14 Sep 2016 16:30:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38170) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkGhY-0006m6-HB for qemu-devel@nongnu.org; Wed, 14 Sep 2016 16:22:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bkGhU-0001H3-Eq for qemu-devel@nongnu.org; Wed, 14 Sep 2016 16:22:35 -0400 Received: from mx2.rt-rk.com ([89.216.37.149]:44623 helo=mail.rt-rk.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bkGhU-0001Gh-3p for qemu-devel@nongnu.org; Wed, 14 Sep 2016 16:22:32 -0400 Received: from localhost (localhost [127.0.0.1]) by mail.rt-rk.com (Postfix) with ESMTP id 4C08C1A2297; Wed, 14 Sep 2016 22:22:31 +0200 (CEST) X-Virus-Scanned: amavisd-new at rt-rk.com Received: from mcs19.domain.local (mcs19.domain.local [10.10.13.51]) by mail.rt-rk.com (Postfix) with ESMTPSA id 2FB191A211A; Wed, 14 Sep 2016 22:22:31 +0200 (CEST) From: Aleksandar Markovic To: qemu-devel@nongnu.org, riku.voipio@iki.fi, peter.maydell@linaro.org, petar.jovanovic@imgtec.com, miodrag.dinic@imgtec.com, aleksandar.rikalo@imgtec.com, aleksandar.markovic@imgtec.com Date: Wed, 14 Sep 2016 22:20:00 +0200 Message-Id: <20160914202008.14119-8-aleksandar.markovic@rt-rk.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160914202008.14119-1-aleksandar.markovic@rt-rk.com> References: <20160914202008.14119-1-aleksandar.markovic@rt-rk.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 89.216.37.149 Subject: [Qemu-devel] [PATCH v5 7/8] linux-user: Fix syslog() syscall support 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: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Aleksandar Markovic There are currently several problems related to syslog() support. For example, if the second argument "bufp" of target syslog() syscall is NULL, the current implementation always returns error code EFAULT. However, NULL is a perfectly valid value for the second argument for many use cases of this syscall. This is, for example, visible from this excerpt of man page for syslog(2): > EINVAL Bad arguments (e.g., bad type; or for type 2, 3, or 4, buf is > NULL, or len is less than zero; or for type 8, the level is > outside the range 1 to 8). Moreover, the argument "bufp" is ignored for all cases of values of the first argument, except 2, 3 and 4. This means that for such cases (the first argument is not 2, 3 or 4), there is no need to pass "buf" between host and target, and it can be set to NULL while calling host's syslog(), without loss of emulation accuracy. Note also that if "bufp" is NULL and the first argument is 2, 3 or 4, the correct returned error code is EINVAL, not EFAULT. All these details are reflected in this patch. "#ifdef TARGET_NR_syslog" is also proprerly inserted when needed. Support for Qemu's "-strace" switch for syslog() syscall is included too. LTP tests syslog11 and syslog12 pass with this patch (while fail without it), on any platform. Signed-off-by: Aleksandar Markovic --- linux-user/strace.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ linux-user/strace.list | 2 +- linux-user/syscall.c | 23 +++++++++++----- linux-user/syscall_defs.h | 25 +++++++++++++++++ 4 files changed, 111 insertions(+), 7 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 61911e7..6177f2c 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1709,6 +1709,74 @@ print_rt_sigprocmask(const struct syscallname *name, } #endif +#ifdef TARGET_NR_syslog +static void +print_syslog_action(abi_ulong arg, int last) +{ + switch (arg) { + case TARGET_SYSLOG_ACTION_CLOSE: { + gemu_log("%s%s", "SYSLOG_ACTION_CLOSE", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_OPEN: { + gemu_log("%s%s", "SYSLOG_ACTION_OPEN", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_READ: { + gemu_log("%s%s", "SYSLOG_ACTION_READ", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_READ_ALL: { + gemu_log("%s%s", "SYSLOG_ACTION_READ_ALL", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_READ_CLEAR: { + gemu_log("%s%s", "SYSLOG_ACTION_READ_CLEAR", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_CLEAR: { + gemu_log("%s%s", "SYSLOG_ACTION_CLEAR", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_CONSOLE_OFF: { + gemu_log("%s%s", "SYSLOG_ACTION_CONSOLE_OFF", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_CONSOLE_ON: { + gemu_log("%s%s", "SYSLOG_ACTION_CONSOLE_ON", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: { + gemu_log("%s%s", "SYSLOG_ACTION_CONSOLE_LEVEL", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_SIZE_UNREAD: { + gemu_log("%s%s", "SYSLOG_ACTION_SIZE_UNREAD", get_comma(last)); + break; + } + case TARGET_SYSLOG_ACTION_SIZE_BUFFER: { + gemu_log("%s%s", "SYSLOG_ACTION_SIZE_BUFFER", get_comma(last)); + break; + } + default: { + print_raw_param("%ld", arg, last); + } + } +} + +static void +print_syslog(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_syslog_action(arg0, 0); + print_pointer(arg1, 0); + print_raw_param("%d", arg2, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_mknod static void print_mknod(const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 0bf1bea..2f99ac2 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1380,7 +1380,7 @@ { TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_syslog -{ TARGET_NR_syslog, "syslog" , NULL, NULL, NULL }, +{ TARGET_NR_syslog, "syslog" , NULL, print_syslog, NULL }, #endif #ifdef TARGET_NR_sysmips { TARGET_NR_sysmips, "sysmips" , NULL, NULL, NULL }, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4ffcce5..37ce908 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9219,14 +9219,25 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); break; #endif - +#ifdef TARGET_NR_syslog case TARGET_NR_syslog: - if (!(p = lock_user_string(arg2))) - goto efault; - ret = get_errno(sys_syslog((int)arg1, p, (int)arg3)); - unlock_user(p, arg2, 0); + { + if (((int)arg1 == TARGET_SYSLOG_ACTION_READ) || + ((int)arg1 == TARGET_SYSLOG_ACTION_READ_ALL) || + ((int)arg1 == TARGET_SYSLOG_ACTION_READ_CLEAR)) { + p = lock_user_string(arg2); + if (!p) { + ret = -TARGET_EINVAL; + goto fail; + } + ret = get_errno(sys_syslog((int)arg1, p, (int)arg3)); + unlock_user(p, arg2, 0); + } else { + ret = get_errno(sys_syslog((int)arg1, NULL, (int)arg3)); + } + } break; - +#endif case TARGET_NR_setitimer: { struct itimerval value, ovalue, *pvalue; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index afd9191..50b1b60 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2661,4 +2661,29 @@ struct target_user_cap_data { uint32_t inheritable; }; +/* from kernel's include/linux/syslog.h */ + +/* Close the log. Currently a NOP. */ +#define TARGET_SYSLOG_ACTION_CLOSE 0 +/* Open the log. Currently a NOP. */ +#define TARGET_SYSLOG_ACTION_OPEN 1 +/* Read from the log. */ +#define TARGET_SYSLOG_ACTION_READ 2 +/* Read all messages remaining in the ring buffer. */ +#define TARGET_SYSLOG_ACTION_READ_ALL 3 +/* Read and clear all messages remaining in the ring buffer */ +#define TARGET_SYSLOG_ACTION_READ_CLEAR 4 +/* Clear ring buffer. */ +#define TARGET_SYSLOG_ACTION_CLEAR 5 +/* Disable printk's to console */ +#define TARGET_SYSLOG_ACTION_CONSOLE_OFF 6 +/* Enable printk's to console */ +#define TARGET_SYSLOG_ACTION_CONSOLE_ON 7 +/* Set level of messages printed to console */ +#define TARGET_SYSLOG_ACTION_CONSOLE_LEVEL 8 +/* Return number of unread characters in the log buffer */ +#define TARGET_SYSLOG_ACTION_SIZE_UNREAD 9 +/* Return size of the log buffer */ +#define TARGET_SYSLOG_ACTION_SIZE_BUFFER 10 + #endif