Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/syscall/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@
#define SYS_getresuid 148
#define SYS_setresgid 149
#define SYS_getresgid 150
#define SYS_setfsuid 151
#define SYS_setfsgid 152
#define SYS_setpgid 154
#define SYS_getpgid 155
#define SYS_getsid 156
Expand Down Expand Up @@ -225,8 +227,8 @@
#define SYS_mlockall 230
#define SYS_munlockall 231
/* memory policy stubs */
#define SYS_set_mempolicy 238
#define SYS_get_mempolicy 239
#define SYS_get_mempolicy 236
#define SYS_set_mempolicy 237
/* System V IPC */
#define SYS_msgget 186
#define SYS_msgctl 187
Expand Down
2 changes: 2 additions & 0 deletions src/syscall/dispatch.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ SYS_setresuid sc_setresuid 1
SYS_getresuid sc_getresuid 0
SYS_setresgid sc_setresgid 1
SYS_getresgid sc_getresgid 0
SYS_setfsuid sc_setfsuid 0
SYS_setfsgid sc_setfsgid 0
SYS_setpgid sc_setpgid 0
SYS_getpgid sc_getpgid 1
SYS_getsid sc_getsid 1
Expand Down
9 changes: 9 additions & 0 deletions src/syscall/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,15 @@ SC_FORWARD(sc_setreuid, CRED_BRACKETED(g, proc_sys_setreuid((uint32_t) x0, (uin
SC_FORWARD(sc_setregid, CRED_BRACKETED(g, proc_sys_setregid((uint32_t) x0, (uint32_t) x1)))
SC_FORWARD(sc_setresuid, CRED_BRACKETED(g, proc_sys_setresuid((uint32_t) x0, (uint32_t) x1, (uint32_t) x2)))
SC_FORWARD(sc_setresgid, CRED_BRACKETED(g, proc_sys_setresgid((uint32_t) x0, (uint32_t) x1, (uint32_t) x2)))

/* setfs{uid,gid}: Linux returns the previous fs{uid,gid} and only mutates state
* on a permitted transition. elfuse does not track fsuid separately from euid,
* so report the current e{uid,gid} and ignore the change. procps brackets /proc
* walks with setfsuid(uid)/setfsuid(0); both calls observe a stable cred
* snapshot, which is what it needs.
*/
SC_FORWARD(sc_setfsuid, (int64_t) proc_get_euid())
SC_FORWARD(sc_setfsgid, (int64_t) proc_get_egid())
SC_FORWARD(sc_setpgid, proc_sys_setpgid(g, (int64_t) x0, (int64_t) x1))
SC_STUB(sc_fadvise64, 0)
SC_STUB(sc_sched_yield, (sched_yield(), 0))
Expand Down
35 changes: 35 additions & 0 deletions tests/test-credentials.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#define __NR_getresuid 148
#define __NR_getresgid 150
#define __NR_setreuid 145
#define __NR_setfsuid 151
#define __NR_setfsgid 152
#define __NR_capset 91
#define __NR_setpriority 140
#define __NR_getpriority 141
Expand Down Expand Up @@ -119,6 +121,39 @@ int main(void)
TEST("setgid(0) returns -EPERM");
EXPECT_TRUE(raw_syscall1(__NR_setgid, 0) == -1, "expected -EPERM");

/* setfsuid / setfsgid: Linux contract is to return the previous fsuid /
* fsgid. elfuse reports the current euid / egid (1000) on every call,
* with no state mutation, which is what procps relies on when it
* brackets /proc reads with setfsuid(uid) / setfsuid(0).
*/
TEST("setfsuid(0) returns 1000");
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, 0) == 1000,
"setfsuid(0) did not return current euid");

TEST("setfsuid(1000) returns 1000");
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, 1000) == 1000,
"setfsuid(1000) did not return current euid");

TEST("setfsgid(0) returns 1000");
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, 0) == 1000,
"setfsgid(0) did not return current egid");

TEST("setfsgid(1000) returns 1000");
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, 1000) == 1000,
"setfsgid(1000) did not return current egid");

/* setfsuid(-1) / setfsgid(-1) is the canonical glibc "read fsuid without
* changing it" idiom: -1 is never a valid uid, so the kernel only
* reports the current fsuid.
*/
TEST("setfsuid(-1) reports current fsuid");
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, (long) (unsigned) -1) == 1000,
"setfsuid(-1) did not report current euid");

TEST("setfsgid(-1) reports current fsgid");
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, (long) (unsigned) -1) == 1000,
"setfsgid(-1) did not report current egid");

/* capset: unprivileged process cannot set capabilities */
TEST("capset returns -EPERM");
{
Expand Down
4 changes: 2 additions & 2 deletions tests/test-tier-a.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ static void test_msgctl_rmid(void)
* Use raw syscall since glibc may not wrap them.
*/
#ifndef __NR_get_mempolicy
#define __NR_get_mempolicy 239
#define __NR_get_mempolicy 236
#endif
#ifndef __NR_set_mempolicy
#define __NR_set_mempolicy 238
#define __NR_set_mempolicy 237
#endif

static void test_get_mempolicy(void)
Expand Down
Loading