Fix decoding of get[ug]id, gete[ug]id and setfs[ug]id return values
* defs.h (SYSCALL_NEVER_FAILS): New syscall flag.
* linux/dummy.h: Change redirection for sys_get[ug]id, sys_gete[ug]id
and setfs[ug]id.
* linux/*/syscallent.h: Set SYSCALL_NEVER_FAILS flag for get[ug]id,
gete[ug]id and setfs[ug]id syscalls.
* process.c [LINUX] (sys_getuid, sys_setfsuid): New functions.
* syscall.c (NF): New shorthand macro for use in syscallent.h files.
(get_error): Check SYSCALL_NEVER_FAILS flag.
Reported by Марк Коренберг <socketpair@gmail.com>.
diff --git a/syscall.c b/syscall.c
index 8fcd10b..39135f7 100644
--- a/syscall.c
+++ b/syscall.c
@@ -109,6 +109,7 @@
#define TN TRACE_NETWORK
#define TP TRACE_PROCESS
#define TS TRACE_SIGNAL
+#define NF SYSCALL_NEVER_FAILS
static const struct sysent sysent0[] = {
#include "syscallent.h"
@@ -143,6 +144,7 @@
#undef TN
#undef TP
#undef TS
+#undef NF
static const char *const errnoent0[] = {
#include "errnoent.h"
@@ -1553,8 +1555,13 @@
{
int u_error = 0;
#ifdef LINUX
+ int check_errno = 1;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
+ sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
+ check_errno = 0;
+ }
# if defined(S390) || defined(S390X)
- if (is_negated_errno(gpr2)) {
+ if (check_errno && is_negated_errno(gpr2)) {
tcp->u_rval = -1;
u_error = -gpr2;
}
@@ -1563,7 +1570,7 @@
u_error = 0;
}
# elif defined(I386)
- if (is_negated_errno(eax)) {
+ if (check_errno && is_negated_errno(eax)) {
tcp->u_rval = -1;
u_error = -eax;
}
@@ -1572,7 +1579,7 @@
u_error = 0;
}
# elif defined(X86_64)
- if (is_negated_errno(rax)) {
+ if (check_errno && is_negated_errno(rax)) {
tcp->u_rval = -1;
u_error = -rax;
}
@@ -1585,7 +1592,7 @@
int err;
err = (int)r8;
- if (is_negated_errno(err)) {
+ if (check_errno && is_negated_errno(err)) {
tcp->u_rval = -1;
u_error = -err;
}
@@ -1594,7 +1601,7 @@
u_error = 0;
}
} else {
- if (r10) {
+ if (check_errno && r10) {
tcp->u_rval = -1;
u_error = r8;
} else {
@@ -1603,7 +1610,7 @@
}
}
# elif defined(MIPS)
- if (a3) {
+ if (check_errno && a3) {
tcp->u_rval = -1;
u_error = r2;
} else {
@@ -1611,7 +1618,7 @@
u_error = 0;
}
# elif defined(POWERPC)
- if (is_negated_errno(result)) {
+ if (check_errno && is_negated_errno(result)) {
tcp->u_rval = -1;
u_error = -result;
}
@@ -1620,7 +1627,7 @@
u_error = 0;
}
# elif defined(M68K)
- if (is_negated_errno(d0)) {
+ if (check_errno && is_negated_errno(d0)) {
tcp->u_rval = -1;
u_error = -d0;
}
@@ -1629,7 +1636,7 @@
u_error = 0;
}
# elif defined(ARM)
- if (is_negated_errno(regs.ARM_r0)) {
+ if (check_errno && is_negated_errno(regs.ARM_r0)) {
tcp->u_rval = -1;
u_error = -regs.ARM_r0;
}
@@ -1638,7 +1645,7 @@
u_error = 0;
}
# elif defined(AVR32)
- if (regs.r12 && (unsigned) -regs.r12 < nerrnos) {
+ if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
tcp->u_rval = -1;
u_error = -regs.r12;
}
@@ -1647,7 +1654,7 @@
u_error = 0;
}
# elif defined(BFIN)
- if (is_negated_errno(r0)) {
+ if (check_errno && is_negated_errno(r0)) {
tcp->u_rval = -1;
u_error = -r0;
} else {
@@ -1655,7 +1662,7 @@
u_error = 0;
}
# elif defined(ALPHA)
- if (a3) {
+ if (check_errno && a3) {
tcp->u_rval = -1;
u_error = r0;
}
@@ -1664,7 +1671,7 @@
u_error = 0;
}
# elif defined(SPARC)
- if (regs.psr & PSR_C) {
+ if (check_errno && regs.psr & PSR_C) {
tcp->u_rval = -1;
u_error = regs.u_regs[U_REG_O0];
}
@@ -1673,7 +1680,7 @@
u_error = 0;
}
# elif defined(SPARC64)
- if (regs.tstate & 0x1100000000UL) {
+ if (check_errno && regs.tstate & 0x1100000000UL) {
tcp->u_rval = -1;
u_error = regs.u_regs[U_REG_O0];
}
@@ -1682,7 +1689,7 @@
u_error = 0;
}
# elif defined(HPPA)
- if (is_negated_errno(r28)) {
+ if (check_errno && is_negated_errno(r28)) {
tcp->u_rval = -1;
u_error = -r28;
}
@@ -1692,7 +1699,7 @@
}
# elif defined(SH)
/* interpret R0 as return value or error number */
- if (is_negated_errno(r0)) {
+ if (check_errno && is_negated_errno(r0)) {
tcp->u_rval = -1;
u_error = -r0;
}
@@ -1702,7 +1709,7 @@
}
# elif defined(SH64)
/* interpret result as return value or error number */
- if (is_negated_errno(r9)) {
+ if (check_errno && is_negated_errno(r9)) {
tcp->u_rval = -1;
u_error = -r9;
}
@@ -1711,7 +1718,7 @@
u_error = 0;
}
# elif defined(CRISV10) || defined(CRISV32)
- if (r10 && (unsigned) -r10 < nerrnos) {
+ if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
tcp->u_rval = -1;
u_error = -r10;
}
@@ -1724,7 +1731,7 @@
/* interpret result as return value or error number */
if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
return -1;
- if (rval < 0 && rval > -nerrnos) {
+ if (check_errno && rval < 0 && rval > -nerrnos) {
tcp->u_rval = -1;
u_error = -rval;
}
@@ -1734,7 +1741,7 @@
}
# elif defined(MICROBLAZE)
/* interpret result as return value or error number */
- if (is_negated_errno(r3)) {
+ if (check_errno && is_negated_errno(r3)) {
tcp->u_rval = -1;
u_error = -r3;
}