qcacmn: Fix for read and write operations in wmi_recording

With linux4.4 definition of seq_printf is changed. New definition
updated in driver applies va_start twice which causes incorrect
output hence definition is updated to make sure va_start is applied
only once. For write operations using copy_from_user to avoid
crash due to accessing user space area.

CRs-Fixed: 2042210
IRs-Fixed: 201729
Change-Id: I4043ab027411d42e15adaf53e6e92ae57aa987c7
This commit is contained in:
Pratik Gandhi
2017-05-03 20:15:50 +05:30
committed by snandini
parent 6fcc2020d3
commit 795ab91e23

View File

@@ -98,18 +98,18 @@ typedef PREPACK struct {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
/* TODO Cleanup this backported function */ /* TODO Cleanup this backported function */
static int qcacld_bp_seq_printf(struct seq_file *m, const char *f, ...) static int wmi_bp_seq_printf(struct seq_file *m, const char *f, ...)
{ {
va_list args; va_list args;
va_start(args, f); va_start(args, f);
seq_printf(m, f, args); seq_vprintf(m, f, args);
va_end(args); va_end(args);
return m->count; return 0;
} }
#else
#define seq_printf(m, fmt, ...) qcacld_bp_seq_printf((m), fmt, ##__VA_ARGS__) #define wmi_bp_seq_printf(m, fmt, ...) seq_printf((m), fmt, ##__VA_ARGS__)
#endif #endif
#define WMI_MIN_HEAD_ROOM 64 #define WMI_MIN_HEAD_ROOM 64
@@ -758,7 +758,7 @@ const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"};
qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \ qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \
if (!wmi_log->length) { \ if (!wmi_log->length) { \
qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\ qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
return seq_printf(m, \ return wmi_bp_seq_printf(m, \
"no elements to read from ring buffer!\n"); \ "no elements to read from ring buffer!\n"); \
} \ } \
\ \
@@ -773,28 +773,27 @@ const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"};
else \ else \
pos = *(wmi_log->p_buf_tail_idx) - 1; \ pos = *(wmi_log->p_buf_tail_idx) - 1; \
\ \
outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\ outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \ qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \
while (nread--) { \ while (nread--) { \
struct wmi_command_debug *wmi_record; \ struct wmi_command_debug *wmi_record; \
\ \
wmi_record = (struct wmi_command_debug *) \ wmi_record = (struct wmi_command_debug *) \
&(((struct wmi_command_debug *)wmi_log->buf)[pos]);\ &(((struct wmi_command_debug *)wmi_log->buf)[pos]);\
outlen += seq_printf(m, "CMD ID = %x\n", \ outlen += wmi_bp_seq_printf(m, "CMD ID = %x\n", \
(wmi_record->command)); \ (wmi_record->command)); \
outlen += seq_printf(m, "CMD = "); \ outlen += wmi_bp_seq_printf(m, "CMD = "); \
for (i = 0; i < (wmi_record_max_length/ \ for (i = 0; i < (wmi_record_max_length/ \
sizeof(uint32_t)); i++) \ sizeof(uint32_t)); i++) \
outlen += seq_printf(m, "%x ", \ outlen += wmi_bp_seq_printf(m, "%x ", \
wmi_record->data[i]); \ wmi_record->data[i]); \
outlen += seq_printf(m, "\n"); \ outlen += wmi_bp_seq_printf(m, "\n"); \
\ \
if (pos == 0) \ if (pos == 0) \
pos = wmi_ring_size - 1; \ pos = wmi_ring_size - 1; \
else \ else \
pos--; \ pos--; \
} \ } \
\
return outlen; \ return outlen; \
} \ } \
@@ -811,7 +810,7 @@ const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"};
qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \ qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock); \
if (!wmi_log->length) { \ if (!wmi_log->length) { \
qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\ qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
return seq_printf(m, \ return wmi_bp_seq_printf(m, \
"no elements to read from ring buffer!\n"); \ "no elements to read from ring buffer!\n"); \
} \ } \
\ \
@@ -826,28 +825,27 @@ const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"};
else \ else \
pos = *(wmi_log->p_buf_tail_idx) - 1; \ pos = *(wmi_log->p_buf_tail_idx) - 1; \
\ \
outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\ outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \ qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock); \
while (nread--) { \ while (nread--) { \
struct wmi_event_debug *wmi_record; \ struct wmi_event_debug *wmi_record; \
\ \
wmi_record = (struct wmi_event_debug *) \ wmi_record = (struct wmi_event_debug *) \
&(((struct wmi_event_debug *)wmi_log->buf)[pos]);\ &(((struct wmi_event_debug *)wmi_log->buf)[pos]);\
outlen += seq_printf(m, "Event ID = %x\n", \ outlen += wmi_bp_seq_printf(m, "Event ID = %x\n",\
(wmi_record->event)); \ (wmi_record->event)); \
outlen += seq_printf(m, "CMD = "); \ outlen += wmi_bp_seq_printf(m, "CMD = "); \
for (i = 0; i < (wmi_record_max_length/ \ for (i = 0; i < (wmi_record_max_length/ \
sizeof(uint32_t)); i++) \ sizeof(uint32_t)); i++) \
outlen += seq_printf(m, "%x ", \ outlen += wmi_bp_seq_printf(m, "%x ", \
wmi_record->data[i]); \ wmi_record->data[i]); \
outlen += seq_printf(m, "\n"); \ outlen += wmi_bp_seq_printf(m, "\n"); \
\ \
if (pos == 0) \ if (pos == 0) \
pos = wmi_ring_size - 1; \ pos = wmi_ring_size - 1; \
else \ else \
pos--; \ pos--; \
} \ } \
\
return outlen; \ return outlen; \
} }
@@ -873,8 +871,8 @@ static int debug_wmi_enable_show(struct seq_file *m, void *v)
{ {
wmi_unified_t wmi_handle = (wmi_unified_t) m->private; wmi_unified_t wmi_handle = (wmi_unified_t) m->private;
return seq_printf(m, "%d\n", wmi_handle->log_info.wmi_logging_enable); return wmi_bp_seq_printf(m, "%d\n",
wmi_handle->log_info.wmi_logging_enable);
} }
/** /**
@@ -889,9 +887,11 @@ static int debug_wmi_enable_show(struct seq_file *m, void *v)
static int debug_wmi_log_size_show(struct seq_file *m, void *v) static int debug_wmi_log_size_show(struct seq_file *m, void *v)
{ {
seq_printf(m, "WMI command/event log max size:%d\n", wmi_log_max_entry); wmi_bp_seq_printf(m, "WMI command/event log max size:%d\n",
return seq_printf(m, "WMI management command/events log max size:%d\n", wmi_log_max_entry);
wmi_mgmt_log_max_entry); return wmi_bp_seq_printf(m,
"WMI management command/events log max size:%d\n",
wmi_mgmt_log_max_entry);
} }
/** /**
@@ -915,9 +915,16 @@ static int debug_wmi_log_size_show(struct seq_file *m, void *v)
((struct seq_file *)file->private_data)->private;\ ((struct seq_file *)file->private_data)->private;\
struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info. \ struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info. \
wmi_##func_base##_buf_info; \ wmi_##func_base##_buf_info; \
char locbuf[50]; \
\ \
ret = sscanf(buf, "%d", &k); \ if ((!buf) || (count > 50)) \
if ((ret != 1) || (k != 0)) { \ return -EFAULT; \
\
if (copy_from_user(locbuf, buf, count)) \
return -EFAULT; \
\
ret = sscanf(locbuf, "%d", &k); \
if ((ret != 1) || (k != 0)) { \
qdf_print("Wrong input, echo 0 to clear the wmi buffer\n");\ qdf_print("Wrong input, echo 0 to clear the wmi buffer\n");\
return -EINVAL; \ return -EINVAL; \
} \ } \
@@ -964,8 +971,15 @@ static ssize_t debug_wmi_enable_write(struct file *file, const char __user *buf,
wmi_unified_t wmi_handle = wmi_unified_t wmi_handle =
((struct seq_file *)file->private_data)->private; ((struct seq_file *)file->private_data)->private;
int k, ret; int k, ret;
char locbuf[50];
ret = sscanf(buf, "%d", &k); if ((!buf) || (count > 50))
return -EFAULT;
if (copy_from_user(locbuf, buf, count))
return -EFAULT;
ret = sscanf(locbuf, "%d", &k);
if ((ret != 1) || ((k != 0) && (k != 1))) if ((ret != 1) || ((k != 0) && (k != 1)))
return -EINVAL; return -EINVAL;