summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl_dpa_offload
diff options
context:
space:
mode:
authorAnca Jeanina Floarea <anca.floarea@freescale.com>2014-09-17 15:07:38 (GMT)
committerMatthew Weigel <Matthew.Weigel@freescale.com>2014-12-11 18:39:32 (GMT)
commit8572340361bed44ac4133bc7af91bdc92489d474 (patch)
treef8f3f6e47213cd274831520c56975faa6132207b /drivers/staging/fsl_dpa_offload
parentb41fa90d6d3ab71153d271484cb7967391fecda9 (diff)
downloadlinux-fsl-qoriq-8572340361bed44ac4133bc7af91bdc92489d474.tar.xz
dpa_offload: Fix DPA Stats issues caused by tainted values
Fix DPA Stats issues related to tainted values by adding constraints to user-provided parameters. Signed-off-by: Anca Jeanina Floarea <anca.floarea@freescale.com> Change-Id: Ib59f89518d96c9102a71be4c673e2d065b0a71f8 Reviewed-on: http://git.am.freescale.net:8181/19070 Reviewed-by: Marian-Cornel Chereji <marian.chereji@freescale.com> Tested-by: Marian-Cornel Chereji <marian.chereji@freescale.com>
Diffstat (limited to 'drivers/staging/fsl_dpa_offload')
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.c101
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c62
2 files changed, 117 insertions, 46 deletions
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.c b/drivers/staging/fsl_dpa_offload/dpa_stats.c
index 0e05594..c1e09132 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.c
@@ -46,7 +46,6 @@
/* FMD includes */
#include "fm_pcd_ext.h"
-#define STATS_VAL_SIZE 4
#define UNSUPPORTED_CNT_SEL -1
#define CLASSIF_STATS_SHIFT 4
#define WORKQUEUE_MAX_ACTIVE 3
@@ -120,9 +119,12 @@ static int check_dpa_stats_params(const struct dpa_stats_params *params)
return -EINVAL;
}
- if (params->storage_area_len < STATS_VAL_SIZE) {
- log_err("Parameter storage_area_len %d cannot be bellow %d\n",
- params->storage_area_len, STATS_VAL_SIZE);
+ /* Check user-provided storage area length */
+ if (params->storage_area_len < DPA_STATS_CNT_SEL_LEN ||
+ params->storage_area_len > DPA_STATS_MAX_STORAGE_AREA_SIZE) {
+ log_err("Parameter storage_area_len %d must be in range (%d - %d)\n",
+ params->storage_area_len,
+ DPA_STATS_CNT_SEL_LEN, DPA_STATS_MAX_STORAGE_AREA_SIZE);
return -EINVAL;
}
@@ -1152,7 +1154,7 @@ static int copy_key_descriptor(const struct dpa_offload_lookup_key *src,
}
/* Check that key size is not zero */
- if (src->size == 0) {
+ if ((src->size == 0) || (src->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
log_err("Lookup key descriptor size (%d) must be in range (1 - %d) bytes\n",
src->size, DPA_OFFLD_MAXENTRYKEYSIZE);
return -EINVAL;
@@ -1378,7 +1380,7 @@ static int cnt_gen_sel_to_stats(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
return 0;
}
@@ -1498,7 +1500,7 @@ static int set_cnt_eth_cb(struct dpa_stats_cnt_cb *cnt_cb,
return err;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
/* Get FM MAC handle */
err = get_fm_mac(params->eth_params.src, &fm_mac);
@@ -1589,7 +1591,7 @@ static int set_cnt_reass_cb(struct dpa_stats_cnt_cb *cnt_cb,
return err;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
/* Check the user-provided reassembly manip */
err = FM_PCD_ManipGetStatistics(params->reass_params.reass, &stats);
@@ -1653,7 +1655,7 @@ static int set_cnt_frag_cb(struct dpa_stats_cnt_cb *cnt_cb,
return err;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
/* Check the user-provided fragmentation handle */
err = FM_PCD_ManipGetStatistics(params->frag_params.frag, &stats);
@@ -1718,7 +1720,7 @@ static int set_cnt_plcr_cb(struct dpa_stats_cnt_cb *cnt_cb,
return err;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
if (err)
@@ -1816,7 +1818,7 @@ static int set_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
cnt_cb->members_num = 1;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
if (err)
@@ -1921,7 +1923,7 @@ static int set_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
return err;
/* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ cnt_cb->bytes_num = DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
if (err)
@@ -2151,7 +2153,7 @@ static int set_cls_cnt_eth_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
GFP_KERNEL);
@@ -2235,7 +2237,7 @@ static int set_cls_cnt_reass_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
GFP_KERNEL);
@@ -2303,7 +2305,7 @@ static int set_cls_cnt_frag_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
GFP_KERNEL);
@@ -2372,7 +2374,7 @@ static int set_cls_cnt_plcr_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
GFP_KERNEL);
@@ -2551,7 +2553,7 @@ static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
/* Allocate memory for key descriptors */
tbl_cb->keys = kcalloc(params->class_members, sizeof(*tbl_cb->keys),
@@ -2746,7 +2748,7 @@ static int set_cls_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Set number of bytes that will be written by this counter */
cnt_cb->bytes_num = cnt_cb->members_num *
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
/* Set retrieve function depending on counter type */
err = set_cnt_classif_node_retrieve_func(cnt_cb, prm.ccnode_type);
@@ -3174,10 +3176,10 @@ static inline void get_cnt_32bit_stats(struct dpa_stats_req_cb *req_cb,
for (j = 0; j < stats_info->stats_num; j++) {
if (stats_info->stats_off[j] == UNSUPPORTED_CNT_SEL) {
/* Write the memory location */
- memset(req_cb->request_area, 0, STATS_VAL_SIZE);
+ memset(req_cb->request_area, 0, DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE;
+ req_cb->request_area += DPA_STATS_CNT_SEL_LEN;
continue;
}
@@ -3204,7 +3206,7 @@ static inline void get_cnt_32bit_stats(struct dpa_stats_req_cb *req_cb,
stats_info->stats[stats_index];
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE;
+ req_cb->request_area += DPA_STATS_CNT_SEL_LEN;
if (stats_info->reset)
stats_info->stats[stats_index] = 0;
@@ -3245,7 +3247,7 @@ static inline void get_cnt_64bit_stats(struct dpa_stats_req_cb *req_cb,
(uint32_t)stats_info->stats[stats_index];
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE;
+ req_cb->request_area += DPA_STATS_CNT_SEL_LEN;
if (stats_info->reset)
stats_info->stats[stats_index] = 0;
@@ -3353,7 +3355,7 @@ static int get_cnt_plcr_stats(struct dpa_stats_req_cb *req_cb,
(uint32_t)info->stats[stats_index];
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE;
+ req_cb->request_area += DPA_STATS_CNT_SEL_LEN;
if (info->reset)
info->stats[stats_index] = 0;
@@ -3374,11 +3376,11 @@ static int get_cnt_cls_tbl_match_stats(struct dpa_stats_req_cb *req_cb,
if (!cnt_cb->tbl_cb.keys[i].valid) {
/* Write the memory location */
memset(req_cb->request_area, 0,
- cnt_cb->info.stats_num * STATS_VAL_SIZE);
+ cnt_cb->info.stats_num * DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE *
- cnt_cb->info.stats_num;
+ req_cb->request_area +=
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
continue;
}
@@ -3424,11 +3426,11 @@ static int get_cnt_cls_tbl_hash_stats(struct dpa_stats_req_cb *req_cb,
if (!cnt_cb->tbl_cb.keys[i].valid) {
/* Write the memory location */
memset(req_cb->request_area, 0,
- cnt_cb->info.stats_num * STATS_VAL_SIZE);
+ cnt_cb->info.stats_num * DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE *
- cnt_cb->info.stats_num;
+ req_cb->request_area +=
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
continue;
}
@@ -3464,11 +3466,11 @@ static int get_cnt_cls_tbl_index_stats(struct dpa_stats_req_cb *req_cb,
if (!cnt_cb->tbl_cb.keys[i].valid) {
/* Write the memory location */
memset(req_cb->request_area, 0,
- cnt_cb->info.stats_num * STATS_VAL_SIZE);
+ cnt_cb->info.stats_num * DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE *
- cnt_cb->info.stats_num;
+ req_cb->request_area +=
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
continue;
}
@@ -3504,11 +3506,11 @@ static int get_cnt_cls_tbl_frag_stats(struct dpa_stats_req_cb *req_cb,
if (!cnt_cb->tbl_cb.keys[i].valid) {
/* Write the memory location */
memset(req_cb->request_area, 0,
- cnt_cb->info.stats_num * STATS_VAL_SIZE);
+ cnt_cb->info.stats_num * DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE *
- cnt_cb->info.stats_num;
+ req_cb->request_area +=
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
continue;
}
@@ -3629,11 +3631,11 @@ static int get_cnt_ipsec_stats(struct dpa_stats_req_cb *req_cb,
if (!cnt_cb->ipsec_cb.valid[i]) {
/* Write the memory location */
memset(req_cb->request_area, 0,
- cnt_cb->info.stats_num * STATS_VAL_SIZE);
+ cnt_cb->info.stats_num * DPA_STATS_CNT_SEL_LEN);
/* Update the memory pointer */
req_cb->request_area +=
- STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ DPA_STATS_CNT_SEL_LEN * cnt_cb->info.stats_num;
continue;
}
@@ -3705,7 +3707,7 @@ static int get_cnt_us_stats(struct dpa_stats_req_cb *req_cb,
/* Write the memory location */
*(uint32_t *)(req_cb->request_area) = 0;
/* Update the memory pointer */
- req_cb->request_area += STATS_VAL_SIZE;
+ req_cb->request_area += DPA_STATS_CNT_SEL_LEN;
}
}
return 0;
@@ -4340,6 +4342,14 @@ int dpa_stats_get_counters(struct dpa_stats_cnt_request_params params,
return -EPERM;
}
+ /* Check user-provided size for array of counters */
+ if (params.cnts_ids_len == 0 ||
+ params.cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Number of requested counter ids (%d) must be in range (1 - %d)\n",
+ params.cnts_ids_len, DPA_STATS_REQ_CNTS_IDS_LEN);
+ return -EINVAL;
+ }
+
/* Check user-provided cnts_len pointer */
if (!cnts_len) {
log_err("Parameter cnts_len cannot be NULL\n");
@@ -4358,10 +4368,10 @@ int dpa_stats_get_counters(struct dpa_stats_cnt_request_params params,
for (i = 0; i < params.cnts_ids_len; i++) {
if (params.cnts_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID ||
- params.cnts_ids[i] > dpa_stats->config.max_counters) {
- log_err("Counter id (cnt_ids[%d]) %d is not initialized or is greater than maximum counters %d\n",
+ params.cnts_ids[i] >= dpa_stats->config.max_counters) {
+ log_err("Counter id (cnt_ids[%d]) %d is not initialized or is greater than maximum counter id %d\n",
i, params.cnts_ids[i],
- dpa_stats->config.max_counters);
+ dpa_stats->config.max_counters - 1);
return -EINVAL;
}
}
@@ -4459,8 +4469,9 @@ int dpa_stats_reset_counters(int *cnts_ids, unsigned int cnts_ids_len)
}
/* Check user-provided cnts_len pointer */
- if (cnts_ids_len == 0) {
- log_err("Parameter cnts_ids_len cannot be 0\n");
+ if (cnts_ids_len == 0 || cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Parameter cnts_ids_len %d must be in range (1 - %d)\n",
+ cnts_ids_len, DPA_STATS_REQ_CNTS_IDS_LEN);
return -EINVAL;
}
@@ -4474,8 +4485,8 @@ int dpa_stats_reset_counters(int *cnts_ids, unsigned int cnts_ids_len)
for (i = 0; i < cnts_ids_len; i++)
if (cnts_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID ||
- cnts_ids[i] > dpa_stats->config.max_counters) {
- log_err("Counter id (cnts_ids[%d]) %d is not initialized or is greater than maximum counters %d\n",
+ cnts_ids[i] >= dpa_stats->config.max_counters) {
+ log_err("Counter id (cnt_ids[%d]) %d is not initialized or is greater than maximum counter id %d\n",
i, cnts_ids[i],
dpa_stats->config.max_counters - 1);
return -EINVAL;
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
index 49545e85..57784a9 100644
--- a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
@@ -555,6 +555,15 @@ static long do_ioctl_stats_init(struct ioc_dpa_stats_params *prm)
long ret = 0;
uint16_t i;
+ /* Check user-provided storage area length */
+ if (prm->storage_area_len < DPA_STATS_CNT_SEL_LEN ||
+ prm->storage_area_len > DPA_STATS_MAX_STORAGE_AREA_SIZE) {
+ log_err("Parameter storage_area_len %d must be in range (%d - %d)\n",
+ prm->storage_area_len,
+ DPA_STATS_CNT_SEL_LEN, DPA_STATS_MAX_STORAGE_AREA_SIZE);
+ return -EINVAL;
+ }
+
/* Save user-provided parameters */
params.max_counters = prm->max_counters;
params.storage_area_len = prm->storage_area_len;
@@ -841,6 +850,13 @@ static int do_ioctl_stats_create_class_counter(void *args)
return -EINVAL;
}
+ if (prm.cnt_params.class_members > DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS) {
+ log_err("Parameter class_members %d exceeds maximum number of class members: %d\n",
+ prm.cnt_params.class_members,
+ DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS);
+ return -EINVAL;
+ }
+
cls_mbrs = prm.cnt_params.class_members;
switch (prm.cnt_params.type) {
@@ -1102,6 +1118,13 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
return -EINVAL;
}
+ if (uprm_cls->class_members > DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS) {
+ log_err("Parameter class_members %d exceeds maximum number of class members: %d\n",
+ uprm_cls->class_members,
+ DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS);
+ return -EINVAL;
+ }
+
memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cls_cnt_params));
kprm.stats_id = uprm.stats_id;
kprm_cls->type = uprm_cls->type;
@@ -1451,6 +1474,14 @@ static int do_ioctl_stats_get_counters(void *args)
return -EINVAL;
}
+ if (prm.req_params.cnts_ids_len == 0 ||
+ prm.req_params.cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Number of requested counter ids (%d) must be in range (1 - %d)\n",
+ prm.req_params.cnts_ids_len,
+ DPA_STATS_REQ_CNTS_IDS_LEN);
+ return -EINVAL;
+ }
+
/* Save the user-space array of counter ids */
cnts_ids = prm.req_params.cnts_ids;
@@ -1520,8 +1551,15 @@ static int do_ioctl_stats_compat_get_counters(void *args)
return -EINVAL;
}
+ if (uprm.req_params.cnts_ids_len == 0 ||
+ uprm.req_params.cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Number of requested counter ids (%d) must be in range (1 - %d)\n",
+ uprm.req_params.cnts_ids_len,
+ DPA_STATS_REQ_CNTS_IDS_LEN);
+ return -EINVAL;
+ }
+
memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cnt_request_params));
- kprm.cnts_len = uprm.cnts_len;
kprm.request_done = (dpa_stats_request_cb)
((compat_ptr)(uprm.request_done));
kprm.req_params.cnts_ids_len = uprm.req_params.cnts_ids_len;
@@ -1608,6 +1646,13 @@ static int do_ioctl_stats_reset_counters(void *args)
return -EINVAL;
}
+ if (prm.cnts_ids_len == 0 ||
+ prm.cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Number of counters to reset %d must be in range (1 - %d)\n",
+ prm.cnts_ids_len, DPA_STATS_REQ_CNTS_IDS_LEN);
+ return -EINVAL;
+ }
+
/* Allocate kernel-space memory area to copy the counters ids */
cnt_ids = kcalloc(prm.cnts_ids_len, sizeof(int), GFP_KERNEL);
if (!cnt_ids) {
@@ -1653,6 +1698,13 @@ static int do_ioctl_stats_compat_reset_counters(void *args)
return -EINVAL;
}
+ if (uprm.cnts_ids_len == 0 ||
+ uprm.cnts_ids_len > DPA_STATS_REQ_CNTS_IDS_LEN) {
+ log_err("Number of counters to reset %d must be in range (1 - %d)\n",
+ uprm.cnts_ids_len, DPA_STATS_REQ_CNTS_IDS_LEN);
+ return -EINVAL;
+ }
+
memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cnts_reset_params));
kprm.cnts_ids_len = uprm.cnts_ids_len;
@@ -2005,6 +2057,14 @@ static int copy_key_descriptor_compatcpy(
return -ENOMEM;
}
+ if ((compat_ptr(key.byte) || compat_ptr(key.mask))) {
+ if (key.size == 0 || key.size > DPA_OFFLD_MAXENTRYKEYSIZE) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+ }
+
if (compat_ptr(key.byte)) {
/* Allocate memory to store the key byte array */
kparam->byte = kmalloc(key.size, GFP_KERNEL);