mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-18 18:17:49 +07:00
firewire: check cdev response length
Add a check that the data length in the SEND_RESPONSE ioctl is correct. Incidentally, this also fixes the previously wrong response length of software-handled lock requests. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
262444eecc
commit
a10c0ce760
@ -756,9 +756,12 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
|
|||||||
if (is_fcp_request(r->request))
|
if (is_fcp_request(r->request))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (a->length < r->length)
|
if (a->length != fw_get_response_length(r->request)) {
|
||||||
r->length = a->length;
|
ret = -EINVAL;
|
||||||
if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) {
|
kfree(r->request);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
kfree(r->request);
|
kfree(r->request);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -580,6 +580,41 @@ static void free_response_callback(struct fw_packet *packet,
|
|||||||
kfree(request);
|
kfree(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fw_get_response_length(struct fw_request *r)
|
||||||
|
{
|
||||||
|
int tcode, ext_tcode, data_length;
|
||||||
|
|
||||||
|
tcode = HEADER_GET_TCODE(r->request_header[0]);
|
||||||
|
|
||||||
|
switch (tcode) {
|
||||||
|
case TCODE_WRITE_QUADLET_REQUEST:
|
||||||
|
case TCODE_WRITE_BLOCK_REQUEST:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case TCODE_READ_QUADLET_REQUEST:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
case TCODE_READ_BLOCK_REQUEST:
|
||||||
|
data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);
|
||||||
|
return data_length;
|
||||||
|
|
||||||
|
case TCODE_LOCK_REQUEST:
|
||||||
|
ext_tcode = HEADER_GET_EXTENDED_TCODE(r->request_header[3]);
|
||||||
|
data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);
|
||||||
|
switch (ext_tcode) {
|
||||||
|
case EXTCODE_FETCH_ADD:
|
||||||
|
case EXTCODE_LITTLE_ADD:
|
||||||
|
return data_length;
|
||||||
|
default:
|
||||||
|
return data_length / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
WARN(1, KERN_ERR "wrong tcode %d", tcode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
||||||
int rcode, void *payload, size_t length)
|
int rcode, void *payload, size_t length)
|
||||||
{
|
{
|
||||||
@ -713,7 +748,8 @@ void fw_send_response(struct fw_card *card,
|
|||||||
|
|
||||||
if (rcode == RCODE_COMPLETE)
|
if (rcode == RCODE_COMPLETE)
|
||||||
fw_fill_response(&request->response, request->request_header,
|
fw_fill_response(&request->response, request->request_header,
|
||||||
rcode, request->data, request->length);
|
rcode, request->data,
|
||||||
|
fw_get_response_length(request));
|
||||||
else
|
else
|
||||||
fw_fill_response(&request->response, request->request_header,
|
fw_fill_response(&request->response, request->request_header,
|
||||||
rcode, NULL, 0);
|
rcode, NULL, 0);
|
||||||
|
@ -218,6 +218,7 @@ static inline bool is_next_generation(int new_generation, int old_generation)
|
|||||||
|
|
||||||
void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
|
void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
|
||||||
void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
|
void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
|
||||||
|
int fw_get_response_length(struct fw_request *request);
|
||||||
void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
||||||
int rcode, void *payload, size_t length);
|
int rcode, void *payload, size_t length);
|
||||||
void fw_send_phy_config(struct fw_card *card,
|
void fw_send_phy_config(struct fw_card *card,
|
||||||
|
Loading…
Reference in New Issue
Block a user