mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-25 08:21:08 +00:00
nova: support dropping caps just locally
without revocation of all subsequent delegations. Fixes #1950
This commit is contained in:
parent
0ac1d1774d
commit
77c4510787
repos/base-nova
include
ports
src
@ -60,7 +60,7 @@ namespace Genode {
|
||||
|
||||
Cap_range *find_by_id(addr_t);
|
||||
|
||||
void inc(unsigned id, bool inc_if_one = false);
|
||||
void inc(unsigned id);
|
||||
void dec(unsigned id, bool revoke = true, unsigned num_log2 = 0);
|
||||
|
||||
addr_t alloc(size_t const num_log2);
|
||||
@ -88,10 +88,10 @@ namespace Genode {
|
||||
|
||||
bool valid() const { return _range; }
|
||||
|
||||
inline void inc(bool inc_if_one = false)
|
||||
inline void inc()
|
||||
{
|
||||
if (_range)
|
||||
_range->inc(_local_name - _range->base(), inc_if_one);
|
||||
_range->inc(_local_name - _range->base());
|
||||
}
|
||||
|
||||
inline void dec()
|
||||
|
@ -60,10 +60,10 @@ namespace Genode {
|
||||
|
||||
protected:
|
||||
|
||||
inline void _inc(bool inc_if_one = false) const
|
||||
inline void _inc() const
|
||||
{
|
||||
Cap_index idx(cap_map()->find(local_name()));
|
||||
idx.inc(inc_if_one);
|
||||
idx.inc();
|
||||
}
|
||||
|
||||
inline void _dec() const
|
||||
@ -106,15 +106,6 @@ namespace Genode {
|
||||
bool operator==(const Native_capability &o) const {
|
||||
return local_name() == o.local_name(); }
|
||||
|
||||
/**
|
||||
* Inhibit removal of capability from cap map if it's the last reference
|
||||
*/
|
||||
void keep_if_last_reference()
|
||||
{
|
||||
if (valid())
|
||||
_inc(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
|
@ -298,21 +298,37 @@ namespace Nova {
|
||||
* \param sm SM selector which gets an up() by the kernel if the
|
||||
* memory of the current revoke invocation gets freed up
|
||||
* (end of RCU period)
|
||||
* \param kim keep_in_mdb - if set to true the kernel will make the
|
||||
* resource inaccessible for solely for the specified pd.
|
||||
* All already beforehand delegated resources will not be
|
||||
* changed, e.g. revoked. All rights of the local resource
|
||||
* will be removed (independent of what is specified by crd).
|
||||
*/
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t revoke(Crd crd, bool self = true, bool remote = false,
|
||||
mword_t pd = 0, mword_t sm = 0)
|
||||
mword_t pd = 0, mword_t sm = 0, bool kim = false)
|
||||
{
|
||||
uint8_t flags = self ? 0x1 : 0;
|
||||
|
||||
if (remote)
|
||||
flags |= 0x2;
|
||||
if (kim)
|
||||
flags |= 0x4;
|
||||
|
||||
mword_t value_crd = crd.value();
|
||||
return syscall_5(NOVA_REVOKE, flags, sm, value_crd, pd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shortcut for revoke, where solely the local cap should be revoked and
|
||||
* not all subsequent delegations of the local cap.
|
||||
*/
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t drop(Crd crd) {
|
||||
return revoke(crd, true, false, 0, 0, true); }
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t lookup(Crd &crd)
|
||||
{
|
||||
|
@ -250,21 +250,38 @@ namespace Nova {
|
||||
* \param sm SM selector which gets an up() by the kernel if the
|
||||
* memory of the current revoke invocation gets freed up
|
||||
* (end of RCU period)
|
||||
* \param kim keep_in_mdb - if set to true the kernel will make the
|
||||
* resource inaccessible solely inside the specified pd.
|
||||
* All already beforehand delegated resources will not be
|
||||
* changed, e.g. revoked. All rights of the local resource
|
||||
* will be removed (independent of what is specified by crd).
|
||||
*/
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t revoke(Crd crd, bool self = true, bool remote = false,
|
||||
mword_t pd = 0, mword_t sm = 0)
|
||||
mword_t pd = 0, mword_t sm = 0, bool kim = false)
|
||||
{
|
||||
uint8_t flags = self ? 0x1 : 0;
|
||||
|
||||
if (remote)
|
||||
flags |= 0x2;
|
||||
|
||||
if (kim)
|
||||
flags |= 0x4;
|
||||
|
||||
mword_t value_crd = crd.value();
|
||||
return syscall_5(NOVA_REVOKE, flags, sm, value_crd, pd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shortcut for revoke, where solely the local cap should be revoked and
|
||||
* not all subsequent delegations of the local cap.
|
||||
*/
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t drop(Crd crd) {
|
||||
return revoke(crd, true, false, 0, 0, true); }
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t lookup(Crd &crd)
|
||||
{
|
||||
|
@ -1 +1 @@
|
||||
061565ecaea829f5a5ab48e39b4fae9148da7e4b
|
||||
bde8909f6367ea2767c54b85ddf90afc2e6baee8
|
||||
|
@ -4,7 +4,7 @@ DOWNLOADS := nova.git
|
||||
|
||||
# r9 branch - use r9_debug for more verbose kernel messages
|
||||
URL(nova) := https://github.com/alex-ab/NOVA.git
|
||||
REV(nova) := 172fe0dc1b6228fec20e220d2524f25b1016f6ab
|
||||
REV(nova) := 8548c34df01504789b01f4e1a31b71e6d08a79c7
|
||||
DIR(nova) := src/kernel/nova
|
||||
|
||||
PATCHES := $(wildcard $(REP_DIR)/patches/*.patch)
|
||||
|
@ -42,15 +42,12 @@ Cap_range *Cap_range::find_by_id(addr_t id)
|
||||
}
|
||||
|
||||
|
||||
void Cap_range::inc(unsigned id, bool inc_if_one)
|
||||
void Cap_range::inc(unsigned id)
|
||||
{
|
||||
bool failure = false;
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (inc_if_one && _cap_array[id] != 1)
|
||||
return;
|
||||
|
||||
if (_cap_array[id] + 1 == 0)
|
||||
failure = true;
|
||||
else
|
||||
@ -78,7 +75,7 @@ void Cap_range::dec(unsigned const id_start, bool revoke, unsigned num_log_2)
|
||||
}
|
||||
|
||||
if (revoke && _cap_array[id] == 1)
|
||||
Nova::revoke(Nova::Obj_crd(_base + id, 0));
|
||||
Nova::drop(Nova::Obj_crd(_base + id, 0));
|
||||
|
||||
_cap_array[id]--;
|
||||
}
|
||||
|
@ -166,15 +166,6 @@ void Rpc_entrypoint::_activation_entry()
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inhibit removal of capabilities sent as results of client requests.
|
||||
* This prevents the recursive revocation of NOVA portal caps and,
|
||||
* therefore, permits clients to use result capabilities after server
|
||||
* code dropped all references.
|
||||
*/
|
||||
for (unsigned i = 0; i < ep._snd_buf.used_caps(); ++i)
|
||||
ep._snd_buf.cap(i).keep_if_last_reference();
|
||||
|
||||
/* dispatch request */
|
||||
ep._snd_buf.reset();
|
||||
try { exc = obj->dispatch(opcode, unmarshaller, ep._snd_buf); }
|
||||
|
59
repos/base-nova/src/test/platform/ipc.cc
Normal file
59
repos/base-nova/src/test/platform/ipc.cc
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* \brief Helper classes to make raw Nova IPC calls which can't be expressed
|
||||
* via the Genode base RPC abstractions
|
||||
* \author Alexander Boettcher
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/thread.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* test specific includes */
|
||||
#include "server.h"
|
||||
|
||||
using namespace Test;
|
||||
|
||||
long Test::cap_void_manual(Genode::Native_capability dst,
|
||||
Genode::Native_capability arg1,
|
||||
Genode::addr_t &local_reply)
|
||||
{
|
||||
Genode::Thread * myself = Genode::Thread::myself();
|
||||
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
|
||||
|
||||
/* save original receive window */
|
||||
Nova::Crd orig_crd = utcb->crd_rcv;
|
||||
|
||||
/* don't open receive window */
|
||||
utcb->crd_rcv = Nova::Obj_crd();
|
||||
/* not used on base-nova */
|
||||
utcb->msg[0] = 0;
|
||||
/* method number of RPC interface to be called on server side */
|
||||
utcb->msg[1] = 0;
|
||||
utcb->set_msg_word(2);
|
||||
|
||||
if (!arg1.valid())
|
||||
return Genode::Rpc_exception_code::INVALID_OBJECT;
|
||||
|
||||
Nova::Obj_crd crd(arg1.local_name(), 0, arg1.dst().rights());
|
||||
if (!utcb->append_item(crd, 0, false, false, false))
|
||||
return Genode::Rpc_exception_code::INVALID_OBJECT;
|
||||
|
||||
Genode::uint8_t res = Nova::call(dst.local_name());
|
||||
|
||||
/* restore original receive window */
|
||||
utcb->crd_rcv = orig_crd;
|
||||
|
||||
local_reply = utcb->msg[2];
|
||||
return (res == Nova::NOVA_OK && utcb->msg_words() == 3)
|
||||
? utcb->msg[0] : Genode::Rpc_exception_code::INVALID_OBJECT;
|
||||
}
|
@ -32,8 +32,236 @@ static unsigned failed = 0;
|
||||
|
||||
static unsigned check_pat = 1;
|
||||
|
||||
static Genode::Cap_connection cap;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void test_translate()
|
||||
{
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_translate");
|
||||
|
||||
Test::Component component;
|
||||
Test::Capability session_cap = ep.manage(&component);
|
||||
Test::Client client(session_cap);
|
||||
|
||||
Genode::addr_t local_name = Native_thread::INVALID_INDEX;
|
||||
|
||||
long rpc = Test::cap_void_manual(session_cap, session_cap, local_name);
|
||||
if (rpc != Genode::Rpc_exception_code::SUCCESS ||
|
||||
local_name == session_cap.local_name() ||
|
||||
local_name == Native_thread::INVALID_INDEX)
|
||||
{
|
||||
failed ++;
|
||||
PERR("%s: ipc call failed %lx", __func__, rpc);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Native_capability copy1(local_name);
|
||||
|
||||
rpc = Test::cap_void_manual(session_cap, copy1, local_name);
|
||||
if (rpc != Genode::Rpc_exception_code::SUCCESS ||
|
||||
local_name == copy1.local_name() ||
|
||||
local_name == Native_thread::INVALID_INDEX)
|
||||
{
|
||||
failed ++;
|
||||
PERR("%s: ipc call failed %lx", __func__, rpc);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Native_capability copy2(local_name);
|
||||
|
||||
PINF("delegation session_cap->copy1->copy2 0x%lx->0x%lx->0x%lx",
|
||||
session_cap.local_name(), copy1.local_name(), copy2.local_name());
|
||||
|
||||
/* sanity checks translate which must work */
|
||||
Genode::Native_capability got_cap = client.cap_cap(copy2.local_name());
|
||||
if (got_cap.local_name() != copy1.local_name()) {
|
||||
failed ++;
|
||||
PERR("%u:%s translate failed", __LINE__, __func__);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
got_cap = client.cap_cap(copy1.local_name());
|
||||
if (got_cap.local_name() != session_cap.local_name()) {
|
||||
failed ++;
|
||||
PERR("%u:%s translate failed", __LINE__, __func__);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
got_cap = client.cap_cap(session_cap.local_name());
|
||||
if (got_cap.local_name() != session_cap.local_name()) {
|
||||
failed ++;
|
||||
PERR("%u:%s translate failed", __LINE__, __func__);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test special revoke by make the intermediate cap (copy1) inaccessible
|
||||
* and check that translate of copy2 get the right results.
|
||||
*/
|
||||
|
||||
Nova::Obj_crd crd_ses(copy1.local_name(), 0);
|
||||
enum { SELF = true, LOCAL_REVOKE = false, LOCAL_PD = 0, NO_BLOCKING = 0, KEEP_IN_MDB = true };
|
||||
Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING, KEEP_IN_MDB);
|
||||
|
||||
crd_ses = Nova::Obj_crd(copy1.local_name(), 0);
|
||||
Genode::uint8_t res = Nova::lookup(crd_ses);
|
||||
if (res != Nova::NOVA_OK || !crd_ses.is_null()) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x", __LINE__, res);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy1 should be skipped and session_cap is the valid response */
|
||||
got_cap = client.cap_cap(copy2.local_name());
|
||||
if (got_cap.local_name() != session_cap.local_name()) {
|
||||
failed ++;
|
||||
PERR("%u:%s translate failed", __LINE__, __func__);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
ep.dissolve(&component);
|
||||
}
|
||||
|
||||
void test_revoke()
|
||||
{
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_revoke");
|
||||
|
||||
Test::Component component;
|
||||
Test::Capability session_cap = ep.manage(&component);
|
||||
Test::Client client(session_cap);
|
||||
|
||||
Genode::addr_t local_name = Native_thread::INVALID_INDEX;
|
||||
|
||||
long rpc = Test::cap_void_manual(session_cap, session_cap, local_name);
|
||||
if (rpc != Genode::Rpc_exception_code::SUCCESS ||
|
||||
local_name == session_cap.local_name() ||
|
||||
local_name == Native_thread::INVALID_INDEX)
|
||||
{
|
||||
failed ++;
|
||||
PERR("test_revoke ipc call failed %lx", rpc);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Native_capability copy_session_cap(local_name);
|
||||
|
||||
rpc = Test::cap_void_manual(copy_session_cap, copy_session_cap, local_name);
|
||||
if (rpc != Genode::Rpc_exception_code::SUCCESS ||
|
||||
local_name == copy_session_cap.local_name() ||
|
||||
local_name == Native_thread::INVALID_INDEX)
|
||||
{
|
||||
failed ++;
|
||||
PERR("test_revoke ipc call failed %lx", rpc);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
Nova::Obj_crd crd_dst(local_name, 0);
|
||||
Genode::uint8_t res = Nova::lookup(crd_dst);
|
||||
if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
|
||||
crd_dst.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed %x", __LINE__, res);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
Nova::Obj_crd crd_ses(copy_session_cap.local_name(), 0);
|
||||
res = Nova::lookup(crd_ses);
|
||||
if (res != Nova::NOVA_OK || crd_ses.base() != copy_session_cap.local_name() || crd_ses.type() != 3 ||
|
||||
crd_ses.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_ses.is_null());
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
res = Nova::lookup(crd_dst);
|
||||
if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
|
||||
crd_dst.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
|
||||
enum { SELF = true, LOCAL_REVOKE = false, LOCAL_PD = 0, NO_BLOCKING = 0, KEEP_IN_MDB = true };
|
||||
Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING, KEEP_IN_MDB);
|
||||
|
||||
crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
|
||||
res = Nova::lookup(crd_ses);
|
||||
if (res != Nova::NOVA_OK || !crd_ses.is_null()) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x", __LINE__, res);
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
res = Nova::lookup(crd_dst);
|
||||
if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
|
||||
crd_dst.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Request some other capability and place it on very same selector
|
||||
* as used before by copy_session_cap
|
||||
*/
|
||||
Genode::Thread * myself = Genode::Thread::myself();
|
||||
Genode::Native_capability pager_cap(myself->native_thread().ec_sel + 1);
|
||||
request_event_portal(pager_cap, copy_session_cap.local_name(), 0, 0);
|
||||
|
||||
/* check whether the requested cap before is valid and placed well */
|
||||
crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
|
||||
res = Nova::lookup(crd_ses);
|
||||
if (res != Nova::NOVA_OK || crd_ses.base() != copy_session_cap.local_name() ||
|
||||
crd_ses.type() != 3 || crd_ses.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_ses.is_null());
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
/* revoke it */
|
||||
Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING);
|
||||
|
||||
/* the delegated cap to the client should still be there */
|
||||
res = Nova::lookup(crd_dst);
|
||||
if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
|
||||
crd_dst.order() != 0) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
|
||||
ep.dissolve(&component);
|
||||
return;
|
||||
}
|
||||
|
||||
/* kill the original session capability */
|
||||
ep.dissolve(&component);
|
||||
/* manually: cap.free_rpc_cap(session_cap); */
|
||||
|
||||
/* the delegated cap to the client should be now invalid */
|
||||
res = Nova::lookup(crd_dst);
|
||||
if (res != Nova::NOVA_OK || !crd_dst.is_null()) {
|
||||
failed ++;
|
||||
PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void test_pat()
|
||||
{
|
||||
/* read out the tsc frequenzy once */
|
||||
@ -47,8 +275,7 @@ void test_pat()
|
||||
|
||||
enum { STACK_SIZE = 4096 };
|
||||
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep");
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_pat");
|
||||
|
||||
Test::Component component;
|
||||
Test::Capability session_cap = ep.manage(&component);
|
||||
@ -138,8 +365,7 @@ void test_server_oom()
|
||||
|
||||
enum { STACK_SIZE = 4096 };
|
||||
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep");
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_oom");
|
||||
|
||||
Test::Component component;
|
||||
Test::Capability session_cap = ep.manage(&component);
|
||||
@ -317,6 +543,12 @@ int main(int argc, char **argv)
|
||||
/* test PAT kernel feature */
|
||||
test_pat();
|
||||
|
||||
/* test special revoke */
|
||||
test_revoke();
|
||||
|
||||
/* test translate together with special revoke */
|
||||
test_translate();
|
||||
|
||||
/**
|
||||
* Test to provoke out of memory during capability transfer of
|
||||
* server/client.
|
||||
|
@ -21,7 +21,15 @@
|
||||
#include <cap_session/connection.h>
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
namespace Test { struct Session; struct Client; struct Component; }
|
||||
namespace Test {
|
||||
struct Session;
|
||||
struct Client;
|
||||
struct Component;
|
||||
|
||||
long cap_void_manual(Genode::Native_capability dst,
|
||||
Genode::Native_capability arg1,
|
||||
Genode::addr_t &local_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test session interface definition
|
||||
@ -30,25 +38,31 @@ struct Test::Session : Genode::Session
|
||||
{
|
||||
static const char *service_name() { return "TEST"; }
|
||||
|
||||
GENODE_RPC(Rpc_cap_void, bool, cap_void,
|
||||
Genode::Native_capability);
|
||||
GENODE_RPC(Rpc_cap_void, bool, cap_void, Genode::Native_capability,
|
||||
Genode::addr_t &);
|
||||
GENODE_RPC(Rpc_void_cap, Genode::Native_capability,
|
||||
void_cap);
|
||||
GENODE_RPC(Rpc_cap_cap, Genode::Native_capability, cap_cap,
|
||||
Genode::addr_t);
|
||||
GENODE_RPC(Rpc_leak_utcb_address, Genode::addr_t, leak_utcb_address);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_leak_utcb_address);
|
||||
GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_cap_cap,
|
||||
Rpc_leak_utcb_address);
|
||||
};
|
||||
|
||||
struct Test::Client : Genode::Rpc_client<Session>
|
||||
{
|
||||
Client(Capability<Session> cap) : Rpc_client<Session>(cap) { }
|
||||
|
||||
bool cap_void(Genode::Native_capability cap) {
|
||||
return call<Rpc_cap_void>(cap); }
|
||||
bool cap_void(Genode::Native_capability cap, Genode::addr_t &local_name) {
|
||||
return call<Rpc_cap_void>(cap, local_name); }
|
||||
|
||||
Genode::Native_capability void_cap() {
|
||||
return call<Rpc_void_cap>(); }
|
||||
|
||||
Genode::Native_capability cap_cap(Genode::addr_t cap) {
|
||||
return call<Rpc_cap_cap>(cap); }
|
||||
|
||||
Genode::addr_t leak_utcb_address() {
|
||||
return call<Rpc_leak_utcb_address>(); }
|
||||
};
|
||||
@ -56,9 +70,11 @@ struct Test::Client : Genode::Rpc_client<Session>
|
||||
struct Test::Component : Genode::Rpc_object<Test::Session, Test::Component>
|
||||
{
|
||||
/* Test to transfer a object capability during send */
|
||||
bool cap_void(Genode::Native_capability);
|
||||
bool cap_void(Genode::Native_capability, Genode::addr_t &);
|
||||
/* Test to transfer a object capability during reply */
|
||||
Genode::Native_capability void_cap();
|
||||
/* Test to transfer a specific object capability during reply */
|
||||
Genode::Native_capability cap_cap(Genode::addr_t);
|
||||
/* Leak utcb address of entrypoint to manipulate utcb receive window */
|
||||
Genode::addr_t leak_utcb_address();
|
||||
};
|
||||
@ -68,7 +84,11 @@ namespace Test { typedef Genode::Capability<Test::Session> Capability; }
|
||||
/**
|
||||
* Session implementation
|
||||
*/
|
||||
bool Test::Component::cap_void(Genode::Native_capability got_cap) {
|
||||
inline bool Test::Component::cap_void(Genode::Native_capability got_cap,
|
||||
Genode::addr_t &local_name)
|
||||
{
|
||||
local_name = got_cap.local_name();
|
||||
|
||||
if (!got_cap.valid())
|
||||
return false;
|
||||
|
||||
@ -79,7 +99,7 @@ bool Test::Component::cap_void(Genode::Native_capability got_cap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Genode::Native_capability Test::Component::void_cap() {
|
||||
inline Genode::Native_capability Test::Component::void_cap() {
|
||||
Genode::Native_capability send_cap = cap();
|
||||
|
||||
/* XXX this code does does no longer work since the removal of 'solely_map' */
|
||||
@ -91,5 +111,8 @@ Genode::Native_capability Test::Component::void_cap() {
|
||||
return send_cap;
|
||||
}
|
||||
|
||||
Genode::addr_t Test::Component::leak_utcb_address() {
|
||||
inline Genode::addr_t Test::Component::leak_utcb_address() {
|
||||
return reinterpret_cast<Genode::addr_t>(Genode::Thread::myself()->utcb()); }
|
||||
|
||||
inline Genode::Native_capability Test::Component::cap_cap(Genode::addr_t cap) {
|
||||
return Genode::Native_capability(cap); }
|
||||
|
@ -1,3 +1,3 @@
|
||||
TARGET = test-platform
|
||||
SRC_CC = main.cc
|
||||
SRC_CC = main.cc ipc.cc
|
||||
LIBS = base config
|
||||
|
Loading…
Reference in New Issue
Block a user