Browse Source

Introduce PTRACE_GET_SYSCALL_INFO support

When PTRACE_GET_SYSCALL_INFO API works,
use it instead of traditional upeek/get_regs API.

Tested on x86_64 and x86.

* get_personality.c: New file.
* get_personality.h: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* linux/aarch64/arch_get_personality.c: New file.
* linux/powerpc64/arch_get_personality.c: Likewise.
* linux/riscv/arch_get_personality.c: Likewise.
* linux/s390x/arch_get_personality.c: Likewise.
* linux/sparc64/arch_get_personality.c: Likewise.
* linux/tile/arch_get_personality.c: Likewise.
* linux/x32/arch_get_personality.c: Likewise.
* linux/x86_64/arch_get_personality.c: Likewise.
* linux/check_scno.c: Likewise.
* linux/x32/check_scno.c: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
* linux/ia64/arch_getrval2.c (getrval2): Invoke get_regs()
if ptrace_syscall_info is in use.
* linux/mips/arch_getrval2.c: Likewise.
* linux/sparc/arch_getrval2.c: Likewise.
* defs.h (get_personality_from_syscall_info): New prototype.
* syscall.c: Include "get_personality.h" and "ptrace_syscall_info.h".
(get_regs_error): Define unconditionally.
(ptrace_sci): New static variable.
(clear_regs): Reset ptrace_sci.op.
(ptrace_syscall_info_is_valid, ptrace_get_syscall_info,
get_syscall_regs): New functions.
(get_syscall_result_regs): Change to get_syscall_regs.
(get_instruction_pointer, get_stack_pointer, get_scno, get_syscall_args,
get_error, set_error, set_success): Add ptrace_syscall_info support.
* tests/int_0x80.test: New test.
* tests/Makefile.am (DECODER_TESTS): Add int_0x80.test.
(XFAIL_TESTS_x86_64, XFAIL_TESTS_x32): Remove.
* tests/gen_tests.in (int_0x80): Remove.
Dmitry V. Levin 1 year ago
parent
commit
e3b80cb65f

+ 13
- 1
Makefile.am View File

@@ -134,6 +134,8 @@ strace_SOURCES =	\
134 134
 	fs_x_ioctl.c	\
135 135
 	futex.c		\
136 136
 	gcc_compat.h	\
137
+	get_personality.c \
138
+	get_personality.h \
137 139
 	get_robust_list.c \
138 140
 	getcpu.c	\
139 141
 	getcwd.c	\
@@ -417,6 +419,7 @@ EXTRA_DIST =				\
417 419
 	linux/64/ioctls_inc.h		\
418 420
 	linux/64/syscallent.h		\
419 421
 	linux/aarch64/arch_defs_.h	\
422
+	linux/aarch64/arch_get_personality.c \
420 423
 	linux/aarch64/arch_regs.c	\
421 424
 	linux/aarch64/arch_sigreturn.c	\
422 425
 	linux/aarch64/get_error.c	\
@@ -505,6 +508,7 @@ EXTRA_DIST =				\
505 508
 	linux/bfin/set_scno.c		\
506 509
 	linux/bfin/syscallent.h		\
507 510
 	linux/bfin/userent.h		\
511
+	linux/check_scno.c		\
508 512
 	linux/dummy.h			\
509 513
 	linux/errnoent.h		\
510 514
 	linux/getregs_old.h		\
@@ -524,8 +528,8 @@ EXTRA_DIST =				\
524 528
 	linux/hppa/set_scno.c		\
525 529
 	linux/hppa/signalent.h		\
526 530
 	linux/hppa/syscallent.h		\
527
-	linux/i386/arch_kvm.c		\
528 531
 	linux/i386/arch_defs_.h		\
532
+	linux/i386/arch_kvm.c		\
529 533
 	linux/i386/arch_regs.c		\
530 534
 	linux/i386/arch_rt_sigframe.c	\
531 535
 	linux/i386/arch_sigreturn.c	\
@@ -663,6 +667,7 @@ EXTRA_DIST =				\
663 667
 	linux/powerpc/syscallent.h	\
664 668
 	linux/powerpc/userent.h		\
665 669
 	linux/powerpc64/arch_defs_.h	\
670
+	linux/powerpc64/arch_get_personality.c \
666 671
 	linux/powerpc64/arch_regs.c	\
667 672
 	linux/powerpc64/arch_rt_sigframe.c	\
668 673
 	linux/powerpc64/arch_sigreturn.c	\
@@ -686,6 +691,7 @@ EXTRA_DIST =				\
686 691
 	linux/ptrace_pokeuser.c		\
687 692
 	linux/raw_syscall.h		\
688 693
 	linux/riscv/arch_defs_.h	\
694
+	linux/riscv/arch_get_personality.c \
689 695
 	linux/riscv/arch_regs.c		\
690 696
 	linux/riscv/get_error.c		\
691 697
 	linux/riscv/get_scno.c		\
@@ -717,6 +723,7 @@ EXTRA_DIST =				\
717 723
 	linux/s390/userent0.h		\
718 724
 	linux/s390/userent1.h		\
719 725
 	linux/s390x/arch_defs_.h	\
726
+	linux/s390x/arch_get_personality.c \
720 727
 	linux/s390x/arch_regs.c		\
721 728
 	linux/s390x/arch_sigreturn.c	\
722 729
 	linux/s390x/get_error.c		\
@@ -786,6 +793,7 @@ EXTRA_DIST =				\
786 793
 	linux/sparc/syscallent.h	\
787 794
 	linux/sparc/userent.h		\
788 795
 	linux/sparc64/arch_defs_.h	\
796
+	linux/sparc64/arch_get_personality.c \
789 797
 	linux/sparc64/arch_getrval2.c	\
790 798
 	linux/sparc64/arch_regs.c	\
791 799
 	linux/sparc64/arch_rt_sigframe.c	\
@@ -809,6 +817,7 @@ EXTRA_DIST =				\
809 817
 	linux/subcall.h			\
810 818
 	linux/syscall.h			\
811 819
 	linux/tile/arch_defs_.h		\
820
+	linux/tile/arch_get_personality.c \
812 821
 	linux/tile/arch_regs.c		\
813 822
 	linux/tile/arch_sigreturn.c	\
814 823
 	linux/tile/get_error.c		\
@@ -829,11 +838,13 @@ EXTRA_DIST =				\
829 838
 	linux/userent.h			\
830 839
 	linux/userent0.h		\
831 840
 	linux/x32/arch_defs_.h		\
841
+	linux/x32/arch_get_personality.c \
832 842
 	linux/x32/arch_kvm.c		\
833 843
 	linux/x32/arch_regs.c		\
834 844
 	linux/x32/arch_regs.h		\
835 845
 	linux/x32/arch_rt_sigframe.c	\
836 846
 	linux/x32/arch_sigreturn.c	\
847
+	linux/x32/check_scno.c		\
837 848
 	linux/x32/get_error.c		\
838 849
 	linux/x32/get_scno.c		\
839 850
 	linux/x32/get_syscall_args.c	\
@@ -851,6 +862,7 @@ EXTRA_DIST =				\
851 862
 	linux/x32/syscallent1.h		\
852 863
 	linux/x32/userent.h		\
853 864
 	linux/x86_64/arch_defs_.h	\
865
+	linux/x86_64/arch_get_personality.c \
854 866
 	linux/x86_64/arch_kvm.c		\
855 867
 	linux/x86_64/arch_regs.c	\
856 868
 	linux/x86_64/arch_regs.h	\

+ 14
- 0
get_personality.c View File

@@ -0,0 +1,14 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#include "defs.h"
9
+
10
+#if SUPPORTED_PERSONALITIES > 1
11
+# include "get_personality.h"
12
+# include <linux/audit.h>
13
+# include "arch_get_personality.c"
14
+#endif

+ 16
- 0
get_personality.h View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef STRACE_GET_PERSONALITY_H
9
+#define STRACE_GET_PERSONALITY_H
10
+
11
+#include "ptrace.h"
12
+
13
+extern int
14
+get_personality_from_syscall_info(const struct ptrace_syscall_info *);
15
+
16
+#endif /* !STRACE_GET_PERSONALITY_H */

+ 16
- 0
linux/aarch64/arch_get_personality.c View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_ARM
9
+# define AUDIT_ARCH_ARM 0x40000028
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	return sci->arch == AUDIT_ARCH_ARM;
16
+}

+ 6
- 0
linux/check_scno.c View File

@@ -0,0 +1,6 @@
1
+/* Return codes: 1 - ok, 0 - ignore, other - error. */
2
+static int
3
+arch_check_scno(struct tcb *tcp)
4
+{
5
+	return 1;
6
+}

+ 2
- 0
linux/ia64/arch_getrval2.c View File

@@ -1,5 +1,7 @@
1 1
 long
2 2
 getrval2(struct tcb *tcp)
3 3
 {
4
+	if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0)
5
+		return -1;
4 6
 	return ia64_regs.gr[9];
5 7
 }

+ 2
- 0
linux/mips/arch_getrval2.c View File

@@ -1,5 +1,7 @@
1 1
 long
2 2
 getrval2(struct tcb *tcp)
3 3
 {
4
+	if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0)
5
+		return -1;
4 6
 	return mips_regs.uregs[3];
5 7
 }

+ 16
- 0
linux/powerpc64/arch_get_personality.c View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_PPC
9
+# define AUDIT_ARCH_PPC 0x14
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	return sci->arch == AUDIT_ARCH_PPC;
16
+}

+ 16
- 0
linux/riscv/arch_get_personality.c View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_RISCV32
9
+# define AUDIT_ARCH_RISCV32 0x400000f3
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	return sci->arch == AUDIT_ARCH_RISCV32;
16
+}

+ 16
- 0
linux/s390x/arch_get_personality.c View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_S390
9
+# define AUDIT_ARCH_S390 0x16
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	return sci->arch == AUDIT_ARCH_S390;
16
+}

+ 2
- 0
linux/sparc/arch_getrval2.c View File

@@ -1,5 +1,7 @@
1 1
 long
2 2
 getrval2(struct tcb *tcp)
3 3
 {
4
+	if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0)
5
+		return -1;
4 6
 	return sparc_regs.u_regs[U_REG_O1];
5 7
 }

+ 16
- 0
linux/sparc64/arch_get_personality.c View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_SPARC
9
+# define AUDIT_ARCH_SPARC 0x2
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	return sci->arch == AUDIT_ARCH_SPARC;
16
+}

+ 20
- 0
linux/tile/arch_get_personality.c View File

@@ -0,0 +1,20 @@
1
+/*
2
+ * Copyright (c) 2018 Dmitry V. Levin <ldv@altlinux.org>
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_TILEGX32
9
+# define AUDIT_ARCH_TILEGX32 0x400000bf
10
+#endif
11
+#ifndef AUDIT_ARCH_TILEPRO
12
+# define AUDIT_ARCH_TILEPRO 0x400000bc
13
+#endif
14
+
15
+int
16
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
17
+{
18
+	return sci->arch == AUDIT_ARCH_TILEGX32 ||
19
+	       sci->arch == AUDIT_ARCH_TILEPRO;
20
+}

+ 1
- 0
linux/x32/arch_get_personality.c View File

@@ -0,0 +1 @@
1
+#include "x86_64/arch_get_personality.c"

+ 22
- 0
linux/x32/check_scno.c View File

@@ -0,0 +1,22 @@
1
+/*
2
+ * Copyright (c) 2010-2018 The strace developers.
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+/* Return codes: 1 - ok, 0 - ignore, other - error. */
9
+static int
10
+arch_check_scno(struct tcb *tcp)
11
+{
12
+
13
+	const kernel_ulong_t scno = ptrace_sci.entry.nr;
14
+
15
+	if (tcp->currpers == 0 && !(scno & __X32_SYSCALL_BIT)) {
16
+		error_msg("syscall_%" PRI_klu "(...) in unsupported "
17
+			  "64-bit mode of process PID=%d", scno, tcp->pid);
18
+		return 0;
19
+	}
20
+
21
+	return 1;
22
+}

+ 47
- 0
linux/x86_64/arch_get_personality.c View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * Copyright (c) 2010-2018 The strace developers.
3
+ * All rights reserved.
4
+ *
5
+ * SPDX-License-Identifier: LGPL-2.1-or-later
6
+ */
7
+
8
+#ifndef AUDIT_ARCH_I386
9
+# define AUDIT_ARCH_I386 0x40000003
10
+#endif
11
+
12
+int
13
+get_personality_from_syscall_info(const struct ptrace_syscall_info *sci)
14
+{
15
+	unsigned int pers = sci->arch == AUDIT_ARCH_I386;
16
+
17
+#ifndef X32
18
+	switch(sci->op) {
19
+		case PTRACE_SYSCALL_INFO_ENTRY:
20
+		case PTRACE_SYSCALL_INFO_SECCOMP:
21
+			break;
22
+		default:
23
+			return -1;
24
+	}
25
+
26
+	kernel_ulong_t scno = sci->entry.nr;
27
+
28
+#ifndef __X32_SYSCALL_BIT
29
+# define __X32_SYSCALL_BIT	0x40000000
30
+#endif
31
+
32
+	if (pers == 0 && (scno & __X32_SYSCALL_BIT)) {
33
+		/*
34
+		 * Syscall number -1 requires special treatment:
35
+		 * it might be a side effect of SECCOMP_RET_ERRNO
36
+		 * filtering that sets orig_rax to -1
37
+		 * in some versions of linux kernel.
38
+		 * If that is the case, then
39
+		 * __X32_SYSCALL_BIT logic does not apply.
40
+		 */
41
+		if (scno != (kernel_ulong_t) -1)
42
+			pers = 2;
43
+	}
44
+#endif /* !X32 */
45
+
46
+	return pers;
47
+}

+ 150
- 15
syscall.c View File

@@ -13,9 +13,11 @@
13 13
  */
14 14
 
15 15
 #include "defs.h"
16
+#include "get_personality.h"
16 17
 #include "mmap_notify.h"
17 18
 #include "native_defs.h"
18 19
 #include "ptrace.h"
20
+#include "ptrace_syscall_info.h"
19 21
 #include "nsig.h"
20 22
 #include "number_set.h"
21 23
 #include "delay.h"
@@ -461,6 +463,7 @@ static void get_error(struct tcb *, bool);
461 463
 static void set_error(struct tcb *, unsigned long);
462 464
 static void set_success(struct tcb *, kernel_long_t);
463 465
 static int arch_get_scno(struct tcb *);
466
+static int arch_check_scno(struct tcb *);
464 467
 static int arch_set_scno(struct tcb *, kernel_ulong_t);
465 468
 static int arch_get_syscall_args(struct tcb *);
466 469
 static void arch_get_error(struct tcb *, bool);
@@ -943,11 +946,21 @@ restore_cleared_syserror(struct tcb *tcp)
943 946
 	tcp->u_error = saved_u_error;
944 947
 }
945 948
 
949
+static struct ptrace_syscall_info ptrace_sci;
950
+
951
+static bool
952
+ptrace_syscall_info_is_valid(void)
953
+{
954
+	return ptrace_get_syscall_info_supported &&
955
+	       ptrace_sci.op <= PTRACE_SYSCALL_INFO_SECCOMP;
956
+}
957
+
946 958
 #define XLAT_MACROS_ONLY
947 959
 # include "xlat/nt_descriptor_types.h"
948 960
 #undef XLAT_MACROS_ONLY
949 961
 
950 962
 #define ARCH_MIGHT_USE_SET_REGS 1
963
+
951 964
 #include "arch_regs.c"
952 965
 
953 966
 #if HAVE_ARCH_GETRVAL2
@@ -1035,16 +1048,13 @@ ptrace_setregs(pid_t pid)
1035 1048
 
1036 1049
 #endif /* ARCH_REGS_FOR_GETREGSET || ARCH_REGS_FOR_GETREGS */
1037 1050
 
1038
-#ifdef ptrace_getregset_or_getregs
1039
-static long get_regs_error;
1040
-#endif
1051
+static long get_regs_error = -1;
1041 1052
 
1042 1053
 void
1043 1054
 clear_regs(struct tcb *tcp)
1044 1055
 {
1045
-#ifdef ptrace_getregset_or_getregs
1056
+	ptrace_sci.op = 0xff;
1046 1057
 	get_regs_error = -1;
1047
-#endif
1048 1058
 }
1049 1059
 
1050 1060
 static long
@@ -1139,9 +1149,59 @@ free_sysent_buf(void *ptr)
1139 1149
 	free(ptr);
1140 1150
 }
1141 1151
 
1152
+static bool
1153
+ptrace_get_syscall_info(struct tcb *tcp)
1154
+{
1155
+	/*
1156
+	 * ptrace_get_syscall_info_supported should have been checked
1157
+	 * by the caller.
1158
+	 */
1159
+	if (ptrace_sci.op == 0xff) {
1160
+		const size_t size = sizeof(ptrace_sci);
1161
+		if (ptrace(PTRACE_GET_SYSCALL_INFO, tcp->pid,
1162
+			   (void *) size, &ptrace_sci) < 0) {
1163
+			get_regs_error = -2;
1164
+			return false;
1165
+		}
1166
+#if SUPPORTED_PERSONALITIES > 1
1167
+		int newpers = get_personality_from_syscall_info(&ptrace_sci);
1168
+		if (newpers >= 0)
1169
+			update_personality(tcp, newpers);
1170
+#endif
1171
+	}
1172
+
1173
+	if (entering(tcp)) {
1174
+		if (ptrace_sci.op == PTRACE_SYSCALL_INFO_EXIT) {
1175
+			error_msg("pid %d: entering"
1176
+				  ", ptrace_syscall_info.op == %u",
1177
+				  tcp->pid, ptrace_sci.op);
1178
+			/* TODO: handle this.  */
1179
+		}
1180
+	} else {
1181
+		if (ptrace_sci.op == PTRACE_SYSCALL_INFO_ENTRY) {
1182
+			error_msg("pid %d: exiting"
1183
+				  ", ptrace_syscall_info.op == %u",
1184
+				  tcp->pid, ptrace_sci.op);
1185
+			/* TODO: handle this.  */
1186
+		}
1187
+	}
1188
+
1189
+	return true;
1190
+}
1191
+
1142 1192
 bool
1143 1193
 get_instruction_pointer(struct tcb *tcp, kernel_ulong_t *ip)
1144 1194
 {
1195
+	if (get_regs_error < -1)
1196
+		return false;
1197
+
1198
+	if (ptrace_get_syscall_info_supported) {
1199
+		if (!ptrace_get_syscall_info(tcp))
1200
+			return false;
1201
+		*ip = (kernel_ulong_t) ptrace_sci.instruction_pointer;
1202
+		return true;
1203
+	}
1204
+
1145 1205
 #if defined ARCH_PC_REG
1146 1206
 	if (get_regs(tcp) < 0)
1147 1207
 		return false;
@@ -1159,6 +1219,16 @@ get_instruction_pointer(struct tcb *tcp, kernel_ulong_t *ip)
1159 1219
 bool
1160 1220
 get_stack_pointer(struct tcb *tcp, kernel_ulong_t *sp)
1161 1221
 {
1222
+	if (get_regs_error < -1)
1223
+		return false;
1224
+
1225
+	if (ptrace_get_syscall_info_supported) {
1226
+		if (!ptrace_get_syscall_info(tcp))
1227
+			return false;
1228
+		*sp = (kernel_ulong_t) ptrace_sci.stack_pointer;
1229
+		return true;
1230
+	}
1231
+
1162 1232
 #if defined ARCH_SP_REG
1163 1233
 	if (get_regs(tcp) < 0)
1164 1234
 		return false;
@@ -1173,6 +1243,18 @@ get_stack_pointer(struct tcb *tcp, kernel_ulong_t *sp)
1173 1243
 #endif
1174 1244
 }
1175 1245
 
1246
+static int
1247
+get_syscall_regs(struct tcb *tcp)
1248
+{
1249
+	if (get_regs_error != -1)
1250
+		return get_regs_error;
1251
+
1252
+	if (ptrace_get_syscall_info_supported)
1253
+		return ptrace_get_syscall_info(tcp) ? 0 : get_regs_error;
1254
+
1255
+	return get_regs(tcp);
1256
+}
1257
+
1176 1258
 /*
1177 1259
  * Returns:
1178 1260
  * 0: "ignore this ptrace stop", syscall_entering_decode() should return a "bail
@@ -1184,12 +1266,23 @@ get_stack_pointer(struct tcb *tcp, kernel_ulong_t *sp)
1184 1266
 int
1185 1267
 get_scno(struct tcb *tcp)
1186 1268
 {
1187
-	if (get_regs(tcp) < 0)
1269
+	if (get_syscall_regs(tcp) < 0)
1188 1270
 		return -1;
1189 1271
 
1190
-	int rc = arch_get_scno(tcp);
1191
-	if (rc != 1)
1192
-		return rc;
1272
+	if (ptrace_syscall_info_is_valid()) {
1273
+		/*
1274
+		 * So far it's just a workaround for x32,
1275
+		 * but let's pretend it could be used elsewhere.
1276
+		 */
1277
+		int rc = arch_check_scno(tcp);
1278
+		if (rc != 1)
1279
+			return rc;
1280
+		tcp->scno = ptrace_sci.entry.nr;
1281
+	} else {
1282
+		int rc = arch_get_scno(tcp);
1283
+		if (rc != 1)
1284
+			return rc;
1285
+	}
1193 1286
 
1194 1287
 	tcp->scno = shuffle_scno(tcp->scno);
1195 1288
 
@@ -1229,11 +1322,22 @@ get_scno(struct tcb *tcp)
1229 1322
 static int
1230 1323
 get_syscall_args(struct tcb *tcp)
1231 1324
 {
1325
+	if (ptrace_syscall_info_is_valid()) {
1326
+		for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
1327
+			tcp->u_arg[i] = ptrace_sci.entry.args[i];
1328
+#if SUPPORTED_PERSONALITIES > 1
1329
+		if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
1330
+			for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
1331
+				tcp->u_arg[i] = (uint32_t) tcp->u_arg[i];
1332
+		}
1333
+#endif
1334
+		return 1;
1335
+	}
1232 1336
 	return arch_get_syscall_args(tcp);
1233 1337
 }
1234 1338
 
1235 1339
 #ifdef ptrace_getregset_or_getregs
1236
-# define get_syscall_result_regs get_regs
1340
+# define get_syscall_result_regs get_syscall_regs
1237 1341
 #else
1238 1342
 static int get_syscall_result_regs(struct tcb *);
1239 1343
 #endif
@@ -1259,8 +1363,18 @@ get_syscall_result(struct tcb *tcp)
1259 1363
 static void
1260 1364
 get_error(struct tcb *tcp, const bool check_errno)
1261 1365
 {
1262
-	tcp->u_error = 0;
1263
-	arch_get_error(tcp, check_errno);
1366
+	if (ptrace_syscall_info_is_valid()) {
1367
+		if (ptrace_sci.exit.is_error) {
1368
+			tcp->u_rval = -1;
1369
+			tcp->u_error = -ptrace_sci.exit.rval;
1370
+		} else {
1371
+			tcp->u_error = 0;
1372
+			tcp->u_rval = ptrace_sci.exit.rval;
1373
+		}
1374
+	} else {
1375
+		tcp->u_error = 0;
1376
+		arch_get_error(tcp, check_errno);
1377
+	}
1264 1378
 }
1265 1379
 
1266 1380
 static void
@@ -1271,12 +1385,22 @@ set_error(struct tcb *tcp, unsigned long new_error)
1271 1385
 	if (new_error == old_error || new_error > MAX_ERRNO_VALUE)
1272 1386
 		return;
1273 1387
 
1388
+#ifdef ptrace_setregset_or_setregs
1389
+	/* if we are going to invoke set_regs, call get_regs first */
1390
+	if (get_regs(tcp) < 0)
1391
+		return;
1392
+#endif
1393
+
1274 1394
 	tcp->u_error = new_error;
1275 1395
 	if (arch_set_error(tcp)) {
1276 1396
 		tcp->u_error = old_error;
1277 1397
 		/* arch_set_error does not update u_rval */
1278 1398
 	} else {
1279
-		get_error(tcp, !(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS));
1399
+		if (ptrace_syscall_info_is_valid())
1400
+			tcp->u_rval = -1;
1401
+		else
1402
+			get_error(tcp, !(tcp->s_ent->sys_flags &
1403
+					 SYSCALL_NEVER_FAILS));
1280 1404
 	}
1281 1405
 }
1282 1406
 
@@ -1285,16 +1409,27 @@ set_success(struct tcb *tcp, kernel_long_t new_rval)
1285 1409
 {
1286 1410
 	const kernel_long_t old_rval = tcp->u_rval;
1287 1411
 
1412
+#ifdef ptrace_setregset_or_setregs
1413
+	/* if we are going to invoke set_regs, call get_regs first */
1414
+	if (get_regs(tcp) < 0)
1415
+		return;
1416
+#endif
1417
+
1288 1418
 	tcp->u_rval = new_rval;
1289 1419
 	if (arch_set_success(tcp)) {
1290 1420
 		tcp->u_rval = old_rval;
1291
-		/* arch_set_error does not update u_error */
1421
+		/* arch_set_success does not update u_error */
1292 1422
 	} else {
1293
-		get_error(tcp, !(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS));
1423
+		if (ptrace_syscall_info_is_valid())
1424
+			tcp->u_error = 0;
1425
+		else
1426
+			get_error(tcp, !(tcp->s_ent->sys_flags &
1427
+					 SYSCALL_NEVER_FAILS));
1294 1428
 	}
1295 1429
 }
1296 1430
 
1297 1431
 #include "get_scno.c"
1432
+#include "check_scno.c"
1298 1433
 #include "set_scno.c"
1299 1434
 #include "get_syscall_args.c"
1300 1435
 #ifndef ptrace_getregset_or_getregs

+ 1
- 2
tests/Makefile.am View File

@@ -228,6 +228,7 @@ DECODER_TESTS = \
228 228
 	fadvise64.test \
229 229
 	futex.test \
230 230
 	getuid.test \
231
+	int_0x80.test \
231 232
 	ioctl.test \
232 233
 	ioctl_evdev-success.test \
233 234
 	ioctl_evdev-success-v.test \
@@ -347,8 +348,6 @@ TESTS = $(GEN_TESTS) $(DECODER_TESTS) $(MISC_TESTS) $(STACKTRACE_TESTS)
347 348
 XFAIL_TESTS_ =
348 349
 XFAIL_TESTS_m32 = $(STACKTRACE_TESTS)
349 350
 XFAIL_TESTS_mx32 = $(STACKTRACE_TESTS)
350
-XFAIL_TESTS_x86_64 = int_0x80.gen.test
351
-XFAIL_TESTS_x32 = int_0x80.gen.test
352 351
 XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) $(XFAIL_TESTS_$(ARCH))
353 352
 
354 353
 TEST_LOG_COMPILER = env

+ 0
- 1
tests/gen_tests.in View File

@@ -118,7 +118,6 @@ inet-cmsg	-e trace=recvmsg
118 118
 init_module	-a27
119 119
 inotify	-a23 -e trace=inotify_add_watch,inotify_rm_watch
120 120
 inotify_init1	-a27
121
-int_0x80	-a11 -e trace=getgid32
122 121
 ioctl_block	+ioctl.test
123 122
 ioctl_dm	+ioctl.test -s9
124 123
 ioctl_dm-v	+ioctl.test -v -s9

+ 11
- 0
tests/int_0x80.test View File

@@ -0,0 +1,11 @@
1
+#!/bin/sh
2
+#
3
+# Check decoding of int 0x80 on x86_64, x32, and x86.
4
+
5
+. "${srcdir=.}/init.sh"
6
+
7
+$STRACE -d -enone / > /dev/null 2> "$LOG"
8
+grep -x "[^:]*strace: PTRACE_GET_SYSCALL_INFO works" "$LOG" > /dev/null ||
9
+	skip_ 'PTRACE_GET_SYSCALL_INFO does not work'
10
+
11
+run_strace_match_diff -a11 -e trace=getgid32

Loading…
Cancel
Save