mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 07:46:42 +00:00
Linux: Don't access file system outside of core
This patch changes the way of how dataspace content is accessed by processes outside of core. Dataspaces are opened by core only and the corresponding file descriptors are handed out the other processes via the 'Linux_dataspace::fd()' RPC function. At the client side, the returned file descriptor is then used to mmap the file. Consequently, this patch eliminates all files from 'lx_rpath'. The path is still needed by core to temporarily create dataspaces and unix domain sockets. However, those files are unlinked immediately after their creation.
This commit is contained in:
parent
aee0a2061b
commit
7cb45e9648
@ -40,7 +40,8 @@ namespace Genode {
|
||||
** Linux-specific dataspace interface **
|
||||
****************************************/
|
||||
|
||||
Filename fname() { return call<Rpc_fname>(); }
|
||||
Filename fname() { return call<Rpc_fname>(); }
|
||||
Untyped_capability fd() { return call<Rpc_fd>(); }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,23 +24,31 @@ namespace Genode {
|
||||
struct Linux_dataspace : Dataspace
|
||||
{
|
||||
enum { FNAME_LEN = 32 };
|
||||
|
||||
struct Filename { char buf[FNAME_LEN]; };
|
||||
|
||||
virtual ~Linux_dataspace() { }
|
||||
|
||||
/**
|
||||
* Request name of file that represents the dataspace on Linux
|
||||
*
|
||||
* This function is used for calling execve on files passed as ROM
|
||||
* dataspaces.
|
||||
*/
|
||||
virtual Filename fname() = 0;
|
||||
|
||||
/**
|
||||
* Request file descriptor of the dataspace
|
||||
*/
|
||||
virtual Untyped_capability fd() = 0;
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
|
||||
GENODE_RPC(Rpc_fname, Filename, fname);
|
||||
GENODE_RPC_INTERFACE_INHERIT(Dataspace, Rpc_fname);
|
||||
GENODE_RPC(Rpc_fd, Untyped_capability, fd);
|
||||
GENODE_RPC_INTERFACE_INHERIT(Dataspace, Rpc_fname, Rpc_fd);
|
||||
};
|
||||
}
|
||||
|
||||
|
33
base-linux/src/base/env/rm_session_mmap.cc
vendored
33
base-linux/src/base/env/rm_session_mmap.cc
vendored
@ -46,29 +46,30 @@ static void *map_local(Dataspace_capability ds, Genode::size_t size,
|
||||
addr_t offset, bool use_local_addr, addr_t local_addr,
|
||||
bool executable)
|
||||
{
|
||||
Linux_dataspace::Filename fname = Linux_dataspace_client(ds).fname();
|
||||
fname.buf[sizeof(fname.buf) - 1] = 0;
|
||||
int const fd = Linux_dataspace_client(ds).fd().dst().socket;
|
||||
bool const writable = Dataspace_client(ds).writable();
|
||||
|
||||
bool writable = Dataspace_client(ds).writable();
|
||||
int fd = lx_open(fname.buf, (writable ? O_RDWR : O_RDONLY) | LX_O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
PERR("map_local: Could not open file \"%s\"", fname.buf);
|
||||
throw Rm_session::Invalid_dataspace();
|
||||
}
|
||||
|
||||
int flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0);
|
||||
int prot = PROT_READ | (writable ? PROT_WRITE : 0) | (executable ? PROT_EXEC : 0);
|
||||
void *addr = lx_mmap(use_local_addr ? (void*)local_addr : 0, size,
|
||||
prot, flags, fd, offset);
|
||||
int const flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0);
|
||||
int const prot = PROT_READ
|
||||
| (writable ? PROT_WRITE : 0)
|
||||
| (executable ? PROT_EXEC : 0);
|
||||
void * const addr_in = use_local_addr ? (void*)local_addr : 0;
|
||||
void * const addr_out = lx_mmap(addr_in, size, prot, flags, fd, offset);
|
||||
|
||||
/*
|
||||
* We can close the file after calling mmap. The Linux kernel will still
|
||||
* keep the file mapped. By immediately closing the file descriptor, we
|
||||
* won't need to keep track of dataspace file descriptors within the
|
||||
* process.
|
||||
*/
|
||||
lx_close(fd);
|
||||
|
||||
if (((long)addr < 0) && ((long)addr > -4095)) {
|
||||
PERR("map_local: return value of mmap is %ld", (long)addr);
|
||||
if (((long)addr_out < 0) && ((long)addr_out > -4095)) {
|
||||
PERR("map_local: return value of mmap is %ld", (long)addr_out);
|
||||
throw Rm_session::Region_conflict();
|
||||
}
|
||||
|
||||
return addr;
|
||||
return addr_out;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@ namespace Genode {
|
||||
size_t _size; /* size of dataspace in bytes */
|
||||
addr_t _addr; /* meaningless on linux */
|
||||
Filename _fname; /* filename for mmap */
|
||||
int _fd; /* file descriptor */
|
||||
bool _writable; /* false if read-only */
|
||||
|
||||
/* Holds the dataspace owner if a distinction between owner and
|
||||
@ -53,14 +54,14 @@ namespace Genode {
|
||||
Dataspace_component(size_t size, addr_t addr,
|
||||
bool /* write_combined */, bool writable,
|
||||
Dataspace_owner * owner)
|
||||
: _size(size), _addr(addr), _writable(writable),
|
||||
: _size(size), _addr(addr), _fd(-1), _writable(writable),
|
||||
_owner(owner) { }
|
||||
|
||||
/**
|
||||
* Default constructor returns invalid dataspace
|
||||
*/
|
||||
Dataspace_component() : _size(0), _addr(0), _writable(false),
|
||||
_owner(0) { }
|
||||
Dataspace_component()
|
||||
: _size(0), _addr(0), _fd(-1), _writable(false), _owner(0) { }
|
||||
|
||||
/**
|
||||
* This constructor is only provided for compatibility
|
||||
@ -69,20 +70,29 @@ namespace Genode {
|
||||
Dataspace_component(size_t size, addr_t core_local_addr,
|
||||
addr_t phys_addr, bool write_combined,
|
||||
bool writable, Dataspace_owner * _owner)
|
||||
: _size(size), _addr(phys_addr), _owner(_owner)
|
||||
:
|
||||
_size(size), _addr(phys_addr), _fd(-1), _owner(_owner)
|
||||
{
|
||||
PWRN("Should only be used for IOMEM and not within Linux.");
|
||||
_fname.buf[0] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define/request corresponding filename of dataspace
|
||||
* Define corresponding filename of dataspace
|
||||
*
|
||||
* To use dataspaces as shared memory objects on Linux, we have to
|
||||
* assign a file to each dataspace. This way, multiple Linux process
|
||||
* can mmap this file.
|
||||
* The file name is only relevant for ROM dataspaces that should
|
||||
* be executed via execve.
|
||||
*/
|
||||
void fname(const char *fname) { strncpy(_fname.buf, fname, sizeof(_fname.buf)); }
|
||||
|
||||
/**
|
||||
* Assign file descriptor to dataspace
|
||||
*
|
||||
* The file descriptor assigned to the dataspace will be enable
|
||||
* processes outside of core to mmap the dataspace.
|
||||
*/
|
||||
void fd(int fd) { _fd = fd; }
|
||||
|
||||
/**
|
||||
* Check if dataspace is owned by a specified object
|
||||
*/
|
||||
@ -102,6 +112,13 @@ namespace Genode {
|
||||
****************************************/
|
||||
|
||||
Filename fname() { return _fname; }
|
||||
|
||||
Untyped_capability fd()
|
||||
{
|
||||
typedef Untyped_capability::Dst Dst;
|
||||
enum { DUMMY_LOCAL_NAME = 0 };
|
||||
return Untyped_capability(Dst(_fd), DUMMY_LOCAL_NAME);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,24 +32,32 @@ static int ram_ds_cnt = 0; /* counter for creating unique dataspace IDs */
|
||||
|
||||
void Ram_session_component::_export_ram_ds(Dataspace_component *ds)
|
||||
{
|
||||
char fname_buf[Linux_dataspace::FNAME_LEN];
|
||||
char fname[Linux_dataspace::FNAME_LEN];
|
||||
|
||||
/* assign filename to dataspace */
|
||||
snprintf(fname_buf, sizeof(fname_buf), "%s/ds-%d", lx_rpath(), ram_ds_cnt++);
|
||||
|
||||
ds->fname(fname_buf);
|
||||
|
||||
/* create new file representing the dataspace */
|
||||
lx_unlink(fname_buf);
|
||||
int fd = lx_open(fname_buf, O_CREAT | O_RDWR | O_TRUNC | LX_O_CLOEXEC, S_IRWXU);
|
||||
/* create file using a unique file name in 'lx_rpath' */
|
||||
snprintf(fname, sizeof(fname), "%s/ds-%d", lx_rpath(), ram_ds_cnt++);
|
||||
lx_unlink(fname);
|
||||
int const fd = lx_open(fname, O_CREAT|O_RDWR|O_TRUNC|LX_O_CLOEXEC, S_IRWXU);
|
||||
lx_ftruncate(fd, ds->size());
|
||||
lx_close(fd);
|
||||
|
||||
/* remember file descriptor in dataspace component object */
|
||||
ds->fd(fd);
|
||||
|
||||
/*
|
||||
* Wipe the file from the Linux file system. The kernel will still keep the
|
||||
* then unnamed file around until the last reference to the file will be
|
||||
* gone (i.e., an open file descriptor referring to the file). A process
|
||||
* w/o the right file descriptor won't be able to open and access the file.
|
||||
*/
|
||||
lx_unlink(fname);
|
||||
}
|
||||
|
||||
|
||||
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds)
|
||||
{
|
||||
lx_unlink(ds->fname().buf);
|
||||
int const fd = ds->fd().dst().socket;
|
||||
if (fd != -1)
|
||||
lx_close(fd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,15 +45,15 @@ Rom_session_component::Rom_session_component(Rom_fs *rom_fs,
|
||||
: _ds_ep(ds_ep)
|
||||
{
|
||||
/* extract filename from session arguments */
|
||||
char fname_buf[Linux_dataspace::FNAME_LEN];
|
||||
Arg_string::find_arg(args, "filename").string(fname_buf, sizeof(fname_buf), "");
|
||||
char fname[Linux_dataspace::FNAME_LEN];
|
||||
Arg_string::find_arg(args, "filename").string(fname, sizeof(fname), "");
|
||||
|
||||
/* only files inside the current working directory are allowed */
|
||||
for (const char *c = fname_buf; *c; c++)
|
||||
for (const char *c = fname; *c; c++)
|
||||
if (*c == '/')
|
||||
throw Root::Invalid_args();
|
||||
|
||||
Genode::size_t fsize = file_size(fname_buf);
|
||||
Genode::size_t const fsize = file_size(fname);
|
||||
|
||||
/* use invalid capability as default value */
|
||||
_ds_cap = Rom_dataspace_capability();
|
||||
@ -62,8 +62,11 @@ Rom_session_component::Rom_session_component(Rom_fs *rom_fs,
|
||||
if (fsize == 0)
|
||||
throw Root::Invalid_args();
|
||||
|
||||
int const fd = lx_open(fname, O_RDONLY | LX_O_CLOEXEC, S_IRUSR | S_IXUSR);
|
||||
|
||||
_ds = Dataspace_component(fsize, 0, false, false, 0);
|
||||
_ds.fname(fname_buf);
|
||||
_ds.fd(fd);
|
||||
_ds.fname(fname);
|
||||
|
||||
Dataspace_capability ds_cap = _ds_ep->manage(&_ds);
|
||||
_ds_cap = static_cap_cast<Rom_dataspace>(ds_cap);
|
||||
@ -73,4 +76,8 @@ Rom_session_component::Rom_session_component(Rom_fs *rom_fs,
|
||||
Rom_session_component::~Rom_session_component()
|
||||
{
|
||||
_ds_ep->dissolve(&_ds);
|
||||
|
||||
int const fd = _ds.fd().dst().socket;
|
||||
if (fd != -1)
|
||||
lx_close(fd);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <sched.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
|
Loading…
Reference in New Issue
Block a user