Server/driver protocols: no longer allow third-party copies.

Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.

From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:

- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
  when setting REP_ENDPT, matching requests in CANCEL calls, getting
  DEV_SELECT flags, and retrieving of the real user process's endpoint
  in DEV_OPEN.

The changes in this patch are binary backward compatible.
This commit is contained in:
David van Moolenbroek
2011-04-11 17:35:05 +00:00
parent 4e86b0d53f
commit c51cd5fe91
52 changed files with 351 additions and 343 deletions
+27 -26
View File
@@ -8,7 +8,7 @@
*
* The driver supports the following operations:
*
* m_type DEVICE IO_ENDPT COUNT POSITION ADRRESS
* m_type DEVICE USER_ENDPT COUNT POSITION ADRRESS
* -----------------------------------------------------------------
* | DEV_OPEN | device | proc nr | | | |
* |-------------+---------+---------+---------+---------+---------|
@@ -122,7 +122,7 @@ PUBLIC int main(int argc, char *argv[])
/* open the special file ( = parameter) */
r = msg_open(mess.DEVICE);
repl_mess.m_type = DEV_REVIVE;
repl_mess.REP_ENDPT = mess.IO_ENDPT;
repl_mess.REP_ENDPT = mess.USER_ENDPT;
repl_mess.REP_STATUS = r;
send(caller, &repl_mess);
@@ -132,7 +132,7 @@ PUBLIC int main(int argc, char *argv[])
/* close the special file ( = parameter) */
r = msg_close(mess.DEVICE);
repl_mess.m_type = DEV_CLOSE_REPL;
repl_mess.REP_ENDPT = mess.IO_ENDPT;
repl_mess.REP_ENDPT = mess.USER_ENDPT;
repl_mess.REP_STATUS = r;
send(caller, &repl_mess);
@@ -144,7 +144,7 @@ PUBLIC int main(int argc, char *argv[])
if (r != SUSPEND)
{
repl_mess.m_type = DEV_REVIVE;
repl_mess.REP_ENDPT = mess.IO_ENDPT;
repl_mess.REP_ENDPT = mess.USER_ENDPT;
repl_mess.REP_IO_GRANT =
(unsigned)mess.IO_GRANT;
repl_mess.REP_STATUS = r;
@@ -162,7 +162,7 @@ PUBLIC int main(int argc, char *argv[])
/* reopen the special file ( = parameter) */
r = msg_open(mess.DEVICE);
repl_mess.m_type = DEV_REOPEN_REPL;
repl_mess.REP_ENDPT = mess.IO_ENDPT;
repl_mess.REP_ENDPT = mess.USER_ENDPT;
repl_mess.REP_STATUS = r;
send(caller, &repl_mess);
continue;
@@ -479,7 +479,7 @@ PRIVATE int msg_ioctl(const message *m_ptr)
if (m_ptr->REQUEST & _IOC_IN) { /* if there is data for us, copy it */
len = io_ctl_length(m_ptr->REQUEST);
if(sys_safecopyfrom(m_ptr->IO_ENDPT,
if(sys_safecopyfrom(m_ptr->m_source,
(vir_bytes)m_ptr->ADDRESS, 0,
(vir_bytes)io_ctl_buf, len, D) != OK) {
printf("%s:%d: safecopyfrom failed\n", __FILE__, __LINE__);
@@ -493,7 +493,7 @@ PRIVATE int msg_ioctl(const message *m_ptr)
if (status == OK && m_ptr->REQUEST & _IOC_OUT) {
/* copy result back to user */
if(sys_safecopyto(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, 0,
if(sys_safecopyto(m_ptr->m_source, (vir_bytes)m_ptr->ADDRESS, 0,
(vir_bytes)io_ctl_buf, len, D) != OK) {
printf("%s:%d: safecopyto failed\n", __FILE__, __LINE__);
}
@@ -515,7 +515,7 @@ PRIVATE void msg_write(const message *m_ptr)
if (chan == NO_CHANNEL) {
error("%s: No write channel specified!\n", drv.DriverName);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EIO);
return;
}
/* get pointer to sub device data */
@@ -529,20 +529,20 @@ PRIVATE void msg_write(const message *m_ptr)
}
if(m_ptr->COUNT != sub_dev_ptr->FragSize) {
error("Fragment size does not match user's buffer length\n");
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EINVAL);
return;
}
/* if we are busy with something else than writing, return EBUSY */
if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_WRITE_S) {
error("Already busy with something else then writing\n");
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EBUSY);
return;
}
sub_dev_ptr->RevivePending = TRUE;
sub_dev_ptr->ReviveProcNr = m_ptr->IO_ENDPT;
sub_dev_ptr->ReviveProcNr = m_ptr->USER_ENDPT;
sub_dev_ptr->ReviveGrant = (cp_grant_id_t) m_ptr->ADDRESS;
sub_dev_ptr->NotifyProcNr = m_ptr->m_source;
sub_dev_ptr->SourceProcNr = m_ptr->m_source;
data_from_user(sub_dev_ptr);
@@ -566,7 +566,7 @@ PRIVATE void msg_read(message *m_ptr)
if (chan == NO_CHANNEL) {
error("%s: No read channel specified!\n", drv.DriverName);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EIO);
return;
}
/* get pointer to sub device data */
@@ -575,25 +575,26 @@ PRIVATE void msg_read(message *m_ptr)
if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first read */
if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){
error("%s: Could not retrieve fragment size!\n", drv.DriverName);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT,
EIO);
return;
}
}
if(m_ptr->COUNT != sub_dev_ptr->FragSize) {
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EINVAL);
error("fragment size does not match message size\n");
return;
}
/* if we are busy with something else than reading, reply EBUSY */
if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_READ_S) {
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, EBUSY);
return;
}
sub_dev_ptr->RevivePending = TRUE;
sub_dev_ptr->ReviveProcNr = m_ptr->IO_ENDPT;
sub_dev_ptr->ReviveProcNr = m_ptr->USER_ENDPT;
sub_dev_ptr->ReviveGrant = (cp_grant_id_t) m_ptr->ADDRESS;
sub_dev_ptr->NotifyProcNr = m_ptr->m_source;
sub_dev_ptr->SourceProcNr = m_ptr->m_source;
if(!sub_dev_ptr->DmaBusy) { /* Dma tranfer not yet started */
get_started(sub_dev_ptr);
@@ -814,7 +815,7 @@ PRIVATE void data_from_user(sub_dev_t *subdev)
if (subdev->DmaLength < subdev->NrOfDmaFragments) { /* room in dma buf */
sys_safecopyfrom(subdev->ReviveProcNr,
sys_safecopyfrom(subdev->SourceProcNr,
(vir_bytes)subdev->ReviveGrant, 0,
(vir_bytes)subdev->DmaPtr +
subdev->DmaFillNext * subdev->FragSize,
@@ -828,7 +829,7 @@ PRIVATE void data_from_user(sub_dev_t *subdev)
} else { /* room in extra buf */
sys_safecopyfrom(subdev->ReviveProcNr,
sys_safecopyfrom(subdev->SourceProcNr,
(vir_bytes)subdev->ReviveGrant, 0,
(vir_bytes)subdev->ExtraBuf +
subdev->BufFillNext * subdev->FragSize,
@@ -858,11 +859,11 @@ PRIVATE void data_from_user(sub_dev_t *subdev)
m.REP_ENDPT = subdev->ReviveProcNr;
m.REP_IO_GRANT = subdev->ReviveGrant;
m.REP_STATUS = subdev->ReviveStatus;
r= send(subdev->NotifyProcNr, &m); /* send the message */
r= send(subdev->SourceProcNr, &m); /* send the message */
if (r != OK)
{
printf("audio_fw: send to %d failed: %d\n",
subdev->NotifyProcNr, r);
subdev->SourceProcNr, r);
}
/* reset variables */
@@ -883,7 +884,7 @@ PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr)
if(sub_dev_ptr->BufLength != 0) { /* data in extra buffer available */
sys_safecopyto(sub_dev_ptr->ReviveProcNr,
sys_safecopyto(sub_dev_ptr->SourceProcNr,
(vir_bytes)sub_dev_ptr->ReviveGrant,
0, (vir_bytes)sub_dev_ptr->ExtraBuf +
sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize,
@@ -898,7 +899,7 @@ PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr)
} else { /* extra buf empty, but data in dma buf*/
sys_safecopyto(
sub_dev_ptr->ReviveProcNr,
sub_dev_ptr->SourceProcNr,
(vir_bytes)sub_dev_ptr->ReviveGrant, 0,
(vir_bytes)sub_dev_ptr->DmaPtr +
sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
@@ -920,11 +921,11 @@ PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr)
m.REP_ENDPT = sub_dev_ptr->ReviveProcNr;
m.REP_IO_GRANT = sub_dev_ptr->ReviveGrant;
m.REP_STATUS = sub_dev_ptr->ReviveStatus;
r= send(sub_dev_ptr->NotifyProcNr, &m); /* send the message */
r= send(sub_dev_ptr->SourceProcNr, &m); /* send the message */
if (r != OK)
{
printf("audio_fw: send to %d failed: %d\n",
sub_dev_ptr->NotifyProcNr, r);
sub_dev_ptr->SourceProcNr, r);
}
/* reset variables */