diff options
| -rw-r--r-- | net/core/devlink.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/net/core/devlink.c b/net/core/devlink.c index 283c3ed9f25e..1d7502a5a651 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c | |||
| @@ -116,6 +116,8 @@ static struct devlink *devlink_get_from_attrs(struct net *net, | |||
| 116 | busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); | 116 | busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); |
| 117 | devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); | 117 | devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); |
| 118 | 118 | ||
| 119 | lockdep_assert_held(&devlink_mutex); | ||
| 120 | |||
| 119 | list_for_each_entry(devlink, &devlink_list, list) { | 121 | list_for_each_entry(devlink, &devlink_list, list) { |
| 120 | if (strcmp(devlink->dev->bus->name, busname) == 0 && | 122 | if (strcmp(devlink->dev->bus->name, busname) == 0 && |
| 121 | strcmp(dev_name(devlink->dev), devname) == 0 && | 123 | strcmp(dev_name(devlink->dev), devname) == 0 && |
| @@ -3645,27 +3647,35 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, | |||
| 3645 | if (err) | 3647 | if (err) |
| 3646 | goto out_free; | 3648 | goto out_free; |
| 3647 | 3649 | ||
| 3650 | mutex_lock(&devlink_mutex); | ||
| 3648 | devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); | 3651 | devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); |
| 3649 | if (IS_ERR(devlink)) | 3652 | if (IS_ERR(devlink)) { |
| 3650 | goto out_free; | 3653 | err = PTR_ERR(devlink); |
| 3654 | goto out_dev; | ||
| 3655 | } | ||
| 3651 | 3656 | ||
| 3652 | mutex_lock(&devlink_mutex); | ||
| 3653 | mutex_lock(&devlink->lock); | 3657 | mutex_lock(&devlink->lock); |
| 3654 | 3658 | ||
| 3655 | if (!attrs[DEVLINK_ATTR_REGION_NAME] || | 3659 | if (!attrs[DEVLINK_ATTR_REGION_NAME] || |
| 3656 | !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) | 3660 | !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { |
| 3661 | err = -EINVAL; | ||
| 3657 | goto out_unlock; | 3662 | goto out_unlock; |
| 3663 | } | ||
| 3658 | 3664 | ||
| 3659 | region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); | 3665 | region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); |
| 3660 | region = devlink_region_get_by_name(devlink, region_name); | 3666 | region = devlink_region_get_by_name(devlink, region_name); |
| 3661 | if (!region) | 3667 | if (!region) { |
| 3668 | err = -EINVAL; | ||
| 3662 | goto out_unlock; | 3669 | goto out_unlock; |
| 3670 | } | ||
| 3663 | 3671 | ||
| 3664 | hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, | 3672 | hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
| 3665 | &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, | 3673 | &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, |
| 3666 | DEVLINK_CMD_REGION_READ); | 3674 | DEVLINK_CMD_REGION_READ); |
| 3667 | if (!hdr) | 3675 | if (!hdr) { |
| 3676 | err = -EMSGSIZE; | ||
| 3668 | goto out_unlock; | 3677 | goto out_unlock; |
| 3678 | } | ||
| 3669 | 3679 | ||
| 3670 | err = devlink_nl_put_handle(skb, devlink); | 3680 | err = devlink_nl_put_handle(skb, devlink); |
| 3671 | if (err) | 3681 | if (err) |
| @@ -3676,8 +3686,10 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, | |||
| 3676 | goto nla_put_failure; | 3686 | goto nla_put_failure; |
| 3677 | 3687 | ||
| 3678 | chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); | 3688 | chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); |
| 3679 | if (!chunks_attr) | 3689 | if (!chunks_attr) { |
| 3690 | err = -EMSGSIZE; | ||
| 3680 | goto nla_put_failure; | 3691 | goto nla_put_failure; |
| 3692 | } | ||
| 3681 | 3693 | ||
| 3682 | if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && | 3694 | if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && |
| 3683 | attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { | 3695 | attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { |
| @@ -3700,8 +3712,10 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, | |||
| 3700 | goto nla_put_failure; | 3712 | goto nla_put_failure; |
| 3701 | 3713 | ||
| 3702 | /* Check if there was any progress done to prevent infinite loop */ | 3714 | /* Check if there was any progress done to prevent infinite loop */ |
| 3703 | if (ret_offset == start_offset) | 3715 | if (ret_offset == start_offset) { |
| 3716 | err = -EINVAL; | ||
| 3704 | goto nla_put_failure; | 3717 | goto nla_put_failure; |
| 3718 | } | ||
| 3705 | 3719 | ||
| 3706 | *((u64 *)&cb->args[0]) = ret_offset; | 3720 | *((u64 *)&cb->args[0]) = ret_offset; |
| 3707 | 3721 | ||
| @@ -3717,10 +3731,11 @@ nla_put_failure: | |||
| 3717 | genlmsg_cancel(skb, hdr); | 3731 | genlmsg_cancel(skb, hdr); |
| 3718 | out_unlock: | 3732 | out_unlock: |
| 3719 | mutex_unlock(&devlink->lock); | 3733 | mutex_unlock(&devlink->lock); |
| 3734 | out_dev: | ||
| 3720 | mutex_unlock(&devlink_mutex); | 3735 | mutex_unlock(&devlink_mutex); |
| 3721 | out_free: | 3736 | out_free: |
| 3722 | kfree(attrs); | 3737 | kfree(attrs); |
| 3723 | return 0; | 3738 | return err; |
| 3724 | } | 3739 | } |
| 3725 | 3740 | ||
| 3726 | struct devlink_info_req { | 3741 | struct devlink_info_req { |
