implement Milestone 20: Kernel Integration with LuaSandboxManager (149 tests)
This commit is contained in:
310
src/main/cpp/sandbox/sandbox_manager.cpp
Normal file
310
src/main/cpp/sandbox/sandbox_manager.cpp
Normal file
@@ -0,0 +1,310 @@
|
||||
// sandbox_manager.cpp - Multi-app sandbox orchestrator implementation
|
||||
// Milestone 20: Kernel Integration
|
||||
|
||||
#include "sandbox_manager.h"
|
||||
#include <lua.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
namespace mosis {
|
||||
|
||||
LuaSandboxManager::LuaSandboxManager(const std::string& data_root)
|
||||
: m_data_root(data_root)
|
||||
, m_audit_log()
|
||||
, m_rate_limiter()
|
||||
, m_message_bus()
|
||||
, m_timer_manager()
|
||||
{
|
||||
// Set reasonable default limits
|
||||
m_default_limits.memory_bytes = 50 * 1024 * 1024; // 50MB per app
|
||||
m_default_limits.instructions_per_call = 1000000; // 1M instructions
|
||||
m_default_limits.stack_depth = 200; // 200 recursion depth
|
||||
m_default_limits.max_string_size = 10 * 1024 * 1024; // 10MB strings
|
||||
}
|
||||
|
||||
LuaSandboxManager::~LuaSandboxManager() {
|
||||
// Stop all running apps
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
for (auto& [app_id, app] : m_apps) {
|
||||
if (app && app->is_running) {
|
||||
CleanupApp(*app);
|
||||
}
|
||||
}
|
||||
m_apps.clear();
|
||||
}
|
||||
|
||||
bool LuaSandboxManager::StartApp(const std::string& app_id,
|
||||
const std::string& app_path,
|
||||
const std::vector<std::string>& permissions,
|
||||
bool is_system_app) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Check if already running
|
||||
if (m_apps.count(app_id) && m_apps[app_id]->is_running) {
|
||||
return false; // Already running
|
||||
}
|
||||
|
||||
// Create sandbox context
|
||||
SandboxContext ctx;
|
||||
ctx.app_id = app_id;
|
||||
ctx.app_path = app_path;
|
||||
ctx.permissions = permissions;
|
||||
ctx.is_system_app = is_system_app;
|
||||
|
||||
// Create app sandbox
|
||||
auto app = CreateAppSandbox(ctx);
|
||||
if (!app) {
|
||||
m_audit_log.Log(AuditEvent::AppStart, app_id,
|
||||
"FAILED", "Failed to create sandbox");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register all APIs
|
||||
RegisterAPIs(*app);
|
||||
|
||||
// Mark as running
|
||||
app->is_running = true;
|
||||
|
||||
// Store in map
|
||||
m_apps[app_id] = std::move(app);
|
||||
|
||||
// Log successful start
|
||||
m_audit_log.Log(AuditEvent::AppStart, app_id, "SUCCESS", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaSandboxManager::StopApp(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it == m_apps.end() || !it->second->is_running) {
|
||||
return false; // Not running
|
||||
}
|
||||
|
||||
// Clean up resources
|
||||
CleanupApp(*it->second);
|
||||
|
||||
// Mark as stopped
|
||||
it->second->is_running = false;
|
||||
|
||||
// Log stop
|
||||
m_audit_log.Log(AuditEvent::AppStop, app_id, "SUCCESS", "");
|
||||
|
||||
// Remove from map
|
||||
m_apps.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaSandboxManager::IsAppRunning(const std::string& app_id) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto it = m_apps.find(app_id);
|
||||
return it != m_apps.end() && it->second->is_running;
|
||||
}
|
||||
|
||||
AppSandbox* LuaSandboxManager::GetApp(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it != m_apps.end() && it->second->is_running) {
|
||||
return it->second.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AppSandbox* LuaSandboxManager::GetApp(const std::string& app_id) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it != m_apps.end() && it->second->is_running) {
|
||||
return it->second.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool LuaSandboxManager::ExecuteCode(const std::string& app_id,
|
||||
const std::string& code,
|
||||
const std::string& source_name) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it == m_apps.end() || !it->second->is_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second->lua->LoadString(code, source_name);
|
||||
}
|
||||
|
||||
bool LuaSandboxManager::LoadFile(const std::string& app_id,
|
||||
const std::string& path) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it == m_apps.end() || !it->second->is_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second->lua->LoadFile(path);
|
||||
}
|
||||
|
||||
void LuaSandboxManager::RecordUserGesture(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto it = m_apps.find(app_id);
|
||||
if (it != m_apps.end() && it->second->is_running) {
|
||||
it->second->permissions->RecordUserGesture();
|
||||
}
|
||||
}
|
||||
|
||||
void LuaSandboxManager::UpdateTimers() {
|
||||
// Fire all ready timers
|
||||
m_timer_manager.ProcessTimers();
|
||||
}
|
||||
|
||||
std::vector<std::string> LuaSandboxManager::GetRunningApps() const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::vector<std::string> result;
|
||||
for (const auto& [app_id, app] : m_apps) {
|
||||
if (app && app->is_running) {
|
||||
result.push_back(app_id);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t LuaSandboxManager::GetRunningAppCount() const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
size_t count = 0;
|
||||
for (const auto& [app_id, app] : m_apps) {
|
||||
if (app && app->is_running) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::unique_ptr<AppSandbox> LuaSandboxManager::CreateAppSandbox(
|
||||
const SandboxContext& ctx) {
|
||||
auto app = std::make_unique<AppSandbox>();
|
||||
app->context = ctx;
|
||||
|
||||
// Create core sandbox
|
||||
app->lua = std::make_unique<LuaSandbox>(ctx, m_default_limits);
|
||||
|
||||
// Create permission gate
|
||||
app->permissions = std::make_unique<PermissionGate>(ctx);
|
||||
for (const auto& perm : ctx.permissions) {
|
||||
if (!ctx.is_system_app) {
|
||||
// Normal apps need explicit grants for dangerous permissions
|
||||
auto cat = app->permissions->GetCategory(perm);
|
||||
if (cat == PermissionCategory::Normal) {
|
||||
app->permissions->GrantPermission(perm);
|
||||
}
|
||||
} else {
|
||||
// System apps get all declared permissions
|
||||
app->permissions->GrantPermission(perm);
|
||||
}
|
||||
}
|
||||
|
||||
// Create storage path
|
||||
std::string app_data_path = m_data_root + "/apps/" + ctx.app_id;
|
||||
std::filesystem::create_directories(app_data_path + "/data");
|
||||
std::filesystem::create_directories(app_data_path + "/cache");
|
||||
std::filesystem::create_directories(app_data_path + "/db");
|
||||
|
||||
// Create virtual filesystem
|
||||
app->filesystem = std::make_unique<VirtualFS>(ctx.app_id, app_data_path);
|
||||
|
||||
// Create database manager
|
||||
app->database = std::make_unique<DatabaseManager>(ctx.app_id, app_data_path + "/db");
|
||||
|
||||
// Create network components
|
||||
app->network = std::make_unique<NetworkManager>(ctx.app_id);
|
||||
app->websocket = std::make_unique<WebSocketManager>(ctx.app_id);
|
||||
|
||||
// Create hardware interfaces
|
||||
app->camera = std::make_unique<CameraInterface>(ctx.app_id, app->permissions.get());
|
||||
app->microphone = std::make_unique<MicrophoneInterface>(ctx.app_id, app->permissions.get());
|
||||
app->audio = std::make_unique<AudioOutputInterface>(ctx.app_id);
|
||||
app->location = std::make_unique<LocationInterface>(ctx.app_id);
|
||||
app->sensors = std::make_unique<SensorInterface>(ctx.app_id);
|
||||
app->bluetooth = std::make_unique<BluetoothInterface>(ctx.app_id);
|
||||
app->contacts = std::make_unique<ContactsInterface>(ctx.app_id);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void LuaSandboxManager::RegisterAPIs(AppSandbox& app) {
|
||||
lua_State* L = app.lua->GetState();
|
||||
if (!L) return;
|
||||
|
||||
// Register JSON API
|
||||
RegisterJsonAPI(L);
|
||||
|
||||
// Register crypto API
|
||||
RegisterCryptoAPI(L);
|
||||
|
||||
// Register timer APIs with the shared timer manager
|
||||
// Note: Individual API registration would be done here if we
|
||||
// were exposing these to Lua. For now, the timer manager
|
||||
// provides the backend and apps use it via registered functions.
|
||||
|
||||
// Store app context in registry for API callbacks
|
||||
lua_pushlightuserdata(L, &app);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__app_sandbox");
|
||||
|
||||
// Store manager reference for cross-app operations
|
||||
lua_pushlightuserdata(L, this);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__sandbox_manager");
|
||||
}
|
||||
|
||||
void LuaSandboxManager::CleanupApp(AppSandbox& app) {
|
||||
// Clear timers for this app
|
||||
m_timer_manager.ClearAppTimers(app.context.app_id);
|
||||
|
||||
// Close WebSocket connections
|
||||
if (app.websocket) {
|
||||
app.websocket->CloseAll();
|
||||
}
|
||||
|
||||
// Stop camera/microphone sessions
|
||||
if (app.camera) {
|
||||
app.camera->Shutdown();
|
||||
}
|
||||
if (app.microphone) {
|
||||
app.microphone->Shutdown();
|
||||
}
|
||||
|
||||
// Stop audio
|
||||
if (app.audio) {
|
||||
app.audio->Shutdown();
|
||||
}
|
||||
|
||||
// Stop location watching
|
||||
if (app.location) {
|
||||
app.location->Shutdown();
|
||||
}
|
||||
|
||||
// Stop sensors
|
||||
if (app.sensors) {
|
||||
app.sensors->Shutdown();
|
||||
}
|
||||
|
||||
// Stop bluetooth
|
||||
if (app.bluetooth) {
|
||||
app.bluetooth->Shutdown();
|
||||
}
|
||||
|
||||
// Clean up temp files in filesystem
|
||||
if (app.filesystem) {
|
||||
app.filesystem->ClearTemp();
|
||||
}
|
||||
|
||||
// Close database connections
|
||||
if (app.database) {
|
||||
app.database->CloseAll();
|
||||
}
|
||||
|
||||
// Unregister from message bus
|
||||
m_message_bus.UnregisterApp(app.context.app_id);
|
||||
}
|
||||
|
||||
} // namespace mosis
|
||||
127
src/main/cpp/sandbox/sandbox_manager.h
Normal file
127
src/main/cpp/sandbox/sandbox_manager.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// sandbox_manager.h - Multi-app sandbox orchestrator
|
||||
// Milestone 20: Kernel Integration
|
||||
#pragma once
|
||||
|
||||
#include "lua_sandbox.h"
|
||||
#include "permission_gate.h"
|
||||
#include "audit_log.h"
|
||||
#include "rate_limiter.h"
|
||||
#include "timer_manager.h"
|
||||
#include "virtual_fs.h"
|
||||
#include "database_manager.h"
|
||||
#include "network_manager.h"
|
||||
#include "websocket_manager.h"
|
||||
#include "camera_interface.h"
|
||||
#include "microphone_interface.h"
|
||||
#include "audio_output.h"
|
||||
#include "location_interface.h"
|
||||
#include "sensor_interface.h"
|
||||
#include "bluetooth_interface.h"
|
||||
#include "contacts_interface.h"
|
||||
#include "message_bus.h"
|
||||
#include "json_api.h"
|
||||
#include "crypto_api.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
|
||||
namespace mosis {
|
||||
|
||||
// Per-app sandbox instance with all components
|
||||
struct AppSandbox {
|
||||
std::unique_ptr<LuaSandbox> lua;
|
||||
std::unique_ptr<PermissionGate> permissions;
|
||||
std::unique_ptr<VirtualFS> filesystem;
|
||||
std::unique_ptr<DatabaseManager> database;
|
||||
std::unique_ptr<NetworkManager> network;
|
||||
std::unique_ptr<WebSocketManager> websocket;
|
||||
std::unique_ptr<CameraInterface> camera;
|
||||
std::unique_ptr<MicrophoneInterface> microphone;
|
||||
std::unique_ptr<AudioOutputInterface> audio;
|
||||
std::unique_ptr<LocationInterface> location;
|
||||
std::unique_ptr<SensorInterface> sensors;
|
||||
std::unique_ptr<BluetoothInterface> bluetooth;
|
||||
std::unique_ptr<ContactsInterface> contacts;
|
||||
SandboxContext context;
|
||||
bool is_running = false;
|
||||
};
|
||||
|
||||
// Callback for recording user gestures (from UI events)
|
||||
using UserGestureCallback = std::function<void(const std::string& app_id)>;
|
||||
|
||||
class LuaSandboxManager {
|
||||
public:
|
||||
explicit LuaSandboxManager(const std::string& data_root = ".");
|
||||
~LuaSandboxManager();
|
||||
|
||||
// Prevent copying
|
||||
LuaSandboxManager(const LuaSandboxManager&) = delete;
|
||||
LuaSandboxManager& operator=(const LuaSandboxManager&) = delete;
|
||||
|
||||
// App lifecycle
|
||||
bool StartApp(const std::string& app_id, const std::string& app_path,
|
||||
const std::vector<std::string>& permissions,
|
||||
bool is_system_app = false);
|
||||
bool StopApp(const std::string& app_id);
|
||||
bool IsAppRunning(const std::string& app_id) const;
|
||||
|
||||
// Get app sandbox for direct access
|
||||
AppSandbox* GetApp(const std::string& app_id);
|
||||
const AppSandbox* GetApp(const std::string& app_id) const;
|
||||
|
||||
// Execute Lua code in app context
|
||||
bool ExecuteCode(const std::string& app_id, const std::string& code,
|
||||
const std::string& source_name = "script");
|
||||
bool LoadFile(const std::string& app_id, const std::string& path);
|
||||
|
||||
// User gesture tracking (for permission-sensitive operations)
|
||||
void RecordUserGesture(const std::string& app_id);
|
||||
|
||||
// Timer management - called from main loop
|
||||
void UpdateTimers();
|
||||
|
||||
// Get all running app IDs
|
||||
std::vector<std::string> GetRunningApps() const;
|
||||
|
||||
// Shared components
|
||||
AuditLog& GetAuditLog() { return m_audit_log; }
|
||||
RateLimiter& GetRateLimiter() { return m_rate_limiter; }
|
||||
MessageBus& GetMessageBus() { return m_message_bus; }
|
||||
TimerManager& GetTimerManager() { return m_timer_manager; }
|
||||
|
||||
// Configuration
|
||||
void SetDefaultLimits(const SandboxLimits& limits) { m_default_limits = limits; }
|
||||
const SandboxLimits& GetDefaultLimits() const { return m_default_limits; }
|
||||
|
||||
// Stats
|
||||
size_t GetRunningAppCount() const;
|
||||
|
||||
private:
|
||||
// Create and configure a new app sandbox
|
||||
std::unique_ptr<AppSandbox> CreateAppSandbox(const SandboxContext& ctx);
|
||||
|
||||
// Register all Lua APIs with sandbox
|
||||
void RegisterAPIs(AppSandbox& app);
|
||||
|
||||
// Clean up app resources
|
||||
void CleanupApp(AppSandbox& app);
|
||||
|
||||
// Data storage
|
||||
std::string m_data_root;
|
||||
mutable std::mutex m_mutex;
|
||||
std::unordered_map<std::string, std::unique_ptr<AppSandbox>> m_apps;
|
||||
|
||||
// Shared components across all apps
|
||||
AuditLog m_audit_log;
|
||||
RateLimiter m_rate_limiter;
|
||||
MessageBus m_message_bus;
|
||||
TimerManager m_timer_manager;
|
||||
|
||||
// Default limits for new sandboxes
|
||||
SandboxLimits m_default_limits;
|
||||
};
|
||||
|
||||
} // namespace mosis
|
||||
Reference in New Issue
Block a user