Skip to content

Commit 23c3948

Browse files
committed
Merge branch 'ethtool-fail-with-error-if-request-has-unknown-flags'
Michal Kubecek says: ==================== ethtool: fail with error if request has unknown flags Jakub Kicinski pointed out that if unrecognized flags are set in netlink header request, kernel shoud fail with an error rather than silently ignore them so that we have more freedom in future flags semantics. To help userspace with handling such errors, inform the client which flags are supported by kernel. For that purpose, we need to allow passing cookies as part of extack also in case of error (they can be only passed on success now). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents ef299cc + 2363d73 commit 23c3948

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

include/linux/netlink.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ static inline void nl_set_extack_cookie_u64(struct netlink_ext_ack *extack,
119119
extack->cookie_len = sizeof(__cookie);
120120
}
121121

122+
static inline void nl_set_extack_cookie_u32(struct netlink_ext_ack *extack,
123+
u32 cookie)
124+
{
125+
u32 __cookie = cookie;
126+
127+
memcpy(extack->cookie, &__cookie, sizeof(__cookie));
128+
extack->cookie_len = sizeof(__cookie);
129+
}
130+
122131
void netlink_kernel_release(struct sock *sk);
123132
int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
124133
int netlink_change_ngroups(struct sock *sk, unsigned int groups);

net/ethtool/netlink.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ int ethnl_parse_header(struct ethnl_req_info *req_info,
4040
struct nlattr *tb[ETHTOOL_A_HEADER_MAX + 1];
4141
const struct nlattr *devname_attr;
4242
struct net_device *dev = NULL;
43+
u32 flags = 0;
4344
int ret;
4445

4546
if (!header) {
@@ -50,8 +51,17 @@ int ethnl_parse_header(struct ethnl_req_info *req_info,
5051
ethnl_header_policy, extack);
5152
if (ret < 0)
5253
return ret;
53-
devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
54+
if (tb[ETHTOOL_A_HEADER_FLAGS]) {
55+
flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);
56+
if (flags & ~ETHTOOL_FLAG_ALL) {
57+
NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_HEADER_FLAGS],
58+
"unrecognized request flags");
59+
nl_set_extack_cookie_u32(extack, ETHTOOL_FLAG_ALL);
60+
return -EOPNOTSUPP;
61+
}
62+
}
5463

64+
devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
5565
if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) {
5666
u32 ifindex = nla_get_u32(tb[ETHTOOL_A_HEADER_DEV_INDEX]);
5767

@@ -90,9 +100,7 @@ int ethnl_parse_header(struct ethnl_req_info *req_info,
90100
}
91101

92102
req_info->dev = dev;
93-
if (tb[ETHTOOL_A_HEADER_FLAGS])
94-
req_info->flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);
95-
103+
req_info->flags = flags;
96104
return 0;
97105
}
98106

net/netlink/af_netlink.c

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,19 +2392,14 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
23922392
if (nlk_has_extack && extack && extack->_msg)
23932393
tlvlen += nla_total_size(strlen(extack->_msg) + 1);
23942394

2395-
if (err) {
2396-
if (!(nlk->flags & NETLINK_F_CAP_ACK))
2397-
payload += nlmsg_len(nlh);
2398-
else
2399-
flags |= NLM_F_CAPPED;
2400-
if (nlk_has_extack && extack && extack->bad_attr)
2401-
tlvlen += nla_total_size(sizeof(u32));
2402-
} else {
2395+
if (err && !(nlk->flags & NETLINK_F_CAP_ACK))
2396+
payload += nlmsg_len(nlh);
2397+
else
24032398
flags |= NLM_F_CAPPED;
2404-
2405-
if (nlk_has_extack && extack && extack->cookie_len)
2406-
tlvlen += nla_total_size(extack->cookie_len);
2407-
}
2399+
if (err && nlk_has_extack && extack && extack->bad_attr)
2400+
tlvlen += nla_total_size(sizeof(u32));
2401+
if (nlk_has_extack && extack && extack->cookie_len)
2402+
tlvlen += nla_total_size(extack->cookie_len);
24082403

24092404
if (tlvlen)
24102405
flags |= NLM_F_ACK_TLVS;
@@ -2427,20 +2422,16 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
24272422
WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG,
24282423
extack->_msg));
24292424
}
2430-
if (err) {
2431-
if (extack->bad_attr &&
2432-
!WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
2433-
(u8 *)extack->bad_attr >= in_skb->data +
2434-
in_skb->len))
2435-
WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
2436-
(u8 *)extack->bad_attr -
2437-
(u8 *)nlh));
2438-
} else {
2439-
if (extack->cookie_len)
2440-
WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
2441-
extack->cookie_len,
2442-
extack->cookie));
2443-
}
2425+
if (err && extack->bad_attr &&
2426+
!WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
2427+
(u8 *)extack->bad_attr >= in_skb->data +
2428+
in_skb->len))
2429+
WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
2430+
(u8 *)extack->bad_attr -
2431+
(u8 *)nlh));
2432+
if (extack->cookie_len)
2433+
WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
2434+
extack->cookie_len, extack->cookie));
24442435
}
24452436

24462437
nlmsg_end(skb, rep);

0 commit comments

Comments
 (0)