Modifying Transport State Management
To enforce security, a global authentication flag must be introduced to track the session status. This flag ensures that any change in the transport state (connection or disconnection) invalidates the current session, requiring the user to re-authenticate.
In system/core/adb/adb.cpp, add a global variable and reset it within the transport handlers.
// system/core/adb/adb.cpp
#if !ADB_HOST
// Global flag to track if the current client is authorized
bool g_is_session_valid = false;
#endif
void handle_online(atransport* t) {
D("adb: online");
t->online = 1;
t->SetConnectionEstablished(true);
#if !ADB_HOST
// Reset authentication state when the device comes online
g_is_session_valid = false;
#endif
}
void handle_offline(atransport* t) {
D("adb: offline");
const atransport* hangup_transport = t;
// ... existing logic ...
t->online = 0;
#if !ADB_HOST
// Invalidate session when transport goes offline
g_is_session_valid = false;
#endif
// ... existing logic ...
close_all_sockets(t);
}Implementing Credential Verification
The service layer must intercept incoming shell requests to verify credentials. If the session is not marked as valid, the system checks for a password in the command string. This password is compared against a system property, defaulting to "admin" if the property is not set.
In system/core/adb/services.cpp, implement the verification logic within the service dispatcher.
// system/core/adb/services.cpp
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#if !ADB_HOST
extern bool g_is_session_valid;
static void RespondWithStatus(unique_fd fd, bool success) {
const char* status = success ? "Login Success\n" : "Login Failed\n";
WriteFdExactly(fd, status);
}
#endif
unique_fd service_to_fd(std::string_view name, atransport* transport) {
unique_fd fd_result;
#if !ADB_HOST
if (!g_is_session_valid) {
// Look for the 'raw' prefix in the service name to identify auth attempts
const char* cmd_ptr = name.data();
const char* raw_keyword = strstr(cmd_ptr, "raw");
if (raw_keyword != nullptr) {
// Retrieve the stored password from system properties
std::string stored_secret = android::base::GetProperty("persist.otg.passwd", "admin");
std::string_view input_secret(raw_keyword + 4); // Pointer arithmetic to skip 'raw'
if (input_secret == stored_secret) {
g_is_session_valid = true;
fd_result = create_service_thread("auth_success", [](unique_fd fd) {
RespondWithStatus(std::move(fd), true);
});
} else {
// Ensure auth remains false
g_is_session_valid = false;
fd_result = create_service_thread("auth_fail", [](unique_fd fd) {
RespondWithStatus(std::move(fd), false);
});
}
if (fd_result >= 0) {
close_on_exec(fd_result);
}
return fd_result;
}
// If not authenticated and not an auth attempt, block access
return fd_result;
}
#endif
// ... existing socket and service logic follows ...
}