core: fix regression in dataspace ownership test

This patch revives our ds_ownership test from 2012, which just revealed
a regression in core where the dataspace-free operation of the RAM
service would unconditionally destroy dataspace objects from foreign
sessions. The patch fixes the bug and adds an updated version of the
test to the autopilot.

Fixes #2065
This commit is contained in:
Norman Feske 2016-08-19 17:55:39 +02:00 committed by Christian Helmuth
parent fdf41cd08c
commit 8d1cf08b1a
4 changed files with 35 additions and 40 deletions

View File

@ -33,10 +33,7 @@ install_config {
build_boot_image "core init test-ds_ownership" build_boot_image "core init test-ds_ownership"
run_genode_until {.*Test ended.*\.} 10 append qemu_args "-nographic -m 64"
grep_output {\[init -\> test-ds_ownership\] Test ended} run_genode_until {.*test succeeded.*\n} 10
compare_output_to {
[init -> test-ds_ownership] Test ended successfully.
}

View File

@ -34,13 +34,13 @@ addr_t Ram_session_component::phys_addr(Ram_dataspace_capability ds)
void Ram_session_component::_free_ds(Dataspace_capability ds_cap) void Ram_session_component::_free_ds(Dataspace_capability ds_cap)
{ {
Dataspace_component *ds; Dataspace_component *ds = nullptr;
_ds_ep->apply(ds_cap, [&] (Dataspace_component *c) _ds_ep->apply(ds_cap, [&] (Dataspace_component *c)
{ {
ds = c; if (!c) return;
if (!c->owner(this)) return;
if (!ds) return; ds = c;
if (!ds->owner(this)) return;
size_t ds_size = ds->size(); size_t ds_size = ds->size();
@ -62,6 +62,7 @@ void Ram_session_component::_free_ds(Dataspace_capability ds_cap)
}); });
/* call dataspace destructors and free memory */ /* call dataspace destructors and free memory */
if (ds)
destroy(&_ds_slab, ds); destroy(&_ds_slab, ds);
} }

View File

@ -1,57 +1,53 @@
/* /*
* \brief Testing the distinction between user and owner of a RAM dataspace * \brief Testing the distinction between user and owner of a RAM dataspace
* \author Martin Stein * \author Martin Stein
* \author Norman Feske
* \date 2012-04-19 * \date 2012-04-19
*
*/ */
/* /*
* Copyright (C) 2008-2013 Genode Labs GmbH * Copyright (C) 2008-2016 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */ /* Genode includes */
#include <base/env.h>
#include <ram_session/connection.h> #include <ram_session/connection.h>
#include <base/printf.h> #include <base/log.h>
#include <base/component.h>
using namespace Genode;
int main(int argc, char **argv) void Component::construct(Genode::Env &env)
{ {
/* Create some RAM sessions */ using namespace Genode;
printf("Dataspace ownership test\n");
static Ram_connection ram_1;
static Ram_connection ram_2;
/* Allocate dataspace at one of the RAM sessions */ log("--- dataspace ownership test ---");
ram_1.ref_account(env()->ram_session_cap());
env()->ram_session()->transfer_quota(ram_1.cap(), 8*1024); static Ram_connection ram_1 { env };
static Ram_connection ram_2 { env };
log("allocate dataspace from one RAM session");
ram_1.ref_account(env.ram_session_cap());
env.ram().transfer_quota(ram_1.cap(), 8*1024);
Ram_dataspace_capability ds = ram_1.alloc(sizeof(unsigned)); Ram_dataspace_capability ds = ram_1.alloc(sizeof(unsigned));
/* Try to free dataspace at another RAM session */ log("attempt to free dataspace from foreign RAM session");
ram_2.free(ds); ram_2.free(ds);
/* Check if dataspace was falsely freed */ log("try to attach dataspace to see if it still exists");
try { env()->rm_session()->attach(ds); } env.rm().attach(ds);
catch (...) {
printf("Test ended faulty.\n");
return -2;
}
/* Try to free dataspace at its originating RAM session */ log("attach operation succeeded");
log("free dataspace from legitimate RAM session");
size_t const quota_before_free = ram_1.avail();
ram_1.free(ds); ram_1.free(ds);
size_t const quota_after_free = ram_1.avail();
/* Check if dataspace was freed as expected */ if (quota_after_free > quota_before_free)
try { env()->rm_session()->attach(ds); } log("test succeeded");
catch (...) { else
printf("Test ended successfully.\n"); error("test failed");
return 0;
}
printf("Test ended faulty.\n");
return -4;
} }

View File

@ -66,3 +66,4 @@ clipboard
rust rust
xml_node xml_node
fpu fpu
ds_ownership