Delegate access to entrypoints via SCM rights

This patch eliminates the thread ID portion of the 'Native_capability'
type. The access to entrypoints is now exclusively handled by passing
socket descripts over Unix domain sockets and by inheriting the socket
descriptor of the parent entrypoint at process-creation time.

Each entrypoint creates a socket pair. The server-side socket is bound
to a unique name defined by the server. The client-side socket is then
connected to the same name. Whereas the server-side socket is meant to
be exclusively used by the server to wait for incoming requests, the
client-side socket can be delegated to other processes as payload of RPC
messages (via SCM rights). Anyone who receives a capability over RPC
receives the client-side socket of the entrypoint to which the
capability refers. Given this socket descriptor, the unique name (as
defined by the server) can be requested using 'getpeername'. Using this
name, it is possible to compare socket descriptors, which is important
to avoid duplicates from polluting the limited socket-descriptor name
space.

Wheras this patch introduces capability-based delegation of access
rights to entrypoints, it does not cover the protection of the integrity
of RPC objects. RPC objects are still referenced by a global ID passed
as normal message payload.
This commit is contained in:
Norman Feske
2012-08-08 22:01:04 +02:00
parent 64efaf249a
commit f33c7c73bd
10 changed files with 337 additions and 210 deletions

View File

@ -16,50 +16,23 @@
#include <base/ipc_generic.h>
#include <base/snprintf.h>
extern "C" int raw_write_str(const char *str);
extern "C" void wait_for_continue(void);
#define PRAWW(fmt, ...) \
do { \
char str[128]; \
Genode::snprintf(str, sizeof(str), \
ESC_ERR fmt ESC_END "\n", ##__VA_ARGS__); \
raw_write_str(str); \
} while (0)
inline void Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap)
{
PRAWW("_marshal_capability called: local_name=%ld, tid=%ld, socket=%d",
cap.local_name(), cap.dst().tid, cap.dst().socket);
_write_to_buf(cap.local_name());
_write_to_buf(cap.dst().tid);
if (cap.valid()) {
PRAWW("append_cap");
if (cap.valid())
_snd_msg->append_cap(cap.dst().socket);
}
}
inline void Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap)
{
long local_name = 0;
long tid = 0;
int socket = -1;
_read_from_buf(local_name);
_read_from_buf(tid);
bool const cap_valid = (tid != 0);
if (cap_valid)
socket = _rcv_msg->read_cap();
cap = Native_capability(Cap_dst_policy::Dst(tid, socket), local_name);
int const socket = _rcv_msg->read_cap();
cap = Native_capability(Cap_dst_policy::Dst(socket), local_name);
}
#endif /* _INCLUDE__BASE__IPC_H_ */

View File

@ -91,10 +91,6 @@ namespace Genode {
{
return index < _used_caps ? _caps[index] : -1;
}
size_t used_size() const { return _used_size; }
void used_size(size_t used_size) { _used_size = used_size; }
};

View File

@ -56,7 +56,7 @@ namespace Genode {
static IF *deref(Capability<IF> cap)
{
/* check if this is a pseudo capability */
if (cap.dst().tid != 0 || !cap.local_name())
if (cap.dst().socket != -1 || !cap.local_name())
throw Non_local_capability();
/*

View File

@ -98,19 +98,17 @@ namespace Genode {
{
struct Dst
{
long tid; /* XXX to be removed once the transition to SCM rights
is completed */
int socket;
/**
* Default constructor creates invalid destination
*/
Dst() : tid(0), socket(-1) { }
Dst() : socket(-1) { }
Dst(long tid, int socket) : tid(tid), socket(socket) { }
explicit Dst(int socket) : socket(socket) { }
};
static bool valid(Dst id) { return id.tid != 0; }
static bool valid(Dst id) { return id.socket != -1; }
static Dst invalid() { return Dst(); }
static void copy(void* dst, Native_capability_tpl<Cap_dst_policy>* src);
};
@ -125,7 +123,15 @@ namespace Genode {
/**
* The connection state is the socket handle of the RPC entrypoint
*/
typedef int Native_connection_state;
struct Native_connection_state
{
int server_sd;
int client_sd;
Native_connection_state() : server_sd(-1), client_sd(-1) { }
};
enum { PARENT_SOCKET_HANDLE = 100 };
struct Native_config
{

View File

@ -28,6 +28,7 @@
#include <parent/client.h>
#include <ram_session/client.h>
#include <cpu_session/client.h>
#include <pd_session/client.h>
namespace Genode {
@ -323,13 +324,12 @@ namespace Genode {
Parent_capability _parent_cap()
{
long tid = _get_env_ulong("parent_tid");
long local_name = _get_env_ulong("parent_local_name");
/* produce typed capability manually */
typedef Native_capability::Dst Dst;
return reinterpret_cap_cast<Parent>(Native_capability(Dst(tid, -1),
local_name));
Dst const dst(PARENT_SOCKET_HANDLE);
return reinterpret_cap_cast<Parent>(Native_capability(dst, local_name));
}
@ -343,6 +343,7 @@ namespace Genode {
Cpu_session_capability _cpu_session_cap;
Cpu_session_client _cpu_session_client;
Rm_session_mmap _rm_session_mmap;
Pd_session_client _pd_session_client;
Heap _heap;
public:
@ -358,6 +359,7 @@ namespace Genode {
_cpu_session_cap(static_cap_cast<Cpu_session>(parent()->session("Env::cpu_session", ""))),
_cpu_session_client(_cpu_session_cap),
_rm_session_mmap(false),
_pd_session_client(static_cap_cast<Pd_session>(parent()->session("Env::pd_session", ""))),
_heap(&_ram_session_client, &_rm_session_mmap)
{ }