+++ /dev/null
-diff -r -u src/src/syscall/chain.c src_set_syscall_workaround/src/syscall/chain.c
---- src/src/syscall/chain.c 2015-07-23 21:50:10.000000000 +0200
-+++ src_set_syscall_workaround/src/syscall/chain.c 2016-08-12 19:33:13.920471000 +0200
-@@ -39,17 +39,10 @@
-
- STAILQ_HEAD(chained_syscalls, chained_syscall);
-
--/**
-- * Append a new syscall (@sysnum, @sysarg_*) to the list of
-- * "unrequested" syscalls for the given @tracee. These new syscalls
-- * will be triggered in order once the current syscall is done. The
-- * caller is free to force the last result of this syscall chain in
-- * @tracee->chain.final_result. This function returns -errno if an
-- * error occurred, otherwise 0.
-- */
--int register_chained_syscall(Tracee *tracee, Sysnum sysnum,
-+static int register_chained_syscall_internal(Tracee *tracee, Sysnum sysnum,
- word_t sysarg_1, word_t sysarg_2, word_t sysarg_3,
-- word_t sysarg_4, word_t sysarg_5, word_t sysarg_6)
-+ word_t sysarg_4, word_t sysarg_5, word_t sysarg_6,
-+ bool at_front)
- {
- struct chained_syscall *syscall;
-
-@@ -73,12 +66,35 @@
- syscall->sysargs[4] = sysarg_5;
- syscall->sysargs[5] = sysarg_6;
-
-- STAILQ_INSERT_TAIL(tracee->chain.syscalls, syscall, link);
-+ if (at_front) {
-+ STAILQ_INSERT_HEAD(tracee->chain.syscalls, syscall, link);
-+ } else {
-+ STAILQ_INSERT_TAIL(tracee->chain.syscalls, syscall, link);
-+ }
-
- return 0;
- }
-
- /**
-+ * Append a new syscall (@sysnum, @sysarg_*) to the list of
-+ * "unrequested" syscalls for the given @tracee. These new syscalls
-+ * will be triggered in order once the current syscall is done. The
-+ * caller is free to force the last result of this syscall chain in
-+ * @tracee->chain.final_result. This function returns -errno if an
-+ * error occurred, otherwise 0.
-+ */
-+int register_chained_syscall(Tracee *tracee, Sysnum sysnum,
-+ word_t sysarg_1, word_t sysarg_2, word_t sysarg_3,
-+ word_t sysarg_4, word_t sysarg_5, word_t sysarg_6) {
-+ return register_chained_syscall_internal(
-+ tracee, sysnum,
-+ sysarg_1, sysarg_2, sysarg_3,
-+ sysarg_4, sysarg_5, sysarg_6,
-+ false
-+ );
-+}
-+
-+/**
- * Use/remove the first element of @tracee->chain.syscalls to forge a
- * new syscall. This function should be called only at the end of in
- * the sysexit stage.
-@@ -126,6 +142,9 @@
- /* Move the instruction pointer back to the original trap. */
- instr_pointer = peek_reg(tracee, CURRENT, INSTR_POINTER);
- poke_reg(tracee, INSTR_POINTER, instr_pointer - SYSTRAP_SIZE);
-+
-+ /* Break after exit from syscall, there may be another one in chain */
-+ tracee->restart_how = PTRACE_SYSCALL;
- }
-
- /**
-@@ -154,3 +173,18 @@
- peek_reg(tracee, ORIGINAL, SYSARG_5),
- peek_reg(tracee, ORIGINAL, SYSARG_6));
- }
-+
-+int restart_current_syscall_as_chained(Tracee *tracee)
-+{
-+ assert(tracee->chain.sysnum_workaround_state == SYSNUM_WORKAROUND_INACTIVE);
-+ tracee->chain.sysnum_workaround_state = SYSNUM_WORKAROUND_PROCESS_FAULTY_CALL;
-+ return register_chained_syscall_internal(tracee,
-+ get_sysnum(tracee, CURRENT),
-+ peek_reg(tracee, CURRENT, SYSARG_1),
-+ peek_reg(tracee, CURRENT, SYSARG_2),
-+ peek_reg(tracee, CURRENT, SYSARG_3),
-+ peek_reg(tracee, CURRENT, SYSARG_4),
-+ peek_reg(tracee, CURRENT, SYSARG_5),
-+ peek_reg(tracee, CURRENT, SYSARG_6),
-+ true);
-+}
-diff -r -u src/src/syscall/chain.h src_set_syscall_workaround/src/syscall/chain.h
---- src/src/syscall/chain.h 2015-07-23 21:50:10.000000000 +0200
-+++ src_set_syscall_workaround/src/syscall/chain.h 2016-08-09 17:12:36.448471000 +0200
-@@ -37,5 +37,7 @@
-
- extern void chain_next_syscall(Tracee *tracee);
-
-+extern int restart_current_syscall_as_chained(Tracee *tracee);
-+
-
- #endif /* CHAIN_H */
-diff -r -u src/src/syscall/syscall.c src_set_syscall_workaround/src/syscall/syscall.c
---- src/src/syscall/syscall.c 2015-07-23 21:50:10.000000000 +0200
-+++ src_set_syscall_workaround/src/syscall/syscall.c 2016-08-12 19:32:35.199527000 +0200
-@@ -31,6 +31,7 @@
- #include "tracee/tracee.h"
- #include "tracee/reg.h"
- #include "tracee/mem.h"
-+#include "cli/note.h"
-
- /**
- * Copy in @path a C string (PATH_MAX bytes max.) from the @tracee's
-@@ -126,7 +127,9 @@
- save_current_regs(tracee, MODIFIED);
- }
- else {
-- status = notify_extensions(tracee, SYSCALL_CHAINED_ENTER, 0, 0);
-+ if (tracee->chain.sysnum_workaround_state != SYSNUM_WORKAROUND_PROCESS_REPLACED_CALL) {
-+ status = notify_extensions(tracee, SYSCALL_CHAINED_ENTER, 0, 0);
-+ }
- tracee->restart_how = PTRACE_SYSCALL;
- }
-
-@@ -159,8 +162,13 @@
- /* Translate the syscall only if it was actually
- * requested by the tracee, it is not a syscall
- * chained by PRoot. */
-- if (tracee->chain.syscalls == NULL)
-+ if (tracee->chain.syscalls == NULL || tracee->chain.sysnum_workaround_state == SYSNUM_WORKAROUND_PROCESS_REPLACED_CALL) {
-+ tracee->chain.sysnum_workaround_state = SYSNUM_WORKAROUND_INACTIVE;
- translate_syscall_exit(tracee);
-+ }
-+ else if (tracee->chain.sysnum_workaround_state == SYSNUM_WORKAROUND_PROCESS_FAULTY_CALL) {
-+ tracee->chain.sysnum_workaround_state = SYSNUM_WORKAROUND_PROCESS_REPLACED_CALL;
-+ }
- else
- (void) notify_extensions(tracee, SYSCALL_CHAINED_EXIT, 0, 0);
-
-@@ -172,7 +180,42 @@
- chain_next_syscall(tracee);
- }
-
-- (void) push_regs(tracee);
-+ bool override_sysnum = is_enter_stage && tracee->chain.syscalls == NULL;
-+ int push_regs_status = push_specific_regs(tracee, override_sysnum);
-+
-+ /* Handle inability to change syscall number */
-+ if (push_regs_status < 0 && override_sysnum) {
-+ word_t orig_sysnum = peek_reg(tracee, ORIGINAL, SYSARG_NUM);
-+ word_t current_sysnum = peek_reg(tracee, CURRENT, SYSARG_NUM);
-+ if (orig_sysnum != current_sysnum) {
-+ /* Restart current syscall as chained */
-+ if (current_sysnum != SYSCALL_AVOIDER) {
-+ restart_current_syscall_as_chained(tracee);
-+ }
-+
-+ /* Set syscall arguments to make it fail
-+ * TODO: More reliable way to make invalid arguments */
-+ if (get_sysnum(tracee, ORIGINAL) == PR_brk) {
-+ /* For brk() we pass 0 as first arg; this is used to query value without changing it */
-+ poke_reg(tracee, SYSARG_1, 0);
-+ } else {
-+ /* For other syscalls we set all args to -1
-+ * Hoping there is among them invalid request/address/fd/value that will make syscall fail */
-+ poke_reg(tracee, SYSARG_1, -1);
-+ poke_reg(tracee, SYSARG_2, -1);
-+ poke_reg(tracee, SYSARG_3, -1);
-+ poke_reg(tracee, SYSARG_4, -1);
-+ poke_reg(tracee, SYSARG_5, -1);
-+ poke_reg(tracee, SYSARG_6, -1);
-+ }
-+
-+ /* Push regs again without changing syscall */
-+ push_regs_status = push_specific_regs(tracee, false);
-+ if (push_regs_status != 0) {
-+ note(tracee, WARNING, SYSTEM, "can't set tracee registers in workaround");
-+ }
-+ }
-+ }
-
- if (is_enter_stage)
- print_current_regs(tracee, 5, "sysenter end" );
-diff -r -u src/src/tracee/reg.c src_set_syscall_workaround/src/tracee/reg.c
---- src/src/tracee/reg.c 2015-07-23 21:50:10.000000000 +0200
-+++ src_set_syscall_workaround/src/tracee/reg.c 2016-08-12 14:48:31.410423000 +0200
-@@ -262,12 +262,7 @@
- return 0;
- }
-
--/**
-- * Copy the cached values of all @tracee's general purpose registers
-- * back to the process, if necessary. This function returns -errno if
-- * an error occured, 0 otherwise.
-- */
--int push_regs(Tracee *tracee)
-+int push_specific_regs(Tracee *tracee, bool including_sysnum)
- {
- int status;
-
-@@ -306,12 +301,14 @@
- /* Update syscall number if needed. On arm64, a new
- * subcommand has been added to PTRACE_{S,G}ETREGSET
- * to allow write/read of current sycall number. */
-- if (current_sysnum != REG(tracee, ORIGINAL, SYSARG_NUM)) {
-+ if (including_sysnum && current_sysnum != REG(tracee, ORIGINAL, SYSARG_NUM)) {
- regs.iov_base = ¤t_sysnum;
- regs.iov_len = sizeof(current_sysnum);
- status = ptrace(PTRACE_SETREGSET, tracee->pid, NT_ARM_SYSTEM_CALL, ®s);
-- if (status < 0)
-- note(tracee, WARNING, SYSTEM, "can't set the syscall number");
-+ if (status < 0) {
-+ //note(tracee, WARNING, SYSTEM, "can't set the syscall number");
-+ return status;
-+ }
- }
-
- /* Update other registers. */
-@@ -325,10 +322,12 @@
- * change effectively the syscall number during a
- * ptrace-stop. */
- word_t current_sysnum = REG(tracee, CURRENT, SYSARG_NUM);
-- if (current_sysnum != REG(tracee, ORIGINAL, SYSARG_NUM)) {
-+ if (including_sysnum && current_sysnum != REG(tracee, ORIGINAL, SYSARG_NUM)) {
- status = ptrace(PTRACE_SET_SYSCALL, tracee->pid, 0, current_sysnum);
-- if (status < 0)
-- note(tracee, WARNING, SYSTEM, "can't set the syscall number");
-+ if (status < 0) {
-+ //note(tracee, WARNING, SYSTEM, "can't set the syscall number");
-+ return status;
-+ }
- }
- # endif
-
-@@ -340,3 +339,12 @@
-
- return 0;
- }
-+
-+/**
-+ * Copy the cached values of all @tracee's general purpose registers
-+ * back to the process, if necessary. This function returns -errno if
-+ * an error occured, 0 otherwise.
-+ */
-+int push_regs(Tracee *tracee) {
-+ return push_specific_regs(tracee, true);
-+}
-diff -r -u src/src/tracee/reg.h src_set_syscall_workaround/src/tracee/reg.h
---- src/src/tracee/reg.h 2015-07-23 21:50:10.000000000 +0200
-+++ src_set_syscall_workaround/src/tracee/reg.h 2016-08-09 21:38:03.863456000 +0200
-@@ -43,6 +43,7 @@
- } Reg;
-
- extern int fetch_regs(Tracee *tracee);
-+extern int push_specific_regs(Tracee *tracee, bool including_sysnum);
- extern int push_regs(Tracee *tracee);
-
- extern word_t peek_reg(const Tracee *tracee, RegVersion version, Reg reg);
-diff -r -u src/src/tracee/tracee.h src_set_syscall_workaround/src/tracee/tracee.h
---- src/src/tracee/tracee.h 2016-08-12 19:44:07.301407472 +0200
-+++ src_set_syscall_workaround/src/tracee/tracee.h 2016-08-12 19:52:43.554712737 +0200
-@@ -193,6 +193,11 @@
- struct chained_syscalls *syscalls;
- bool force_final_result;
- word_t final_result;
-+ enum {
-+ SYSNUM_WORKAROUND_INACTIVE,
-+ SYSNUM_WORKAROUND_PROCESS_FAULTY_CALL,
-+ SYSNUM_WORKAROUND_PROCESS_REPLACED_CALL
-+ } sysnum_workaround_state;
- } chain;
-
- /* Load info generated during execve sysenter and used during