diag: Prevent out-of-bound access while processing userspace data
Proper buffer length checks are missing in diagchar_write handlers for userspace data while processing the same buffer. Change-Id: I5b8095766e09c22f164398089505fe827fee8b54 Signed-off-by: Hardik Arya <harya@codeaurora.org>
This commit is contained in:
parent
2692bfe650
commit
25e6769daa
2 changed files with 32 additions and 22 deletions
|
@ -643,7 +643,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
|
|||
struct diag_build_mask_req_t *req = NULL;
|
||||
struct diag_msg_build_mask_t rsp;
|
||||
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 ||
|
||||
src_len < sizeof(struct diag_build_mask_req_t)) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len);
|
||||
|
@ -705,7 +705,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
|
|||
info = diag_md_session_get_pid(pid);
|
||||
|
||||
mask_info = (!info) ? &msg_mask : info->msg_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 ||
|
||||
!mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
|
@ -787,8 +787,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
|
|||
info = diag_md_session_get_pid(pid);
|
||||
|
||||
mask_info = (!info) ? &msg_mask : info->msg_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
|
||||
(src_len < sizeof(struct diag_msg_build_mask_t))) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -872,7 +872,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
|
|||
break;
|
||||
}
|
||||
mask_size = mask_size * sizeof(uint32_t);
|
||||
memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
|
||||
if (mask_size && src_len >= header_len + mask_size)
|
||||
memcpy(mask->ptr + offset, src_buf + header_len,
|
||||
mask_size);
|
||||
mutex_unlock(&mask->lock);
|
||||
mask_info->status = DIAG_CTRL_MASK_VALID;
|
||||
break;
|
||||
|
@ -929,8 +931,8 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
|
|||
info = diag_md_session_get_pid(pid);
|
||||
|
||||
mask_info = (!info) ? &msg_mask : info->msg_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
|
||||
(src_len < sizeof(struct diag_msg_config_rsp_t))) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -1049,8 +1051,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
|
|||
mutex_lock(&driver->md_session_lock);
|
||||
info = diag_md_session_get_pid(pid);
|
||||
mask_info = (!info) ? &event_mask : info->event_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
|
||||
src_len < sizeof(struct diag_event_mask_config_t)) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -1073,7 +1075,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
|
|||
}
|
||||
|
||||
mutex_lock(&mask_info->lock);
|
||||
memcpy(mask_info->ptr, src_buf + header_len, mask_len);
|
||||
if (src_len >= header_len + mask_len)
|
||||
memcpy(mask_info->ptr, src_buf + header_len, mask_len);
|
||||
mask_info->status = DIAG_CTRL_MASK_VALID;
|
||||
mutex_unlock(&mask_info->lock);
|
||||
mutex_unlock(&driver->md_session_lock);
|
||||
|
@ -1117,8 +1120,8 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
|
|||
mutex_lock(&driver->md_session_lock);
|
||||
info = diag_md_session_get_pid(pid);
|
||||
mask_info = (!info) ? &event_mask : info->event_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || src_len <= sizeof(uint8_t) ||
|
||||
dest_len <= 0 || !mask_info) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -1185,8 +1188,8 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
|
|||
info = diag_md_session_get_pid(pid);
|
||||
|
||||
mask_info = (!info) ? &log_mask : info->log_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
|
||||
src_len < sizeof(struct diag_log_config_req_t)) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -1329,8 +1332,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
|
|||
info = diag_md_session_get_pid(pid);
|
||||
|
||||
mask_info = (!info) ? &log_mask : info->log_mask;
|
||||
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
|
||||
!mask_info) {
|
||||
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
|
||||
src_len < sizeof(struct diag_log_config_req_t)) {
|
||||
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
|
||||
__func__, src_buf, src_len, dest_buf, dest_len,
|
||||
mask_info);
|
||||
|
@ -1404,7 +1407,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
|
|||
mask->range_tools = mask_size;
|
||||
}
|
||||
req->num_items = mask->num_items_tools;
|
||||
if (mask_size > 0)
|
||||
if (mask_size > 0 && src_len >= read_len + mask_size)
|
||||
memcpy(mask->ptr, src_buf + read_len, mask_size);
|
||||
DIAG_LOG(DIAG_DEBUG_MASKS,
|
||||
"copying log mask, e %d num %d range %d size %d\n",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -1187,15 +1187,19 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int mask_request_validate(unsigned char mask_buf[])
|
||||
static int mask_request_validate(unsigned char mask_buf[], int len)
|
||||
{
|
||||
uint8_t packet_id;
|
||||
uint8_t subsys_id;
|
||||
uint16_t ss_cmd;
|
||||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
packet_id = mask_buf[0];
|
||||
|
||||
if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
|
||||
if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
|
||||
return 0;
|
||||
subsys_id = mask_buf[1];
|
||||
ss_cmd = *(uint16_t *)(mask_buf + 2);
|
||||
switch (subsys_id) {
|
||||
|
@ -1211,6 +1215,8 @@ static int mask_request_validate(unsigned char mask_buf[])
|
|||
return 0;
|
||||
}
|
||||
} else if (packet_id == 0x4B) {
|
||||
if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
|
||||
return 0;
|
||||
subsys_id = mask_buf[1];
|
||||
ss_cmd = *(uint16_t *)(mask_buf + 2);
|
||||
/* Packets with SSID which are allowed */
|
||||
|
@ -2892,7 +2898,8 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
|
|||
}
|
||||
|
||||
/* Check for proc_type */
|
||||
remote_proc = diag_get_remote(*(int *)user_space_data);
|
||||
if (len >= sizeof(int))
|
||||
remote_proc = diag_get_remote(*(int *)user_space_data);
|
||||
if (remote_proc) {
|
||||
token_offset = sizeof(int);
|
||||
if (len <= MIN_SIZ_ALLOW) {
|
||||
|
@ -2906,7 +2913,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
|
|||
}
|
||||
if (driver->mask_check) {
|
||||
if (!mask_request_validate(user_space_data +
|
||||
token_offset)) {
|
||||
token_offset, len)) {
|
||||
pr_alert("diag: mask request Invalid\n");
|
||||
diagmem_free(driver, user_space_data, mempool);
|
||||
user_space_data = NULL;
|
||||
|
@ -2984,7 +2991,7 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
|
|||
/* Check masks for On-Device logging */
|
||||
if (driver->mask_check) {
|
||||
if (!mask_request_validate(driver->user_space_data_buf +
|
||||
token_offset)) {
|
||||
token_offset, len)) {
|
||||
pr_alert("diag: mask request Invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue