aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-10-10 13:19:10 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-10 13:19:10 -0400
commit8b79f410438f5407ff45ceb72ad1eb02409652b4 (patch)
tree834c7d34a735b3be2621f897c76275bd6427f694
parent4cf34c0cf60e328b72ae17016b7c12fc66dbf76b (diff)
parentbde74ad10eb55aaa472c37b107934e6b8563c25e (diff)
Merge branch 'devlink-param-type-string-fixes'
Moshe Shemesh says: ==================== devlink param type string fixes This patchset fixes devlink param infrastructure for string param type. The devlink param infrastructure doesn't handle copying the string data correctly. The first two patches fix it and the third patch adds helper function to safely copy string value without exceeding DEVLINK_PARAM_MAX_STRING_VALUE. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/devlink.h12
-rw-r--r--net/core/devlink.c43
2 files changed, 47 insertions, 8 deletions
diff --git a/include/net/devlink.h b/include/net/devlink.h
index b9b89d6604d4..99efc156a309 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -298,7 +298,7 @@ struct devlink_resource {
298 298
299#define DEVLINK_RESOURCE_ID_PARENT_TOP 0 299#define DEVLINK_RESOURCE_ID_PARENT_TOP 0
300 300
301#define DEVLINK_PARAM_MAX_STRING_VALUE 32 301#define __DEVLINK_PARAM_MAX_STRING_VALUE 32
302enum devlink_param_type { 302enum devlink_param_type {
303 DEVLINK_PARAM_TYPE_U8, 303 DEVLINK_PARAM_TYPE_U8,
304 DEVLINK_PARAM_TYPE_U16, 304 DEVLINK_PARAM_TYPE_U16,
@@ -311,7 +311,7 @@ union devlink_param_value {
311 u8 vu8; 311 u8 vu8;
312 u16 vu16; 312 u16 vu16;
313 u32 vu32; 313 u32 vu32;
314 const char *vstr; 314 char vstr[__DEVLINK_PARAM_MAX_STRING_VALUE];
315 bool vbool; 315 bool vbool;
316}; 316};
317 317
@@ -553,6 +553,8 @@ int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
553int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 553int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
554 union devlink_param_value init_val); 554 union devlink_param_value init_val);
555void devlink_param_value_changed(struct devlink *devlink, u32 param_id); 555void devlink_param_value_changed(struct devlink *devlink, u32 param_id);
556void devlink_param_value_str_fill(union devlink_param_value *dst_val,
557 const char *src);
556struct devlink_region *devlink_region_create(struct devlink *devlink, 558struct devlink_region *devlink_region_create(struct devlink *devlink,
557 const char *region_name, 559 const char *region_name,
558 u32 region_max_snapshots, 560 u32 region_max_snapshots,
@@ -789,6 +791,12 @@ devlink_param_value_changed(struct devlink *devlink, u32 param_id)
789{ 791{
790} 792}
791 793
794static inline void
795devlink_param_value_str_fill(union devlink_param_value *dst_val,
796 const char *src)
797{
798}
799
792static inline struct devlink_region * 800static inline struct devlink_region *
793devlink_region_create(struct devlink *devlink, 801devlink_region_create(struct devlink *devlink,
794 const char *region_name, 802 const char *region_name,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 8c0ed225e280..6bc42933be4a 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2995,6 +2995,8 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
2995 struct genl_info *info, 2995 struct genl_info *info,
2996 union devlink_param_value *value) 2996 union devlink_param_value *value)
2997{ 2997{
2998 int len;
2999
2998 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 3000 if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
2999 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3001 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
3000 return -EINVAL; 3002 return -EINVAL;
@@ -3010,10 +3012,13 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
3010 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3012 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3011 break; 3013 break;
3012 case DEVLINK_PARAM_TYPE_STRING: 3014 case DEVLINK_PARAM_TYPE_STRING:
3013 if (nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) > 3015 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
3014 DEVLINK_PARAM_MAX_STRING_VALUE) 3016 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3017 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
3018 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3015 return -EINVAL; 3019 return -EINVAL;
3016 value->vstr = nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3020 strcpy(value->vstr,
3021 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3017 break; 3022 break;
3018 case DEVLINK_PARAM_TYPE_BOOL: 3023 case DEVLINK_PARAM_TYPE_BOOL:
3019 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3024 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
@@ -3100,7 +3105,10 @@ static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3100 return -EOPNOTSUPP; 3105 return -EOPNOTSUPP;
3101 3106
3102 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3107 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3103 param_item->driverinit_value = value; 3108 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3109 strcpy(param_item->driverinit_value.vstr, value.vstr);
3110 else
3111 param_item->driverinit_value = value;
3104 param_item->driverinit_value_valid = true; 3112 param_item->driverinit_value_valid = true;
3105 } else { 3113 } else {
3106 if (!param->set) 3114 if (!param->set)
@@ -4540,7 +4548,10 @@ int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
4540 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4548 DEVLINK_PARAM_CMODE_DRIVERINIT))
4541 return -EOPNOTSUPP; 4549 return -EOPNOTSUPP;
4542 4550
4543 *init_val = param_item->driverinit_value; 4551 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
4552 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
4553 else
4554 *init_val = param_item->driverinit_value;
4544 4555
4545 return 0; 4556 return 0;
4546} 4557}
@@ -4571,7 +4582,10 @@ int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
4571 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4582 DEVLINK_PARAM_CMODE_DRIVERINIT))
4572 return -EOPNOTSUPP; 4583 return -EOPNOTSUPP;
4573 4584
4574 param_item->driverinit_value = init_val; 4585 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
4586 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
4587 else
4588 param_item->driverinit_value = init_val;
4575 param_item->driverinit_value_valid = true; 4589 param_item->driverinit_value_valid = true;
4576 4590
4577 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4591 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW);
@@ -4604,6 +4618,23 @@ void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
4604EXPORT_SYMBOL_GPL(devlink_param_value_changed); 4618EXPORT_SYMBOL_GPL(devlink_param_value_changed);
4605 4619
4606/** 4620/**
4621 * devlink_param_value_str_fill - Safely fill-up the string preventing
4622 * from overflow of the preallocated buffer
4623 *
4624 * @dst_val: destination devlink_param_value
4625 * @src: source buffer
4626 */
4627void devlink_param_value_str_fill(union devlink_param_value *dst_val,
4628 const char *src)
4629{
4630 size_t len;
4631
4632 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
4633 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
4634}
4635EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
4636
4637/**
4607 * devlink_region_create - create a new address region 4638 * devlink_region_create - create a new address region
4608 * 4639 *
4609 * @devlink: devlink 4640 * @devlink: devlink