Re: l4_task_cap_equal broken?

2012-04-20 Thread Alexander Warg
On Wed, 2012-04-18 at 15:01 +0200, Stefan kalkowski wrote:
 Dear Fiasco.OC developers,
 
 while working with Genode on top of Fiasco.OC, I've encountered the
 following problem. When I transfer ipc-gates via ipc between tasks, it
 comes to the point where a task receives a gate it already owns. These
 duplicates are detected due to an additional identifier that is
 transfered together with the gate. To detect fraud (whether somebody has
 send an invalid gate/id combination) the received gate gets compared
 with the locally available one via l4_task_cap_equal. Now, the problem
 is l4_task_cap_equal often fails even when both capabilities point to
 the same ipc-gate. The following code-snippet demonstrates this issue:
 
 ...
 tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i-kcap(), rcv_cap);
 if (!l4_msgtag_label(tag)) {
unsigned long id1 = l4_debugger_global_id(i-kcap()),
  id2 = l4_debugger_global_id(rcv_cap);
printf(my_cap=%lx (id=%lx) rcv_cap=%lx (id=%lx),
   i-kcap(), id1, rcv_cap, id2);
if (id1 == id2)
  enter_kdebug(FAIL);
 }
 ...
 
 This snippet is executed after a thread in the roottask received from
 another thread of the same task a capability via IPC. Thereby rcv_cap is
 the cap that was received via ipc and i-kcap() is the cap that was
 retrieved via the additional transfered identifier.
 When executed I get the following output:
 
 ...
 my_cap=20f000 (id=12) rcv_cap=205000 (id=12)
   -
 CPU 0 [00145e81]: FAIL
 [  entrypoint] jdb:
 
 The debugger's global id (here: 12) indicates that both capabilities
 reference the same object. Nevertheless, the equality test fails.
 Can you confirm that this is undesired syscall's behaviour, or do I miss
 something important?

Yes, you missed the rights assigned to the capabilities. Two
capabilities are equal if they are exactly equal. This means they must
point to the same object and have exactly the same rights.

 
 The attached kernel patch fixes the problem for me, but may introduce
 other problems (e.g.: not sure whether obj() returns always valid pointers).

The patch uses a debugging feature of the Kobject class and additionally
removes the rights check. Note, the object pointers in two capabilities
may also differ if they point to the same kernel object but have
different rights!


-- 
Alex


___
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers


Re: l4_task_cap_equal broken?

2012-04-20 Thread Stefan kalkowski
Hi Alexander,

thanks for your explanations.

On 19.04.2012 17:36, Alexander Warg wrote:
 Yes, you missed the rights assigned to the capabilities. Two
 capabilities are equal if they are exactly equal. This means they must
 point to the same object and have exactly the same rights.

Ok, in that case I think the documentation is misleading, citation:

Test if two capabilities point to the same object.

Nevertheless, I already recognized the rights being encountered in the
comparison when looking at the kernel-source. From my understanding the
two least significant bits of the kobject_iface pointer are used for
that. But they're equal in my situation, as well as the kernel-object
the capabilities point to. Nevertheless, the kobject_iface pointer
differs between both.
When using the original source and adding the following prints to
Task::sys_caps_equal:

  printf(cap a: kobject=%lx rights=%x obj()=%lx\n,
 c_a.obj()-kobject_start_addr(), c_a.rights(), c_a.obj());
  printf(cap b: kobject=%lx rights=%x obj()=%lx\n,
 c_b.obj()-kobject_start_addr(), c_b.rights(), c_b.obj());
  printf(a == b ? %x\n, (c_a == c_b));

I get for instance the following output:

  cap a: kobject=fd9b4ec0 rights=3 obj()=fd9b4efc
  cap b: kobject=fd9b4ec0 rights=3 obj()=fd9b4ec0
  a == b ? 0

Can you please shed light on this behaviour? In what situation do I have
differing kobject_iface objects (with the same rights) that represent
actually the same kobject?

 The patch uses a debugging feature of the Kobject class and additionally
 removes the rights check. Note, the object pointers in two capabilities
 may also differ if they point to the same kernel object but have
 different rights!

Sorry, I didn't recognized kobject_start_addr() being a debugging
feature. The patch just circumnavigated my actual problem. I didn't
wanted you to apply it mainline ;-).

Regards Stefan

___
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers


l4_task_cap_equal broken?

2012-04-18 Thread Stefan kalkowski
Dear Fiasco.OC developers,

while working with Genode on top of Fiasco.OC, I've encountered the
following problem. When I transfer ipc-gates via ipc between tasks, it
comes to the point where a task receives a gate it already owns. These
duplicates are detected due to an additional identifier that is
transfered together with the gate. To detect fraud (whether somebody has
send an invalid gate/id combination) the received gate gets compared
with the locally available one via l4_task_cap_equal. Now, the problem
is l4_task_cap_equal often fails even when both capabilities point to
the same ipc-gate. The following code-snippet demonstrates this issue:

...
tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i-kcap(), rcv_cap);
if (!l4_msgtag_label(tag)) {
   unsigned long id1 = l4_debugger_global_id(i-kcap()),
 id2 = l4_debugger_global_id(rcv_cap);
   printf(my_cap=%lx (id=%lx) rcv_cap=%lx (id=%lx),
  i-kcap(), id1, rcv_cap, id2);
   if (id1 == id2)
 enter_kdebug(FAIL);
}
...

This snippet is executed after a thread in the roottask received from
another thread of the same task a capability via IPC. Thereby rcv_cap is
the cap that was received via ipc and i-kcap() is the cap that was
retrieved via the additional transfered identifier.
When executed I get the following output:

...
my_cap=20f000 (id=12) rcv_cap=205000 (id=12)
  -
CPU 0 [00145e81]: FAIL
[  entrypoint] jdb:

The debugger's global id (here: 12) indicates that both capabilities
reference the same object. Nevertheless, the equality test fails.
Can you confirm that this is undesired syscall's behaviour, or do I miss
something important?

The attached kernel patch fixes the problem for me, but may introduce
other problems (e.g.: not sure whether obj() returns always valid pointers).

Regards
Stefan
Index: src/kern/task.cpp
===
--- src/kern/task.cpp	(revision 38)
+++ src/kern/task.cpp	(working copy)
@@ -511,7 +511,8 @@
   Obj_space::Capability c_a = obj_space()-lookup(obj_a.cap());
   Obj_space::Capability c_b = obj_space()-lookup(obj_b.cap());
 
-  return commit_result(c_a == c_b);
+  return commit_result(c_a.obj()-kobject_start_addr() ==
+   c_b.obj()-kobject_start_addr());
 }
 
 PRIVATE inline NOEXPORT
___
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers