Be more careful when copying response payloads on firewire-core

When faced with bogus config ROM read responses from an audio device
that did not support block requests as advertized, libffado's csr1212
code was able to recover when running on top of raw1394 but corrupted
its config ROM cache when running on top of firewire-core.
http://subversion.ffado.org/ticket/299

While the actual cause was a combination of firmware bug of the device
and flaw in csr1212.c of libffado, the much less graceful behavior when
running on firewire-core was obviously due to libraw1394's
firewire-core backend.  Hence,
  - do not write into the client's buffer if rcode != RCODE_COMPLETE,
  - do not copy more data than the actual response contained.

The latter safeguard is not overly effective though.  The libraw1394 API
has no means to inform a client about the error case that a responder
node sent less bytes than were requested.  (The case that the responder
sent more bytes than requested is covered up by the kernel already.)
Should we synthesize an I/O failure?  Does not sound ideal either.
However, such a size mismatch should never happen; the important part of
this change is the RCODE_COMPLETE check.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Stefan Richter 2010-09-05 01:32:16 +02:00
parent 824ababa4d
commit 7416da6112
2 changed files with 7 additions and 9 deletions

View File

@ -303,8 +303,9 @@ handle_device_event(raw1394handle_t handle,
case FW_CDEV_EVENT_RESPONSE: case FW_CDEV_EVENT_RESPONSE:
rc = u64_to_ptr(u->response.closure); rc = u64_to_ptr(u->response.closure);
if (rc->data != NULL) /* Kernel ensures that u->response.length does not overflow. */
memcpy(rc->data, u->response.data, rc->length); if (rc->data != NULL && u->response.rcode == RCODE_COMPLETE)
memcpy(rc->data, u->response.data, u->response.length);
errcode = fw_to_raw1394_errcode(u->response.rcode); errcode = fw_to_raw1394_errcode(u->response.rcode);
tag = rc->tag; tag = rc->tag;
@ -1059,7 +1060,6 @@ node_id_ok:
} }
closure->data = out; closure->data = out;
closure->length = out_length;
closure->tag = tag; closure->tag = tag;
request = (struct fw_cdev_send_request *) handle->buffer; request = (struct fw_cdev_send_request *) handle->buffer;
@ -1240,7 +1240,6 @@ fw_start_phy_packet_write(fw_handle_t handle, quadlet_t data, unsigned long tag)
} }
closure->data = NULL; closure->data = NULL;
closure->length = 0;
closure->tag = tag; closure->tag = tag;
send_phy_packet.closure = ptr_to_u64(closure); send_phy_packet.closure = ptr_to_u64(closure);

View File

@ -69,7 +69,6 @@ struct device {
struct request_closure { struct request_closure {
void *data; void *data;
size_t length;
unsigned long tag; unsigned long tag;
}; };