kernel: re-implement sending handles via port messages
This commit is contained in:
101
syscall/msg.c
101
syscall/msg.c
@@ -161,17 +161,17 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle)
|
||||
|
||||
static bool validate_iovec(
|
||||
struct task *task,
|
||||
const struct iovec *iov,
|
||||
const kern_iovec_t *iov,
|
||||
size_t count,
|
||||
bool rw)
|
||||
{
|
||||
if (!validate_access_r(task, iov, count * sizeof(struct iovec))) {
|
||||
if (!validate_access_r(task, iov, count * sizeof(*iov))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
bool ok = false;
|
||||
const struct iovec *vec = &iov[i];
|
||||
const kern_iovec_t *vec = &iov[i];
|
||||
if (rw) {
|
||||
ok = validate_access_w(task, vec->io_base, vec->io_len);
|
||||
} else {
|
||||
@@ -186,23 +186,55 @@ static bool validate_iovec(
|
||||
return true;
|
||||
}
|
||||
|
||||
kern_status_t sys_msg_send(
|
||||
kern_handle_t port_handle,
|
||||
const struct iovec *req_data,
|
||||
size_t req_data_count,
|
||||
struct iovec *resp_data,
|
||||
size_t resp_data_count)
|
||||
static bool validate_msg(struct task *task, const kern_msg_t *msg, bool rw)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_iovec(self, req_data, req_data_count, false)) {
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_iovec(self, resp_data, resp_data_count, true)) {
|
||||
vm_prot_t flags;
|
||||
if (rw) {
|
||||
flags = VM_PROT_WRITE | VM_PROT_USER;
|
||||
} else {
|
||||
flags = VM_PROT_READ | VM_PROT_USER;
|
||||
}
|
||||
|
||||
if (!validate_access(task, msg, sizeof *msg, flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_iovec(task, msg->msg_data, msg->msg_data_count, rw)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t handle_buffer_len
|
||||
= msg->msg_handles_count * sizeof(*msg->msg_handles);
|
||||
if (!validate_access(
|
||||
task,
|
||||
msg->msg_handles,
|
||||
handle_buffer_len,
|
||||
flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
kern_status_t sys_msg_send(
|
||||
kern_handle_t port_handle,
|
||||
const kern_msg_t *msg,
|
||||
kern_msg_t *out_reply)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_msg(self, msg, false)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_msg(self, out_reply, true)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
task_lock_irqsave(self, &flags);
|
||||
@@ -230,32 +262,18 @@ kern_status_t sys_msg_send(
|
||||
}
|
||||
|
||||
port_lock_irqsave(port, &flags);
|
||||
status = port_send_msg(
|
||||
port,
|
||||
req_data,
|
||||
req_data_count,
|
||||
resp_data,
|
||||
resp_data_count,
|
||||
&flags);
|
||||
status = port_send_msg(port, msg, out_reply, &flags);
|
||||
port_unlock_irqrestore(port, flags);
|
||||
object_unref(port_obj);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
kern_status_t sys_msg_recv(
|
||||
kern_handle_t channel_handle,
|
||||
msgid_t *out_id,
|
||||
struct iovec *out_data,
|
||||
size_t out_data_count)
|
||||
kern_status_t sys_msg_recv(kern_handle_t channel_handle, kern_msg_t *out_msg)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_access_w(self, out_id, sizeof *out_id)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_iovec(self, out_data, out_data_count, true)) {
|
||||
if (!validate_msg(self, out_msg, true)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
@@ -286,12 +304,7 @@ kern_status_t sys_msg_recv(
|
||||
}
|
||||
|
||||
channel_lock_irqsave(channel, &flags);
|
||||
status = channel_recv_msg(
|
||||
channel,
|
||||
out_id,
|
||||
out_data,
|
||||
out_data_count,
|
||||
&flags);
|
||||
status = channel_recv_msg(channel, out_msg, &flags);
|
||||
channel_unlock_irqrestore(channel, flags);
|
||||
object_unref(channel_obj);
|
||||
|
||||
@@ -301,12 +314,11 @@ kern_status_t sys_msg_recv(
|
||||
kern_status_t sys_msg_reply(
|
||||
kern_handle_t channel_handle,
|
||||
msgid_t id,
|
||||
const struct iovec *reply_data,
|
||||
size_t reply_data_count)
|
||||
const kern_msg_t *reply)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_iovec(self, reply_data, reply_data_count, false)) {
|
||||
if (!validate_msg(self, reply, true)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
@@ -337,12 +349,7 @@ kern_status_t sys_msg_reply(
|
||||
}
|
||||
|
||||
channel_lock_irqsave(channel, &flags);
|
||||
status = channel_reply_msg(
|
||||
channel,
|
||||
id,
|
||||
reply_data,
|
||||
reply_data_count,
|
||||
&flags);
|
||||
status = channel_reply_msg(channel, id, reply, &flags);
|
||||
channel_unlock_irqrestore(channel, flags);
|
||||
object_unref(channel_obj);
|
||||
|
||||
@@ -353,7 +360,7 @@ kern_status_t sys_msg_read(
|
||||
kern_handle_t channel_handle,
|
||||
msgid_t id,
|
||||
size_t offset,
|
||||
const struct iovec *iov,
|
||||
const kern_iovec_t *iov,
|
||||
size_t iov_count,
|
||||
size_t *nr_read)
|
||||
{
|
||||
@@ -412,7 +419,7 @@ kern_status_t sys_msg_write(
|
||||
kern_handle_t channel_handle,
|
||||
msgid_t id,
|
||||
size_t offset,
|
||||
const struct iovec *iov,
|
||||
const kern_iovec_t *iov,
|
||||
size_t iov_count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user