From 7727e08e5f055aef8db4f3920ba5a4c8769d1fa8 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 17 Apr 2008 17:46:02 +0000 Subject: [PATCH] Added experimental public API get_port_message_info_etc(). It is similar to port_buffer_size_etc(), but returns the info through a structure, which also identifies the sender (uid, gid, team ID) of the message. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25003 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/OS.h | 19 +++++++++++ headers/private/kernel/port.h | 3 ++ headers/private/kernel/syscalls.h | 3 ++ src/system/kernel/port.cpp | 57 ++++++++++++++++++++++++++++--- src/system/libroot/os/port.c | 8 +++++ 5 files changed, 85 insertions(+), 5 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 5fe4713c54..3e04690a5b 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -135,6 +135,25 @@ extern status_t _get_next_port_info(team_id team, int32 *cookie, port_info *port _get_next_port_info((team), (cookie), (info), sizeof(*(info))) +// WARNING: The following is Haiku experimental API. It might be removed or +// changed in the future. + +typedef struct port_message_info { + size_t size; + uid_t sender; + gid_t sender_group; + team_id sender_team; +} port_message_info; + +// similar to port_buffer_size_etc(), but returns (more) info +extern status_t _get_port_message_info_etc(port_id port, + port_message_info *info, size_t infoSize, uint32 flags, + bigtime_t timeout); + +#define get_port_message_info_etc(port, info, flags, timeout) \ + _get_port_message_info_etc((port), (info), sizeof(*(info)), flags, \ + timeout) + /*-------------------------------------------------------------*/ /* Semaphores */ diff --git a/headers/private/kernel/port.h b/headers/private/kernel/port.h index d20d64c2c5..6e47e93bd4 100644 --- a/headers/private/kernel/port.h +++ b/headers/private/kernel/port.h @@ -55,6 +55,9 @@ status_t _user_write_port_etc(port_id port, int32 msgCode, status_t _user_writev_port_etc(port_id id, int32 msgCode, const iovec *msgVecs, size_t vecCount, size_t bufferSize, uint32 flags, bigtime_t timeout); +status_t _user_get_port_message_info_etc(port_id port, + port_message_info *info, size_t infoSize, uint32 flags, + bigtime_t timeout); #ifdef __cplusplus } diff --git a/headers/private/kernel/syscalls.h b/headers/private/kernel/syscalls.h index 66da2c0a88..4a3d622cbe 100644 --- a/headers/private/kernel/syscalls.h +++ b/headers/private/kernel/syscalls.h @@ -318,6 +318,9 @@ extern status_t _kern_write_port_etc(port_id port, int32 msgCode, const void *m extern status_t _kern_writev_port_etc(port_id id, int32 msgCode, const struct iovec *msgVecs, size_t vecCount, size_t bufferSize, uint32 flags, bigtime_t timeout); +extern status_t _kern_get_port_message_info_etc(port_id port, + port_message_info *info, size_t infoSize, uint32 flags, + bigtime_t timeout); // debug support functions extern void _kern_debugger(const char *message); diff --git a/src/system/kernel/port.cpp b/src/system/kernel/port.cpp index 1bbd883e35..90a7b6e1ab 100644 --- a/src/system/kernel/port.cpp +++ b/src/system/kernel/port.cpp @@ -40,6 +40,9 @@ typedef struct port_msg { int32 code; cbuf *buffer_chain; size_t size; + uid_t sender; + gid_t sender_group; + team_id sender_team; } port_msg; struct port_entry { @@ -811,11 +814,22 @@ port_buffer_size(port_id id) ssize_t port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout) { + port_message_info info; + status_t error = get_port_message_info_etc(id, &info, flags, timeout); + return error != B_OK ? error : info.size; +} + +status_t +_get_port_message_info_etc(port_id id, port_message_info *info, + size_t infoSize, uint32 flags, bigtime_t timeout) +{ + if (info == NULL || infoSize != sizeof(port_message_info)) + return B_BAD_VALUE; + cpu_status state; sem_id cachedSem; status_t status; port_msg *msg; - ssize_t size; int32 slot; if (!sPortsActive || id < 0) @@ -860,14 +874,19 @@ port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout) } // determine tail & get the length of the message + status_t error = B_OK; msg = (port_msg*)list_get_first_item(&sPorts[slot].msg_queue); if (msg == NULL) { if (status == B_OK) panic("port %ld: no messages found\n", sPorts[slot].id); - size = B_BAD_PORT_ID; - } else - size = msg->size; + error = B_BAD_PORT_ID; + } else { + info->size = msg->size; + info->sender = msg->sender; + info->sender_group = msg->sender_group; + info->sender_team = msg->sender_team; + } RELEASE_PORT_LOCK(sPorts[slot]); restore_interrupts(state); @@ -876,7 +895,7 @@ port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout) release_sem(cachedSem); // return length of item at end of queue - return size; + return error; } @@ -1119,6 +1138,11 @@ writev_port_etc(port_id id, int32 msgCode, const iovec *msgVecs, if (msg == NULL) return B_NO_MEMORY; + // sender credentials + msg->sender = geteuid(); + msg->sender_group = getegid(); + msg->sender_team = team_get_current_team_id(); + if (bufferSize > 0) { uint32 i; if (userCopy) { @@ -1418,3 +1442,26 @@ _user_writev_port_etc(port_id port, int32 messageCode, const iovec *userVecs, free(vecs); return syscall_restart_handle_timeout_post(status, timeout); } + + +status_t +_user_get_port_message_info_etc(port_id port, port_message_info *userInfo, + size_t infoSize, uint32 flags, bigtime_t timeout) +{ + if (userInfo == NULL || infoSize != sizeof(port_message_info)) + return B_BAD_VALUE; + + syscall_restart_handle_timeout_pre(flags, timeout); + + port_message_info info; + status_t error = _get_port_message_info_etc(port, &info, sizeof(info), + flags | B_CAN_INTERRUPT, timeout); + + // copy info to userland + if (error == B_OK && (!IS_USER_ADDRESS(userInfo) + || user_memcpy(userInfo, &info, sizeof(info)) != B_OK)) { + error = B_BAD_ADDRESS; + } + + return syscall_restart_handle_timeout_post(error, timeout); +} diff --git a/src/system/libroot/os/port.c b/src/system/libroot/os/port.c index 8d16fffed1..740273123d 100644 --- a/src/system/libroot/os/port.c +++ b/src/system/libroot/os/port.c @@ -110,3 +110,11 @@ _get_port_info(port_id port, port_info *info, size_t size) return _kern_get_port_info(port, info); } + +status_t +_get_port_message_info_etc(port_id port, port_message_info *info, + size_t infoSize, uint32 flags, bigtime_t timeout) +{ + return _kern_get_port_message_info_etc(port, info, infoSize, flags, + timeout); +}