-
Notifications
You must be signed in to change notification settings - Fork 241
/
uid.c
142 lines (114 loc) · 3.14 KB
/
uid.c
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
#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 "child.h"
#include "debug.h"
#include "exit.h"
#include "params.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;
getresuid(&uid, &euid, &suid);
getresgid(&gid, &egid, &sgid);
outputstd("initial uid:%u gid:%u euid:%u egid:%u suid:%u sgid:%u\n",
uid, gid, euid, egid, suid, sgid);
}
bool drop_privs(struct childdata *child)
{
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) {
;
}
if (setresuid(nobody_uid, nobody_uid, nobody_uid) < 0) {
output(0, "Error setting nobody uid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
// debugf("set uid to %u and gid to %d (nobody)\n", nobody_uid, nobody_gid);
child->dropped_privs = TRUE;
return TRUE;
}
void init_uids(void)
{
struct passwd *passwd;
orig_uid = getuid();
orig_gid = getgid();
if (dropprivs == FALSE)
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;
/* if we're already unprivileged, then don't worry. */
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");
outputstd("You might want to check out running with --dropprivs (currently experimental).\n\n");
} else {
if (dropprivs == FALSE) {
outputstd("Don't run as root (or pass --dangerous, or --dropprivs if you know what you are doing).\n");
exit(EXIT_FAILURE);
} else {
outputstd("--dropprivs is still in development, and really shouldn't be used unless you're helping development. Expect crashes.\n");
outputstd("Going to run as user nobody (uid:%d gid:%d)\n", nobody_uid, nobody_gid);
}
}
if (clowntown == TRUE) {
printf("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;
/* If we were root, then obviously setuid() will change us, so don't even check. */
if (orig_uid == 0)
return;
myuid = getuid();
/* we should be 'nobody' if we ran with --dropprivs */
if (dropprivs == TRUE) {
if (myuid == nobody_uid)
return;
else
goto changed;
}
if (myuid != orig_uid) {
changed:
/* unshare() can change us to /proc/sys/kernel/overflowuid */
if (myuid == 65534)
return;
output(0, "uid changed! Was: %u, now %u\n", orig_uid, myuid);
panic(EXIT_UID_CHANGED);
_exit(EXIT_FAILURE);
}
}