-
Notifications
You must be signed in to change notification settings - Fork 243
Expand file tree
/
Copy pathuid.c
More file actions
157 lines (132 loc) · 3.9 KB
/
Copy pathuid.c
File metadata and controls
157 lines (132 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include "debug.h"
#include "exit.h"
#include "params.h"
#include "shm.h"
#include "trinity.h"
#include "uid.h"
uid_t orig_uid;
gid_t orig_gid;
uid_t nobody_uid;
gid_t nobody_gid;
void dump_uids(void)
{
uid_t uid, euid, suid;
gid_t gid, egid, sgid;
if (getresuid(&uid, &euid, &suid) == -1) {
perror("getresuid");
return;
}
if (getresgid(&gid, &egid, &sgid) == -1) {
perror("getresgid");
return;
}
outputstd("initial uid:%u gid:%u euid:%u egid:%u suid:%u sgid:%u\n",
uid, gid, euid, egid, suid, sgid);
}
void drop_privs(void)
{
if (setresgid(nobody_gid, nobody_gid, nobody_gid) < 0) {
output(0, "Error setting nobody gid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (setgroups(0, NULL) == -1) {
output(0, "Error setting setgroups (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (setresuid(nobody_uid, nobody_uid, nobody_uid) < 0) {
output(0, "Error setting nobody uid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
void init_uids(void)
{
struct passwd *passwd;
orig_uid = getuid();
orig_gid = getgid();
if (orig_uid != 0)
return;
passwd = getpwnam("nobody");
if (passwd == NULL) {
outputerr("Error getting nobody pwent (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
nobody_uid = passwd->pw_uid;
nobody_gid = passwd->pw_gid;
}
void do_uid0_check(void)
{
unsigned int i;
/* Already unprivileged; no UID/GID drop is needed. */
if (orig_uid != 0)
return;
if (dangerous == true) {
outputstd("DANGER: RUNNING AS ROOT.\n");
outputstd("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
outputstd("or similar which could potentially make this machine unbootable without a firmware reset.\n");
} else {
output(0, "Detected running as root -- children will drop privileges to nobody (uid:%u gid:%u)\n",
nobody_uid, nobody_gid);
}
if (clowntown == true) {
output(0, "THIS CLOWN GOES TO 11.\n");
return;
}
outputstd("ctrl-c now unless you really know what you are doing.\n");
for (i = 10; i > 0; i--) {
outputstd("Continuing in %u seconds.\r", i);
(void)fflush(stdout);
sleep(1);
}
}
void check_uid(void)
{
uid_t myuid, expected_uid;
uid_t overflowuid = 65534;
FILE *fp;
/* init_uids() loaded nobody_uid when we started as root; child
* init then dropped to it. Otherwise we expect to still be the
* uid we were invoked under. */
expected_uid = (orig_uid == 0) ? nobody_uid : orig_uid;
myuid = getuid();
if (myuid == expected_uid)
return;
/* unshare() can change us to /proc/sys/kernel/overflowuid */
fp = fopen("/proc/sys/kernel/overflowuid", "r");
if (fp) {
if (fscanf(fp, "%u", &overflowuid) != 1)
overflowuid = 65534;
fclose(fp);
}
if (myuid == overflowuid)
return;
/* uid drifted to root: this is the ONLY case that's actually
* dangerous -- subsequent fuzz syscalls would run with root
* privileges and could damage the host. Hard bail. */
if (myuid == 0) {
output(0, "uid changed to ROOT! Was: %u, now %u -- bailing for safety\n",
expected_uid, myuid);
/* Release-store the offending uid before panic() writes
* exit_reason, so a reader who observes
* exit_reason==EXIT_UID_CHANGED is guaranteed to see
* uid_at_exit too. */
__atomic_store_n(&shm->uid_at_exit, myuid, __ATOMIC_RELEASE);
panic(EXIT_UID_CHANGED);
_exit(EXIT_UID_CHANGED);
}
/* Any other drift: log + bump counter + continue. Most often
* this is a fuzzed setresuid/setreuid/setfsuid succeeding
* inside an unshared user namespace -- interesting coverage,
* not a danger. Verbose-only because at high fuzz rates this
* can fire frequently. */
output(1, "uid changed (continuing): was %u, now %u (overflowuid=%u)\n",
expected_uid, myuid, overflowuid);
__atomic_fetch_add(&shm->stats.uid_change_logged, 1, __ATOMIC_RELAXED);
}