kernel: channel: implement channel_read_msg and msg_read

This commit is contained in:
2026-02-23 21:51:59 +00:00
parent 11c741bd68
commit 1c7c90ef39
4 changed files with 120 additions and 31 deletions

View File

@@ -162,6 +162,29 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle)
return status;
}
static bool validate_iovec(
struct task *task,
const struct iovec *iov,
size_t count,
bool rw)
{
for (size_t i = 0; i < count; i++) {
bool ok = false;
const struct iovec *vec = &iov[i];
if (rw) {
ok = validate_access_w(task, vec->io_base, vec->io_len);
} else {
ok = validate_access_r(task, vec->io_base, vec->io_len);
}
if (!ok) {
return false;
}
}
return true;
}
static bool validate_msg(struct task *task, const struct msg *msg, bool rw)
{
if (!validate_access_r(task, msg, sizeof *msg)) {
@@ -184,18 +207,8 @@ static bool validate_msg(struct task *task, const struct msg *msg, bool rw)
return false;
}
for (size_t i = 0; i < msg->msg_data_count; i++) {
bool ok = false;
const struct iovec *iov = &msg->msg_data[i];
if (rw) {
ok = validate_access_w(task, iov->io_base, iov->io_len);
} else {
ok = validate_access_r(task, iov->io_base, iov->io_len);
}
if (!ok) {
return false;
}
if (!validate_iovec(task, msg->msg_data, msg->msg_data_count, rw)) {
return false;
}
for (size_t i = 0; i < msg->msg_handles_count; i++) {
@@ -368,13 +381,56 @@ kern_status_t sys_msg_reply(
}
kern_status_t sys_msg_read(
kern_handle_t channel,
kern_handle_t channel_handle,
msgid_t id,
size_t offset,
struct iovec *out,
size_t nr_out)
const struct iovec *iov,
size_t iov_count,
size_t *nr_read)
{
return KERN_UNIMPLEMENTED;
struct task *self = current_task();
unsigned long flags;
task_lock_irqsave(self, &flags);
struct object *channel_obj = NULL;
handle_flags_t channel_handle_flags = 0;
kern_status_t status = task_resolve_handle(
self,
channel_handle,
&channel_obj,
&channel_handle_flags);
if (status != KERN_OK) {
return status;
}
/* add a reference to the port object to make sure it isn't deleted
* while we're using it */
object_ref(channel_obj);
task_unlock_irqrestore(self, flags);
struct channel *channel = channel_cast(channel_obj);
if (!channel) {
object_unref(channel_obj);
return KERN_INVALID_ARGUMENT;
}
channel_lock_irqsave(channel, &flags);
vm_region_lock(self->t_address_space);
status = channel_read_msg(
channel,
id,
offset,
self->t_address_space,
iov,
iov_count,
nr_read);
vm_region_unlock(self->t_address_space);
channel_unlock_irqrestore(channel, flags);
object_unref(channel_obj);
return status;
}
kern_status_t sys_msg_read_handles(