static bool secure_mkdirs(const std::string& path) { uid_t uid = -1; gid_t gid = -1; unsigned int mode = 0775; uint64_t capabilities = 0; if (path[0] != '/') return false; std::vector<std::string> path_components = android::base::Split(path, "/"); 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, &capabilities); } 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); if (!update_capabilities(partial_path.c_str(), capabilities)) return false; } } return true; }
static void name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data) { NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data); NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); char *owner; g_return_if_fail (proxy == priv->proxy); owner = g_dbus_proxy_get_name_owner (proxy); nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant %s", owner ? "running" : "stopped"); if (owner) { set_running (self, TRUE); update_capabilities (self); } else if (priv->running) { /* Reschedule the die count reset timeout. Every time the supplicant * dies we wait 10 seconds before resetting the counter. If the * supplicant died more than twice before the timer is reset, then * we don't try to talk to the supplicant for a while. */ if (priv->die_count_reset_id) g_source_remove (priv->die_count_reset_id); priv->die_count_reset_id = g_timeout_add_seconds (10, wpas_die_count_reset_cb, self); set_die_count (self, priv->die_count + 1); if (die_count_exceeded (priv->die_count)) { nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant die count %d; ignoring for 10 seconds", priv->die_count); } set_running (self, FALSE); priv->fast_supported = FALSE; } g_free (owner); }
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; }