mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
devlink: heap-allocate param fill buffers in devlink_nl_param_fill
devlink_nl_param_fill() kept two per-configuration-mode copies of union devlink_param_value plus a struct devlink_param_gset_ctx on the stack while building the Netlink reply. Allocate those with kcalloc() and kzalloc_obj() instead, and route failures through a single cleanup path so temporary buffers are always freed. Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com> Link: https://patch.msgid.link/20260609040453.711932-4-rkannoth@marvell.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
4655902dee
commit
c0e67fd123
@@ -304,56 +304,79 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
u32 portid, u32 seq, int flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
union devlink_param_value default_value[DEVLINK_PARAM_CMODE_MAX + 1];
|
||||
union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
|
||||
bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
|
||||
bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
|
||||
const struct devlink_param *param = param_item->param;
|
||||
struct devlink_param_gset_ctx ctx;
|
||||
union devlink_param_value *default_value;
|
||||
union devlink_param_value *param_value;
|
||||
struct devlink_param_gset_ctx *ctx;
|
||||
struct nlattr *param_values_list;
|
||||
struct nlattr *param_attr;
|
||||
void *hdr;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
default_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
|
||||
sizeof(*default_value), GFP_KERNEL);
|
||||
if (!default_value)
|
||||
return -ENOMEM;
|
||||
|
||||
param_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
|
||||
sizeof(*param_value), GFP_KERNEL);
|
||||
if (!param_value) {
|
||||
kfree(default_value);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx = kzalloc_obj(*ctx);
|
||||
if (!ctx) {
|
||||
kfree(param_value);
|
||||
kfree(default_value);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get value from driver part to driverinit configuration mode */
|
||||
for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
|
||||
if (!devlink_param_cmode_is_supported(param, i))
|
||||
continue;
|
||||
if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
|
||||
if (param_item->driverinit_value_new_valid)
|
||||
if (param_item->driverinit_value_new_valid) {
|
||||
param_value[i] = param_item->driverinit_value_new;
|
||||
else if (param_item->driverinit_value_valid)
|
||||
} else if (param_item->driverinit_value_valid) {
|
||||
param_value[i] = param_item->driverinit_value;
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
} else {
|
||||
err = -EOPNOTSUPP;
|
||||
goto get_put_fail;
|
||||
}
|
||||
|
||||
if (param_item->driverinit_value_valid) {
|
||||
default_value[i] = param_item->driverinit_default;
|
||||
default_value_set[i] = true;
|
||||
}
|
||||
} else {
|
||||
ctx.cmode = i;
|
||||
err = devlink_param_get(devlink, param, &ctx, extack);
|
||||
ctx->cmode = i;
|
||||
err = devlink_param_get(devlink, param, ctx, extack);
|
||||
if (err)
|
||||
return err;
|
||||
param_value[i] = ctx.val;
|
||||
goto get_put_fail;
|
||||
|
||||
err = devlink_param_get_default(devlink, param, &ctx,
|
||||
param_value[i] = ctx->val;
|
||||
|
||||
err = devlink_param_get_default(devlink, param, ctx,
|
||||
extack);
|
||||
if (!err) {
|
||||
default_value[i] = ctx.val;
|
||||
default_value[i] = ctx->val;
|
||||
default_value_set[i] = true;
|
||||
} else if (err != -EOPNOTSUPP) {
|
||||
return err;
|
||||
goto get_put_fail;
|
||||
}
|
||||
}
|
||||
param_value_set[i] = true;
|
||||
}
|
||||
|
||||
err = -EMSGSIZE;
|
||||
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
|
||||
if (!hdr)
|
||||
return -EMSGSIZE;
|
||||
goto get_put_fail;
|
||||
|
||||
if (devlink_nl_put_handle(msg, devlink))
|
||||
goto genlmsg_cancel;
|
||||
@@ -393,6 +416,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
nla_nest_end(msg, param_values_list);
|
||||
nla_nest_end(msg, param_attr);
|
||||
genlmsg_end(msg, hdr);
|
||||
kfree(default_value);
|
||||
kfree(param_value);
|
||||
kfree(ctx);
|
||||
return 0;
|
||||
|
||||
values_list_nest_cancel:
|
||||
@@ -401,7 +427,11 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
nla_nest_cancel(msg, param_attr);
|
||||
genlmsg_cancel:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
get_put_fail:
|
||||
kfree(default_value);
|
||||
kfree(param_value);
|
||||
kfree(ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void devlink_param_notify(struct devlink *devlink,
|
||||
|
||||
Reference in New Issue
Block a user