blob: 8e3726ae9a23fb109d153d248020e9401a69e5b5 [file] [log] [blame]
Koushik Dutta05258fd2013-02-16 19:20:58 -08001/*
2** Copyright 2010, Adam Shanks (@ChainsDD)
3** Copyright 2008, Zinx Verituse (@zinxv)
Bruno Martinsbffcdef2018-08-27 18:24:41 +01004** Copyright 2017-2018, The LineageOS Project
Koushik Dutta05258fd2013-02-16 19:20:58 -08005**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
Koushik Dutta05258fd2013-02-16 19:20:58 -080019#include <getopt.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080020#include <pwd.h>
Luca Stefanidd47f312018-08-26 12:59:23 +020021#include <stdlib.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080022#include <sys/stat.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080023#include <sys/types.h>
Luca Stefanidd47f312018-08-26 12:59:23 +020024#include <sys/wait.h>
25#include <unistd.h>
26
Luca Stefani7c86b052018-08-26 11:50:32 +020027#include <cutils/android_filesystem_config.h>
28#include <cutils/properties.h>
Diogo Ferreira9d0f2342014-12-16 18:18:28 +000029#include <log/log.h>
Koushik Dutta05258fd2013-02-16 19:20:58 -080030
Luca Stefanidd47f312018-08-26 12:59:23 +020031#include "binder/pm-wrapper.h"
Koushik Dutta05258fd2013-02-16 19:20:58 -080032#include "su.h"
33#include "utils.h"
34
Koushik Duttac200cf72013-07-26 21:35:23 -070035extern int is_daemon;
36extern int daemon_from_uid;
37extern int daemon_from_pid;
38
Koushik Dutta5f2c6582013-07-30 15:38:48 -070039int fork_zero_fucks() {
40 int pid = fork();
41 if (pid) {
42 int status;
43 waitpid(pid, &status, 0);
44 return pid;
Luca Stefani5eb52ea2018-08-26 11:35:00 +020045 } else {
46 if ((pid = fork())) exit(0);
Koushik Dutta5f2c6582013-07-30 15:38:48 -070047 return 0;
48 }
49}
50
Luca Stefani5eb52ea2018-08-26 11:35:00 +020051static int from_init(struct su_initiator* from) {
Koushik Dutta05258fd2013-02-16 19:20:58 -080052 char path[PATH_MAX], exe[PATH_MAX];
53 char args[4096], *argv0, *argv_rest;
54 int fd;
55 ssize_t len;
56 int i;
57 int err;
58
59 from->uid = getuid();
60 from->pid = getppid();
61
Marcos Maradof465a0a2014-02-01 22:58:19 +000062 if (is_daemon) {
63 from->uid = daemon_from_uid;
64 from->pid = daemon_from_pid;
65 }
66
Koushik Dutta05258fd2013-02-16 19:20:58 -080067 /* Get the command line */
Tom Marshallbeddaf72018-08-24 19:38:42 +020068 snprintf(path, sizeof(path), "/proc/%d/cmdline", from->pid);
Koushik Dutta05258fd2013-02-16 19:20:58 -080069 fd = open(path, O_RDONLY);
70 if (fd < 0) {
71 PLOGE("Opening command line");
72 return -1;
73 }
74 len = read(fd, args, sizeof(args));
75 err = errno;
76 close(fd);
77 if (len < 0 || len == sizeof(args)) {
78 PLOGEV("Reading command line", err);
79 return -1;
80 }
81
82 argv0 = args;
83 argv_rest = NULL;
84 for (i = 0; i < len; i++) {
85 if (args[i] == '\0') {
86 if (!argv_rest) {
Luca Stefani5eb52ea2018-08-26 11:35:00 +020087 argv_rest = &args[i + 1];
Koushik Dutta05258fd2013-02-16 19:20:58 -080088 } else {
89 args[i] = ' ';
90 }
91 }
92 }
93 args[len] = '\0';
94
95 if (argv_rest) {
Daniel Micayc9d292e2015-11-08 16:52:17 -050096 if (strlcpy(from->args, argv_rest, sizeof(from->args)) >= sizeof(from->args)) {
97 ALOGE("argument too long");
98 return -1;
99 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800100 } else {
101 from->args[0] = '\0';
102 }
103
104 /* If this isn't app_process, use the real path instead of argv[0] */
Tom Marshallbeddaf72018-08-24 19:38:42 +0200105 snprintf(path, sizeof(path), "/proc/%d/exe", from->pid);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800106 len = readlink(path, exe, sizeof(exe));
107 if (len < 0) {
108 PLOGE("Getting exe path");
109 return -1;
110 }
111 exe[len] = '\0';
Tom Marshallbeddaf72018-08-24 19:38:42 +0200112 if (strcmp(exe, "/system/bin/app_process") != 0) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800113 argv0 = exe;
114 }
115
Daniel Micayc9d292e2015-11-08 16:52:17 -0500116 if (strlcpy(from->bin, argv0, sizeof(from->bin)) >= sizeof(from->bin)) {
117 ALOGE("binary path too long");
118 return -1;
119 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800120
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200121 struct passwd* pw;
Koushik Duttaa1943222013-02-22 00:24:54 -0800122 pw = getpwuid(from->uid);
123 if (pw && pw->pw_name) {
Daniel Micayc9d292e2015-11-08 16:52:17 -0500124 if (strlcpy(from->name, pw->pw_name, sizeof(from->name)) >= sizeof(from->name)) {
125 ALOGE("name too long");
126 return -1;
127 }
Koushik Duttaa1943222013-02-22 00:24:54 -0800128 }
129
Koushik Dutta05258fd2013-02-16 19:20:58 -0800130 return 0;
131}
132
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200133static void populate_environment(const struct su_context* ctx) {
134 struct passwd* pw;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800135
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200136 if (ctx->to.keepenv) return;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800137
138 pw = getpwuid(ctx->to.uid);
139 if (pw) {
140 setenv("HOME", pw->pw_dir, 1);
Koushik Dutta379371b2013-03-11 17:30:53 -0700141 if (ctx->to.shell)
142 setenv("SHELL", ctx->to.shell, 1);
143 else
144 setenv("SHELL", DEFAULT_SHELL, 1);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800145 if (ctx->to.login || ctx->to.uid) {
146 setenv("USER", pw->pw_name, 1);
147 setenv("LOGNAME", pw->pw_name, 1);
148 }
149 }
150}
151
Koushik Dutta045c68a2013-02-17 17:03:56 -0800152void set_identity(unsigned int uid) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800153 /*
154 * Set effective uid back to root, otherwise setres[ug]id will fail
155 * if uid isn't root.
156 */
157 if (seteuid(0)) {
158 PLOGE("seteuid (root)");
159 exit(EXIT_FAILURE);
160 }
161 if (setresgid(uid, uid, uid)) {
162 PLOGE("setresgid (%u)", uid);
163 exit(EXIT_FAILURE);
164 }
165 if (setresuid(uid, uid, uid)) {
166 PLOGE("setresuid (%u)", uid);
167 exit(EXIT_FAILURE);
168 }
169}
170
Koushik Dutta045c68a2013-02-17 17:03:56 -0800171static void usage(int status) {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200172 FILE* stream = (status == EXIT_SUCCESS) ? stdout : stderr;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800173
174 fprintf(stream,
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200175 "Usage: su [options] [--] [-] [LOGIN] [--] [args...]\n\n"
176 "Options:\n"
177 " --daemon start the su daemon agent\n"
178 " -c, --command COMMAND pass COMMAND to the invoked shell\n"
179 " -h, --help display this help message and exit\n"
180 " -, -l, --login pretend the shell to be a login shell\n"
181 " -m, -p,\n"
182 " --preserve-environment do not change environment variables\n"
183 " -s, --shell SHELL use SHELL instead of the default " DEFAULT_SHELL
184 "\n"
185 " -v, --version display version number and exit\n"
186 " -V display version code and exit,\n"
187 " this is used almost exclusively by Superuser.apk\n");
Koushik Dutta05258fd2013-02-16 19:20:58 -0800188 exit(status);
189}
190
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200191static __attribute__((noreturn)) void deny(struct su_context* ctx) {
192 char* cmd = get_command(&ctx->to);
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000193 ALOGW("request rejected (%u->%u %s)", ctx->from.uid, ctx->to.uid, cmd);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800194 fprintf(stderr, "%s\n", strerror(EACCES));
195 exit(EXIT_FAILURE);
196}
197
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200198static __attribute__((noreturn)) void allow(struct su_context* ctx, const char* packageName) {
199 char* arg0;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800200 int argc, err;
201
202 umask(ctx->umask);
Koushik Dutta379371b2013-03-11 17:30:53 -0700203
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200204 char* binary;
Koushik Dutta379371b2013-03-11 17:30:53 -0700205 argc = ctx->to.optind;
206 if (ctx->to.command) {
207 binary = ctx->to.shell;
208 ctx->to.argv[--argc] = ctx->to.command;
209 ctx->to.argv[--argc] = "-c";
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200210 } else if (ctx->to.shell) {
Koushik Dutta379371b2013-03-11 17:30:53 -0700211 binary = ctx->to.shell;
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200212 } else {
Koushik Dutta379371b2013-03-11 17:30:53 -0700213 if (ctx->to.argv[argc]) {
214 binary = ctx->to.argv[argc++];
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200215 } else {
Koushik Dutta379371b2013-03-11 17:30:53 -0700216 binary = DEFAULT_SHELL;
217 }
218 }
219
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200220 arg0 = strrchr(binary, '/');
Koushik Dutta379371b2013-03-11 17:30:53 -0700221 arg0 = (arg0) ? arg0 + 1 : binary;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800222 if (ctx->to.login) {
223 int s = strlen(arg0) + 2;
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200224 char* p = malloc(s);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800225
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200226 if (!p) exit(EXIT_FAILURE);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800227
228 *p = '-';
229 strcpy(p + 1, arg0);
230 arg0 = p;
231 }
232
233 populate_environment(ctx);
234 set_identity(ctx->to.uid);
235
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200236#define PARG(arg) \
237 (argc + (arg) < ctx->to.argc) ? " " : "", \
238 (argc + (arg) < ctx->to.argc) ? ctx->to.argv[argc + (arg)] : ""
Koushik Dutta05258fd2013-02-16 19:20:58 -0800239
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200240 ALOGD("%u %s executing %u %s using binary %s : %s%s%s%s%s%s%s%s%s%s%s%s%s%s", ctx->from.uid,
241 ctx->from.bin, ctx->to.uid, get_command(&ctx->to), binary, arg0, PARG(0), PARG(1),
242 PARG(2), PARG(3), PARG(4), PARG(5), (ctx->to.optind + 6 < ctx->to.argc) ? " ..." : "");
Koushik Dutta05258fd2013-02-16 19:20:58 -0800243
Koushik Dutta05258fd2013-02-16 19:20:58 -0800244 ctx->to.argv[--argc] = arg0;
Diogo Ferreira9d646652014-12-17 12:24:46 +0000245
246 int pid = fork();
247 if (!pid) {
248 execvp(binary, ctx->to.argv + argc);
249 err = errno;
250 PLOGE("exec");
251 fprintf(stderr, "Cannot execute %s: %s\n", binary, strerror(err));
252 exit(EXIT_FAILURE);
253 } else {
gwzhang11730a52017-09-12 18:59:06 +0800254 int status, code;
Diogo Ferreira9d646652014-12-17 12:24:46 +0000255
256 ALOGD("Waiting for pid %d.", pid);
257 waitpid(pid, &status, 0);
gwzhang11730a52017-09-12 18:59:06 +0800258 ALOGD("pid %d returned %d.", pid, status);
259 code = WIFSIGNALED(status) ? WTERMSIG(status) + 128 : WEXITSTATUS(status);
260
Diogo Ferreira9d646652014-12-17 12:24:46 +0000261 if (packageName) {
262 appops_finish_op_su(ctx->from.uid, packageName);
263 }
gwzhang11730a52017-09-12 18:59:06 +0800264 exit(code);
Diogo Ferreira9d646652014-12-17 12:24:46 +0000265 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800266}
267
Luca Stefani7c86b052018-08-26 11:50:32 +0200268int access_disabled(const struct su_initiator* from) {
Koushik Dutta05258fd2013-02-16 19:20:58 -0800269 char build_type[PROPERTY_VALUE_MAX];
Luca Stefani7c86b052018-08-26 11:50:32 +0200270 int enabled;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800271
Luca Stefani7c86b052018-08-26 11:50:32 +0200272 /* Only allow su on debuggable builds */
273 if (!property_get_bool("ro.debuggable", false)) {
MSe1969ae77c1a2018-06-24 17:00:53 +0200274 ALOGE("Root access is disabled on non-debug builds");
275 return 1;
276 }
277
Luca Stefani7c86b052018-08-26 11:50:32 +0200278 /* Enforce persist.sys.root_access on non-eng builds for apps */
279 enabled = property_get_int32("persist.sys.root_access", 2);
280 property_get("ro.build.type", build_type, "");
281 if (strcmp("eng", build_type) != 0 && from->uid != AID_SHELL && from->uid != AID_ROOT &&
282 (enabled & LINEAGE_ROOT_ACCESS_APPS_ONLY) != LINEAGE_ROOT_ACCESS_APPS_ONLY) {
283 ALOGE(
284 "Apps root access is disabled by system setting - "
285 "enable it under settings -> developer options");
MSe1969ae77c1a2018-06-24 17:00:53 +0200286 return 1;
287 }
288
289 /* disallow su in a shell if appropriate */
290 if (from->uid == AID_SHELL &&
Luca Stefani7c86b052018-08-26 11:50:32 +0200291 (enabled & LINEAGE_ROOT_ACCESS_ADB_ONLY) != LINEAGE_ROOT_ACCESS_ADB_ONLY) {
292 ALOGE(
293 "Shell root access is disabled by a system setting - "
294 "enable it under settings -> developer options");
MSe1969ae77c1a2018-06-24 17:00:53 +0200295 return 1;
296 }
297
Koushik Dutta05258fd2013-02-16 19:20:58 -0800298 return 0;
299}
300
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200301int main(int argc, char* argv[]) {
Daniel Micay4fb98c12015-11-08 19:06:51 -0500302 if (getuid() != geteuid()) {
303 ALOGE("must not be a setuid binary");
304 return 1;
305 }
306
Koushik Dutta8829fc32013-11-21 09:19:47 -0800307 return su_main(argc, argv, 1);
308}
309
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200310int su_main(int argc, char* argv[], int need_client) {
Koushik Duttac200cf72013-07-26 21:35:23 -0700311 // start up in daemon mode if prompted
312 if (argc == 2 && strcmp(argv[1], "--daemon") == 0) {
313 return run_daemon();
314 }
315
Marcos Maradof465a0a2014-02-01 22:58:19 +0000316 int ppid = getppid();
Kevin Cernekeeb27031e2013-11-23 15:02:58 -0800317
Koushik Dutta8066f2c2013-02-16 19:59:10 -0800318 // Sanitize all secure environment variables (from linker_environ.c in AOSP linker).
319 /* The same list than GLibc at this point */
320 static const char* const unsec_vars[] = {
321 "GCONV_PATH",
322 "GETCONF_DIR",
323 "HOSTALIASES",
324 "LD_AUDIT",
325 "LD_DEBUG",
326 "LD_DEBUG_OUTPUT",
327 "LD_DYNAMIC_WEAK",
328 "LD_LIBRARY_PATH",
329 "LD_ORIGIN_PATH",
330 "LD_PRELOAD",
331 "LD_PROFILE",
332 "LD_SHOW_AUXV",
333 "LD_USE_LOAD_BIAS",
334 "LOCALDOMAIN",
335 "LOCPATH",
336 "MALLOC_TRACE",
337 "MALLOC_CHECK_",
338 "NIS_PATH",
339 "NLSPATH",
340 "RESOLV_HOST_CONF",
341 "RES_OPTIONS",
342 "TMPDIR",
343 "TZDIR",
344 "LD_AOUT_LIBRARY_PATH",
345 "LD_AOUT_PRELOAD",
346 // not listed in linker, used due to system() call
347 "IFS",
348 };
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200349 const char* const* cp = unsec_vars;
350 const char* const* endp = cp + sizeof(unsec_vars) / sizeof(unsec_vars[0]);
Koushik Dutta8066f2c2013-02-16 19:59:10 -0800351 while (cp < endp) {
352 unsetenv(*cp);
353 cp++;
354 }
355
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000356 ALOGD("su invoked.");
Koushik Dutta05258fd2013-02-16 19:20:58 -0800357
358 struct su_context ctx = {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200359 .from =
360 {
361 .pid = -1,
362 .uid = 0,
363 .bin = "",
364 .args = "",
365 .name = "",
366 },
367 .to =
368 {
369 .uid = AID_ROOT,
370 .login = 0,
371 .keepenv = 0,
372 .shell = NULL,
373 .command = NULL,
374 .argv = argv,
375 .argc = argc,
376 .optind = 0,
377 .name = "",
378 },
Koushik Dutta05258fd2013-02-16 19:20:58 -0800379 };
Luca Stefanibce29762017-01-22 23:09:15 +0100380 int c;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800381 struct option long_opts[] = {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200382 {"command", required_argument, NULL, 'c'},
383 {"help", no_argument, NULL, 'h'},
384 {"login", no_argument, NULL, 'l'},
385 {"preserve-environment", no_argument, NULL, 'p'},
386 {"shell", required_argument, NULL, 's'},
387 {"version", no_argument, NULL, 'v'},
388 {NULL, 0, NULL, 0},
Koushik Dutta05258fd2013-02-16 19:20:58 -0800389 };
390
Diogo Ferreira9d0f2342014-12-16 18:18:28 +0000391 while ((c = getopt_long(argc, argv, "+c:hlmps:Vv", long_opts, NULL)) != -1) {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200392 switch (c) {
393 case 'c':
394 ctx.to.shell = DEFAULT_SHELL;
395 ctx.to.command = optarg;
396 break;
397 case 'h':
398 usage(EXIT_SUCCESS);
399 break;
400 case 'l':
401 ctx.to.login = 1;
402 break;
403 case 'm':
404 case 'p':
405 ctx.to.keepenv = 1;
406 break;
407 case 's':
408 ctx.to.shell = optarg;
409 break;
410 case 'V':
411 printf("%d\n", VERSION_CODE);
412 exit(EXIT_SUCCESS);
413 case 'v':
414 printf("%s\n", VERSION);
415 exit(EXIT_SUCCESS);
416 default:
417 /* Bionic getopt_long doesn't terminate its error output by newline */
418 fprintf(stderr, "\n");
419 usage(2);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800420 }
421 }
Koushik Dutta8829fc32013-11-21 09:19:47 -0800422
423 if (need_client) {
Daniel Micayf40b0682015-11-14 18:28:34 -0500424 // attempt to connect to daemon...
425 ALOGD("starting daemon client %d %d", getuid(), geteuid());
426 return connect_daemon(argc, argv, ppid);
Koushik Dutta8829fc32013-11-21 09:19:47 -0800427 }
428
Koushik Dutta05258fd2013-02-16 19:20:58 -0800429 if (optind < argc && !strcmp(argv[optind], "-")) {
430 ctx.to.login = 1;
431 optind++;
432 }
433 /* username or uid */
Tom Marshallbeddaf72018-08-24 19:38:42 +0200434 if (optind < argc && strcmp(argv[optind], "--") != 0) {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200435 struct passwd* pw;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800436 pw = getpwnam(argv[optind]);
437 if (!pw) {
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200438 char* endptr;
Koushik Dutta05258fd2013-02-16 19:20:58 -0800439
440 /* It seems we shouldn't do this at all */
441 errno = 0;
442 ctx.to.uid = strtoul(argv[optind], &endptr, 10);
443 if (errno || *endptr) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000444 ALOGE("Unknown id: %s\n", argv[optind]);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800445 fprintf(stderr, "Unknown id: %s\n", argv[optind]);
446 exit(EXIT_FAILURE);
447 }
448 } else {
449 ctx.to.uid = pw->pw_uid;
Daniel Micayc9d292e2015-11-08 16:52:17 -0500450 if (pw->pw_name) {
451 if (strlcpy(ctx.to.name, pw->pw_name, sizeof(ctx.to.name)) >= sizeof(ctx.to.name)) {
452 ALOGE("name too long");
453 exit(EXIT_FAILURE);
454 }
455 }
Koushik Dutta05258fd2013-02-16 19:20:58 -0800456 }
457 optind++;
458 }
459 if (optind < argc && !strcmp(argv[optind], "--")) {
460 optind++;
461 }
462 ctx.to.optind = optind;
463
Koushik Dutta05258fd2013-02-16 19:20:58 -0800464 if (from_init(&ctx.from) < 0) {
465 deny(&ctx);
466 }
Koushik Duttac200cf72013-07-26 21:35:23 -0700467
Diogo Ferreira590ddd22014-12-16 10:27:31 +0000468 ALOGE("SU from: %s", ctx.from.name);
469
Michael Bestasaf630882019-03-06 23:49:53 +0200470 if (ctx.from.uid == AID_ROOT) {
471 ALOGD("Allowing root.");
472 allow(&ctx, NULL);
473 }
474
Koushik Dutta33b3f162013-03-03 22:41:48 -0800475 // check if superuser is disabled completely
476 if (access_disabled(&ctx.from)) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000477 ALOGD("access_disabled");
Koushik Dutta33b3f162013-03-03 22:41:48 -0800478 deny(&ctx);
479 }
480
Koushik Dutta62843e12013-03-11 14:39:55 -0700481 // autogrant shell at this point
482 if (ctx.from.uid == AID_SHELL) {
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000483 ALOGD("Allowing shell.");
Diogo Ferreira9d646652014-12-17 12:24:46 +0000484 allow(&ctx, NULL);
Koushik Dutta62843e12013-03-11 14:39:55 -0700485 }
486
Luca Stefani5eb52ea2018-08-26 11:35:00 +0200487 char* packageName = resolve_package_name(ctx.from.uid);
Tom Marshallbeddaf72018-08-24 19:38:42 +0200488 if (packageName) {
489 if (!appops_start_op_su(ctx.from.uid, packageName)) {
490 ALOGD("Allowing via appops.");
491 allow(&ctx, packageName);
492 }
493 free(packageName);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800494 }
Diogo Ferreira910c8412014-12-16 17:38:44 +0000495
Diogo Ferreira4aaba1e2014-12-16 17:58:55 +0000496 ALOGE("Allow chain exhausted, denying request");
Diogo Ferreira910c8412014-12-16 17:38:44 +0000497 deny(&ctx);
Koushik Dutta05258fd2013-02-16 19:20:58 -0800498}