mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-22 10:02:33 +00:00
default ahci_drv and part_blk Block sessions to read-only
Add a "writeable" policy option to the ahci_drv and part_blk Block servers and default from writeable to ready-only. Should a policy permit write acesss the session request argument "writeable" may still downgrade a session to ready-only. Fix #2469
This commit is contained in:
parent
cf2886dc8f
commit
1fce8d0d74
repos
dde_linux/src/lib/usb/storage
dde_rump/src/server/rump_cgd
gems/src/server/http_blk
libports/run
os
include/block
run
src
ports/run
@ -222,9 +222,11 @@ void scsi_add_device(struct scsi_device *sdev)
|
||||
* XXX move to 'main'
|
||||
*/
|
||||
if (!announce) {
|
||||
enum { WRITEABLE = true };
|
||||
|
||||
PREPARE_WORK(&delayed, ack_packet);
|
||||
static Block::Root root(_signal->ep(), Lx::Malloc::mem(),
|
||||
_signal->rm(), factory);
|
||||
_signal->rm(), factory, WRITEABLE);
|
||||
_signal->parent().announce(_signal->ep().rpc_ep().manage(&root));
|
||||
announce = true;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct Main
|
||||
|
||||
} factory { env, heap };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
|
||||
Main(Genode::Env &env) : env(env) {
|
||||
env.parent().announce(env.ep().manage(root)); }
|
||||
|
@ -102,7 +102,7 @@ struct Main
|
||||
Env &env;
|
||||
Heap heap { env.ram(), env.rm() };
|
||||
Factory factory { env, heap };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
|
||||
Main(Env &env) : env(env) {
|
||||
env.parent().announce(env.ep().manage(root)); }
|
||||
|
@ -105,7 +105,7 @@ append_if $use_ahci config {
|
||||
</route>
|
||||
<config>}
|
||||
append_if $use_ahci config "
|
||||
<policy label_prefix=\"test-libc_$filesystem\" device=\"0\" />"
|
||||
<policy label_prefix=\"test-libc_$filesystem\" device=\"0\" writeable=\"yes\"/>"
|
||||
append_if $use_ahci config {
|
||||
</config>
|
||||
</start>}
|
||||
|
@ -76,6 +76,7 @@ class Block::Session_component : public Block::Session_component_base,
|
||||
bool _ack_queue_full;
|
||||
Packet_descriptor _p_to_handle;
|
||||
unsigned _p_in_fly;
|
||||
bool _writeable;
|
||||
|
||||
/**
|
||||
* Acknowledge a packet already handled
|
||||
@ -127,6 +128,10 @@ class Block::Session_component : public Block::Session_component_base,
|
||||
break;
|
||||
|
||||
case Block::Packet_descriptor::WRITE:
|
||||
if (!_writeable) {
|
||||
_ack_packet(_p_to_handle);
|
||||
break;
|
||||
}
|
||||
if (_driver.dma_enabled())
|
||||
_driver.write_dma(packet.block_number(),
|
||||
packet.block_count(),
|
||||
@ -178,14 +183,16 @@ class Block::Session_component : public Block::Session_component_base,
|
||||
Session_component(Driver_factory &driver_factory,
|
||||
Genode::Entrypoint &ep,
|
||||
Genode::Region_map &rm,
|
||||
size_t buf_size)
|
||||
size_t buf_size,
|
||||
bool writeable)
|
||||
: Session_component_base(driver_factory, buf_size),
|
||||
Driver_session(rm, _rq_ds, ep.rpc_ep()),
|
||||
_rq_phys(Dataspace_client(_rq_ds).phys_addr()),
|
||||
_sink_ack(ep, *this, &Session_component::_signal),
|
||||
_sink_submit(ep, *this, &Session_component::_signal),
|
||||
_req_queue_full(false),
|
||||
_p_in_fly(0)
|
||||
_p_in_fly(0),
|
||||
_writeable(writeable)
|
||||
{
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
@ -232,9 +239,19 @@ class Block::Session_component : public Block::Session_component_base,
|
||||
void info(sector_t *blk_count, size_t *blk_size,
|
||||
Operations *ops)
|
||||
{
|
||||
Operations driver_ops = _driver.ops();
|
||||
|
||||
*blk_count = _driver.block_count();
|
||||
*blk_size = _driver.block_size();
|
||||
*ops = _driver.ops();
|
||||
*ops = Operations();
|
||||
|
||||
typedef Block::Packet_descriptor::Opcode Opcode;
|
||||
|
||||
if (driver_ops.supported(Opcode::READ))
|
||||
ops->set_operation(Opcode::READ);
|
||||
if (_writeable && driver_ops.supported(Opcode::WRITE))
|
||||
ops->set_operation(Opcode::WRITE);
|
||||
|
||||
}
|
||||
|
||||
void sync() { _driver.sync(); }
|
||||
@ -252,6 +269,7 @@ class Block::Root : public Genode::Root_component<Block::Session_component,
|
||||
Driver_factory &_driver_factory;
|
||||
Genode::Entrypoint &_ep;
|
||||
Genode::Region_map &_rm;
|
||||
bool const _writeable;
|
||||
|
||||
protected:
|
||||
|
||||
@ -283,8 +301,13 @@ class Block::Root : public Genode::Root_component<Block::Session_component,
|
||||
throw Insufficient_ram_quota();
|
||||
}
|
||||
|
||||
bool writeable = _writeable
|
||||
? Arg_string::find_arg(args, "writeable").bool_value(true)
|
||||
: false;
|
||||
|
||||
return new (md_alloc()) Session_component(_driver_factory,
|
||||
_ep, _rm, tx_buf_size);
|
||||
_ep, _rm, tx_buf_size,
|
||||
writeable);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -300,10 +323,11 @@ class Block::Root : public Genode::Root_component<Block::Session_component,
|
||||
Root(Genode::Entrypoint &ep,
|
||||
Allocator &md_alloc,
|
||||
Genode::Region_map &rm,
|
||||
Driver_factory &driver_factory)
|
||||
Driver_factory &driver_factory,
|
||||
bool writeable)
|
||||
:
|
||||
Root_component(ep, md_alloc),
|
||||
_driver_factory(driver_factory), _ep(ep), _rm(rm)
|
||||
_driver_factory(driver_factory), _ep(ep), _rm(rm), _writeable(writeable)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,7 @@ append config {
|
||||
<resource name="RAM" quantum="10M" />
|
||||
<provides><service name="Block" /></provides>
|
||||
<config>
|
||||
<policy label_prefix="test-ahci" device="0" />
|
||||
<policy label_prefix="test-ahci" device="0" writeable="yes" />
|
||||
</config>
|
||||
</start>
|
||||
|
||||
|
@ -64,7 +64,7 @@ append config {
|
||||
<provides><service name="Block" /></provides>
|
||||
<config atapi="yes">
|
||||
<report ports="yes"/>
|
||||
<policy label_prefix="test-ahci" device="0" />
|
||||
<policy label_prefix="test-ahci" device="0" writeable="yes" />
|
||||
</config>
|
||||
<route>
|
||||
<service name="Report"> <child name="ahci_report_rom"/> </service>
|
||||
|
@ -19,15 +19,18 @@ which client can access a certain device:
|
||||
! </route>
|
||||
! <config atapi="no">
|
||||
! <!-- use model and serial number -->
|
||||
! <policy label_prefix="test-ahci" model="QEMU HARDDISK" serial="QM00005" />
|
||||
! <policy label_prefix="test-ahci" model="QEMU HARDDISK" serial="QM00005" writeable="yes" />
|
||||
! <!-- use controller port number -->
|
||||
! <policy label_prefix="bench" device="1" />
|
||||
! <policy label_prefix="bench" device="1" writeable="yes" />
|
||||
! <!-- read-only access -->
|
||||
! <policy label_prefix="boot_fs" device="2"/>
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
In the example above, a session request labeled with "test-ahci" gains access to
|
||||
a device with certain model and serial numbers, while "bench" gains access to
|
||||
device at port 1. ATAPI support is by default disabled and can be enabled by
|
||||
a device with certain model and serial numbers, "bench" gains access to
|
||||
device at port 1, and finally the session "boot_fs" gains read-only access to
|
||||
port 2. ATAPI support is by default disabled and can be enabled by
|
||||
setting the config attribute "atapi" to "yes".
|
||||
|
||||
ahci_drv supports reporting of active ports, which can be enabled via
|
||||
|
@ -57,8 +57,9 @@ class Session_component : public Block::Session_component
|
||||
Session_component(Block::Driver_factory &driver_factory,
|
||||
Genode::Entrypoint &ep,
|
||||
Genode::Region_map &rm,
|
||||
Genode::size_t buf_size)
|
||||
: Block::Session_component(driver_factory, ep, rm, buf_size) { }
|
||||
Genode::size_t buf_size,
|
||||
bool writeable)
|
||||
: Block::Session_component(driver_factory, ep, rm, buf_size, writeable) { }
|
||||
|
||||
Block::Driver_factory &factory() { return _driver_factory; }
|
||||
};
|
||||
@ -73,32 +74,12 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
|
||||
Genode::Allocator &_alloc;
|
||||
Genode::Xml_node _config;
|
||||
|
||||
long _device_num(Session_label const &label, char *model, char *sn, size_t bufs_len)
|
||||
{
|
||||
long num = -1;
|
||||
|
||||
try {
|
||||
Session_policy policy(label, _config);
|
||||
|
||||
/* try read device port number attribute */
|
||||
try { policy.attribute("device").value(&num); }
|
||||
catch (...) { }
|
||||
|
||||
/* try read device model and serial number attributes */
|
||||
model[0] = sn[0] = 0;
|
||||
policy.attribute("model").value(model, bufs_len);
|
||||
policy.attribute("serial").value(sn, bufs_len);
|
||||
|
||||
} catch (...) { }
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
::Session_component *_create_session(const char *args)
|
||||
{
|
||||
Session_label const label = label_from_args(args);
|
||||
Session_policy const policy(label, _config);
|
||||
|
||||
size_t ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
@ -117,18 +98,24 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
|
||||
throw Insufficient_ram_quota();
|
||||
}
|
||||
|
||||
/* Search for configured device */
|
||||
char model_buf[64], sn_buf[64];
|
||||
/* try read device port number attribute */
|
||||
long num = policy.attribute_value("device", -1L);
|
||||
|
||||
/* try read device model and serial number attributes */
|
||||
auto const model = policy.attribute_value("model", String<64>());
|
||||
auto const serial = policy.attribute_value("serial", String<64>());
|
||||
|
||||
/* sessions are not writeable by default */
|
||||
bool writeable = policy.attribute_value("writeable", false);
|
||||
|
||||
long num = _device_num(label, model_buf, sn_buf, sizeof(model_buf));
|
||||
/* prefer model/serial routing */
|
||||
if ((model_buf[0] != 0) && (sn_buf[0] != 0))
|
||||
num = Ahci_driver::device_number(model_buf, sn_buf);
|
||||
if ((model != "") && (serial != ""))
|
||||
num = Ahci_driver::device_number(model.string(), serial.string());
|
||||
|
||||
if (num < 0) {
|
||||
error("rejecting session request, no matching policy for '", label, "'",
|
||||
model_buf[0] == 0 ? ""
|
||||
: " (model=", Cstring(model_buf), " serial=", Cstring(sn_buf), ")");
|
||||
model == "" ? ""
|
||||
: " (model=", model, " serial=", serial, ")");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
@ -137,10 +124,15 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
if (writeable)
|
||||
writeable = Arg_string::find_arg(args, "writeable").bool_value(true);
|
||||
|
||||
Block::Factory *factory = new (&_alloc) Block::Factory(num);
|
||||
::Session_component *session = new (&_alloc)
|
||||
::Session_component(*factory, _env.ep(), _env.rm(), tx_buf_size);
|
||||
log("session opened at device ", num, " for '", label, "'");
|
||||
::Session_component(*factory, _env.ep(), _env.rm(), tx_buf_size, writeable);
|
||||
log(
|
||||
writeable ? "writeable " : "read-only ",
|
||||
"session opened at device ", num, " for '", label, "'");
|
||||
return session;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ struct Main
|
||||
|
||||
} factory { env, heap };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
|
||||
Main(Genode::Env &env) : env(env)
|
||||
{
|
||||
|
@ -818,7 +818,7 @@ struct Usb::Main
|
||||
};
|
||||
|
||||
Factory factory { env, heap, announce_dispatcher };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
|
||||
Main(Env &env) : env(env) { }
|
||||
};
|
||||
|
@ -70,7 +70,7 @@ struct Main
|
||||
Genode::Env &env;
|
||||
Genode::Heap heap { env.ram(), env.rm() };
|
||||
Factory<Lru_policy> factory { env, heap };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
Genode::Signal_handler<Main> resource_dispatcher {
|
||||
env.ep(), *this, &Main::resource_handler };
|
||||
|
||||
|
@ -22,7 +22,7 @@ In order to route a client to the right partition, the server parses its
|
||||
configuration section looking for 'policy' tags.
|
||||
|
||||
XML Syntax:
|
||||
! <policy labal="<program name>" parition="<partition number>" />
|
||||
! <policy label="<program name>" partition="<partition number>" writeable="<boolean>"/>
|
||||
|
||||
part_blk supports partition reporting, which can be enabled via the
|
||||
<report> configuration node. See below for an example. The report
|
||||
@ -41,6 +41,8 @@ looks like follows (for MBR resp. GPT).
|
||||
! guid="87199a83-d0f4-4a01-b9e3-6516a8579d61" start="4096" length="16351"/>
|
||||
! </partitions>
|
||||
|
||||
Clients have read-only access to partitions unless overriden by a 'writeable'
|
||||
policy attribute.
|
||||
|
||||
Usage
|
||||
-----
|
||||
@ -65,8 +67,8 @@ Configuration snippet with two clients and an (hypothetical) IDE driver:
|
||||
! 'test-part2' receives access to primary partition 1 -->
|
||||
! <config>
|
||||
! <report partitions="yes"/>
|
||||
! <policy label_prefix="test-part1" partition="6"/>
|
||||
! <policy label_prefix="test-part2" partition="1"/>
|
||||
! <policy label_prefix="test-part1" partition="6" writeable="yes"/>
|
||||
! <policy label_prefix="test-part2" partition="1" writeable="yes"/>
|
||||
! </config>
|
||||
!</start>
|
||||
!
|
||||
|
@ -47,6 +47,7 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
Packet_descriptor _p_to_handle;
|
||||
unsigned _p_in_fly;
|
||||
Block::Driver &_driver;
|
||||
bool _writeable;
|
||||
|
||||
/**
|
||||
* Acknowledge a packet already handled
|
||||
@ -84,6 +85,12 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
sector_t off = _p_to_handle.block_number() + _partition->lba;
|
||||
size_t cnt = _p_to_handle.block_count();
|
||||
void* addr = tx_sink()->packet_content(_p_to_handle);
|
||||
|
||||
if (write && !_writeable) {
|
||||
_ack_packet(_p_to_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_driver.io(write, off, cnt, addr, *this, _p_to_handle);
|
||||
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
@ -126,7 +133,8 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
Partition *partition,
|
||||
Genode::Entrypoint &ep,
|
||||
Genode::Region_map &rm,
|
||||
Block::Driver &driver)
|
||||
Block::Driver &driver,
|
||||
bool writeable)
|
||||
: Session_rpc_object(rm, rq_ds, ep.rpc_ep()),
|
||||
_rq_ds(rq_ds),
|
||||
_rq_phys(Dataspace_client(_rq_ds).phys_addr()),
|
||||
@ -136,7 +144,8 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
_req_queue_full(false),
|
||||
_ack_queue_full(false),
|
||||
_p_in_fly(0),
|
||||
_driver(driver)
|
||||
_driver(driver),
|
||||
_writeable(writeable)
|
||||
{
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
@ -193,9 +202,18 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
void info(sector_t *blk_count, size_t *blk_size,
|
||||
Operations *ops)
|
||||
{
|
||||
Operations driver_ops = _driver.ops();
|
||||
|
||||
*blk_count = _partition->sectors;
|
||||
*blk_size = _driver.blk_size();
|
||||
*ops = _driver.ops();
|
||||
*ops = Operations();
|
||||
|
||||
typedef Block::Packet_descriptor::Opcode Opcode;
|
||||
|
||||
if (driver_ops.supported(Opcode::READ))
|
||||
ops->set_operation(Opcode::READ);
|
||||
if (_writeable && driver_ops.supported(Opcode::WRITE))
|
||||
ops->set_operation(Opcode::WRITE);
|
||||
}
|
||||
|
||||
void sync() { _driver.session().sync(); }
|
||||
@ -230,6 +248,7 @@ class Block::Root :
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
long num = -1;
|
||||
bool writeable = false;
|
||||
|
||||
Session_label const label = label_from_args(args);
|
||||
char const *label_str = label.string();
|
||||
@ -239,6 +258,9 @@ class Block::Root :
|
||||
/* read partition attribute */
|
||||
policy.attribute("partition").value(&num);
|
||||
|
||||
/* sessions are not writeable by default */
|
||||
writeable = policy.attribute_value("writeable", false);
|
||||
|
||||
} catch (Xml_node::Nonexistent_attribute) {
|
||||
error("policy does not define partition number for for '",
|
||||
label_str, "'");
|
||||
@ -280,11 +302,15 @@ class Block::Root :
|
||||
throw Insufficient_ram_quota();
|
||||
}
|
||||
|
||||
if (writeable)
|
||||
writeable = Arg_string::find_arg(args, "writeable").bool_value(true);
|
||||
|
||||
Ram_dataspace_capability ds_cap;
|
||||
ds_cap = _env.ram().alloc(tx_buf_size);
|
||||
Session_component *session = new (md_alloc())
|
||||
Session_component(ds_cap, _table.partition(num),
|
||||
_env.ep(), _env.rm(), _driver);
|
||||
_env.ep(), _env.rm(), _driver,
|
||||
writeable);
|
||||
|
||||
log("session opened at partition ", num, " for '", label_str, "'");
|
||||
return session;
|
||||
|
@ -194,7 +194,9 @@ struct Main
|
||||
Genode::destroy(&alloc, driver); }
|
||||
} factory { env, heap, config_rom.xml() };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
enum { WRITEABLE = true };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, WRITEABLE };
|
||||
|
||||
Main(Env &env) : env(env)
|
||||
{
|
||||
|
@ -117,7 +117,9 @@ struct Main
|
||||
Genode::destroy(&heap, driver); }
|
||||
} factory { env, heap };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
enum { WRITEABLE = false };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, WRITEABLE };
|
||||
|
||||
Main(Env &env) : env(env) {
|
||||
env.parent().announce(env.ep().manage(root)); }
|
||||
|
@ -124,7 +124,7 @@ struct Main
|
||||
void destroy(Block::Driver *driver) { }
|
||||
} factory { env, heap };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory };
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
Timer::Connection timer { env };
|
||||
Genode::Signal_handler<Driver> dispatcher { env.ep(), *factory.driver,
|
||||
&Driver::handler };
|
||||
|
@ -181,7 +181,7 @@ append_if $use_block_sata config {
|
||||
<resource name="RAM" quantum="1M" />
|
||||
<provides><service name="Block"/></provides>
|
||||
<config>
|
||||
<policy label="seoul -> VirtualDisk 0" device="0" />
|
||||
<policy label="seoul -> VirtualDisk 0" device="0" writeable="yes"/>
|
||||
</config>
|
||||
</start>}
|
||||
|
||||
|
@ -92,7 +92,7 @@ append config {
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Block"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="part_blk" device="0"/>
|
||||
<policy label_prefix="part_blk" device="0" writeable="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="part_blk" priority="-1">
|
||||
@ -103,9 +103,9 @@ append config {
|
||||
</route>
|
||||
<config>}
|
||||
append_if [expr $use_rumpfs] config {
|
||||
<policy label_prefix="rump_fs" partition="4"/>}
|
||||
<policy label_prefix="rump_fs" partition="4" writeable="yes"/>}
|
||||
append_if [expr !$use_rumpfs] config {
|
||||
<policy label_prefix="vbox1 -> raw" partition="3"/>}
|
||||
<policy label_prefix="vbox1 -> raw" partition="3" writeable="yes"/>}
|
||||
append config {
|
||||
</config>
|
||||
</start>}
|
||||
|
Loading…
x
Reference in New Issue
Block a user