aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Moore <dcm@acm.org>2008-12-20 19:28:01 -0800
committerDan Dennedy <dan@dennedy.org>2008-12-29 11:12:32 -0800
commitcb8b7bf86af003ac6eeb167305c70192c4959c7b (patch)
tree32b9472cb6a1d7af1443d17032c239ca5ccddb7b
parentd69397ae8f3519cf291ba2efc173ad257376cf0d (diff)
downloadlibraw1394-cb8b7bf86af003ac6eeb167305c70192c4959c7b.tar.gz
Fix stack corruption during juju lock transactions
When performing a lock transaction (such as with fw_lock) under Juju, 4 bytes of the stack gets corrupted. This is because the lock transaction has 8 bytes of data sent and 4 bytes received. Since the transaction "length" is specified as 8, handle_device_event() copies 8 bytes into the destination variable instead of the desired 4, and overflows into the stack by 4 bytes. This patch fixes the corruption by adding an extra "out_length" argument to the send_request() function so that both in_length and out_length can be specified separately. Signed-off-by: Dan Dennedy <dan@dennedy.org>
-rw-r--r--src/fw.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/fw.c b/src/fw.c
index 03e34a7..e211b60 100644
--- a/src/fw.c
+++ b/src/fw.c
@@ -928,7 +928,8 @@ fw_start_phy_packet_write(fw_handle_t handle,
static int
send_request(fw_handle_t handle, int tcode,
nodeid_t node, nodeaddr_t addr,
- size_t length, void *in, void *out, unsigned long tag)
+ size_t in_length, void *in, size_t out_length, void *out,
+ unsigned long tag)
{
struct fw_cdev_send_request *request;
struct request_closure *closure;
@@ -961,14 +962,14 @@ send_request(fw_handle_t handle, int tcode,
}
closure->data = out;
- closure->length = length;
+ closure->length = out_length;
closure->tag = tag;
request = (struct fw_cdev_send_request *) handle->buffer;
request->tcode = tcode;
request->generation = handle->generation;
request->offset = addr;
- request->length = length;
+ request->length = in_length > out_length ? in_length : out_length;
request->closure = ptr_to_u64(closure);
request->data = ptr_to_u64(in);
@@ -987,7 +988,7 @@ fw_start_read(fw_handle_t handle, nodeid_t node, nodeaddr_t addr,
tcode = TCODE_READ_BLOCK_REQUEST;
return send_request(handle, tcode,
- node, addr, length, NULL, buffer, tag);
+ node, addr, 0, NULL, length, buffer, tag);
}
int
@@ -1002,7 +1003,7 @@ fw_start_write(fw_handle_t handle, nodeid_t node, nodeaddr_t addr,
tcode = TCODE_WRITE_BLOCK_REQUEST;
return send_request(handle, tcode,
- node, addr, length, data, NULL, tag);
+ node, addr, length, data, 0, NULL, tag);
}
static int
@@ -1064,7 +1065,8 @@ fw_start_lock(fw_handle_t handle, nodeid_t node, nodeaddr_t addr,
return length;
return send_request(handle, 16 + extcode,
- node, addr, length, buffer, result, tag);
+ node, addr, length, buffer,
+ sizeof *result, result, tag);
}
int
@@ -1080,7 +1082,8 @@ fw_start_lock64(fw_handle_t handle, nodeid_t node, nodeaddr_t addr,
return length;
return send_request(handle, 16 + extcode,
- node, addr, length, buffer, result, tag);
+ node, addr, length, buffer,
+ sizeof *result, result, tag);
}
int
@@ -1123,7 +1126,7 @@ sync_callback(raw1394handle_t handle, void *data, raw1394_errcode_t err)
static int
send_request_sync(raw1394handle_t handle, int tcode,
nodeid_t node, nodeaddr_t addr,
- size_t length, void *in, void *out)
+ size_t in_length, void *in, size_t out_length, void *out)
{
fw_handle_t fwhandle = handle->mode.fw;
struct raw1394_reqhandle reqhandle;
@@ -1134,7 +1137,8 @@ send_request_sync(raw1394handle_t handle, int tcode,
reqhandle.data = &sd;
err = send_request(fwhandle, tcode, node, addr,
- length, in, out, (unsigned long) &reqhandle);
+ in_length, in, out_length, out,
+ (unsigned long) &reqhandle);
while (!sd.done) {
if (err < 0)
@@ -1160,7 +1164,7 @@ fw_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
tcode = TCODE_READ_BLOCK_REQUEST;
return send_request_sync(handle, tcode,
- node, addr, length, NULL, buffer);
+ node, addr, 0, NULL, length, buffer);
}
int
@@ -1175,7 +1179,7 @@ fw_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
tcode = TCODE_WRITE_BLOCK_REQUEST;
return send_request_sync(handle, tcode,
- node, addr, length, data, NULL);
+ node, addr, length, data, 0, NULL);
}
int
@@ -1191,7 +1195,8 @@ fw_lock(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
return length;
return send_request_sync(handle, 16 + extcode, node, addr,
- (size_t) length, buffer, result);
+ (size_t) length, buffer,
+ sizeof *result, result);
}
int
@@ -1207,7 +1212,8 @@ fw_lock64(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
return length;
return send_request_sync(handle, 16 + extcode, node, addr,
- (size_t) length, buffer, result);
+ (size_t) length, buffer,
+ sizeof *result, result);
}
int