Skip to content

Commit 7d97cfe

Browse files
Gleb O. Raikogit-core
authored andcommitted
Fix potential security flaw in creation of sockets/directories
Previous code created a file object with two steps: the creation itself with default umask/mode and setting necessary permissions then. This approach is known to lead to a race condition when malicious process can open an object before permissions is set. The patch sets creation mask (mask) to 027, thus denying any access from others. Also, the patch removes all dead code which is not needed after changes mentioned.
1 parent 4c6ea93 commit 7d97cfe

File tree

1 file changed

+12
-20
lines changed

1 file changed

+12
-20
lines changed

su.c

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ static void cleanup_signal(int sig)
146146
exit(sig);
147147
}
148148

149-
static int socket_create_temp(unsigned req_uid)
149+
static int socket_create_temp(void)
150150
{
151151
static char buf[PATH_MAX];
152-
int fd, err;
152+
int fd;
153153

154154
struct sockaddr_un sun;
155155

@@ -176,18 +176,6 @@ static int socket_create_temp(unsigned req_uid)
176176
}
177177
}
178178

179-
if (chmod(sun.sun_path, 0600) < 0) {
180-
PLOGE("chmod(socket)");
181-
unlink(sun.sun_path);
182-
return -1;
183-
}
184-
185-
if (chown(sun.sun_path, req_uid, req_uid) < 0) {
186-
PLOGE("chown(socket)");
187-
unlink(sun.sun_path);
188-
return -1;
189-
}
190-
191179
if (listen(fd, 1) < 0) {
192180
PLOGE("listen");
193181
return -1;
@@ -276,12 +264,13 @@ static void deny(void)
276264
exit(EXIT_FAILURE);
277265
}
278266

279-
static void allow(char *shell)
267+
static void allow(char *shell, mode_t mask)
280268
{
281269
struct su_initiator *from = &su_from;
282270
struct su_request *to = &su_to;
283271
char *exe = NULL;
284272

273+
umask(mask);
285274
send_intent(&su_from, &su_to, "", 1, 1);
286275

287276
if (!strcmp(shell, "")) {
@@ -308,6 +297,7 @@ int main(int argc, char *argv[])
308297
char buf[64], shell[PATH_MAX], *result;
309298
int i, dballow;
310299
unsigned req_uid;
300+
mode_t orig_umask;
311301

312302
for (i = 1; i < argc; i++) {
313303
if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) {
@@ -356,8 +346,10 @@ int main(int argc, char *argv[])
356346
deny();
357347
}
358348

349+
orig_umask = umask(027);
350+
359351
if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL)
360-
allow(shell);
352+
allow(shell, orig_umask);
361353

362354
if (stat(REQUESTOR_DATA_PATH, &st) < 0) {
363355
PLOGE("stat");
@@ -373,7 +365,7 @@ int main(int argc, char *argv[])
373365

374366
req_uid = st.st_uid;
375367

376-
if (mkdir(REQUESTOR_CACHE_PATH, 0771) >= 0) {
368+
if (mkdir(REQUESTOR_CACHE_PATH, 0770) >= 0) {
377369
chown(REQUESTOR_CACHE_PATH, req_uid, req_uid);
378370
}
379371

@@ -400,12 +392,12 @@ int main(int argc, char *argv[])
400392

401393
switch (dballow) {
402394
case DB_DENY: deny();
403-
case DB_ALLOW: allow(shell);
395+
case DB_ALLOW: allow(shell, orig_umask);
404396
case DB_INTERACTIVE: break;
405397
default: deny();
406398
}
407399

408-
socket_serv_fd = socket_create_temp(req_uid);
400+
socket_serv_fd = socket_create_temp();
409401
if (socket_serv_fd < 0) {
410402
deny();
411403
}
@@ -432,7 +424,7 @@ int main(int argc, char *argv[])
432424
if (!strcmp(result, "DENY")) {
433425
deny();
434426
} else if (!strcmp(result, "ALLOW")) {
435-
allow(shell);
427+
allow(shell, orig_umask);
436428
} else {
437429
LOGE("unknown response from Superuser Requestor: %s", result);
438430
deny();

0 commit comments

Comments
 (0)