Skip to content

Commit c69663d

Browse files
authored
Merge pull request #92 from sysprog21/setfsuid
Correct mempolicy syscalls and add setfs{uid,gid}
2 parents 596a1d2 + faefa45 commit c69663d

5 files changed

Lines changed: 52 additions & 4 deletions

File tree

src/syscall/abi.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@
117117
#define SYS_getresuid 148
118118
#define SYS_setresgid 149
119119
#define SYS_getresgid 150
120+
#define SYS_setfsuid 151
121+
#define SYS_setfsgid 152
120122
#define SYS_setpgid 154
121123
#define SYS_getpgid 155
122124
#define SYS_getsid 156
@@ -225,8 +227,8 @@
225227
#define SYS_mlockall 230
226228
#define SYS_munlockall 231
227229
/* memory policy stubs */
228-
#define SYS_set_mempolicy 238
229-
#define SYS_get_mempolicy 239
230+
#define SYS_get_mempolicy 236
231+
#define SYS_set_mempolicy 237
230232
/* System V IPC */
231233
#define SYS_msgget 186
232234
#define SYS_msgctl 187

src/syscall/dispatch.tbl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ SYS_setresuid sc_setresuid 1
157157
SYS_getresuid sc_getresuid 0
158158
SYS_setresgid sc_setresgid 1
159159
SYS_getresgid sc_getresgid 0
160+
SYS_setfsuid sc_setfsuid 0
161+
SYS_setfsgid sc_setfsgid 0
160162
SYS_setpgid sc_setpgid 0
161163
SYS_getpgid sc_getpgid 1
162164
SYS_getsid sc_getsid 1

src/syscall/syscall.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,15 @@ SC_FORWARD(sc_setreuid, CRED_BRACKETED(g, proc_sys_setreuid((uint32_t) x0, (uin
542542
SC_FORWARD(sc_setregid, CRED_BRACKETED(g, proc_sys_setregid((uint32_t) x0, (uint32_t) x1)))
543543
SC_FORWARD(sc_setresuid, CRED_BRACKETED(g, proc_sys_setresuid((uint32_t) x0, (uint32_t) x1, (uint32_t) x2)))
544544
SC_FORWARD(sc_setresgid, CRED_BRACKETED(g, proc_sys_setresgid((uint32_t) x0, (uint32_t) x1, (uint32_t) x2)))
545+
546+
/* setfs{uid,gid}: Linux returns the previous fs{uid,gid} and only mutates state
547+
* on a permitted transition. elfuse does not track fsuid separately from euid,
548+
* so report the current e{uid,gid} and ignore the change. procps brackets /proc
549+
* walks with setfsuid(uid)/setfsuid(0); both calls observe a stable cred
550+
* snapshot, which is what it needs.
551+
*/
552+
SC_FORWARD(sc_setfsuid, (int64_t) proc_get_euid())
553+
SC_FORWARD(sc_setfsgid, (int64_t) proc_get_egid())
545554
SC_FORWARD(sc_setpgid, proc_sys_setpgid(g, (int64_t) x0, (int64_t) x1))
546555
SC_STUB(sc_fadvise64, 0)
547556
SC_STUB(sc_sched_yield, (sched_yield(), 0))

tests/test-credentials.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define __NR_getresuid 148
1919
#define __NR_getresgid 150
2020
#define __NR_setreuid 145
21+
#define __NR_setfsuid 151
22+
#define __NR_setfsgid 152
2123
#define __NR_capset 91
2224
#define __NR_setpriority 140
2325
#define __NR_getpriority 141
@@ -119,6 +121,39 @@ int main(void)
119121
TEST("setgid(0) returns -EPERM");
120122
EXPECT_TRUE(raw_syscall1(__NR_setgid, 0) == -1, "expected -EPERM");
121123

124+
/* setfsuid / setfsgid: Linux contract is to return the previous fsuid /
125+
* fsgid. elfuse reports the current euid / egid (1000) on every call,
126+
* with no state mutation, which is what procps relies on when it
127+
* brackets /proc reads with setfsuid(uid) / setfsuid(0).
128+
*/
129+
TEST("setfsuid(0) returns 1000");
130+
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, 0) == 1000,
131+
"setfsuid(0) did not return current euid");
132+
133+
TEST("setfsuid(1000) returns 1000");
134+
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, 1000) == 1000,
135+
"setfsuid(1000) did not return current euid");
136+
137+
TEST("setfsgid(0) returns 1000");
138+
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, 0) == 1000,
139+
"setfsgid(0) did not return current egid");
140+
141+
TEST("setfsgid(1000) returns 1000");
142+
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, 1000) == 1000,
143+
"setfsgid(1000) did not return current egid");
144+
145+
/* setfsuid(-1) / setfsgid(-1) is the canonical glibc "read fsuid without
146+
* changing it" idiom: -1 is never a valid uid, so the kernel only
147+
* reports the current fsuid.
148+
*/
149+
TEST("setfsuid(-1) reports current fsuid");
150+
EXPECT_TRUE(raw_syscall1(__NR_setfsuid, (long) (unsigned) -1) == 1000,
151+
"setfsuid(-1) did not report current euid");
152+
153+
TEST("setfsgid(-1) reports current fsgid");
154+
EXPECT_TRUE(raw_syscall1(__NR_setfsgid, (long) (unsigned) -1) == 1000,
155+
"setfsgid(-1) did not report current egid");
156+
122157
/* capset: unprivileged process cannot set capabilities */
123158
TEST("capset returns -EPERM");
124159
{

tests/test-tier-a.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ static void test_msgctl_rmid(void)
168168
* Use raw syscall since glibc may not wrap them.
169169
*/
170170
#ifndef __NR_get_mempolicy
171-
#define __NR_get_mempolicy 239
171+
#define __NR_get_mempolicy 236
172172
#endif
173173
#ifndef __NR_set_mempolicy
174-
#define __NR_set_mempolicy 238
174+
#define __NR_set_mempolicy 237
175175
#endif
176176

177177
static void test_get_mempolicy(void)

0 commit comments

Comments
 (0)