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;
}
示例#2
0
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;
}
示例#3
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
  }
示例#6
0
	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
}
示例#9
0
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;
}
示例#10
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;
}
示例#12
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;
}
示例#15
0
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;
}
示例#16
0
int restorecon_recursive(const char* pathname)
{
    return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE);
}
示例#17
0
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();
        }
    }
}
示例#18
0
int restorecon(const char* pathname, int flags)
{
    return selinux_android_restorecon(pathname, flags);
}