8000 net: fix decnet rtnexthop parsing · bsd-unix/linux@ab58298 · GitHub
[go: up one dir, main page]

Skip to content {"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}

Commit ab58298

Browse files
vegarddavem330
authored andcommitted
net: fix decnet rtnexthop parsing
dn_fib_count_nhs() could enter an infinite loop if nhp->rtnh_len == 0 (i.e. if userspace passes a malformed netlink message). Let's use the helpers from net/nexthop.h which take care of all this stuff. We can do exactly the same as e.g. fib_count_nexthops() and fib_get_nhs() from net/ipv4/fib_semantics.c. This fixes the softlockup for me. Cc: Thomas Graf <tgraf@suug.ch> Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f5d6516 commit ab58298

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

net/decnet/dn_fib.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <net/dn_fib.h>
4242
#include <net/dn_neigh.h>
4343
#include <net/dn_dev.h>
44+
#include <net/nexthop.h>
4445

4546
#define RT_MIN_TABLE 1
4647

@@ -150,14 +151,13 @@ static int dn_fib_count_nhs(const struct nlattr *attr)
150151
struct rtnexthop *nhp = nla_data(attr);
151152
int nhs = 0, nhlen = nla_len(attr);
152153

153-
while(nhlen >= (int)sizeof(struct rtnexthop)) {
154-
if ((nhlen -= nhp->rtnh_len) < 0)
155-
return 0;
154+
while (rtnh_ok(nhp, nhlen)) {
156155
nhs++;
< 8000 /td>
157-
nhp = RTNH_NEXT(nhp);
156+
nhp = rtnh_next(nhp, &nhlen);
158157
}
159158

160-
return nhs;
159+
/* leftover implies invalid nexthop configuration, discard it */
160+
return nhlen > 0 ? 0 : nhs;
161161
}
162162

163163
static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr,
@@ -167,21 +167,24 @@ static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr,
167167
int nhlen = nla_len(attr);
168168

169169
change_nexthops(fi) {
170-
int attrlen = nhlen - sizeof(struct rtnexthop);
171-
if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
170+
int attrlen;
171+
172+
if (!rtnh_ok(nhp, nhlen))
172173
return -EINVAL;
173174

174175
nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags;
175176
nh->nh_oif = nhp->rtnh_ifindex;
176177
nh->nh_weight = nhp->rtnh_hops + 1;
177178

178-
if (attrlen) {
179+
attrlen = rtnh_attrlen(nhp);
180+
if (attrlen > 0) {
179181
struct nlattr *gw_attr;
180182

181183
gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
182184
nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0;
183185
}
184-
nhp = RTNH_NEXT(nhp);
186+
187+
nhp = rtnh_next(nhp, &nhlen);
185188
} endfor_nexthops(fi);
186189

187190
return 0;

0 commit comments

Comments
 (0)
0