fix(userspace): clip display rects, bounds-check session app ids and fat16 handles, reject bad fat16 geometry, session kills via process cap
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use server_framework::Server;
|
||||
use types::bounded::CapSlot;
|
||||
use types::id::ProcessId;
|
||||
|
||||
use crate::protocol::{AppId, SessionRequest, SessionResponse};
|
||||
|
||||
@@ -15,8 +14,8 @@ pub struct AppEntry {
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct RunningApp {
|
||||
app: AppId,
|
||||
pid: ProcessId,
|
||||
/// The capability `Kill` is invoked on.
|
||||
process: CapSlot,
|
||||
}
|
||||
|
||||
pub struct SessionServer {
|
||||
@@ -24,11 +23,12 @@ pub struct SessionServer {
|
||||
app_count: usize,
|
||||
running: [Option<RunningApp>; MAX_APPS],
|
||||
active: Option<AppId>,
|
||||
create_cap: CapSlot,
|
||||
/// Lets the server create processes; without one, Launch fails.
|
||||
create_cap: Option<CapSlot>,
|
||||
}
|
||||
|
||||
impl SessionServer {
|
||||
pub fn new(create_cap: CapSlot) -> Self {
|
||||
pub fn new(create_cap: Option<CapSlot>) -> Self {
|
||||
Self {
|
||||
apps: [const { None }; MAX_APPS],
|
||||
app_count: 0,
|
||||
@@ -38,11 +38,17 @@ impl SessionServer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_app(&mut self, name: &'static str, path: &'static str) -> AppId {
|
||||
/// Adds an app to the menu; `None` once the table is full.
|
||||
pub fn register_app(&mut self, name: &'static str, path: &'static str) -> Option<AppId> {
|
||||
let slot = self.apps.get_mut(self.app_count)?;
|
||||
*slot = Some(AppEntry {
|
||||
name,
|
||||
path,
|
||||
registered: true,
|
||||
});
|
||||
let id = AppId::new(self.app_count as u16);
|
||||
self.apps[self.app_count] = Some(AppEntry { name, path, registered: true });
|
||||
self.app_count += 1;
|
||||
id
|
||||
Some(id)
|
||||
}
|
||||
|
||||
pub fn app_count(&self) -> usize {
|
||||
@@ -53,8 +59,10 @@ impl SessionServer {
|
||||
self.active
|
||||
}
|
||||
|
||||
fn is_running(&self, app: AppId) -> bool {
|
||||
self.running[app.raw() as usize].is_some()
|
||||
/// The running-table entry for `app`; `None` for ids past the table,
|
||||
/// which come straight from clients.
|
||||
fn running_mut(&mut self, app: AppId) -> Option<&mut Option<RunningApp>> {
|
||||
self.running.get_mut(app.raw() as usize)
|
||||
}
|
||||
|
||||
fn launch_app(&mut self, app: AppId) -> SessionResponse {
|
||||
@@ -63,31 +71,27 @@ impl SessionServer {
|
||||
return SessionResponse::NotFound;
|
||||
}
|
||||
|
||||
if self.is_running(app) {
|
||||
if self.apps.get(idx).is_none_or(Option::is_none) {
|
||||
return SessionResponse::NotFound;
|
||||
}
|
||||
if self.running_mut(app).is_none_or(|r| r.is_some()) {
|
||||
return SessionResponse::Error;
|
||||
}
|
||||
|
||||
let _app_entry = match &self.apps[idx] {
|
||||
Some(entry) => entry,
|
||||
None => return SessionResponse::NotFound,
|
||||
let Some(process) = self.create_cap.and_then(libkos::syscall::create_process) else {
|
||||
return SessionResponse::Error;
|
||||
};
|
||||
|
||||
let process_cap = match libkos::syscall::create_process(self.create_cap) {
|
||||
Some(cap) => cap,
|
||||
None => return SessionResponse::Error,
|
||||
};
|
||||
|
||||
let pid = ProcessId::from_raw(process_cap.value() as u16);
|
||||
self.running[idx] = Some(RunningApp { app, pid });
|
||||
if let Some(r) = self.running_mut(app) {
|
||||
*r = Some(RunningApp { process });
|
||||
}
|
||||
self.active = Some(app);
|
||||
|
||||
SessionResponse::Launched { app }
|
||||
}
|
||||
|
||||
fn kill_app(&mut self, app: AppId) -> SessionResponse {
|
||||
let idx = app.raw() as usize;
|
||||
match self.running[idx].take() {
|
||||
Some(_running) => {
|
||||
match self.running_mut(app).and_then(Option::take) {
|
||||
Some(running) => {
|
||||
let _ = libkos::syscall::kill(running.process);
|
||||
if self.active == Some(app) {
|
||||
self.active = None;
|
||||
}
|
||||
@@ -106,7 +110,9 @@ impl Server for SessionServer {
|
||||
match request {
|
||||
SessionRequest::Launch { app } => self.launch_app(app),
|
||||
SessionRequest::Kill { app } => self.kill_app(app),
|
||||
SessionRequest::ListApps => SessionResponse::AppList { count: self.app_count },
|
||||
SessionRequest::ListApps => SessionResponse::AppList {
|
||||
count: self.app_count,
|
||||
},
|
||||
SessionRequest::ActiveApp => match self.active {
|
||||
Some(app) => SessionResponse::Active { app },
|
||||
None => SessionResponse::NotFound,
|
||||
|
||||
Reference in New Issue
Block a user