summaryrefslogtreecommitdiff
path: root/libhurd-cap-server/ctx-cap-use.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhurd-cap-server/ctx-cap-use.c')
-rw-r--r--libhurd-cap-server/ctx-cap-use.c278
1 files changed, 0 insertions, 278 deletions
diff --git a/libhurd-cap-server/ctx-cap-use.c b/libhurd-cap-server/ctx-cap-use.c
deleted file mode 100644
index 3758c19..0000000
--- a/libhurd-cap-server/ctx-cap-use.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* ctx-cap-use.c - Use capabilities within an RPC context.
- Copyright (C) 2005 Free Software Foundation, Inc.
- Written by Marcus Brinkmann <marcus@gnu.org>
-
- This file is part of the GNU Hurd.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include <hurd/cap-server.h>
-
-#include <compiler.h>
-
-#include "cap-server-intern.h"
-
-
-/* Return the number of bytes required for a hurd_cap_ctx_cap_use
- structure. */
-size_t
-hurd_cap_ctx_size (void)
-{
- return sizeof (struct hurd_cap_ctx_cap_use);
-}
-
-/* If you want to use other capabilities in an RPC handler beside the
- one on which the RPC was invoked, you need to make sure that
- inhibition works on those other capabilities and cancel your
- operation. For this, the following interfaces are provided. */
-
-/* The calling thread wishes to execute an RPC on the the handle
- HANDLE. The calling thread must already be registered as executing
- an RPC. RPC_CTX is the cooresponding RPC context. The function
- uses the structure CAP_USE, which must point to the number of bytes
- returned by hurd_cap_ctx_size, to store data required by
- hurd_cap_ctx_end_cap_use. The capability object corresponding to
- HANDLE is locked and returned in *OBJP.
-
- Returns EINVAL if the capability handle is invalid for the client.
-
- Returns ENOENT if there is no object associated with handle HANDLE.
-
- Returns EBAD if the capability is dead.
-
- Returns EDOM if the object associated with HANDLE is not in class
- REQUIRED_CLASS. If no type check is required, it will be skipped
- if REQURIED_CLASS is NULL. */
-error_t
-hurd_cap_ctx_start_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- hurd_cap_handle_t handle,
- hurd_cap_class_t required_class,
- struct hurd_cap_ctx_cap_use *cap_use,
- hurd_cap_obj_t *objp)
-{
- error_t err = 0;
- hurd_cap_bucket_t bucket = rpc_ctx->bucket;
- _hurd_cap_client_t client = rpc_ctx->client;
- hurd_cap_obj_t obj;
- hurd_cap_class_t cap_class;
- _hurd_cap_obj_entry_t obj_entry;
- _hurd_cap_obj_entry_t *obj_entryp;
-
-
- /* HANDLE must belong to the same client as RPC_CTX->HANDLE. */
- if (_hurd_cap_client_id (handle) != _hurd_cap_client_id (rpc_ctx->handle))
- return EINVAL;
-
- pthread_mutex_lock (&client->lock);
-
- /* Look up the object. */
- obj_entryp = (_hurd_cap_obj_entry_t *)
- hurd_table_lookup (&client->caps, _hurd_cap_id (handle));
- if (!obj_entryp)
- err = ENOENT;
- else
- {
- cap_use->_obj_entry = obj_entry = *obj_entryp;
-
- if (EXPECT_FALSE (!obj_entry->external_refs))
- err = ENOENT;
- else if (EXPECT_FALSE (obj_entry->dead))
- err = EBADF;
- else
- {
- obj_entry->internal_refs++;
- *objp = obj = obj_entry->cap_obj;
- }
- }
- pthread_mutex_unlock (&client->lock);
-
- if (err)
- /* Either the capability ID is invalid, or it was revoked. */
- return err;
-
- /* If HANDLE and RPC_CTX->HANDLE are the same, we are done. */
- if (EXPECT_FALSE (_hurd_cap_id (handle) == _hurd_cap_id (rpc_ctx->handle)))
- {
- assert (obj == rpc_ctx->obj);
- return 0;
- }
-
- /* At this point, CAP and OBJ are valid and we have one internal
- reference to the capability entry. */
-
- cap_class = obj->cap_class;
-
- if (required_class && cap_class != required_class)
- {
- err = EINVAL;
- goto client_cleanup;
- }
-
- if (cap_class != rpc_ctx->obj->cap_class)
- /* The capability class is not the same as the first caps. We
- need to add ourself to the cap class pending rpc list. */
- {
- pthread_mutex_lock (&cap_class->lock);
- /* First, we have to check if the class is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- while (!err && cap_class->state != _HURD_CAP_STATE_GREEN)
- err = hurd_cond_wait (&cap_class->cond, &cap_class->lock);
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&cap_class->lock);
- goto client_cleanup;
- }
-
- /* Now add ourself to the pending rpc list of the class */
- cap_use->_worker_class.thread = pthread_self ();
- cap_use->_worker_class.tid = l4_myself ();
- _hurd_cap_list_item_add (&cap_class->pending_rpcs,
- &cap_use->_worker_class);
-
- pthread_mutex_unlock (&cap_class->lock);
- }
-
- pthread_mutex_lock (&obj->lock);
- /* First, we have to check if the object is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- if (obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- pthread_mutex_lock (&cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- while (!err && obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- err = hurd_cond_wait (&cap_class->obj_cond,
- &cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- }
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
- }
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
-
- /* Now check if the client still has the capability, or if it was
- revoked. */
- pthread_mutex_lock (&client->lock);
- if (obj_entry->dead)
- err = EBADF;
- pthread_mutex_unlock (&client->lock);
- if (err)
- {
- /* The capability was revoked in the meantime. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
-
- cap_use->_worker_obj.thread = pthread_self ();
- cap_use->_worker_obj.tid = l4_myself ();
- _hurd_cap_list_item_add (&cap_class->pending_rpcs, &cap_use->_worker_obj);
-
- /* At this point, we have looked up the capability, acquired an
- internal reference for its entry in the client table (which
- implicitely keeps a reference acquired for the object itself),
- acquired a reference for the capability client in the bucket, and
- have added an item to the pending_rpcs lists in the class (if
- necessary) and object. The object is locked. */
-
- return 0;
-
- class_cleanup:
- if (cap_use->_obj_entry->cap_obj->cap_class != rpc_ctx->obj->cap_class)
- /* Different classes. */
- {
- pthread_mutex_lock (&cap_class->lock);
- _hurd_cap_list_item_remove (&cap_use->_worker_class);
- _hurd_cap_class_cond_check (cap_class);
- pthread_mutex_unlock (&cap_class->lock);
- }
-
- client_cleanup:
- pthread_mutex_lock (&client->lock);
-
- /* You are not allowed to revoke a capability while there are
- pending RPCs on it. This is the reason we know that there must
- be at least one extra internal reference. FIXME: For
- cleanliness, this could still call some inline function that does
- the decrement. The assert can be a hint to the compiler to
- optimize the inline function expansion anyway. */
- assert (!obj_entry->dead);
- assert (obj_entry->internal_refs > 1);
- obj_entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-
- return err;
-}
-
-
-/* End the use of the object CAP_USE->OBJ, which must be locked. */
-void
-hurd_cap_ctx_end_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- struct hurd_cap_ctx_cap_use *cap_use)
-{
- _hurd_cap_obj_entry_t entry = cap_use->_obj_entry;
- hurd_cap_obj_t obj = entry->cap_obj;
- _hurd_cap_client_t client = rpc_ctx->client;
-
- /* Is this an additional use of the main capability object? */
- if (EXPECT_TRUE (obj != rpc_ctx->obj))
- /* No. */
- {
- hurd_cap_class_t cap_class = obj->cap_class;
-
- /* End the RPC on the object. */
- _hurd_cap_list_item_remove (&cap_use->_worker_obj);
- _hurd_cap_obj_cond_check (obj);
-
- if (cap_class != rpc_ctx->obj->cap_class)
- /* The capability object is in a different class from the primary
- capability object. */
- {
- pthread_mutex_lock (&cap_class->lock);
- _hurd_cap_list_item_remove (&cap_use->_worker_class);
- _hurd_cap_class_cond_check (cap_class);
- pthread_mutex_unlock (&cap_class->lock);
- }
- }
-
- hurd_cap_obj_unlock (obj);
-
- /* You are not allowed to revoke a capability while there are
- pending RPCs on it. This is the reason why we know that there
- must be at least one extra internal reference. FIXME: For
- cleanliness, this could still call some inline function that does
- the decrement. The assert can be a hint to the compiler to
- optimize the inline function expansion anyway. */
-
- pthread_mutex_lock (&client->lock);
- assert (!entry->dead);
- assert (entry->internal_refs > 1);
- entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-}