blob: 3ce0bad4c8e58b27675e7224564141596fcce65c [file] [log] [blame]
Koushik Dutta05258fd2013-02-16 19:20:58 -08001/*
2** Copyright 2010, Adam Shanks (@ChainsDD)
3** Copyright 2008, Zinx Verituse (@zinxv)
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <sys/types.h>
19#include <sys/socket.h>
Danny Baumanned55b0e2013-11-22 16:43:04 +010020#include <sys/uio.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080021#include <sys/un.h>
22#include <sys/wait.h>
23#include <sys/select.h>
24#include <sys/time.h>
25#include <unistd.h>
26#include <limits.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <getopt.h>
31#include <stdint.h>
32#include <pwd.h>
33#include <sys/stat.h>
34#include <stdarg.h>
35#include <sys/types.h>
Diogo Ferreira9d0f2342014-12-16 18:18:28 +000036#include <log/log.h>
Ricardo Cerqueirab2ffaf22015-01-04 03:07:14 +000037#include <private/android_filesystem_config.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080038
39#include "su.h"
40#include "utils.h"
Diogo Ferreira590ddd22014-12-16 10:27:31 +000041#include "binder/pm-wrapper.h"
Koushik Dutta05258fd2013-02-16 19:20:58 -080042
Koushik Duttac200cf72013-07-26 21:35:23 -070043extern int is_daemon;
44extern int daemon_from_uid;
45extern int daemon_from_pid;
46
Koushik Dutta5f2c6582013-07-30 15:38:48 -070047int fork_zero_fucks() {
48 int pid = fork();
49 if (pid) {
50 int status;
51 waitpid(pid, &status, 0);
52 return pid;
53 }
54 else {
Marcos Marado2b782d12014-12-11 20:41:24 +000055 if ((pid = fork()))
Koushik Dutta5f2c6582013-07-30 15:38:48 -070056 exit(0);
57 return 0;
58 }
59}
60
Koushik Dutta045c68a2013-02-17 17:03:56 -080061static int from_init(struct su_initiator *from) {
Koushik Dutta05258fd2013-02-16 19:20:58 -080062 char path[PATH_MAX], exe[PATH_MAX];
63 char args[4096], *argv0, *argv_rest;
64 int fd;
65 ssize_t len;
66 int i;
67 int err;
68
69 from->uid = getuid();
70 from->pid = getppid();
71
Marcos Maradof465a0a2014-02-01 22:58:19 +000072 if (is_daemon) {
73 from->uid = daemon_from_uid;
74 from->pid = daemon_from_pid;
75 }
76
Koushik Dutta05258fd2013-02-16 19:20:58 -080077 /* Get the command line */
78 snprintf(path, sizeof(path), "/proc/%u/cmdline", from->pid);
79 fd = open(path, O_RDONLY);
80 if (fd < 0) {
81 PLOGE("Opening command line");
82 return -1;
83 }
84 len = read(fd, args, sizeof(args));
85 err = errno;
86 close(fd);
87 if (len < 0 || len == sizeof(args)) {
88 PLOGEV("Reading command line", err);
89 return -1;
90 }
91
92 argv0 = args;
93 argv_rest = NULL;
94 for (i = 0; i < len; i++) {
95 if (args[i] == '\0') {
96 if (!argv_rest) {
97 argv_rest = &args[i+1];
98 } else {
99 args[i] = ' ';
100 }
101 }
102 }
103 args[len] = '\0';
104
105 if (argv_rest) {
Daniel Micayc9d292e2015-11-08 16:52:17 -0500106 if (strlcpy(from->args, argv_rest, sizeof(from->args)) >= sizeof(from->args)) {
107 ALOGE("argument too long");
108 return -1;
109 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800110 } else {
111 from->args[0] = '\0';
112 }
113
114 /* If this isn't app_process, use the real path instead of argv[0] */
115 snprintf(path, sizeof(path), "/proc/%u/exe", from->pid);
116 len = readlink(path, exe, sizeof(exe));
117 if (len < 0) {
118 PLOGE("Getting exe path");
119 return -1;
120 }
121 exe[len] = '\0';
122 if (strcmp(exe, "/system/bin/app_process")) {
123 argv0 = exe;
124 }
125
Daniel Micayc9d292e2015-11-08 16:52:17 -0500126 if (strlcpy(from->bin, argv0, sizeof(from->bin)) >= sizeof(from->bin)) {
127 ALOGE("binary path too long");
128 return -1;
129 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800130
Koushik Duttaa1943222013-02-22 00:24:54 -0800131 struct passwd *pw;
132 pw = getpwuid(from->uid);
133 if (pw && pw->pw_name) {
Daniel Micayc9d292e2015-11-08 16:52:17 -0500134 if (strlcpy(from->name, pw->pw_name, sizeof(from->name)) >= sizeof(from->name)) {
135 ALOGE("name too long");
136 return -1;
137 }
Koushik Duttaa1943222013-02-22 00:24:54 -0800138 }
139
Koushik Dutta05258fd2013-02-16 19:20:58 -0800140 return 0;
141}
142
Koushik Dutta045c68a2013-02-17 17:03:56 -0800143static void populate_environment(const struct su_context *ctx) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800144 struct passwd *pw;
145
146 if (ctx->to.keepenv)
147 return;
148
149 pw = getpwuid(ctx->to.uid);
150 if (pw) {
151 setenv("HOME", pw->pw_dir, 1);
Koushik Dutta379371b2013-03-11 17:30:53 -0700152 if (ctx->to.shell)
153 setenv("SHELL", ctx->to.shell, 1);
154 else
155 setenv("SHELL", DEFAULT_SHELL, 1);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800156 if (ctx->to.login || ctx->to.uid) {
157 setenv("USER", pw->pw_name, 1);
158 setenv("LOGNAME", pw->pw_name, 1);
159 }
160 }
161}
162
Koushik Dutta045c68a2013-02-17 17:03:56 -0800163void set_identity(unsigned int uid) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800164 /*
165 * Set effective uid back to root, otherwise setres[ug]id will fail
166 * if uid isn't root.
167 */
168 if (seteuid(0)) {
169 PLOGE("seteuid (root)");
170 exit(EXIT_FAILURE);
171 }
172 if (setresgid(uid, uid, uid)) {
173 PLOGE("setresgid (%u)", uid);
174 exit(EXIT_FAILURE);
175 }
176 if (setresuid(uid, uid, uid)) {
177 PLOGE("setresuid (%u)", uid);
178 exit(EXIT_FAILURE);
179 }
180}
181
Koushik Dutta045c68a2013-02-17 17:03:56 -0800182static void usage(int status) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800183 FILE *stream = (status == EXIT_SUCCESS) ? stdout : stderr;
184
185 fprintf(stream,
186 "Usage: su [options] [--] [-] [LOGIN] [--] [args...]\n\n"
187 "Options:\n"
Koushik Duttac7adb382013-07-29 20:59:41 -0700188 " --daemon start the su daemon agent\n"
Koushik Dutta05258fd2013-02-16 19:20:58 -0800189 " -c, --command COMMAND pass COMMAND to the invoked shell\n"
190 " -h, --help display this help message and exit\n"
191 " -, -l, --login pretend the shell to be a login shell\n"
192 " -m, -p,\n"
193 " --preserve-environment do not change environment variables\n"
194 " -s, --shell SHELL use SHELL instead of the default " DEFAULT_SHELL "\n"
195 " -v, --version display version number and exit\n"
196 " -V display version code and exit,\n"
197 " this is used almost exclusively by Superuser.apk\n");
198 exit(status);
199}
200
Koushik Dutta045c68a2013-02-17 17:03:56 -0800201static __attribute__ ((noreturn)) void deny(struct su_context *ctx) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800202 char *cmd = get_command(&ctx->to);
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000203 ALOGW("request rejected (%u->%u %s)", ctx->from.uid, ctx->to.uid, cmd);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800204 fprintf(stderr, "%s\n", strerror(EACCES));
205 exit(EXIT_FAILURE);
206}
207
Diogo Ferreira9d646652014-12-17 12:24:46 +0000208static __attribute__ ((noreturn)) void allow(struct su_context *ctx, const char *packageName) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800209 char *arg0;
210 int argc, err;
211
212 umask(ctx->umask);
Koushik Dutta379371b2013-03-11 17:30:53 -0700213
214 char *binary;
215 argc = ctx->to.optind;
216 if (ctx->to.command) {
217 binary = ctx->to.shell;
218 ctx->to.argv[--argc] = ctx->to.command;
219 ctx->to.argv[--argc] = "-c";
220 }
221 else if (ctx->to.shell) {
222 binary = ctx->to.shell;
223 }
224 else {
225 if (ctx->to.argv[argc]) {
226 binary = ctx->to.argv[argc++];
227 }
228 else {
229 binary = DEFAULT_SHELL;
230 }
231 }
232
233 arg0 = strrchr (binary, '/');
234 arg0 = (arg0) ? arg0 + 1 : binary;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800235 if (ctx->to.login) {
236 int s = strlen(arg0) + 2;
237 char *p = malloc(s);
238
239 if (!p)
240 exit(EXIT_FAILURE);
241
242 *p = '-';
243 strcpy(p + 1, arg0);
244 arg0 = p;
245 }
246
247 populate_environment(ctx);
248 set_identity(ctx->to.uid);
249
250#define PARG(arg) \
Koushik Dutta379371b2013-03-11 17:30:53 -0700251 (argc + (arg) < ctx->to.argc) ? " " : "", \
252 (argc + (arg) < ctx->to.argc) ? ctx->to.argv[argc + (arg)] : ""
Koushik Dutta05258fd2013-02-16 19:20:58 -0800253
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000254 ALOGD("%u %s executing %u %s using binary %s : %s%s%s%s%s%s%s%s%s%s%s%s%s%s",
Koushik Dutta05258fd2013-02-16 19:20:58 -0800255 ctx->from.uid, ctx->from.bin,
Koushik Dutta379371b2013-03-11 17:30:53 -0700256 ctx->to.uid, get_command(&ctx->to), binary,
Koushik Dutta05258fd2013-02-16 19:20:58 -0800257 arg0, PARG(0), PARG(1), PARG(2), PARG(3), PARG(4), PARG(5),
258 (ctx->to.optind + 6 < ctx->to.argc) ? " ..." : "");
259
Koushik Dutta05258fd2013-02-16 19:20:58 -0800260 ctx->to.argv[--argc] = arg0;
Diogo Ferreira9d646652014-12-17 12:24:46 +0000261
262 int pid = fork();
263 if (!pid) {
264 execvp(binary, ctx->to.argv + argc);
265 err = errno;
266 PLOGE("exec");
267 fprintf(stderr, "Cannot execute %s: %s\n", binary, strerror(err));
268 exit(EXIT_FAILURE);
269 } else {
270 int status;
271
272 ALOGD("Waiting for pid %d.", pid);
273 waitpid(pid, &status, 0);
274 if (packageName) {
275 appops_finish_op_su(ctx->from.uid, packageName);
276 }
277 exit(status);
278 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800279}
280
281/*
282 * CyanogenMod-specific behavior
283 *
284 * we can't simply use the property service, since we aren't launched from init
285 * and can't trust the location of the property workspace.
286 * Find the properties ourselves.
287 */
Koushik Dutta045c68a2013-02-17 17:03:56 -0800288int access_disabled(const struct su_initiator *from) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800289 char *data;
290 char build_type[PROPERTY_VALUE_MAX];
291 char debuggable[PROPERTY_VALUE_MAX], enabled[PROPERTY_VALUE_MAX];
292 size_t len;
293
294 data = read_file("/system/build.prop");
295 if (check_property(data, "ro.cm.version")) {
296 get_property(data, build_type, "ro.build.type", "");
297 free(data);
298
299 data = read_file("/default.prop");
300 get_property(data, debuggable, "ro.debuggable", "0");
301 free(data);
302 /* only allow su on debuggable builds */
303 if (strcmp("1", debuggable) != 0) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000304 ALOGE("Root access is disabled on non-debug builds");
Koushik Dutta05258fd2013-02-16 19:20:58 -0800305 return 1;
306 }
307
308 data = read_file("/data/property/persist.sys.root_access");
309 if (data != NULL) {
310 len = strlen(data);
311 if (len >= PROPERTY_VALUE_MAX)
Shareef Alia1229fc2015-01-04 18:58:43 -0600312 memcpy(enabled, "0", 2);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800313 else
314 memcpy(enabled, data, len + 1);
315 free(data);
316 } else
Shareef Alia1229fc2015-01-04 18:58:43 -0600317 memcpy(enabled, "0", 2);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800318
319 /* enforce persist.sys.root_access on non-eng builds for apps */
320 if (strcmp("eng", build_type) != 0 &&
321 from->uid != AID_SHELL && from->uid != AID_ROOT &&
322 (atoi(enabled) & CM_ROOT_ACCESS_APPS_ONLY) != CM_ROOT_ACCESS_APPS_ONLY ) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000323 ALOGE("Apps root access is disabled by system setting - "
Koushik Dutta05258fd2013-02-16 19:20:58 -0800324 "enable it under settings -> developer options");
325 return 1;
326 }
327
328 /* disallow su in a shell if appropriate */
329 if (from->uid == AID_SHELL &&
330 (atoi(enabled) & CM_ROOT_ACCESS_ADB_ONLY) != CM_ROOT_ACCESS_ADB_ONLY ) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000331 ALOGE("Shell root access is disabled by a system setting - "
Koushik Dutta05258fd2013-02-16 19:20:58 -0800332 "enable it under settings -> developer options");
333 return 1;
334 }
Koushik Duttac200cf72013-07-26 21:35:23 -0700335
Koushik Dutta05258fd2013-02-16 19:20:58 -0800336 }
337 return 0;
338}
339
Kevin Cernekeeb27031e2013-11-23 15:02:58 -0800340static void fork_for_samsung(void)
341{
342 // Samsung CONFIG_SEC_RESTRICT_SETUID wants the parent process to have
343 // EUID 0, or else our setresuid() calls will be denied. So make sure
344 // all such syscalls are executed by a child process.
345 int rv;
346
347 switch (fork()) {
348 case 0:
349 return;
350 case -1:
351 PLOGE("fork");
352 exit(1);
353 default:
354 if (wait(&rv) < 0) {
355 exit(1);
356 } else {
357 exit(WEXITSTATUS(rv));
358 }
359 }
360}
361
Koushik Dutta045c68a2013-02-17 17:03:56 -0800362int main(int argc, char *argv[]) {
Daniel Micay4fb98c12015-11-08 19:06:51 -0500363 if (getuid() != geteuid()) {
364 ALOGE("must not be a setuid binary");
365 return 1;
366 }
367
Koushik Dutta8829fc32013-11-21 09:19:47 -0800368 return su_main(argc, argv, 1);
369}
370
371int su_main(int argc, char *argv[], int need_client) {
Koushik Duttac200cf72013-07-26 21:35:23 -0700372 // start up in daemon mode if prompted
373 if (argc == 2 && strcmp(argv[1], "--daemon") == 0) {
374 return run_daemon();
375 }
376
Marcos Maradof465a0a2014-02-01 22:58:19 +0000377 int ppid = getppid();
Kevin Cernekeeb27031e2013-11-23 15:02:58 -0800378 fork_for_samsung();
379
Koushik Dutta8066f2c2013-02-16 19:59:10 -0800380 // Sanitize all secure environment variables (from linker_environ.c in AOSP linker).
381 /* The same list than GLibc at this point */
382 static const char* const unsec_vars[] = {
383 "GCONV_PATH",
384 "GETCONF_DIR",
385 "HOSTALIASES",
386 "LD_AUDIT",
387 "LD_DEBUG",
388 "LD_DEBUG_OUTPUT",
389 "LD_DYNAMIC_WEAK",
390 "LD_LIBRARY_PATH",
391 "LD_ORIGIN_PATH",
392 "LD_PRELOAD",
393 "LD_PROFILE",
394 "LD_SHOW_AUXV",
395 "LD_USE_LOAD_BIAS",
396 "LOCALDOMAIN",
397 "LOCPATH",
398 "MALLOC_TRACE",
399 "MALLOC_CHECK_",
400 "NIS_PATH",
401 "NLSPATH",
402 "RESOLV_HOST_CONF",
403 "RES_OPTIONS",
404 "TMPDIR",
405 "TZDIR",
406 "LD_AOUT_LIBRARY_PATH",
407 "LD_AOUT_PRELOAD",
408 // not listed in linker, used due to system() call
409 "IFS",
410 };
411 const char* const* cp = unsec_vars;
412 const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]);
413 while (cp < endp) {
414 unsetenv(*cp);
415 cp++;
416 }
417
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000418 ALOGD("su invoked.");
Koushik Dutta05258fd2013-02-16 19:20:58 -0800419
420 struct su_context ctx = {
421 .from = {
422 .pid = -1,
423 .uid = 0,
424 .bin = "",
425 .args = "",
Koushik Duttaa1943222013-02-22 00:24:54 -0800426 .name = "",
Koushik Dutta05258fd2013-02-16 19:20:58 -0800427 },
428 .to = {
429 .uid = AID_ROOT,
430 .login = 0,
431 .keepenv = 0,
Koushik Dutta379371b2013-03-11 17:30:53 -0700432 .shell = NULL,
Koushik Dutta05258fd2013-02-16 19:20:58 -0800433 .command = NULL,
434 .argv = argv,
435 .argc = argc,
436 .optind = 0,
Koushik Duttaa1943222013-02-22 00:24:54 -0800437 .name = "",
Koushik Dutta05258fd2013-02-16 19:20:58 -0800438 },
Koushik Dutta05258fd2013-02-16 19:20:58 -0800439 };
Luca Stefani2b2cde22017-01-22 23:09:15 +0100440 int c;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800441 struct option long_opts[] = {
442 { "command", required_argument, NULL, 'c' },
443 { "help", no_argument, NULL, 'h' },
444 { "login", no_argument, NULL, 'l' },
445 { "preserve-environment", no_argument, NULL, 'p' },
446 { "shell", required_argument, NULL, 's' },
447 { "version", no_argument, NULL, 'v' },
448 { NULL, 0, NULL, 0 },
449 };
450
Diogo Ferreira9d0f2342014-12-16 18:18:28 +0000451 while ((c = getopt_long(argc, argv, "+c:hlmps:Vv", long_opts, NULL)) != -1) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800452 switch(c) {
453 case 'c':
Koushik Dutta379371b2013-03-11 17:30:53 -0700454 ctx.to.shell = DEFAULT_SHELL;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800455 ctx.to.command = optarg;
456 break;
457 case 'h':
458 usage(EXIT_SUCCESS);
459 break;
460 case 'l':
461 ctx.to.login = 1;
462 break;
463 case 'm':
464 case 'p':
465 ctx.to.keepenv = 1;
466 break;
467 case 's':
468 ctx.to.shell = optarg;
469 break;
470 case 'V':
471 printf("%d\n", VERSION_CODE);
472 exit(EXIT_SUCCESS);
473 case 'v':
474 printf("%s\n", VERSION);
475 exit(EXIT_SUCCESS);
476 default:
477 /* Bionic getopt_long doesn't terminate its error output by newline */
478 fprintf(stderr, "\n");
479 usage(2);
480 }
481 }
Koushik Dutta8829fc32013-11-21 09:19:47 -0800482
483 if (need_client) {
Daniel Micayf40b0682015-11-14 18:28:34 -0500484 // attempt to connect to daemon...
485 ALOGD("starting daemon client %d %d", getuid(), geteuid());
486 return connect_daemon(argc, argv, ppid);
Koushik Dutta8829fc32013-11-21 09:19:47 -0800487 }
488
Koushik Dutta05258fd2013-02-16 19:20:58 -0800489 if (optind < argc && !strcmp(argv[optind], "-")) {
490 ctx.to.login = 1;
491 optind++;
492 }
493 /* username or uid */
494 if (optind < argc && strcmp(argv[optind], "--")) {
495 struct passwd *pw;
496 pw = getpwnam(argv[optind]);
497 if (!pw) {
498 char *endptr;
499
500 /* It seems we shouldn't do this at all */
501 errno = 0;
502 ctx.to.uid = strtoul(argv[optind], &endptr, 10);
503 if (errno || *endptr) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000504 ALOGE("Unknown id: %s\n", argv[optind]);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800505 fprintf(stderr, "Unknown id: %s\n", argv[optind]);
506 exit(EXIT_FAILURE);
507 }
508 } else {
509 ctx.to.uid = pw->pw_uid;
Daniel Micayc9d292e2015-11-08 16:52:17 -0500510 if (pw->pw_name) {
511 if (strlcpy(ctx.to.name, pw->pw_name, sizeof(ctx.to.name)) >= sizeof(ctx.to.name)) {
512 ALOGE("name too long");
513 exit(EXIT_FAILURE);
514 }
515 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800516 }
517 optind++;
518 }
519 if (optind < argc && !strcmp(argv[optind], "--")) {
520 optind++;
521 }
522 ctx.to.optind = optind;
523
Koushik Dutta05258fd2013-02-16 19:20:58 -0800524 if (from_init(&ctx.from) < 0) {
525 deny(&ctx);
526 }
Koushik Duttac200cf72013-07-26 21:35:23 -0700527
Diogo Ferreira590ddd22014-12-16 10:27:31 +0000528 ALOGE("SU from: %s", ctx.from.name);
529
Koushik Dutta62843e12013-03-11 14:39:55 -0700530 // the latter two are necessary for stock ROMs like note 2 which do dumb things with su, or crash otherwise
Koushik Dutta379371b2013-03-11 17:30:53 -0700531 if (ctx.from.uid == AID_ROOT) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000532 ALOGD("Allowing root/system/radio.");
Diogo Ferreira9d646652014-12-17 12:24:46 +0000533 allow(&ctx, NULL);
Koushik Dutta75c720a2013-03-04 16:16:41 -0800534 }
535
Koushik Dutta33b3f162013-03-03 22:41:48 -0800536 // check if superuser is disabled completely
537 if (access_disabled(&ctx.from)) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000538 ALOGD("access_disabled");
Koushik Dutta33b3f162013-03-03 22:41:48 -0800539 deny(&ctx);
540 }
541
Koushik Dutta62843e12013-03-11 14:39:55 -0700542 // autogrant shell at this point
543 if (ctx.from.uid == AID_SHELL) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000544 ALOGD("Allowing shell.");
Diogo Ferreira9d646652014-12-17 12:24:46 +0000545 allow(&ctx, NULL);
Koushik Dutta62843e12013-03-11 14:39:55 -0700546 }
547
Diogo Ferreira9d646652014-12-17 12:24:46 +0000548 const char *packageName = resolve_package_name(ctx.from.uid);
549 if (!appops_start_op_su(ctx.from.uid, packageName)) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000550 ALOGD("Allowing via appops.");
Diogo Ferreira9d646652014-12-17 12:24:46 +0000551 allow(&ctx, packageName);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800552 }
Diogo Ferreira910c8412014-12-16 17:38:44 +0000553
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000554 ALOGE("Allow chain exhausted, denying request");
Diogo Ferreira910c8412014-12-16 17:38:44 +0000555 deny(&ctx);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800556}