/* * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities. * Our group, cache, was set by init. */ void switchUser() { char debuggable[PROP_VALUE_MAX]; prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setuid(AID_RADIO); struct __user_cap_header_struct header; memset(&header, 0, sizeof(header)); header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; struct __user_cap_data_struct data[2]; memset(&data, 0, sizeof(data)); data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); if (capset(&header, &data[0]) == -1) { RLOGE("capset failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /* * Debuggable build only: * Set DUMPABLE that was cleared by setuid() to have tombstone on RIL crash */ property_get("ro.debuggable", debuggable, "0"); if (strcmp(debuggable, "1") == 0) { prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } }
static int drop_privs() { struct sched_param param; memset(¶m, 0, sizeof(param)); if (set_sched_policy(0, SP_BACKGROUND) < 0) { return -1; } if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) { return -1; } if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) { return -1; } if (prctl(PR_SET_KEEPCAPS, 1) < 0) { return -1; } gid_t groups[] = { AID_READPROC }; if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) == -1) { return -1; } if (setgid(AID_LOGD) != 0) { return -1; } if (setuid(AID_LOGD) != 0) { return -1; } struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL); capdata[0].effective = capdata[0].permitted; capdata[1].effective = capdata[1].permitted; capdata[0].inheritable = 0; capdata[1].inheritable = 0; if (capset(&capheader, &capdata[0]) < 0) { return -1; } return 0; }
int SetPermission(int flag) { int errno = 0; struct __user_cap_header_struct header; header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = (int)ISyscall(__NR_gettid); printf("version: 0x%08x\n", header.version); unsigned int data[3]; memset(data, 0, sizeof(data)); if (ISyscall(__NR_capget, &header, &data)) { printf("capget failed!\n"); return 0; } //memset(data, 0, sizeof(data)); data[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag); if ((errno = ISyscall(__NR_capset, &header, &data))) { printf("capset failed! [%d]\n", errno); printf("version: 0x%08x\n", header.version); return 0; } printf("0x%08x\n", data[0]); printf("0x%08x\n", data[1]); printf("0x%08x\n", data[2]); return 1; }
/* audit interface for capability */ void kse_cap_audit(struct task_struct *tsk, int cap, int result) { int sclass, request; struct common_audit_data ad; if (kse_noyaudit == 1 && result == 0) return; COMMON_AUDIT_DATA_INIT(&ad, CAP); ad.tsk = tsk; ad.u.cap = cap; request = CAP_TO_MASK(cap); switch (CAP_TO_INDEX(cap)) { case 0: sclass = SECCLASS_CAPABILITY; break; case 1: sclass = SECCLASS_CAPABILITY2; break; default: printk(KERN_ERR "KUXSE: out of range capability %d\n", cap); BUG(); } //kse_audit(task_cred_xxx(tsk, security), NULL, NULL, 0, sclass, //request, result, &ad); kse_audit(tsk->security, NULL, NULL, 0, sclass, request, result, &ad); }
static int drop_privs() { struct sched_param param; memset(¶m, 0, sizeof(param)); if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) { return -1; } if (prctl(PR_SET_KEEPCAPS, 1) < 0) { return -1; } if (setgid(AID_LOGD) != 0) { return -1; } if (setuid(AID_LOGD) != 0) { return -1; } struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL); capdata[0].effective = capdata[0].permitted; capdata[1].effective = capdata[1].permitted; capdata[0].inheritable = 0; capdata[1].inheritable = 0; if (capset(&capheader, &capdata[0]) < 0) { return -1; } return 0; }
static int drop_privs(void) { struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { return -1; } /* * ensure we're running as the system user */ if (setgid(AID_SYSTEM) != 0) { return -1; } if (setuid(AID_SYSTEM) != 0) { return -1; } /* * drop all capabilities except SYS_RAWIO */ memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted = CAP_TO_MASK(CAP_SYS_RAWIO); capdata[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective = CAP_TO_MASK(CAP_SYS_RAWIO); if (capset(&capheader, &capdata[0]) < 0) { return -1; } /* no-execute for user, no access for group and other */ umask(S_IXUSR | S_IRWXG | S_IRWXO); return 0; }
static void drop_privileges() { if (prctl(PR_SET_KEEPCAPS, 1) < 0) { ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); exit(1); } if (setgid(AID_INSTALL) < 0) { ALOGE("setgid() can't drop privileges; exiting.\n"); exit(1); } if (setuid(AID_INSTALL) < 0) { ALOGE("setuid() can't drop privileges; exiting.\n"); exit(1); } struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE); capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN); capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); capdata[0].effective = capdata[0].permitted; capdata[1].effective = capdata[1].permitted; capdata[0].inheritable = 0; capdata[1].inheritable = 0; if (capset(&capheader, &capdata[0]) < 0) { ALOGE("capset failed: %s\n", strerror(errno)); exit(1); } }
static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { size_t sz; assert(c); assert(capability >= 0); assert(c->capability); if ((unsigned) capability > cap_last_cap()) return 0; sz = DIV_ROUND_UP(cap_last_cap(), 32U); return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability)); }
/* * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities. * Our group, cache, was set by init. */ void switchUser() { prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setuid(AID_RADIO); struct __user_cap_header_struct header; memset(&header, 0, sizeof(header)); header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; struct __user_cap_data_struct data[2]; memset(&data, 0, sizeof(data)); data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); if (capset(&header, &data[0]) == -1) { RLOGE("capset failed: %s", strerror(errno)); exit(EXIT_FAILURE); } }
void linux_cap_change(int on, ...) { struct __user_cap_header_struct x; struct __user_cap_data_struct s[3] = {}; x.version = _LINUX_CAPABILITY_VERSION_3; x.pid = syscall(SYS_gettid); if(syscall(SYS_capget, &x, s)) { perror("capget"); exit(1); } va_list ap; va_start(ap, on); int cap; while((cap = va_arg(ap, int)) != -1) { if(!cap_valid(cap)) { fprintf(stderr, "cap %d is not valid\n", cap); exit(1); } if(on) { s[CAP_TO_INDEX(cap)].effective |= CAP_TO_MASK(cap); } else { s[CAP_TO_INDEX(cap)].effective &= ~CAP_TO_MASK(cap); } } if(syscall(SYS_capset, &x, s)) { perror("capset"); exit(1); } }
/** Drop all capabilities except for the mentioned ones */ void dropCapabilities(int8_t keep[]) { struct __user_cap_header_struct header; struct __user_cap_data_struct cap[2]; memset(&header, 0, sizeof(header)); memset(&cap, 0, sizeof(cap)); header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; if (keep != NULL) { for (int i = 0; keep[i] >= 0; i++) { cap[CAP_TO_INDEX(keep[i])].permitted |= CAP_TO_MASK(keep[i]); } cap[0].effective = cap[0].inheritable = cap[0].permitted; cap[1].effective = cap[1].inheritable = cap[1].permitted; } capset(&header, &cap[0]); }
int CheckPermission(int flag) { struct __user_cap_header_struct header; header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = (int)ISyscall(__NR_getpid); unsigned int data[3]; memset(data, 0, sizeof(data)); if (ISyscall(__NR_capget, &header, &data)) { return 0; } printf("0x%08x\n", data[0]); printf("0x%08x\n", data[1]); printf("0x%08x\n", data[2]); printf("i: %d\n", CAP_TO_INDEX(CAP_BLOCK_SUSPEND)); return CHECK_FLAG(data, flag); }
int main(int argc, char *argv[]) { struct sigaction sigact; int do_add_date = 0; int do_compress = 0; int do_vibrate = 1; char* use_outfile = 0; char* begin_sound = 0; char* end_sound = 0; int use_socket = 0; int do_fb = 0; if (getuid() != 0) { // Old versions of the adb client would call the // dumpstate command directly. Newer clients // call /system/bin/bugreport instead. If we detect // we're being called incorrectly, then exec the // correct program. return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL); } ALOGI("begin\n"); memset(&sigact, 0, sizeof(sigact)); sigact.sa_handler = sigpipe_handler; sigaction(SIGPIPE, &sigact, NULL); /* set as high priority, and protect from OOM killer */ setpriority(PRIO_PROCESS, 0, -20); FILE *oom_adj = fopen("/proc/self/oom_adj", "w"); if (oom_adj) { fputs("-17", oom_adj); fclose(oom_adj); } /* very first thing, collect stack traces from Dalvik and native processes (needs root) */ dump_traces_path = dump_traces(); int c; while ((c = getopt(argc, argv, "b:de:ho:svqzp")) != -1) { switch (c) { case 'b': begin_sound = optarg; break; case 'd': do_add_date = 1; break; case 'e': end_sound = optarg; break; case 'o': use_outfile = optarg; break; case 's': use_socket = 1; break; case 'v': break; // compatibility no-op case 'q': do_vibrate = 0; break; case 'z': do_compress = 6; break; case 'p': do_fb = 1; break; case '?': printf("\n"); case 'h': usage(); exit(1); } } FILE *vibrator = 0; if (do_vibrate) { /* open the vibrator before dropping root */ vibrator = fopen("/sys/class/timed_output/vibrator/enable", "w"); if (vibrator) fcntl(fileno(vibrator), F_SETFD, FD_CLOEXEC); } /* read /proc/cmdline before dropping root */ FILE *cmdline = fopen("/proc/cmdline", "r"); if (cmdline != NULL) { fgets(cmdline_buf, sizeof(cmdline_buf), cmdline); fclose(cmdline); } if (prctl(PR_SET_KEEPCAPS, 1) < 0) { ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); return -1; } /* switch to non-root user and group */ gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW, AID_MOUNT, AID_INET, AID_NET_BW_STATS }; if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) { ALOGE("Unable to setgroups, aborting: %s\n", strerror(errno)); return -1; } if (setgid(AID_SHELL) != 0) { ALOGE("Unable to setgid, aborting: %s\n", strerror(errno)); return -1; } if (setuid(AID_SHELL) != 0) { ALOGE("Unable to setuid, aborting: %s\n", strerror(errno)); return -1; } struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG); capdata[0].inheritable = 0; capdata[1].inheritable = 0; if (capset(&capheader, &capdata[0]) < 0) { ALOGE("capset failed: %s\n", strerror(errno)); return -1; } char path[PATH_MAX], tmp_path[PATH_MAX]; pid_t gzip_pid = -1; if (use_socket) { redirect_to_socket(stdout, "dumpstate"); } else if (use_outfile) { strlcpy(path, use_outfile, sizeof(path)); if (do_add_date) { char date[80]; time_t now = time(NULL); strftime(date, sizeof(date), "-%Y-%m-%d-%H-%M-%S", localtime(&now)); strlcat(path, date, sizeof(path)); } if (do_fb) { strlcpy(screenshot_path, path, sizeof(screenshot_path)); strlcat(screenshot_path, ".png", sizeof(screenshot_path)); } strlcat(path, ".txt", sizeof(path)); if (do_compress) strlcat(path, ".gz", sizeof(path)); strlcpy(tmp_path, path, sizeof(tmp_path)); strlcat(tmp_path, ".tmp", sizeof(tmp_path)); gzip_pid = redirect_to_file(stdout, tmp_path, do_compress); } if (begin_sound) { play_sound(begin_sound); } else if (vibrator) { fputs("150", vibrator); fflush(vibrator); } dumpstate(); if (end_sound) { play_sound(end_sound); } else if (vibrator) { int i; for (i = 0; i < 3; i++) { fputs("75\n", vibrator); fflush(vibrator); usleep((75 + 50) * 1000); } fclose(vibrator); } /* wait for gzip to finish, otherwise it might get killed when we exit */ if (gzip_pid > 0) { fclose(stdout); waitpid(gzip_pid, NULL, 0); } /* rename the (now complete) .tmp file to its final location */ if (use_outfile && rename(tmp_path, path)) { fprintf(stderr, "rename(%s, %s): %s\n", tmp_path, path, strerror(errno)); } ALOGI("done\n"); return 0; }
int main(int argc, char* argv[]) { // Check arguments. if (argc < 2) { error(1, 0, "usage: run-as <package-name> [--user <uid>] <command> [<args>]\n"); } // This program runs with CAP_SETUID and CAP_SETGID capabilities on Android // production devices. Check user id of caller --- must be 'shell' or 'root'. if (getuid() != AID_SHELL && getuid() != AID_ROOT) { error(1, 0, "only 'shell' or 'root' users can run this program"); } __user_cap_header_struct capheader; __user_cap_data_struct capdata[2]; memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capdata[CAP_TO_INDEX(CAP_SETUID)].effective |= CAP_TO_MASK(CAP_SETUID); capdata[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID); capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); if (capset(&capheader, &capdata[0]) == -1) { error(1, errno, "couldn't set capabilities"); } char* pkgname = argv[1]; int cmd_argv_offset = 2; // Get user_id from command line if provided. int userId = 0; if ((argc >= 4) && !strcmp(argv[2], "--user")) { userId = atoi(argv[3]); if (userId < 0) error(1, 0, "negative user id: %d", userId); cmd_argv_offset += 2; } // Retrieve package information from system, switching egid so we can read the file. gid_t old_egid = getegid(); if (setegid(AID_PACKAGE_INFO) == -1) error(1, errno, "setegid(AID_PACKAGE_INFO) failed"); pkg_info info; memset(&info, 0, sizeof(info)); info.name = pkgname; if (!packagelist_parse(packagelist_parse_callback, &info)) { error(1, errno, "packagelist_parse failed"); } if (info.uid == 0) { error(1, 0, "unknown package: %s", pkgname); } if (setegid(old_egid) == -1) error(1, errno, "couldn't restore egid"); // Verify that user id is not too big. if ((UID_MAX - info.uid) / AID_USER < (uid_t)userId) { error(1, 0, "user id too big: %d", userId); } // Calculate user app ID. uid_t userAppId = (AID_USER * userId) + info.uid; // Reject system packages. if (userAppId < AID_APP) { error(1, 0, "package not an application: %s", pkgname); } // Reject any non-debuggable package. if (!info.debuggable) { error(1, 0, "package not debuggable: %s", pkgname); } // Check that the data directory path is valid. if (!check_data_path(info.data_dir, userAppId)) { error(1, 0, "package has corrupt installation: %s", pkgname); } // Ensure that we change all real/effective/saved IDs at the // same time to avoid nasty surprises. uid_t uid = userAppId; uid_t gid = userAppId; if (setresgid(gid, gid, gid) == -1) { error(1, errno, "setresgid failed"); } if (setresuid(uid, uid, uid) == -1) { error(1, errno, "setresuid failed"); } // Required if caller has uid and gid all non-zero. memset(&capdata, 0, sizeof(capdata)); if (capset(&capheader, &capdata[0]) == -1) { error(1, errno, "couldn't clear all capabilities"); } if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) { error(1, errno, "couldn't set SELinux security context"); } // cd into the data directory, and set $HOME correspondingly. if (TEMP_FAILURE_RETRY(chdir(info.data_dir)) == -1) { error(1, errno, "couldn't chdir to package's data directory"); } setenv("HOME", info.data_dir, 1); // Reset parts of the environment, like su would. setenv("PATH", _PATH_DEFPATH, 1); unsetenv("IFS"); // Set the user-specific parts for this user. passwd* pw = getpwuid(uid); setenv("LOGNAME", pw->pw_name, 1); setenv("SHELL", pw->pw_shell, 1); setenv("USER", pw->pw_name, 1); // User specified command for exec. if ((argc >= cmd_argv_offset + 1) && (execvp(argv[cmd_argv_offset], argv+cmd_argv_offset) == -1)) { error(1, errno, "exec failed for %s", argv[cmd_argv_offset]); } // Default exec shell. execlp(_PATH_BSHELL, "sh", NULL); error(1, errno, "exec failed"); }
int adb_main(int is_daemon, int server_port) { #if !ADB_HOST int port; char value[PROPERTY_VALUE_MAX]; umask(000); #endif atexit(adb_cleanup); #ifdef HAVE_WIN32_PROC SetConsoleCtrlHandler( ctrlc_handler, TRUE ); #elif defined(HAVE_FORKEXEC) // No SIGCHLD. Let the service subproc handle its children. signal(SIGPIPE, SIG_IGN); #endif init_transport_registration(); #if ADB_HOST HOST = 1; usb_vendors_init(); usb_init(); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); adb_auth_init(); char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } #else property_get("ro.adb.secure", value, "0"); auth_enabled = !strcmp(value, "1"); if (auth_enabled) adb_auth_init(); // Our external storage path may be different than apps, since // we aren't able to bind mount after dropping root. const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE"); if (NULL != adb_external_storage) { setenv("EXTERNAL_STORAGE", adb_external_storage, 1); } else { D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE" " unchanged.\n"); } /* don't listen on a port (default 5037) if running in secure mode */ /* don't run as root if we are running in secure mode */ if (should_drop_privileges()) { struct __user_cap_header_struct header; struct __user_cap_data_struct cap[2]; if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) { exit(1); } /* add extra groups: ** AID_ADB to access the USB driver ** AID_LOG to read system logs (adb logcat) ** AID_INPUT to diagnose input issues (getevent) ** AID_INET to diagnose network issues (netcfg, ping) ** AID_GRAPHICS to access the frame buffer ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) ** AID_SDCARD_R to allow reading from the SD card ** AID_SDCARD_RW to allow writing to the SD card ** AID_MOUNT to allow unmounting the SD card before rebooting ** AID_NET_BW_STATS to read out qtaguid statistics */ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS, AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW, AID_MOUNT, AID_NET_BW_STATS }; if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) { exit(1); } /* then switch user and group to "shell" */ if (setgid(AID_SHELL) != 0) { exit(1); } if (setuid(AID_SHELL) != 0) { exit(1); } memset(&header, 0, sizeof(header)); memset(cap, 0, sizeof(cap)); /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */ header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; cap[CAP_TO_INDEX(CAP_SYS_BOOT)].effective |= CAP_TO_MASK(CAP_SYS_BOOT); cap[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted |= CAP_TO_MASK(CAP_SYS_BOOT); capset(&header, cap); D("Local port disabled\n"); } else { char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } } int usb = 0; if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) { // listen on USB usb_init(); usb = 1; } // If one of these properties is set, also listen on that port // If one of the properties isn't set and we couldn't listen on usb, // listen on the default port. property_get("service.adb.tcp.port", value, ""); if (!value[0]) { property_get("persist.adb.tcp.port", value, ""); } if (sscanf(value, "%d", &port) == 1 && port > 0) { printf("using port=%d\n", port); // listen on TCP port specified by service.adb.tcp.port property local_init(port); } else if (!usb) { // listen on default port local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); } D("adb_main(): pre init_jdwp()\n"); init_jdwp(); D("adb_main(): post init_jdwp()\n"); #endif if (is_daemon) { // inform our parent that we are up and running. #ifdef HAVE_WIN32_PROC DWORD count; WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL ); #elif defined(HAVE_FORKEXEC) fprintf(stderr, "OK\n"); #endif start_logging(); } D("Event loop starting\n"); fdevent_loop(); usb_cleanup(); return 0; }
int main (int argc, char *argv[]) { int option; // holds the option from getopt_long const char *const short_options = "hp:v:c:mis:g:w:r:lt:j:b:n"; // possible cmd line short options const struct option long_options[] = { // possible cmd line long options { "help", 0, NULL, 'h' }, { "port", 1, NULL, 'p' }, { "verbose", 1, NULL, 'v' }, { "command", 1, NULL, 'c' }, { "memdump", 0, NULL, 'm' }, { "image", 0, NULL, 'i' }, { "sahara", 1, NULL, 's' }, { "prefix", 1, NULL, 'g' }, { "where", 1, NULL, 'w' }, { "ramdumpimage", 1, NULL, 'r' }, { "efssyncloop", 0, NULL, 'l' }, { "rxtimeout", 1, NULL, 't' }, { "maxwrite", 1, NULL, 'j' }, { "addsearchpath", 1, NULL, 'b' }, { "noreset", 0, NULL, 'n' }, { NULL, 0, NULL, 0 } }; bool efs_sync = false; unsigned int i; bool enable_sahara_transfer = false; #ifndef WINDOWSPC unsigned long cap; int err; int rc; struct __user_cap_header_struct capheader; struct __user_cap_data_struct capdata[2]; if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) { dbg(LOG_WARN, "set keepcaps failed!"); } for (cap = 0; prctl(PR_CAPBSET_READ, cap, 0, 0, 0) >= 0; cap++) { if ((cap == CAP_SETUID) || (cap == CAP_SETGID) || (cap == CAP_BLOCK_SUSPEND)) { continue; } err = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0); if ((err < 0) && (errno != EINVAL)) { dbg(LOG_WARN, "Drop capability %d failed\n", cap); } } if (setgid(AID_SYSTEM) != 0) { dbg(LOG_WARN, "setgid failed"); } else { if (setuid(AID_SYSTEM) != 0) { dbg(LOG_WARN, "setuid failed"); } else { memset(&capheader, 0, sizeof(capheader)); memset(&capdata, 0, sizeof(capdata)); capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; capdata[CAP_TO_INDEX(CAP_BLOCK_SUSPEND)].permitted |= CAP_TO_MASK(CAP_BLOCK_SUSPEND); capdata[CAP_TO_INDEX(CAP_BLOCK_SUSPEND)].effective |= CAP_TO_MASK(CAP_BLOCK_SUSPEND); if ((rc = capset(&capheader, capdata)) < 0) { dbg(LOG_WARN, "capset failed: %s, rc = %d\n", strerror(errno), rc); } } } #endif if (false == init_search_path_list() || false == init_sahara_mapping_list()) { dbg(LOG_ERROR, "Could not initialize."); return EXIT_FAILURE; } /* parse command-line options */ do { option = getopt_long (argc, argv, short_options, long_options, NULL); switch (option) { case -1: /* no more option arguments */ break; case 'h': /* -h or --help */ usage(); return EXIT_SUCCESS; case 'p': /* Get the port string name */ com_port.port_name = optarg; dbg(LOG_INFO, "Port name '%s'", com_port.port_name); break; case 's': /* -s or --sahara */ /*add the input to <id,file_name> list*/ if (false == add_input_to_sahara_mapping_list(optarg)) { dbg(LOG_ERROR, "Failed to add file to file list"); return EXIT_FAILURE; } enable_sahara_transfer = true; break; case 'b': if (false == add_search_path(optarg)) { dbg(LOG_ERROR, "Failed to add to search path list"); return EXIT_FAILURE; } break; case 'i': /* -i or --image */ sahara_data.mode = SAHARA_MODE_IMAGE_TX_PENDING; enable_sahara_transfer = true; break; case 'v': /* -v or --verbose */ kickstart_options.verbose = atoi(optarg); break; case 'm': /* -m or --memdump */ sahara_data.mode = SAHARA_MODE_MEMORY_DEBUG; enable_sahara_transfer = true; break; case 'r': /* -r or --ramdumpimage */ sahara_data.ram_dump_image = atoi(optarg); enable_sahara_transfer = true; break; case 'g': /* -g or --prefix */ kickstart_options.saved_file_prefix = optarg; break; case 'w': /* -w or --where - path for memory dump */ kickstart_options.path_to_save_files = optarg; break; case 'c': /* -c or --command */ sahara_data.mode = SAHARA_MODE_COMMAND; sahara_data.command = atoi(optarg); enable_sahara_transfer = true; break; case 'l': /* -l or --loop */ efs_sync = true; sahara_data.mode = SAHARA_MODE_MEMORY_DEBUG; com_port.rx_timeout = -1; enable_sahara_transfer = true; break; case 't': com_port.rx_timeout = atoi(optarg); break; case 'j': /* -c or --command */ com_port.MAX_TO_WRITE = atoi(optarg); break; case 'n': /* -n or --noreset */ sahara_data.allow_sahara_reset = false; break; default: /* unknown option. */ dbg(LOG_ERROR, "unrecognized option: '%c'", option); usage (); return EXIT_FAILURE; } } while (option != -1); #ifndef WINDOWSPC /* After parsing the command line args try to change the verbosity level of the logs if the system property was set. */ kickstart_options.verbose = read_verbosity_property (kickstart_options.verbose); #endif if (true == enable_sahara_transfer) { if (NULL == com_port.port_name) { dbg(LOG_ERROR, "Port device name not specified; use -p option."); return EXIT_FAILURE; } for (i = 0; i < kickstart_options.port_connect_retries; i++) { if (true == port_connect(com_port.port_name)) { break; } } if (kickstart_options.port_connect_retries == i) { dbg(LOG_ERROR, "Could not connect to %s", com_port.port_name); return EXIT_FAILURE; } // This is a little hacky. Ideally the timeout values should be passed in // as an argument, but since they don't change too often, hardcoding them // here for now if (efs_sync) { com_port.rx_timeout_sec = 0; com_port.rx_timeout_usec = 500000; dbg(LOG_STATUS, "Setting timeout to 500ms"); } else { com_port.rx_timeout_sec = 2; com_port.rx_timeout_usec = 0; dbg(LOG_STATUS, "Setting timeout to 2s"); } if (false == sahara_main (efs_sync)) { dbg(LOG_ERROR, "Uploading Image using Sahara protocol failed"); use_wakelock(WAKELOCK_RELEASE); port_disconnect(); return EXIT_FAILURE; } } port_disconnect(); return EXIT_SUCCESS; }