diff --git a/linux-user/strace.c b/linux-user/strace.c
index a52ff58..2c340c3 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1696,6 +1696,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 e8133b0..fadeb29 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1377,7 +1377,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 60a94e4..f7a7709 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
