xous: add syscalls for connecting to a server

This is required because server IDs are 128 bits, but we only have
enough space for 32 bits in the message.

This is fine, because it means we can drop "Connect" permissions to
prevent compromised clients from making new connections.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-03-17 13:00:06 +08:00
parent ebe3efc097
commit 19ddb32d9d
2 changed files with 130 additions and 15 deletions

View file

@ -12,6 +12,9 @@ pub type Connection = usize;
/// Server ID
pub type SID = (usize, usize, usize, usize);
/// Connection ID
pub type CID = usize;
/// Equivalent to a RISC-V Hart ID
pub type CpuID = usize;
@ -43,30 +46,34 @@ pub struct Context {
}
#[repr(C)]
#[derive(Debug)]
pub struct MemoryMessage {
id: MessageId,
in_buf: Option<MemoryAddress>,
in_buf_size: Option<MemorySize>,
out_buf: Option<MemoryAddress>,
out_buf_size: Option<MemorySize>,
pub id: MessageId,
pub in_buf: Option<MemoryAddress>,
pub in_buf_size: Option<MemorySize>,
pub out_buf: Option<MemoryAddress>,
pub out_buf_size: Option<MemorySize>,
}
#[repr(C)]
#[derive(Debug)]
pub struct ScalarMessage {
id: MessageId,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
pub id: MessageId,
pub arg1: usize,
pub arg2: usize,
pub arg3: usize,
pub arg4: usize,
}
#[repr(usize)]
#[derive(Debug)]
pub enum Message {
Memory(MemoryMessage),
Scalar(ScalarMessage),
}
#[repr(C)]
#[derive(Debug)]
pub struct MessageEnvelope {
sender: MessageSender,
message: Message,

View file

@ -1,4 +1,7 @@
use crate::{CpuID, Error, MemoryAddress, PID, SID, MessageEnvelope};
use crate::{
CpuID, Error, MemoryAddress, MemoryMessage, MemorySize, Message, MessageEnvelope,
ScalarMessage, CID, PID, SID,
};
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
@ -240,6 +243,13 @@ pub enum SysCall {
/// be created.
CreateServer(usize /* server name */),
/// Connect to a server. This turns a 128-bit Serever ID into a 32-bit
/// Connection ID.
Connect(SID /* server id */),
/// Send a message to a server
SendMessage(CID, Message),
/// This syscall does not exist
Invalid(usize, usize, usize, usize, usize, usize, usize),
}
@ -259,6 +269,8 @@ enum SysCallNumber {
SetMemRegion = 13,
CreateServer = 14,
WaitMessage = 15,
SendMessage = 16,
Connect = 17,
Invalid,
}
@ -285,7 +297,16 @@ impl SysCall {
],
SysCall::Yield => [SysCallNumber::Yield as usize, 0, 0, 0, 0, 0, 0, 0],
SysCall::WaitEvent => [SysCallNumber::WaitEvent as usize, 0, 0, 0, 0, 0, 0, 0],
SysCall::WaitMessage(sid) => [SysCallNumber::WaitMessage as usize, sid.0, sid.1, sid.2, sid.3, 0, 0, 0],
SysCall::WaitMessage(sid) => [
SysCallNumber::WaitMessage as usize,
sid.0,
sid.1,
sid.2,
sid.3,
0,
0,
0,
],
SysCall::Suspend(a1, a2) => [
SysCallNumber::Suspend as usize,
a1 as usize,
@ -360,7 +381,34 @@ impl SysCall {
0,
],
SysCall::CreateServer(a1) => [SysCallNumber::CreateServer as usize, a1, 0, 0, 0, 0, 0, 0],
SysCall::CreateServer(a1) => {
[SysCallNumber::CreateServer as usize, a1, 0, 0, 0, 0, 0, 0]
},
SysCall::Connect(sid) => {
[SysCallNumber::Connect as usize, sid.0, sid.1, sid.2, sid.3, 0, 0, 0]
}
SysCall::SendMessage(a1, ref a2) => match a2 {
Message::Memory(mm) => [
SysCallNumber::SendMessage as usize,
a1,
1,
mm.id as usize,
mm.in_buf.map(|x| x.get()).unwrap_or(0) as usize,
mm.in_buf_size.map(|x| x.get()).unwrap_or(0) as usize,
mm.out_buf.map(|x| x.get()).unwrap_or(0) as usize,
mm.out_buf_size.map(|x| x.get()).unwrap_or(0) as usize,
],
Message::Scalar(sc) => [
SysCallNumber::SendMessage as usize,
a1,
2,
sc.id as usize,
sc.arg1,
sc.arg2,
sc.arg3,
sc.arg4,
],
},
SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7) => {
[SysCallNumber::Invalid as usize, a1, a2, a3, a4, a5, a6, a7]
}
@ -406,6 +454,53 @@ impl SysCall {
SysCall::SetMemRegion(a1 as PID, MemoryType::from(a2), a3 as *mut usize, a4)
}
Some(SysCallNumber::CreateServer) => SysCall::CreateServer(a1),
Some(SysCallNumber::Connect) => SysCall::Connect((a1, a2, a3, a4)),
Some(SysCallNumber::SendMessage) => match a2 {
1 => SysCall::SendMessage(
a1,
Message::Memory(MemoryMessage {
id: a3,
in_buf: MemoryAddress::new(a4),
in_buf_size: MemorySize::new(a5),
out_buf: MemoryAddress::new(a6),
out_buf_size: MemorySize::new(a7),
}),
),
2 => SysCall::SendMessage(
a1,
Message::Scalar(ScalarMessage {
id: a3,
arg1: a4,
arg2: a5,
arg3: a6,
arg4: a7,
}),
),
_ => SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7),
},
// SysCall::SendMessage(a1, ref a2) => match a2 {
// Message::Memory(mm) => [
// SysCallNumber::SendMessage as usize,
// a1,
// 1,
// mm.id as usize,
// mm.in_buf.map(|x| x.get()).unwrap_or(0) as usize,
// mm.in_buf_size.map(|x| x.get()).unwrap_or(0) as usize,
// mm.out_buf.map(|x| x.get()).unwrap_or(0) as usize,
// mm.out_buf_size.map(|x| x.get()).unwrap_or(0) as usize,
// ],
// Message::Scalar(sc) => [
// SysCallNumber::SendMessage as usize,
// a1,
// 2,
// sc.id as usize,
// sc.arg1,
// sc.arg2,
// sc.arg3,
// sc.arg4,
// ],
// },
Some(SysCallNumber::Invalid) => SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7),
None => return Err(InvalidSyscall {}),
})
@ -524,8 +619,21 @@ pub fn create_server(name: usize) -> core::result::Result<SID, Error> {
///
/// # Errors
///
pub fn receive_message(sid: SID) -> core::result::Result<MessageEnvelope, Error> {
rsyscall(SysCall::WaitMessage(sid)).expect("Couldn't call watimessage");
pub fn receive_message(server: SID) -> core::result::Result<MessageEnvelope, Error> {
let result = rsyscall(SysCall::WaitMessage(server)).expect("Couldn't call watimessage");
Err(Error::UnhandledSyscall)
}
/// Send a message to a server. This thread will block until the message is responded to.
/// If the message type is `Memory`, then the memory addresses pointed to will be
/// unavailable to this process until this function returns.
///
/// # Errors
///
/// * **ServerNotFound**: The server does not exist so the connection is now invalid
/// * **BadAddress**: The client tried to pass a Memory message using an address it doesn't own
/// * **Timeout**: The timeout limit has been reached
pub fn send_message(server: SID, message: MessageEnvelope) -> core::result::Result<(), Error> {
Err(Error::UnhandledSyscall)
}