Compare commits
3 Commits
5f0654430d
...
1c7c90ef39
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c7c90ef39 | |||
| 11c741bd68 | |||
| 34bd6e479c |
@@ -38,15 +38,17 @@ extern kern_status_t channel_read_msg(
|
|||||||
struct channel *channel,
|
struct channel *channel,
|
||||||
msgid_t msg,
|
msgid_t msg,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
void *buf,
|
struct vm_region *dest_region,
|
||||||
size_t len,
|
const struct iovec *dest_iov,
|
||||||
|
size_t dest_iov_count,
|
||||||
size_t *nr_read);
|
size_t *nr_read);
|
||||||
extern kern_status_t channel_write_msg(
|
extern kern_status_t channel_write_msg(
|
||||||
struct channel *channel,
|
struct channel *channel,
|
||||||
msgid_t msg,
|
msgid_t msg,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
const void *buf,
|
struct vm_region *src_region,
|
||||||
size_t len,
|
const struct iovec *src_iov,
|
||||||
|
size_t src_iov_count,
|
||||||
size_t *nr_written);
|
size_t *nr_written);
|
||||||
|
|
||||||
DEFINE_OBJECT_LOCK_FUNCTION(channel, c_base)
|
DEFINE_OBJECT_LOCK_FUNCTION(channel, c_base)
|
||||||
|
|||||||
@@ -158,11 +158,12 @@ extern kern_status_t sys_msg_reply(
|
|||||||
const struct msg *reply);
|
const struct msg *reply);
|
||||||
|
|
||||||
extern kern_status_t sys_msg_read(
|
extern kern_status_t sys_msg_read(
|
||||||
kern_handle_t channel,
|
kern_handle_t channel_handle,
|
||||||
msgid_t id,
|
msgid_t id,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
struct iovec *out,
|
const struct iovec *iov,
|
||||||
size_t nr_out);
|
size_t iov_count,
|
||||||
|
size_t *nr_read);
|
||||||
extern kern_status_t sys_msg_read_handles(
|
extern kern_status_t sys_msg_read_handles(
|
||||||
kern_handle_t channel,
|
kern_handle_t channel,
|
||||||
msgid_t id,
|
msgid_t id,
|
||||||
|
|||||||
@@ -168,13 +168,14 @@ extern kern_status_t vm_region_memmove(
|
|||||||
extern kern_status_t vm_region_memmove_v(
|
extern kern_status_t vm_region_memmove_v(
|
||||||
struct vm_region *dest_region,
|
struct vm_region *dest_region,
|
||||||
size_t dest_offset,
|
size_t dest_offset,
|
||||||
struct iovec *dest,
|
const struct iovec *dest,
|
||||||
size_t nr_dest,
|
size_t nr_dest,
|
||||||
struct vm_region *src_region,
|
struct vm_region *src_region,
|
||||||
size_t src_offset,
|
size_t src_offset,
|
||||||
const struct iovec *src,
|
const struct iovec *src,
|
||||||
size_t nr_src,
|
size_t nr_src,
|
||||||
size_t bytes_to_move);
|
size_t bytes_to_move,
|
||||||
|
size_t *nr_bytes_moved);
|
||||||
|
|
||||||
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
|
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ extern kern_status_t channel_recv_msg(
|
|||||||
0,
|
0,
|
||||||
msg->msg_req.msg_data,
|
msg->msg_req.msg_data,
|
||||||
msg->msg_req.msg_data_count,
|
msg->msg_req.msg_data_count,
|
||||||
VM_REGION_COPY_ALL);
|
VM_REGION_COPY_ALL,
|
||||||
|
NULL);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
kmsg_reply_error(msg, status, &msg_lock_flags);
|
kmsg_reply_error(msg, status, &msg_lock_flags);
|
||||||
return status;
|
return status;
|
||||||
@@ -216,7 +217,8 @@ extern kern_status_t channel_reply_msg(
|
|||||||
0,
|
0,
|
||||||
resp->msg_data,
|
resp->msg_data,
|
||||||
resp->msg_data_count,
|
resp->msg_data_count,
|
||||||
VM_REGION_COPY_ALL);
|
VM_REGION_COPY_ALL,
|
||||||
|
NULL);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
kmsg_reply_error(msg, status, &msg_lock_flags);
|
kmsg_reply_error(msg, status, &msg_lock_flags);
|
||||||
return status;
|
return status;
|
||||||
@@ -241,21 +243,49 @@ extern kern_status_t channel_reply_msg(
|
|||||||
|
|
||||||
extern kern_status_t channel_read_msg(
|
extern kern_status_t channel_read_msg(
|
||||||
struct channel *channel,
|
struct channel *channel,
|
||||||
msgid_t msg,
|
msgid_t id,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
void *buf,
|
struct vm_region *dest_region,
|
||||||
size_t len,
|
const struct iovec *dest_iov,
|
||||||
|
size_t dest_iov_count,
|
||||||
size_t *nr_read)
|
size_t *nr_read)
|
||||||
{
|
{
|
||||||
return KERN_UNIMPLEMENTED;
|
unsigned long msg_lock_flags;
|
||||||
|
struct kmsg *msg = get_msg_with_id(&channel->c_msg, id);
|
||||||
|
if (!msg) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&msg->msg_lock, &msg_lock_flags);
|
||||||
|
if (msg->msg_status != KMSG_WAIT_REPLY) {
|
||||||
|
spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags);
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status = vm_region_memmove_v(
|
||||||
|
dest_region,
|
||||||
|
0,
|
||||||
|
dest_iov,
|
||||||
|
dest_iov_count,
|
||||||
|
msg->msg_sender_thread->tr_parent->t_address_space,
|
||||||
|
offset,
|
||||||
|
msg->msg_req.msg_data,
|
||||||
|
msg->msg_req.msg_data_count,
|
||||||
|
VM_REGION_COPY_ALL,
|
||||||
|
nr_read);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern kern_status_t channel_write_msg(
|
extern kern_status_t channel_write_msg(
|
||||||
struct channel *channel,
|
struct channel *channel,
|
||||||
msgid_t msg,
|
msgid_t msg,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
const void *buf,
|
struct vm_region *src_region,
|
||||||
size_t len,
|
const struct iovec *src_iov,
|
||||||
|
size_t src_iov_count,
|
||||||
size_t *nr_written)
|
size_t *nr_written)
|
||||||
{
|
{
|
||||||
return KERN_UNIMPLEMENTED;
|
return KERN_UNIMPLEMENTED;
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ extern kern_status_t msg_read(
|
|||||||
msgid_t id,
|
msgid_t id,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
struct iovec *out,
|
struct iovec *out,
|
||||||
size_t nr_out);
|
size_t out_count,
|
||||||
|
size_t *nr_read);
|
||||||
extern kern_status_t msg_read_handles(
|
extern kern_status_t msg_read_handles(
|
||||||
kern_handle_t channel,
|
kern_handle_t channel,
|
||||||
msgid_t id,
|
msgid_t id,
|
||||||
|
|||||||
@@ -162,6 +162,29 @@ kern_status_t sys_port_disconnect(kern_handle_t port_handle)
|
|||||||
return status;
|
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)
|
static bool validate_msg(struct task *task, const struct msg *msg, bool rw)
|
||||||
{
|
{
|
||||||
if (!validate_access_r(task, msg, sizeof *msg)) {
|
if (!validate_access_r(task, msg, sizeof *msg)) {
|
||||||
@@ -184,19 +207,9 @@ static bool validate_msg(struct task *task, const struct msg *msg, bool rw)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < msg->msg_data_count; i++) {
|
if (!validate_iovec(task, msg->msg_data, msg->msg_data_count, rw)) {
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < msg->msg_handles_count; i++) {
|
for (size_t i = 0; i < msg->msg_handles_count; i++) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@@ -368,13 +381,56 @@ kern_status_t sys_msg_reply(
|
|||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t sys_msg_read(
|
kern_status_t sys_msg_read(
|
||||||
kern_handle_t channel,
|
kern_handle_t channel_handle,
|
||||||
msgid_t id,
|
msgid_t id,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
struct iovec *out,
|
const struct iovec *iov,
|
||||||
size_t nr_out)
|
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(
|
kern_status_t sys_msg_read_handles(
|
||||||
|
|||||||
@@ -1737,13 +1737,14 @@ kern_status_t vm_region_memmove(
|
|||||||
extern kern_status_t vm_region_memmove_v(
|
extern kern_status_t vm_region_memmove_v(
|
||||||
struct vm_region *dest_region,
|
struct vm_region *dest_region,
|
||||||
size_t dest_offset,
|
size_t dest_offset,
|
||||||
struct iovec *dest_vecs,
|
const struct iovec *dest_vecs,
|
||||||
size_t nr_dest_vecs,
|
size_t nr_dest_vecs,
|
||||||
struct vm_region *src_region,
|
struct vm_region *src_region,
|
||||||
size_t src_offset,
|
size_t src_offset,
|
||||||
const struct iovec *src_vecs,
|
const struct iovec *src_vecs,
|
||||||
size_t nr_src_vecs,
|
size_t nr_src_vecs,
|
||||||
size_t bytes_to_move)
|
size_t bytes_to_move,
|
||||||
|
size_t *nr_bytes_moved)
|
||||||
{
|
{
|
||||||
if (src_region->vr_status != VM_REGION_ONLINE) {
|
if (src_region->vr_status != VM_REGION_ONLINE) {
|
||||||
return KERN_BAD_STATE;
|
return KERN_BAD_STATE;
|
||||||
@@ -1760,6 +1761,7 @@ extern kern_status_t vm_region_memmove_v(
|
|||||||
iovec_iterator_seek(&src, src_offset);
|
iovec_iterator_seek(&src, src_offset);
|
||||||
iovec_iterator_seek(&dest, dest_offset);
|
iovec_iterator_seek(&dest, dest_offset);
|
||||||
|
|
||||||
|
size_t moved = 0;
|
||||||
while (bytes_to_move && src.it_len && dest.it_len) {
|
while (bytes_to_move && src.it_len && dest.it_len) {
|
||||||
size_t to_move
|
size_t to_move
|
||||||
= MIN(MIN(src.it_len, dest.it_len), bytes_to_move);
|
= MIN(MIN(src.it_len, dest.it_len), bytes_to_move);
|
||||||
@@ -1778,6 +1780,11 @@ extern kern_status_t vm_region_memmove_v(
|
|||||||
iovec_iterator_seek(&src, to_move);
|
iovec_iterator_seek(&src, to_move);
|
||||||
iovec_iterator_seek(&dest, to_move);
|
iovec_iterator_seek(&dest, to_move);
|
||||||
bytes_to_move -= to_move;
|
bytes_to_move -= to_move;
|
||||||
|
moved += to_move;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_bytes_moved) {
|
||||||
|
*nr_bytes_moved = moved;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user