[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/3] Use reverse authenticating ioctl-handler protocal
From: |
Carl Fredrik Hammar |
Subject: |
[PATCH 3/3] Use reverse authenticating ioctl-handler protocal |
Date: |
Wed, 26 Aug 2009 16:45:39 +0200 |
* hurd/Makefile (interfaces): Add `ioctl_handler_reply'.
* hurd/fd-ioctl-call.c: Check that handlers are provided by the same user.
---
hurd/Makefile | 3 +-
hurd/fd-ioctl-call.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 158 insertions(+), 2 deletions(-)
diff --git a/hurd/Makefile b/hurd/Makefile
index 768f93a..1286142 100644
--- a/hurd/Makefile
+++ b/hurd/Makefile
@@ -40,7 +40,8 @@ user-interfaces := $(addprefix hurd/,\
msg msg_reply msg_request \
exec exec_startup crash interrupt \
fs fsys io term tioctl socket ifsock \
- login password pfinet ioctl_handler \
+ login password pfinet \
+ ioctl_handler ioctl_handler_reply \
)
server-interfaces := hurd/msg faultexc
diff --git a/hurd/fd-ioctl-call.c b/hurd/fd-ioctl-call.c
index 873a5ca..9b727a6 100644
--- a/hurd/fd-ioctl-call.c
+++ b/hurd/fd-ioctl-call.c
@@ -24,6 +24,158 @@
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
+#include <mach/notify.h>
+#include <sys/mman.h>
+
+
+/* Implement the client-side of the protocol described in
+ <hurd/ioctl_handler.defs>. The resulting ioctl-handler module is
+ returned in FILE, and the ID block is returned in EUIDS, AUIDS, EGIDS,
+ and AGIDS. */
+static error_t
+ioctl_handler_get (io_t io,
+ auth_t auth,
+ mach_port_t rendezvous,
+ mach_msg_type_name_t rendezvous_type,
+ file_t *file,
+ uid_t **euids, size_t *euids_len,
+ uid_t **auids, size_t *auids_len,
+ uid_t **egids, size_t *egids_len,
+ uid_t **agids, size_t *agids_len)
+{
+ struct {
+ mach_msg_header_t head;
+ mach_msg_type_t error_type;
+ kern_return_t error;
+ mach_msg_type_t file_type;
+ file_t file;
+ } reply;
+ mach_port_t reply_port;
+ error_t err, msg_err;
+
+ reply_port = __mach_reply_port ();
+ if (reply_port == MACH_PORT_NULL)
+ return KERN_RESOURCE_SHORTAGE;
+
+ err = __ioctl_handler_request (io, rendezvous, MACH_MSG_TYPE_MAKE_SEND);
+ if (!err)
+ do
+ err = __auth_server_authenticate (auth,
+ rendezvous, rendezvous_type,
+ reply_port, MACH_MSG_TYPE_MAKE_SEND,
+ euids, euids_len,
+ auids, auids_len,
+ egids, egids_len,
+ agids, agids_len);
+ while (err == EINTR);
+ if (err)
+ {
+ __mach_port_destroy (__mach_task_self (), reply_port);
+ return err;
+ }
+
+ if (!err)
+ msg_err = __mach_msg (&reply.head, MACH_RCV_MSG | MACH_RCV_INTERRUPT,
+ 0, sizeof (reply), reply_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ __mach_port_destroy (__mach_task_self (), reply_port);
+ if (err)
+ return err;
+ else
+ err = msg_err;
+
+ if (!err && reply.head.msgh_id == MACH_NOTIFY_SEND_ONCE)
+ err = MIG_SERVER_DIED;
+
+ if (!err && reply.head.msgh_id != 39101)
+ {
+ err = MIG_REPLY_MISMATCH;
+ __mach_msg_destroy (&reply.head);
+ }
+
+ if (!err)
+ {
+ if (reply.head.msgh_size != sizeof (reply)
+ || !(reply.head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
+
+ || reply.error_type.msgt_name != MACH_MSG_TYPE_INTEGER_32
+ || reply.error_type.msgt_size != 32
+ || reply.error_type.msgt_number != 1
+ || reply.error_type.msgt_inline != TRUE
+ || reply.error_type.msgt_longform != FALSE
+ || reply.error_type.msgt_deallocate != FALSE
+
+ || reply.file_type.msgt_name != MACH_MSG_TYPE_PORT_SEND
+ || reply.file_type.msgt_size != 32
+ || reply.file_type.msgt_number != 1
+ || reply.file_type.msgt_inline != TRUE
+ || reply.file_type.msgt_longform != FALSE
+ || reply.file_type.msgt_deallocate != FALSE)
+ {
+ err = MIG_TYPE_ERROR;
+ __mach_msg_destroy (&reply.head);
+ }
+ else
+ {
+ err = reply.error;
+ *file = reply.file;
+ }
+ }
+
+ if (err)
+ {
+ __munmap (*euids, *euids_len * sizeof (uid_t));
+ __munmap (*auids, *auids_len * sizeof (uid_t));
+ __munmap (*egids, *egids_len * sizeof (uid_t));
+ __munmap (*agids, *agids_len * sizeof (uid_t));
+ }
+
+ return err;
+}
+
+
+/* Get the ioctl-handler module from IO, and check that the provider
+ is the same user or root, otherwise return EACCES. */
+static error_t
+ioctl_handler_checked_get (io_t io, file_t *file)
+{
+ auth_t auth;
+ mach_port_t rendezvous;
+ uid_t euid, *euids, *auids, *egids, *agids;
+ size_t euids_len, auids_len, egids_len, agids_len;
+ error_t err;
+ int i;
+
+ rendezvous = __mach_reply_port ();
+ if (rendezvous == MACH_PORT_NULL)
+ return KERN_RESOURCE_SHORTAGE;
+
+ auth = getauth ();
+
+ euids_len = auids_len = egids_len = agids_len = 0;
+ euids = auids = egids = agids = NULL;
+ err = ioctl_handler_get (io, auth, rendezvous, MACH_MSG_TYPE_MAKE_SEND,
+ file, &euids, &euids_len, &auids, &auids_len,
+ &egids, &egids_len, &agids, &agids_len);
+ __mach_port_deallocate (__mach_task_self (), auth);
+ __mach_port_destroy (__mach_task_self (), rendezvous);
+ if (err)
+ return err;
+
+ err = EACCES;
+ euid = geteuid ();
+ for (i = 0; i < euids_len; i++)
+ if (euids[i] == euid || euids[i] == 0)
+ err = 0;
+
+ __munmap (euids, euids_len * sizeof (uid_t));
+ __munmap (auids, auids_len * sizeof (uid_t));
+ __munmap (egids, egids_len * sizeof (uid_t));
+ __munmap (agids, agids_len * sizeof (uid_t));
+
+ return err;
+}
/* Get PORT's ioctl handler module and load it, returning the linker map
@@ -35,7 +187,10 @@ load_ioctl_handler (io_t port, void **map)
io_t handler;
error_t err;
- err = __ioctl_handler_get (port, &handler);
+ /* Avoid spurious "may be used uninitialized" warning. */
+ handler = MACH_PORT_NULL;
+
+ err = ioctl_handler_checked_get (port, &handler);
if (!err)
{
int fd = _hurd_intern_fd (handler, 0, 1); /* Consumes HANDLER. */
--
1.6.3.3
- [PATCH 0/2] Ioctl handler protocol patches, Carl Fredrik Hammar, 2009/08/26
- [PATCH 1/2] Add ioctl-handler interface, Carl Fredrik Hammar, 2009/08/26
- [PATCH 0/3] Use server provided ioctl-handler, Carl Fredrik Hammar, 2009/08/26
- [PATCH 1/3] Reload fd ioctl handler on each call to ioctl, Carl Fredrik Hammar, 2009/08/26
- [PATCH 2/3] Save handlers between calls to ioctl, Carl Fredrik Hammar, 2009/08/26
- [PATCH 3/3] Use reverse authenticating ioctl-handler protocal,
Carl Fredrik Hammar <=
- [PATCH 0/3] Test server provided ioctl-handler, Carl Fredrik Hammar, 2009/08/26
- [PATCH 1/3] Test server provided ioctl-handler, Carl Fredrik Hammar, 2009/08/26
- Re: [PATCH 1/3] Test server provided ioctl-handler, olafBuddenhagen, 2009/08/31
- [PATCH 2/3] Update to reflect ioctl_handler_t change, Carl Fredrik Hammar, 2009/08/26