Skip to content

Commit 25e94a9

Browse files
committed
netfilter: nf_tables: don't call nfnetlink_set_err() if nfnetlink_send() fails
The underlying nlmsg_multicast() already sets sk->sk_err for us to notify socket overruns, so we should not do anything with this return value. So we just call nfnetlink_set_err() if: 1) We fail to allocate the netlink message. or 2) We don't have enough space in the netlink message to place attributes, which means that we likely need to allocate a larger message. Before this patch, the internal ESRCH netlink error code was propagated to userspace, which is quite misleading. Netlink semantics mandate that listeners just hit ENOBUFS if the socket buffer overruns. Reported-by: Alexander Alemayhu <[email protected]> Tested-by: Alexander Alemayhu <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent f912135 commit 25e94a9

File tree

2 files changed

+58
-81
lines changed

2 files changed

+58
-81
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -988,9 +988,9 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
988988
const struct nlattr *nla, u32 objtype,
989989
u8 genmask);
990990

991-
int nft_obj_notify(struct net *net, struct nft_table *table,
992-
struct nft_object *obj, u32 portid, u32 seq,
993-
int event, int family, int report, gfp_t gfp);
991+
void nft_obj_notify(struct net *net, struct nft_table *table,
992+
struct nft_object *obj, u32 portid, u32 seq,
993+
int event, int family, int report, gfp_t gfp);
994994

995995
/**
996996
* struct nft_object_type - stateful object type

net/netfilter/nf_tables_api.c

Lines changed: 55 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -461,16 +461,15 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
461461
return -1;
462462
}
463463

464-
static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
464+
static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
465465
{
466466
struct sk_buff *skb;
467467
int err;
468468

469469
if (!ctx->report &&
470470
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
471-
return 0;
471+
return;
472472

473-
err = -ENOBUFS;
474473
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
475474
if (skb == NULL)
476475
goto err;
@@ -482,14 +481,11 @@ static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
482481
goto err;
483482
}
484483

485-
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
486-
ctx->report, GFP_KERNEL);
484+
nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
485+
ctx->report, GFP_KERNEL);
486+
return;
487487
err:
488-
if (err < 0) {
489-
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
490-
err);
491-
}
492-
return err;
488+
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
493489
}
494490

495491
static int nf_tables_dump_tables(struct sk_buff *skb,
@@ -1050,16 +1046,15 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
10501046
return -1;
10511047
}
10521048

1053-
static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
1049+
static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
10541050
{
10551051
struct sk_buff *skb;
10561052
int err;
10571053

10581054
if (!ctx->report &&
10591055
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
1060-
return 0;
1056+
return;
10611057

1062-
err = -ENOBUFS;
10631058
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
10641059
if (skb == NULL)
10651060
goto err;
@@ -1072,14 +1067,11 @@ static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
10721067
goto err;
10731068
}
10741069

1075-
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1076-
ctx->report, GFP_KERNEL);
1070+
nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1071+
ctx->report, GFP_KERNEL);
1072+
return;
10771073
err:
1078-
if (err < 0) {
1079-
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1080-
err);
1081-
}
1082-
return err;
1074+
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
10831075
}
10841076

10851077
static int nf_tables_dump_chains(struct sk_buff *skb,
@@ -1934,18 +1926,16 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
19341926
return -1;
19351927
}
19361928

1937-
static int nf_tables_rule_notify(const struct nft_ctx *ctx,
1938-
const struct nft_rule *rule,
1939-
int event)
1929+
static void nf_tables_rule_notify(const struct nft_ctx *ctx,
1930+
const struct nft_rule *rule, int event)
19401931
{
19411932
struct sk_buff *skb;
19421933
int err;
19431934

19441935
if (!ctx->report &&
19451936
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
1946-
return 0;
1937+
return;
19471938

1948-
err = -ENOBUFS;
19491939
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
19501940
if (skb == NULL)
19511941
goto err;
@@ -1958,14 +1948,11 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
19581948
goto err;
19591949
}
19601950

1961-
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1962-
ctx->report, GFP_KERNEL);
1951+
nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1952+
ctx->report, GFP_KERNEL);
1953+
return;
19631954
err:
1964-
if (err < 0) {
1965-
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1966-
err);
1967-
}
1968-
return err;
1955+
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
19691956
}
19701957

19711958
struct nft_rule_dump_ctx {
@@ -2696,19 +2683,18 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
26962683
return -1;
26972684
}
26982685

2699-
static int nf_tables_set_notify(const struct nft_ctx *ctx,
2700-
const struct nft_set *set,
2701-
int event, gfp_t gfp_flags)
2686+
static void nf_tables_set_notify(const struct nft_ctx *ctx,
2687+
const struct nft_set *set, int event,
2688+
gfp_t gfp_flags)
27022689
{
27032690
struct sk_buff *skb;
27042691
u32 portid = ctx->portid;
27052692
int err;
27062693

27072694
if (!ctx->report &&
27082695
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
2709-
return 0;
2696+
return;
27102697

2711-
err = -ENOBUFS;
27122698
skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
27132699
if (skb == NULL)
27142700
goto err;
@@ -2719,12 +2705,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
27192705
goto err;
27202706
}
27212707

2722-
err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES,
2723-
ctx->report, gfp_flags);
2708+
nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, ctx->report,
2709+
gfp_flags);
2710+
return;
27242711
err:
2725-
if (err < 0)
2726-
nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
2727-
return err;
2712+
nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
27282713
}
27292714

27302715
static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
@@ -3504,20 +3489,19 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
35043489
return -1;
35053490
}
35063491

3507-
static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
3508-
const struct nft_set *set,
3509-
const struct nft_set_elem *elem,
3510-
int event, u16 flags)
3492+
static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
3493+
const struct nft_set *set,
3494+
const struct nft_set_elem *elem,
3495+
int event, u16 flags)
35113496
{
35123497
struct net *net = ctx->net;
35133498
u32 portid = ctx->portid;
35143499
struct sk_buff *skb;
35153500
int err;
35163501

35173502
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
3518-
return 0;
3503+
return;
35193504

3520-
err = -ENOBUFS;
35213505
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
35223506
if (skb == NULL)
35233507
goto err;
@@ -3529,12 +3513,11 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
35293513
goto err;
35303514
}
35313515

3532-
err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
3533-
GFP_KERNEL);
3516+
nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
3517+
GFP_KERNEL);
3518+
return;
35343519
err:
3535-
if (err < 0)
3536-
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
3537-
return err;
3520+
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
35383521
}
35393522

35403523
static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
@@ -4476,18 +4459,17 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
44764459
return nft_delobj(&ctx, obj);
44774460
}
44784461

4479-
int nft_obj_notify(struct net *net, struct nft_table *table,
4480-
struct nft_object *obj, u32 portid, u32 seq, int event,
4481-
int family, int report, gfp_t gfp)
4462+
void nft_obj_notify(struct net *net, struct nft_table *table,
4463+
struct nft_object *obj, u32 portid, u32 seq, int event,
4464+
int family, int report, gfp_t gfp)
44824465
{
44834466
struct sk_buff *skb;
44844467
int err;
44854468

44864469
if (!report &&
44874470
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
4488-
return 0;
4471+
return;
44894472

4490-
err = -ENOBUFS;
44914473
skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
44924474
if (skb == NULL)
44934475
goto err;
@@ -4499,21 +4481,18 @@ int nft_obj_notify(struct net *net, struct nft_table *table,
44994481
goto err;
45004482
}
45014483

4502-
err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
4484+
nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
4485+
return;
45034486
err:
4504-
if (err < 0) {
4505-
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
4506-
}
4507-
return err;
4487+
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
45084488
}
45094489
EXPORT_SYMBOL_GPL(nft_obj_notify);
45104490

4511-
static int nf_tables_obj_notify(const struct nft_ctx *ctx,
4512-
struct nft_object *obj, int event)
4491+
static void nf_tables_obj_notify(const struct nft_ctx *ctx,
4492+
struct nft_object *obj, int event)
45134493
{
4514-
return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid,
4515-
ctx->seq, event, ctx->afi->family, ctx->report,
4516-
GFP_KERNEL);
4494+
nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
4495+
ctx->afi->family, ctx->report, GFP_KERNEL);
45174496
}
45184497

45194498
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
@@ -4543,17 +4522,17 @@ static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
45434522
return -EMSGSIZE;
45444523
}
45454524

4546-
static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
4525+
static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
4526+
int event)
45474527
{
45484528
struct nlmsghdr *nlh = nlmsg_hdr(skb);
45494529
struct sk_buff *skb2;
45504530
int err;
45514531

45524532
if (nlmsg_report(nlh) &&
45534533
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
4554-
return 0;
4534+
return;
45554535

4556-
err = -ENOBUFS;
45574536
skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
45584537
if (skb2 == NULL)
45594538
goto err;
@@ -4565,14 +4544,12 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
45654544
goto err;
45664545
}
45674546

4568-
err = nfnetlink_send(skb2, net, NETLINK_CB(skb).portid,
4569-
NFNLGRP_NFTABLES, nlmsg_report(nlh), GFP_KERNEL);
4547+
nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
4548+
nlmsg_report(nlh), GFP_KERNEL);
4549+
return;
45704550
err:
4571-
if (err < 0) {
4572-
nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
4573-
err);
4574-
}
4575-
return err;
4551+
nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
4552+
-ENOBUFS);
45764553
}
45774554

45784555
static int nf_tables_getgen(struct net *net, struct sock *nlsk,

0 commit comments

Comments
 (0)