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:
@@ -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 */
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* The drivers support the following operations (using message format m2):
|
||||
*
|
||||
* m_type DEVICE IO_ENDPT COUNT POSITION HIGHPOS IO_GRANT
|
||||
* m_type DEVICE USER_ENDPT COUNT POSITION HIGHPOS IO_GRANT
|
||||
* ----------------------------------------------------------------------------
|
||||
* | DEV_OPEN | device | proc nr | | | | |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
@@ -53,7 +53,7 @@ FORWARD _PROTOTYPE( void clear_open_devs, (void) );
|
||||
FORWARD _PROTOTYPE( int is_open_dev, (int device) );
|
||||
FORWARD _PROTOTYPE( void set_open_dev, (int device) );
|
||||
|
||||
FORWARD _PROTOTYPE( void asyn_reply, (message *mess, int proc_nr, int r) );
|
||||
FORWARD _PROTOTYPE( void asyn_reply, (message *mess, int r) );
|
||||
FORWARD _PROTOTYPE( int driver_reply, (endpoint_t caller_e, int caller_status,
|
||||
message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( int driver_spurious_reply, (endpoint_t caller_e,
|
||||
@@ -61,7 +61,8 @@ FORWARD _PROTOTYPE( int driver_spurious_reply, (endpoint_t caller_e,
|
||||
FORWARD _PROTOTYPE( int do_rdwt, (struct driver *dr, message *mp) );
|
||||
FORWARD _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *mp) );
|
||||
|
||||
int device_caller;
|
||||
PRIVATE endpoint_t device_caller;
|
||||
PUBLIC endpoint_t device_endpt; /* used externally by log driver */
|
||||
PRIVATE mq_t *queue_head = NULL;
|
||||
PRIVATE int open_devs[MAX_NR_OPEN_DEVICES];
|
||||
PRIVATE int next_open_devs_slot = 0;
|
||||
@@ -108,9 +109,8 @@ PRIVATE void set_open_dev(int device)
|
||||
/*===========================================================================*
|
||||
* asyn_reply *
|
||||
*===========================================================================*/
|
||||
PRIVATE void asyn_reply(mess, proc_nr, r)
|
||||
PRIVATE void asyn_reply(mess, r)
|
||||
message *mess;
|
||||
int proc_nr;
|
||||
int r;
|
||||
{
|
||||
/* Send a reply using the new asynchronous character device protocol.
|
||||
@@ -120,13 +120,13 @@ int r;
|
||||
switch (mess->m_type) {
|
||||
case DEV_OPEN:
|
||||
reply_mess.m_type = DEV_REVIVE;
|
||||
reply_mess.REP_ENDPT = proc_nr;
|
||||
reply_mess.REP_ENDPT = device_endpt;
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
|
||||
case DEV_CLOSE:
|
||||
reply_mess.m_type = DEV_CLOSE_REPL;
|
||||
reply_mess.REP_ENDPT = proc_nr;
|
||||
reply_mess.REP_ENDPT = device_endpt;
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
|
||||
@@ -134,10 +134,11 @@ int r;
|
||||
case DEV_WRITE_S:
|
||||
case DEV_IOCTL_S:
|
||||
if (r == SUSPEND)
|
||||
printf("driver_task: reviving %d with SUSPEND\n", proc_nr);
|
||||
printf("driver_task: reviving %d (%d) with SUSPEND\n",
|
||||
device_caller, device_endpt);
|
||||
|
||||
reply_mess.m_type = DEV_REVIVE;
|
||||
reply_mess.REP_ENDPT = proc_nr;
|
||||
reply_mess.REP_ENDPT = device_endpt;
|
||||
reply_mess.REP_IO_GRANT = (cp_grant_id_t) mess->IO_GRANT;
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
@@ -154,7 +155,7 @@ int r;
|
||||
|
||||
default:
|
||||
reply_mess.m_type = TASK_REPLY;
|
||||
reply_mess.REP_ENDPT = proc_nr;
|
||||
reply_mess.REP_ENDPT = device_endpt;
|
||||
/* Status is # of bytes transferred or error code. */
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
@@ -202,7 +203,7 @@ message *m_ptr;
|
||||
int r;
|
||||
|
||||
m_ptr->m_type = TASK_REPLY;
|
||||
m_ptr->REP_ENDPT = m_ptr->IO_ENDPT;
|
||||
m_ptr->REP_ENDPT = m_ptr->USER_ENDPT;
|
||||
m_ptr->REP_STATUS = ERESTART;
|
||||
|
||||
r = driver_reply(caller_e, caller_status, m_ptr);
|
||||
@@ -346,7 +347,7 @@ int type; /* Driver type (DRIVER_STD or DRIVER_ASYN) */
|
||||
{
|
||||
/* Main program of any device driver task. */
|
||||
|
||||
int r, proc_nr, ipc_status;
|
||||
int r, ipc_status;
|
||||
message mess;
|
||||
|
||||
driver_running = TRUE;
|
||||
@@ -371,10 +372,10 @@ int type; /* Driver type (DRIVER_STD or DRIVER_ASYN) */
|
||||
message *m_ptr; /* Pointer to message to handle */
|
||||
int ipc_status;
|
||||
{
|
||||
int r, proc_nr;
|
||||
int r;
|
||||
|
||||
device_caller = m_ptr->m_source;
|
||||
proc_nr = m_ptr->IO_ENDPT;
|
||||
device_endpt = m_ptr->USER_ENDPT;
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
switch (_ENDPOINT_P(m_ptr->m_source)) {
|
||||
case HARDWARE:
|
||||
@@ -425,7 +426,7 @@ send_reply:
|
||||
switch (type) {
|
||||
case DRIVER_STD:
|
||||
m_ptr->m_type = TASK_REPLY;
|
||||
m_ptr->REP_ENDPT = proc_nr;
|
||||
m_ptr->REP_ENDPT = device_endpt;
|
||||
/* Status is # of bytes transferred or error code. */
|
||||
m_ptr->REP_STATUS = r;
|
||||
|
||||
@@ -439,7 +440,7 @@ send_reply:
|
||||
break;
|
||||
|
||||
case DRIVER_ASYN:
|
||||
asyn_reply(m_ptr, proc_nr, r);
|
||||
asyn_reply(m_ptr, r);
|
||||
|
||||
break;
|
||||
|
||||
@@ -495,7 +496,7 @@ message *mp; /* pointer to read or write message */
|
||||
|
||||
/* Transfer bytes from/to the device. */
|
||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||
r = (*dp->dr_transfer)(mp->IO_ENDPT, opcode, position, &iovec1, 1);
|
||||
r = (*dp->dr_transfer)(mp->m_source, opcode, position, &iovec1, 1);
|
||||
|
||||
/* Return the number of bytes transferred or an error code. */
|
||||
return(r == OK ? (mp->COUNT - iovec1.iov_size) : r);
|
||||
@@ -536,7 +537,7 @@ message *mp; /* pointer to read or write message */
|
||||
/* Transfer bytes from/to the device. */
|
||||
opcode = mp->m_type;
|
||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||
r = (*dp->dr_transfer)(mp->IO_ENDPT, opcode, position, iovec, nr_req);
|
||||
r = (*dp->dr_transfer)(mp->m_source, opcode, position, iovec, nr_req);
|
||||
|
||||
/* Copy the I/O vector back to the caller. */
|
||||
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
||||
@@ -659,7 +660,7 @@ message *mp; /* pointer to ioctl request */
|
||||
|
||||
if (mp->REQUEST == DIOCSETP) {
|
||||
/* Copy just this one partition table entry. */
|
||||
s=sys_safecopyfrom(mp->IO_ENDPT, (vir_bytes) mp->IO_GRANT,
|
||||
s=sys_safecopyfrom(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
||||
0, (vir_bytes) &entry, sizeof(entry), D);
|
||||
if(s != OK)
|
||||
return s;
|
||||
@@ -670,7 +671,7 @@ message *mp; /* pointer to ioctl request */
|
||||
entry.base = dv->dv_base;
|
||||
entry.size = dv->dv_size;
|
||||
(*dp->dr_geometry)(&entry);
|
||||
s=sys_safecopyto(mp->IO_ENDPT, (vir_bytes) mp->IO_GRANT,
|
||||
s=sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
||||
0, (vir_bytes) &entry, sizeof(entry), D);
|
||||
if (OK != s)
|
||||
return s;
|
||||
|
||||
@@ -7,7 +7,7 @@ PUBLIC int sys_enable_iop(proc_ep)
|
||||
endpoint_t proc_ep; /* number of process to allow I/O */
|
||||
{
|
||||
message m_iop;
|
||||
m_iop.IO_ENDPT = proc_ep;
|
||||
m_iop.IOP_ENDPT = proc_ep;
|
||||
return _kernel_call(SYS_IOPENABLE, &m_iop);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user