Skip to content

Commit c90c39d

Browse files
jmberg-inteldavem330
authored andcommitted
genetlink: introduce and use genl_family_attrbuf()
This helper function allows family implementations to access their family's attrbuf. This gets rid of the attrbuf usage in families, and also adds locking validation, since it's not valid to use the attrbuf with parallel_ops or outside of the dumpit callback. Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4fe77d8 commit c90c39d

File tree

6 files changed

+55
-35
lines changed

6 files changed

+55
-35
lines changed

include/net/genetlink.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ struct genl_family {
7373
struct module *module;
7474
};
7575

76+
struct nlattr **genl_family_attrbuf(struct genl_family *family);
77+
7678
/**
7779
* struct genl_info - receiving information
7880
* @snd_seq: sending sequence number

net/ieee802154/nl802154.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,14 @@ nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
263263

264264
if (!cb->args[0]) {
265265
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
266-
nl802154_fam.attrbuf, nl802154_fam.maxattr,
266+
genl_family_attrbuf(&nl802154_fam),
267+
nl802154_fam.maxattr,
267268
nl802154_policy);
268269
if (err)
269270
goto out_unlock;
270271

271272
*wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
272-
nl802154_fam.attrbuf);
273+
genl_family_attrbuf(&nl802154_fam));
273274
if (IS_ERR(*wpan_dev)) {
274275
err = PTR_ERR(*wpan_dev);
275276
goto out_unlock;
@@ -575,7 +576,7 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
575576
struct netlink_callback *cb,
576577
struct nl802154_dump_wpan_phy_state *state)
577578
{
578-
struct nlattr **tb = nl802154_fam.attrbuf;
579+
struct nlattr **tb = genl_family_attrbuf(&nl802154_fam);
579580
int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
580581
tb, nl802154_fam.maxattr, nl802154_policy);
581582

net/netlink/genetlink.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,25 @@ static int __init genl_init(void)
10961096

10971097
subsys_initcall(genl_init);
10981098

1099+
/**
1100+
* genl_family_attrbuf - return family's attrbuf
1101+
* @family: the family
1102+
*
1103+
* Return the family's attrbuf, while validating that it's
1104+
* actually valid to access it.
1105+
*
1106+
* You cannot use this function with a family that has parallel_ops
1107+
* and you can only use it within (pre/post) doit/dumpit callbacks.
1108+
*/
1109+
struct nlattr **genl_family_attrbuf(struct genl_family *family)
1110+
{
1111+
if (!WARN_ON(family->parallel_ops))
1112+
lockdep_assert_held(&genl_mutex);
1113+
1114+
return family->attrbuf;
1115+
}
1116+
EXPORT_SYMBOL(genl_family_attrbuf);
1117+
10991118
static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
11001119
gfp_t flags)
11011120
{

net/nfc/netlink.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,21 +120,20 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
120120

121121
static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
122122
{
123+
struct nlattr **attrbuf = genl_family_attrbuf(&nfc_genl_family);
123124
struct nfc_dev *dev;
124125
int rc;
125126
u32 idx;
126127

127128
rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
128-
nfc_genl_family.attrbuf,
129-
nfc_genl_family.maxattr,
130-
nfc_genl_policy);
129+
attrbuf, nfc_genl_family.maxattr, nfc_genl_policy);
131130
if (rc < 0)
132131
return ERR_PTR(rc);
133132

134-
if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
133+
if (!attrbuf[NFC_ATTR_DEVICE_INDEX])
135134
return ERR_PTR(-EINVAL);
136135

137-
idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
136+
idx = nla_get_u32(attrbuf[NFC_ATTR_DEVICE_INDEX]);
138137

139138
dev = nfc_get_device(idx);
140139
if (!dev)

net/tipc/netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
262262
{
263263
u32 maxattr = tipc_genl_family.maxattr;
264264

265-
*attr = tipc_genl_family.attrbuf;
265+
*attr = genl_family_attrbuf(&tipc_genl_family);
266266
if (!*attr)
267267
return -EOPNOTSUPP;
268268

net/wireless/nl80211.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -551,13 +551,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
551551

552552
if (!cb->args[0]) {
553553
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
554-
nl80211_fam.attrbuf, nl80211_fam.maxattr,
555-
nl80211_policy);
554+
genl_family_attrbuf(&nl80211_fam),
555+
nl80211_fam.maxattr, nl80211_policy);
556556
if (err)
557557
goto out_unlock;
558558

559-
*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
560-
nl80211_fam.attrbuf);
559+
*wdev = __cfg80211_wdev_from_attrs(
560+
sock_net(skb->sk),
561+
genl_family_attrbuf(&nl80211_fam));
561562
if (IS_ERR(*wdev)) {
562563
err = PTR_ERR(*wdev);
563564
goto out_unlock;
@@ -1881,7 +1882,7 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
18811882
struct netlink_callback *cb,
18821883
struct nl80211_dump_wiphy_state *state)
18831884
{
1884-
struct nlattr **tb = nl80211_fam.attrbuf;
1885+
struct nlattr **tb = genl_family_attrbuf(&nl80211_fam);
18851886
int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
18861887
tb, nl80211_fam.maxattr, nl80211_policy);
18871888
/* ignore parse errors for backward compatibility */
@@ -7643,6 +7644,7 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
76437644

76447645
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
76457646
{
7647+
struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
76467648
struct survey_info survey;
76477649
struct cfg80211_registered_device *rdev;
76487650
struct wireless_dev *wdev;
@@ -7655,7 +7657,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
76557657
return res;
76567658

76577659
/* prepare_wdev_dump parsed the attributes */
7658-
radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
7660+
radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
76597661

76607662
if (!wdev->netdev) {
76617663
res = -EINVAL;
@@ -8478,24 +8480,23 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
84788480
*/
84798481
phy_idx = cb->args[0] - 1;
84808482
} else {
8483+
struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
8484+
84818485
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
8482-
nl80211_fam.attrbuf, nl80211_fam.maxattr,
8483-
nl80211_policy);
8486+
attrbuf, nl80211_fam.maxattr, nl80211_policy);
84848487
if (err)
84858488
goto out_err;
84868489

8487-
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
8488-
nl80211_fam.attrbuf);
8490+
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
84898491
if (IS_ERR(rdev)) {
84908492
err = PTR_ERR(rdev);
84918493
goto out_err;
84928494
}
84938495
phy_idx = rdev->wiphy_idx;
84948496
rdev = NULL;
84958497

8496-
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
8497-
cb->args[1] =
8498-
(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
8498+
if (attrbuf[NL80211_ATTR_TESTDATA])
8499+
cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
84998500
}
85008501

85018502
if (cb->args[1]) {
@@ -11277,6 +11278,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
1127711278
struct cfg80211_registered_device **rdev,
1127811279
struct wireless_dev **wdev)
1127911280
{
11281+
struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
1128011282
u32 vid, subcmd;
1128111283
unsigned int i;
1128211284
int vcmd_idx = -1;
@@ -11312,31 +11314,28 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
1131211314
}
1131311315

1131411316
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
11315-
nl80211_fam.attrbuf, nl80211_fam.maxattr,
11316-
nl80211_policy);
11317+
attrbuf, nl80211_fam.maxattr, nl80211_policy);
1131711318
if (err)
1131811319
goto out_unlock;
1131911320

11320-
if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] ||
11321-
!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
11321+
if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
11322+
!attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
1132211323
err = -EINVAL;
1132311324
goto out_unlock;
1132411325
}
1132511326

11326-
*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
11327-
nl80211_fam.attrbuf);
11327+
*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
1132811328
if (IS_ERR(*wdev))
1132911329
*wdev = NULL;
1133011330

11331-
*rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
11332-
nl80211_fam.attrbuf);
11331+
*rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
1133311332
if (IS_ERR(*rdev)) {
1133411333
err = PTR_ERR(*rdev);
1133511334
goto out_unlock;
1133611335
}
1133711336

11338-
vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]);
11339-
subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
11337+
vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
11338+
subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
1134011339

1134111340
for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
1134211341
const struct wiphy_vendor_command *vcmd;
@@ -11360,9 +11359,9 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
1136011359
goto out_unlock;
1136111360
}
1136211361

11363-
if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) {
11364-
data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
11365-
data_len = nla_len(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
11362+
if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
11363+
data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
11364+
data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
1136611365
}
1136711366

1136811367
/* 0 is the first index - add 1 to parse only once */

0 commit comments

Comments
 (0)