int restorecon_data() { char *data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); char *user_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_DATADATA; int ret = 0; if (!data_dir || !user_dir) { return -1; } if (selinux_android_restorecon(data_dir, flags) < 0) { ALOGE("restorecon failed for %s: %s\n", data_dir, strerror(errno)); ret |= -1; } if (selinux_android_restorecon(user_dir, flags) < 0) { ALOGE("restorecon failed for %s: %s\n", user_dir, strerror(errno)); ret |= -1; } free(data_dir); free(user_dir); return ret; }
static int mkdirs(char *name) { int ret; char *x = name + 1; uid_t uid = -1; gid_t gid = -1; unsigned int mode = 0775; uint64_t cap = 0; if(name[0] != '/') return -1; for(;;) { x = adb_dirstart(x); if(x == 0) return 0; *x = 0; if (is_on_system(name) || is_on_vendor(name)) { fs_config(name, 1, &uid, &gid, &mode, &cap); } ret = adb_mkdir(name, mode); if((ret < 0) && (errno != EEXIST)) { D("mkdir(\"%s\") -> %s\n", name, strerror(errno)); *x = '/'; return ret; } else if(ret == 0) { ret = chown(name, uid, gid); if (ret < 0) { *x = '/'; return ret; } selinux_android_restorecon(name, 0); } *x++ = '/'; } return 0; }
static bool secure_mkdirs(const std::string& path) { uid_t uid = -1; gid_t gid = -1; unsigned int mode = 0775; uint64_t cap = 0; if (path[0] != '/') return false; std::vector<std::string> path_components = android::base::Split(path, "/"); path_components.pop_back(); // For "/system/bin/sh", only create "/system/bin". std::string partial_path; for (const auto& path_component : path_components) { if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR; partial_path += path_component; if (should_use_fs_config(partial_path)) { fs_config(partial_path.c_str(), 1, nullptr, &uid, &gid, &mode, &cap); } if (adb_mkdir(partial_path.c_str(), mode) == -1) { if (errno != EEXIST) { return false; } } else { if (chown(partial_path.c_str(), uid, gid) == -1) { return false; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(partial_path.c_str(), 0); } } return true; }
/* called to setup bootcharting */ int bootchart_init( void ) { int ret; char buff[4]; int timeout = 0, count = 0; buff[0] = 0; proc_read( LOG_STARTFILE, buff, sizeof(buff) ); if (buff[0] != 0) { timeout = atoi(buff); } else { /* when running with emulator, androidboot.bootchart=<timeout> * might be passed by as kernel parameters to specify the bootchart * timeout. this is useful when using -wipe-data since the /data * partition is fresh */ char cmdline[1024]; char* s; #define KERNEL_OPTION "androidboot.bootchart=" proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) ); s = strstr(cmdline, KERNEL_OPTION); if (s) { s += sizeof(KERNEL_OPTION)-1; timeout = atoi(s); } } if (timeout == 0) return 0; if (timeout > BOOTCHART_MAX_TIME_SEC) timeout = BOOTCHART_MAX_TIME_SEC; count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS; do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR); selinux_android_restorecon(LOG_ROOT, 0); file_buff_open(log_stat, LOG_STAT); file_buff_open(log_procs, LOG_PROCS); file_buff_open(log_disks, LOG_DISK); /* create kernel process accounting file */ { int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd >= 0) { close(fd); acct( LOG_ACCT ); } } log_header(); return count; }
/* * Function: native_restorecon * Purpose: restore default SELinux security context * Parameters: pathname: the pathname for the file to be relabeled * Returns: boolean: (true) file label successfully restored, (false) otherwise * Exceptions: none */ static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) { #ifdef HAVE_SELINUX if (isSELinuxDisabled) return true; const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL)); int ret = selinux_android_restorecon(file); env->ReleaseStringUTFChars(pathname, file); return (ret == 0); #else return true; #endif }
scrolly = m_bg1scrolly; for (i = 0; i < 256; i++) m_bg1_tilemap->set_scrollx((i + scrolly) & 0xff, m_rasterram[i]); m_bg1_tilemap->set_scrolly(0, scrolly); screen.priority().fill(0, cliprect); m_bg1_tilemap->draw(screen, bitmap, cliprect, 0, 0); m_spr_old->turbofrc_draw_sprites(m_spriteram3,m_spriteram3.bytes(),m_spritepalettebank, machine(), bitmap, cliprect, screen.priority(), 0); m_spr_old->turbofrc_draw_sprites(m_spriteram3,m_spriteram3.bytes(),m_spritepalettebank, machine(), bitmap, cliprect, screen.priority(), 1); return 0; } UINT32 aerofgt_state::screen_update_karatblz(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg1_tilemap->set_scrollx(0, m_bg1scrollx - 8); m_bg1_tilemap->set_scrolly(0, m_bg1scrolly); m_bg2_tilemap->set_scrollx(0, m_bg2scrollx - 4); m_bg2_tilemap->set_scrolly(0, m_bg2scrolly); screen.priority().fill(0, cliprect);
/* * Function: native_restorecon * Purpose: restore default SELinux security context * Parameters: pathname: the pathname for the file to be relabeled * Returns: boolean: (true) file label successfully restored, (false) otherwise * Exceptions: none */ static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) { if (isSELinuxDisabled) { return true; } ScopedUtfChars pathname(env, pathnameStr); if (pathname.c_str() == NULL) { ALOGV("restorecon(%p) => threw exception", pathnameStr); return false; } int ret = selinux_android_restorecon(pathname.c_str()); ALOGV("restorecon(%s) => %d", pathname.c_str(), ret); return (ret == 0); }
void restorecon_main(void) { #if defined(__ANDROID__) char **s; int flags = 0; if (toys.optflags & FLAG_D) flags |= SELINUX_ANDROID_RESTORECON_DATADATA; if (toys.optflags & FLAG_F) flags |= SELINUX_ANDROID_RESTORECON_FORCE; if (toys.optflags & (FLAG_R|FLAG_r)) flags |= SELINUX_ANDROID_RESTORECON_RECURSE; if (toys.optflags & FLAG_n) flags |= SELINUX_ANDROID_RESTORECON_NOCHANGE; if (toys.optflags & FLAG_v) flags |= SELINUX_ANDROID_RESTORECON_VERBOSE; for (s = toys.optargs; *s; s++) if (selinux_android_restorecon(*s, flags) < 0) perror_msg("restorecon failed: %s", *s); #endif }
int restorecon_main(int argc, char **argv) { int ch, i, rc; unsigned int flags = 0; progname = argv[0]; do { ch = getopt(argc, argv, "FnrRv"); if (ch == EOF) break; switch (ch) { case 'F': flags |= SELINUX_ANDROID_RESTORECON_FORCE; break; case 'n': flags |= SELINUX_ANDROID_RESTORECON_NOCHANGE; break; case 'r': case 'R': flags |= SELINUX_ANDROID_RESTORECON_RECURSE; break; case 'v': flags |= SELINUX_ANDROID_RESTORECON_VERBOSE; break; default: usage(); } } while (1); argc -= optind; argv += optind; if (!argc) usage(); for (i = 0; i < argc; i++) { rc = selinux_android_restorecon(argv[i], flags); if (rc < 0) fprintf(stderr, "Could not restorecon %s: %s\n", argv[i], strerror(errno)); } return 0; }
int restorecon(const char* pathname) { return selinux_android_restorecon(pathname, 0); }
int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) { char asecFileName[255]; char loopDevice[255]; char mountPoint[255]; if (gid < AID_APP) { SLOGE("Group ID is not in application range"); return -1; } if (!isLegalAsecId(id)) { SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id); errno = EINVAL; return -1; } if (findAsec(id, asecFileName, sizeof(asecFileName))) { SLOGE("Couldn't find ASEC %s", id); return -1; } char idHash[33]; if (!asecHash(id, idHash, sizeof(idHash))) { SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); return -1; } if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno)); return -1; } unsigned int nr_sec = 0; struct asec_superblock sb; if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { return -1; } int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id); return -1; } int result = 0; if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) { return 0; } int ret = Ext4::doMount(loopDevice, mountPoint, false /* read-only */, true /* remount */, false /* executable */, false /* sdcard */); if (ret) { SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno)); return -1; } char *paths[] = { mountPoint, NULL }; FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL); if (fts) { // Traverse the entire hierarchy and chown to system UID. for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) { // We don't care about the lost+found directory. if (!strcmp(ftsent->fts_name, "lost+found")) { continue; } /* * There can only be one file marked as private right now. * This should be more robust, but it satisfies the requirements * we have for right now. */ const bool privateFile = !strcmp(ftsent->fts_name, filename); int fd = open(ftsent->fts_accpath, O_NOFOLLOW); if (fd < 0) { SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno)); result = -1; continue; } result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM); if (ftsent->fts_info & FTS_D) { result |= fchmod(fd, 0755); } else if (ftsent->fts_info & FTS_F) { result |= fchmod(fd, privateFile ? 0640 : 0644); } if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) { SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno)); result |= -1; } close(fd); } fts_close(fts); // Finally make the directory readable by everyone. int dirfd = open(mountPoint, O_DIRECTORY); if (dirfd < 0 || fchmod(dirfd, 0755)) { SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno)); result |= -1; } close(dirfd); } else { result |= -1; } result |= Ext4::doMount(loopDevice, mountPoint, true /* read-only */, true /* remount */, true /* execute */, false /* sdcard */); if (result) { SLOGE("ASEC fix permissions failed (%s)", strerror(errno)); return -1; } if (mDebug) { SLOGD("ASEC %s permissions fixed", id); } return 0; }
static int handle_send_file(int s, char *path, uid_t uid, gid_t gid, mode_t mode, char *buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; int fd; fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if(fd < 0 && errno == ENOENT) { if(mkdirs(path) != 0) { if(fail_errno(s)) return -1; fd = -1; } else { fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } } if(fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if(fd < 0) { if(fail_errno(s)) return -1; fd = -1; } else { if(fchown(fd, uid, gid) != 0) { fail_errno(s); errno = 0; } /* * fchown clears the setuid bit - restore it if present. * Ignore the result of calling fchmod. It's not supported * by all filesystems. b/12441485 */ fchmod(fd, mode); } for(;;) { unsigned int len; if(readx(s, &msg.data, sizeof(msg.data))) goto fail; if(msg.data.id != ID_DATA) { if(msg.data.id == ID_DONE) { timestamp = ltohl(msg.data.size); break; } fail_message(s, "invalid data message"); goto fail; } len = ltohl(msg.data.size); if(syc_size_enabled == 1) { if(len > SYNC_DATA_MAX) { fail_message(s, "oversize data message"); goto fail; } else { unsigned int total = 0; while (total < len) { int count = len - total; if (count > SYNC_DATA_MAX_CUSTOMIZE) { count = SYNC_DATA_MAX_CUSTOMIZE; } if(readx(s, buffer, count)) goto fail; if(fd < 0) continue; if(writex(fd, buffer, count)) { int saved_errno = errno; adb_close(fd); if (do_unlink) adb_unlink(path); fd = -1; errno = saved_errno; if(fail_errno(s)) return -1; } total += count; } } }else { if(len > SYNC_DATA_MAX) { fail_message(s, "oversize data message"); goto fail; } if(readx(s, buffer, len)) goto fail; if(fd < 0) continue; if(writex(fd, buffer, len)) { int saved_errno = errno; adb_close(fd); if (do_unlink) adb_unlink(path); fd = -1; errno = saved_errno; if(fail_errno(s)) return -1; } } } if(fd >= 0) { struct utimbuf u; adb_close(fd); selinux_android_restorecon(path, 0); u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; if(writex(s, &msg.status, sizeof(msg.status))) return -1; } return 0; fail: if(fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return -1; }
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */ const char *dump_traces() { const char* result = NULL; char traces_path[PROPERTY_VALUE_MAX] = ""; property_get("dalvik.vm.stack-trace-file", traces_path, ""); if (!traces_path[0]) return NULL; /* move the old traces.txt (if any) out of the way temporarily */ char anr_traces_path[PATH_MAX]; strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path)); strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path)); if (rename(traces_path, anr_traces_path) && errno != ENOENT) { fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno)); return NULL; // Can't rename old traces.txt -- no permission? -- leave it alone instead } /* make the directory if necessary */ char anr_traces_dir[PATH_MAX]; strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir)); char *slash = strrchr(anr_traces_dir, '/'); if (slash != NULL) { *slash = '\0'; if (!mkdir(anr_traces_dir, 0775)) { chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM); chmod(anr_traces_dir, 0775); if (selinux_android_restorecon(anr_traces_dir, 0) == -1) { fprintf(stderr, "restorecon failed for %s: %s\n", anr_traces_dir, strerror(errno)); } } else if (errno != EEXIST) { fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno)); return NULL; } } /* create a new, empty traces.txt file to receive stack dumps */ int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0666)); /* -rw-rw-rw- */ if (fd < 0) { fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); return NULL; } int chmod_ret = fchmod(fd, 0666); if (chmod_ret < 0) { fprintf(stderr, "fchmod on %s failed: %s\n", traces_path, strerror(errno)); close(fd); return NULL; } /* walk /proc and kill -QUIT all Dalvik processes */ DIR *proc = opendir("/proc"); if (proc == NULL) { fprintf(stderr, "/proc: %s\n", strerror(errno)); goto error_close_fd; } /* use inotify to find when processes are done dumping */ int ifd = inotify_init(); if (ifd < 0) { fprintf(stderr, "inotify_init: %s\n", strerror(errno)); goto error_close_fd; } int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE); if (wfd < 0) { fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno)); goto error_close_ifd; } struct dirent *d; int dalvik_found = 0; while ((d = readdir(proc))) { int pid = atoi(d->d_name); if (pid <= 0) continue; char path[PATH_MAX]; char data[PATH_MAX]; snprintf(path, sizeof(path), "/proc/%d/exe", pid); ssize_t len = readlink(path, data, sizeof(data) - 1); if (len <= 0) { continue; } data[len] = '\0'; if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { /* skip zygote -- it won't dump its stack anyway */ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)); len = read(cfd, data, sizeof(data) - 1); close(cfd); if (len <= 0) { continue; } data[len] = '\0'; if (!strncmp(data, "zygote", strlen("zygote"))) { continue; } ++dalvik_found; uint64_t start = nanotime(); if (kill(pid, SIGQUIT)) { fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); continue; } /* wait for the writable-close notification from inotify */ struct pollfd pfd = { ifd, POLLIN, 0 }; int ret = poll(&pfd, 1, 5000); /* 5 sec timeout */ if (ret < 0) { fprintf(stderr, "poll: %s\n", strerror(errno)); } else if (ret == 0) { fprintf(stderr, "warning: timed out dumping pid %d\n", pid); } else { struct inotify_event ie; read(ifd, &ie, sizeof(ie)); } if (lseek(fd, 0, SEEK_END) < 0) { fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n", pid, (float)(nanotime() - start) / NANOS_PER_SEC); } } else if (should_dump_native_traces(data)) { /* dump native process if appropriate */ if (lseek(fd, 0, SEEK_END) < 0) { fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { static uint16_t timeout_failures = 0; uint64_t start = nanotime(); /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ if (timeout_failures == 3) { dprintf(fd, "too many stack dump failures, skipping...\n"); } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) { dprintf(fd, "dumping failed, likely due to a timeout\n"); timeout_failures++; } else { timeout_failures = 0; } dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n", pid, (float)(nanotime() - start) / NANOS_PER_SEC); } } } if (dalvik_found == 0) { fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n"); } static char dump_traces_path[PATH_MAX]; strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path)); strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path)); if (rename(traces_path, dump_traces_path)) { fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno)); goto error_close_ifd; } result = dump_traces_path; /* replace the saved [ANR] traces.txt file */ rename(anr_traces_path, traces_path); error_close_ifd: close(ifd); error_close_fd: close(fd); return result; }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint64_t capabilities, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path); int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(adb_dirname(path))) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems, so we don't check for success. b/12441485 fchmod(fd, mode); if (!update_capabilities(path, capabilities)) { SendSyncFailErrno(s, "update_capabilities failed"); goto fail; } } while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto abort; } if (msg.data.size > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: // If there's a problem on the device, we'll send an ID_FAIL message and // close the socket. Unfortunately the kernel will sometimes throw that // data away if the other end keeps writing without reading (which is // the case with old versions of adb). To maintain compatibility, keep // reading and throwing away ID_DATA packets until the other side notices // that we've reported an error. while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id == ID_DONE) { goto abort; } else if (msg.data.id != ID_DATA) { char id[5]; memcpy(id, &msg.data.id, sizeof(msg.data.id)); id[4] = '\0'; D("handle_send_fail received unexpected id '%s' during failure", id); goto abort; } if (msg.data.size > buffer.size()) { D("handle_send_fail received oversized packet of length '%u' during failure", msg.data.size); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; } abort: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(path)) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems. b/12441485 fchmod(fd, mode); } while (true) { unsigned int len; if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto fail; } len = msg.data.size; if (len > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto fail; } if (!ReadFdExactly(s, &buffer[0], len)) goto fail; if (!WriteFdExactly(fd, &buffer[0], len)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
int restorecon_recursive(const char* pathname) { return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE); }
void BufferQueueDump::dump(String8& result, const char* prefix) { // dump status to log buffer first const char* bufName = (TRACK_PRODUCER == mMode) ? "Dequeued" : "Acquired"; result.appendFormat("%s*BufferQueueDump mIsBackupBufInited=%d, m%sBufs(size=%d), mMode=%s\n", prefix, mIsBackupBufInited, bufName, mObtainedBufs.size(), (TRACK_PRODUCER == mMode) ? "TRACK_PRODUCER" : "TRACK_CONSUMER"); if ((mLastObtainedBuf != NULL) && (mLastObtainedBuf->mGraphicBuffer != NULL)) { result.appendFormat("%s [-1] mLast%sBuf->mGraphicBuffer->handle=%p\n", prefix, bufName, mLastObtainedBuf->mGraphicBuffer->handle); } for (size_t i = 0; i < mObtainedBufs.size(); i++) { const sp<DumpBuffer>& buffer = mObtainedBufs[i]; result.appendFormat("%s [%02u] handle=%p, fence=%p, time=%#llx\n", prefix, i, buffer->mGraphicBuffer->handle, buffer->mFence.get(), buffer->mTimeStamp); } // start buffer dump check and process char value[PROPERTY_VALUE_MAX]; property_get(PROP_DUMP_NAME, value, DEFAULT_DUMP_NAME); if (strcmp(value, DEFAULT_DUMP_NAME) == 0 || strlen(value) == 0) { // debug feature (bqdump) is not enabled return; } // For aee manual dump, we must create a directory to save files. // The step should not be completed by a script. struct stat sb; if (stat(DUMP_FILE_PATH, &sb) != 0) { // ths permission of /data/SF_dump must be 777, // or some processes cannot save files to /data/SF_dump mode_t mode = umask(0); if (mkdir(DUMP_FILE_PATH, 0777) != 0) { BQD_LOGE("mkdir(%s) failed", DUMP_FILE_PATH); } umask(mode); if (selinux_android_restorecon(DUMP_FILE_PATH, 0) == -1) { BQD_LOGE("restorecon failed(%s) failed", DUMP_FILE_PATH); } else { BQD_LOGD("restorecon(%s)", DUMP_FILE_PATH); } } if (access(DUMP_FILE_PATH, R_OK | W_OK | X_OK) != 0) { BQD_LOGE("The permission of %s cannot be access by this process", DUMP_FILE_PATH); } uint32_t backupCnt = 0; bool isMatched = parseDumpConfig(value, &backupCnt); // if value contains '#', it means setting continues dump // otherwise, dump buffers if (strchr(value, '#') != NULL) { if (isMatched) { setBackupCount(backupCnt); } } else { if (isMatched) { if (mBackupBuf.getSize() > 0) { mBackupBuf.dump(result, prefix); } dumpObtainedBufs(); } } }
int restorecon(const char* pathname, int flags) { return selinux_android_restorecon(pathname, flags); }