aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-05-28 22:39:09 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-28 22:39:09 -0400
commit513acc5b746b8b86eb4f97efe2d874fd3087ff99 (patch)
tree5e815bd4660e5bfcd9bbc398e600f80629d8724d /net
parentbc2dbc5420e82560e650f8531ceca597441ca171 (diff)
parentbbb8c61f97e3a2dd91b30d3e57b7964a67569d11 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for your net tree: 1) Null pointer dereference when dumping conntrack helper configuration, from Taehee Yoo. 2) Missing sanitization in ebtables extension name through compat, from Paolo Abeni. 3) Broken fetch of tracing value, from Taehee Yoo. 4) Incorrect arithmetics in packet ratelimiting. 5) Buffer overflow in IPVS sync daemon, from Julian Anastasov. 6) Wrong argument to nla_strlcpy() in nfnetlink_{acct,cthelper}, from Eric Dumazet. 7) Fix splat in nft_update_chain_stats(). 8) Null pointer dereference from object netlink dump path, from Taehee Yoo. 9) Missing static_branch_inc() when enabling counters in existing chain, from Taehee Yoo. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebtables.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c21
-rw-r--r--net/netfilter/nf_tables_api.c8
-rw-r--r--net/netfilter/nf_tables_core.c4
-rw-r--r--net/netfilter/nfnetlink_acct.c2
-rw-r--r--net/netfilter/nfnetlink_cthelper.c4
-rw-r--r--net/netfilter/nft_ct.c20
-rw-r--r--net/netfilter/nft_limit.c38
-rw-r--r--net/netfilter/nft_meta.c14
9 files changed, 71 insertions, 43 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 28a4c3490359..6ba639f6c51d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1954,7 +1954,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
1954 int off, pad = 0; 1954 int off, pad = 0;
1955 unsigned int size_kern, match_size = mwt->match_size; 1955 unsigned int size_kern, match_size = mwt->match_size;
1956 1956
1957 strlcpy(name, mwt->u.name, sizeof(name)); 1957 if (strscpy(name, mwt->u.name, sizeof(name)) < 0)
1958 return -EINVAL;
1958 1959
1959 if (state->buf_kern_start) 1960 if (state->buf_kern_start)
1960 dst = state->buf_kern_start + state->buf_kern_offset; 1961 dst = state->buf_kern_start + state->buf_kern_offset;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index f36098887ad0..3ecca0616d8c 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2381,8 +2381,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2381 struct ipvs_sync_daemon_cfg cfg; 2381 struct ipvs_sync_daemon_cfg cfg;
2382 2382
2383 memset(&cfg, 0, sizeof(cfg)); 2383 memset(&cfg, 0, sizeof(cfg));
2384 strlcpy(cfg.mcast_ifn, dm->mcast_ifn, 2384 ret = -EINVAL;
2385 sizeof(cfg.mcast_ifn)); 2385 if (strscpy(cfg.mcast_ifn, dm->mcast_ifn,
2386 sizeof(cfg.mcast_ifn)) <= 0)
2387 goto out_dec;
2386 cfg.syncid = dm->syncid; 2388 cfg.syncid = dm->syncid;
2387 ret = start_sync_thread(ipvs, &cfg, dm->state); 2389 ret = start_sync_thread(ipvs, &cfg, dm->state);
2388 } else { 2390 } else {
@@ -2420,12 +2422,19 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2420 } 2422 }
2421 } 2423 }
2422 2424
2425 if ((cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_EDIT) &&
2426 strnlen(usvc.sched_name, IP_VS_SCHEDNAME_MAXLEN) ==
2427 IP_VS_SCHEDNAME_MAXLEN) {
2428 ret = -EINVAL;
2429 goto out_unlock;
2430 }
2431
2423 /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ 2432 /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */
2424 if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && 2433 if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP &&
2425 usvc.protocol != IPPROTO_SCTP) { 2434 usvc.protocol != IPPROTO_SCTP) {
2426 pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", 2435 pr_err("set_ctl: invalid protocol: %d %pI4:%d\n",
2427 usvc.protocol, &usvc.addr.ip, 2436 usvc.protocol, &usvc.addr.ip,
2428 ntohs(usvc.port), usvc.sched_name); 2437 ntohs(usvc.port));
2429 ret = -EFAULT; 2438 ret = -EFAULT;
2430 goto out_unlock; 2439 goto out_unlock;
2431 } 2440 }
@@ -2847,7 +2856,7 @@ static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = {
2847static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { 2856static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = {
2848 [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 }, 2857 [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 },
2849 [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING, 2858 [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING,
2850 .len = IP_VS_IFNAME_MAXLEN }, 2859 .len = IP_VS_IFNAME_MAXLEN - 1 },
2851 [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 }, 2860 [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 },
2852 [IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 }, 2861 [IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 },
2853 [IPVS_DAEMON_ATTR_MCAST_GROUP] = { .type = NLA_U32 }, 2862 [IPVS_DAEMON_ATTR_MCAST_GROUP] = { .type = NLA_U32 },
@@ -2865,7 +2874,7 @@ static const struct nla_policy ip_vs_svc_policy[IPVS_SVC_ATTR_MAX + 1] = {
2865 [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 }, 2874 [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 },
2866 [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 }, 2875 [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 },
2867 [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING, 2876 [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING,
2868 .len = IP_VS_SCHEDNAME_MAXLEN }, 2877 .len = IP_VS_SCHEDNAME_MAXLEN - 1 },
2869 [IPVS_SVC_ATTR_PE_NAME] = { .type = NLA_NUL_STRING, 2878 [IPVS_SVC_ATTR_PE_NAME] = { .type = NLA_NUL_STRING,
2870 .len = IP_VS_PENAME_MAXLEN }, 2879 .len = IP_VS_PENAME_MAXLEN },
2871 [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY, 2880 [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY,
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 91e80aa852d6..501e48a7965b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1298,8 +1298,10 @@ static void nft_chain_stats_replace(struct nft_base_chain *chain,
1298 rcu_assign_pointer(chain->stats, newstats); 1298 rcu_assign_pointer(chain->stats, newstats);
1299 synchronize_rcu(); 1299 synchronize_rcu();
1300 free_percpu(oldstats); 1300 free_percpu(oldstats);
1301 } else 1301 } else {
1302 rcu_assign_pointer(chain->stats, newstats); 1302 rcu_assign_pointer(chain->stats, newstats);
1303 static_branch_inc(&nft_counters_enabled);
1304 }
1303} 1305}
1304 1306
1305static void nf_tables_chain_destroy(struct nft_ctx *ctx) 1307static void nf_tables_chain_destroy(struct nft_ctx *ctx)
@@ -4706,7 +4708,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
4706 if (idx > s_idx) 4708 if (idx > s_idx)
4707 memset(&cb->args[1], 0, 4709 memset(&cb->args[1], 0,
4708 sizeof(cb->args) - sizeof(cb->args[0])); 4710 sizeof(cb->args) - sizeof(cb->args[0]));
4709 if (filter && filter->table[0] && 4711 if (filter && filter->table &&
4710 strcmp(filter->table, table->name)) 4712 strcmp(filter->table, table->name))
4711 goto cont; 4713 goto cont;
4712 if (filter && 4714 if (filter &&
@@ -5380,7 +5382,7 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb,
5380 if (idx > s_idx) 5382 if (idx > s_idx)
5381 memset(&cb->args[1], 0, 5383 memset(&cb->args[1], 0,
5382 sizeof(cb->args) - sizeof(cb->args[0])); 5384 sizeof(cb->args) - sizeof(cb->args[0]));
5383 if (filter && filter->table[0] && 5385 if (filter && filter->table &&
5384 strcmp(filter->table, table->name)) 5386 strcmp(filter->table, table->name))
5385 goto cont; 5387 goto cont;
5386 5388
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 942702a2776f..40e744572283 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -126,15 +126,15 @@ static noinline void nft_update_chain_stats(const struct nft_chain *chain,
126 if (!base_chain->stats) 126 if (!base_chain->stats)
127 return; 127 return;
128 128
129 local_bh_disable();
129 stats = this_cpu_ptr(rcu_dereference(base_chain->stats)); 130 stats = this_cpu_ptr(rcu_dereference(base_chain->stats));
130 if (stats) { 131 if (stats) {
131 local_bh_disable();
132 u64_stats_update_begin(&stats->syncp); 132 u64_stats_update_begin(&stats->syncp);
133 stats->pkts++; 133 stats->pkts++;
134 stats->bytes += pkt->skb->len; 134 stats->bytes += pkt->skb->len;
135 u64_stats_update_end(&stats->syncp); 135 u64_stats_update_end(&stats->syncp);
136 local_bh_enable();
137 } 136 }
137 local_bh_enable();
138} 138}
139 139
140struct nft_jumpstack { 140struct nft_jumpstack {
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 6ddf89183e7b..a0e5adf0b3b6 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -115,7 +115,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
115 nfacct->flags = flags; 115 nfacct->flags = flags;
116 } 116 }
117 117
118 nla_strlcpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX); 118 nla_strlcpy(nfacct->name, tb[NFACCT_NAME], NFACCT_NAME_MAX);
119 119
120 if (tb[NFACCT_BYTES]) { 120 if (tb[NFACCT_BYTES]) {
121 atomic64_set(&nfacct->bytes, 121 atomic64_set(&nfacct->bytes,
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index fa026b269b36..cb5b5f207777 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -150,7 +150,7 @@ nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy,
150 return -EINVAL; 150 return -EINVAL;
151 151
152 nla_strlcpy(expect_policy->name, 152 nla_strlcpy(expect_policy->name,
153 nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN); 153 tb[NFCTH_POLICY_NAME], NF_CT_HELPER_NAME_LEN);
154 expect_policy->max_expected = 154 expect_policy->max_expected =
155 ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX])); 155 ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
156 if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT) 156 if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
@@ -235,7 +235,7 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
235 goto err1; 235 goto err1;
236 236
237 nla_strlcpy(helper->name, 237 nla_strlcpy(helper->name,
238 nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN); 238 tb[NFCTH_NAME], NF_CT_HELPER_NAME_LEN);
239 size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); 239 size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
240 if (size > FIELD_SIZEOF(struct nf_conn_help, data)) { 240 if (size > FIELD_SIZEOF(struct nf_conn_help, data)) {
241 ret = -ENOMEM; 241 ret = -ENOMEM;
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index ea737fd789e8..5c0de704bad5 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -880,22 +880,26 @@ static int nft_ct_helper_obj_dump(struct sk_buff *skb,
880 struct nft_object *obj, bool reset) 880 struct nft_object *obj, bool reset)
881{ 881{
882 const struct nft_ct_helper_obj *priv = nft_obj_data(obj); 882 const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
883 const struct nf_conntrack_helper *helper = priv->helper4; 883 const struct nf_conntrack_helper *helper;
884 u16 family; 884 u16 family;
885 885
886 if (priv->helper4 && priv->helper6) {
887 family = NFPROTO_INET;
888 helper = priv->helper4;
889 } else if (priv->helper6) {
890 family = NFPROTO_IPV6;
891 helper = priv->helper6;
892 } else {
893 family = NFPROTO_IPV4;
894 helper = priv->helper4;
895 }
896
886 if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name)) 897 if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name))
887 return -1; 898 return -1;
888 899
889 if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto)) 900 if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto))
890 return -1; 901 return -1;
891 902
892 if (priv->helper4 && priv->helper6)
893 family = NFPROTO_INET;
894 else if (priv->helper6)
895 family = NFPROTO_IPV6;
896 else
897 family = NFPROTO_IPV4;
898
899 if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family))) 903 if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family)))
900 return -1; 904 return -1;
901 905
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c
index a9fc298ef4c3..72f13a1144dd 100644
--- a/net/netfilter/nft_limit.c
+++ b/net/netfilter/nft_limit.c
@@ -51,10 +51,13 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
51 return !limit->invert; 51 return !limit->invert;
52} 52}
53 53
54/* Use same default as in iptables. */
55#define NFT_LIMIT_PKT_BURST_DEFAULT 5
56
54static int nft_limit_init(struct nft_limit *limit, 57static int nft_limit_init(struct nft_limit *limit,
55 const struct nlattr * const tb[]) 58 const struct nlattr * const tb[], bool pkts)
56{ 59{
57 u64 unit; 60 u64 unit, tokens;
58 61
59 if (tb[NFTA_LIMIT_RATE] == NULL || 62 if (tb[NFTA_LIMIT_RATE] == NULL ||
60 tb[NFTA_LIMIT_UNIT] == NULL) 63 tb[NFTA_LIMIT_UNIT] == NULL)
@@ -68,18 +71,25 @@ static int nft_limit_init(struct nft_limit *limit,
68 71
69 if (tb[NFTA_LIMIT_BURST]) 72 if (tb[NFTA_LIMIT_BURST])
70 limit->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST])); 73 limit->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));
71 else 74
72 limit->burst = 0; 75 if (pkts && limit->burst == 0)
76 limit->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
73 77
74 if (limit->rate + limit->burst < limit->rate) 78 if (limit->rate + limit->burst < limit->rate)
75 return -EOVERFLOW; 79 return -EOVERFLOW;
76 80
77 /* The token bucket size limits the number of tokens can be 81 if (pkts) {
78 * accumulated. tokens_max specifies the bucket size. 82 tokens = div_u64(limit->nsecs, limit->rate) * limit->burst;
79 * tokens_max = unit * (rate + burst) / rate. 83 } else {
80 */ 84 /* The token bucket size limits the number of tokens can be
81 limit->tokens = div_u64(limit->nsecs * (limit->rate + limit->burst), 85 * accumulated. tokens_max specifies the bucket size.
82 limit->rate); 86 * tokens_max = unit * (rate + burst) / rate.
87 */
88 tokens = div_u64(limit->nsecs * (limit->rate + limit->burst),
89 limit->rate);
90 }
91
92 limit->tokens = tokens;
83 limit->tokens_max = limit->tokens; 93 limit->tokens_max = limit->tokens;
84 94
85 if (tb[NFTA_LIMIT_FLAGS]) { 95 if (tb[NFTA_LIMIT_FLAGS]) {
@@ -144,7 +154,7 @@ static int nft_limit_pkts_init(const struct nft_ctx *ctx,
144 struct nft_limit_pkts *priv = nft_expr_priv(expr); 154 struct nft_limit_pkts *priv = nft_expr_priv(expr);
145 int err; 155 int err;
146 156
147 err = nft_limit_init(&priv->limit, tb); 157 err = nft_limit_init(&priv->limit, tb, true);
148 if (err < 0) 158 if (err < 0)
149 return err; 159 return err;
150 160
@@ -185,7 +195,7 @@ static int nft_limit_bytes_init(const struct nft_ctx *ctx,
185{ 195{
186 struct nft_limit *priv = nft_expr_priv(expr); 196 struct nft_limit *priv = nft_expr_priv(expr);
187 197
188 return nft_limit_init(priv, tb); 198 return nft_limit_init(priv, tb, false);
189} 199}
190 200
191static int nft_limit_bytes_dump(struct sk_buff *skb, 201static int nft_limit_bytes_dump(struct sk_buff *skb,
@@ -246,7 +256,7 @@ static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,
246 struct nft_limit_pkts *priv = nft_obj_data(obj); 256 struct nft_limit_pkts *priv = nft_obj_data(obj);
247 int err; 257 int err;
248 258
249 err = nft_limit_init(&priv->limit, tb); 259 err = nft_limit_init(&priv->limit, tb, true);
250 if (err < 0) 260 if (err < 0)
251 return err; 261 return err;
252 262
@@ -289,7 +299,7 @@ static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,
289{ 299{
290 struct nft_limit *priv = nft_obj_data(obj); 300 struct nft_limit *priv = nft_obj_data(obj);
291 301
292 return nft_limit_init(priv, tb); 302 return nft_limit_init(priv, tb, false);
293} 303}
294 304
295static int nft_limit_obj_bytes_dump(struct sk_buff *skb, 305static int nft_limit_obj_bytes_dump(struct sk_buff *skb,
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 8fb91940e2e7..204af9899482 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -234,7 +234,7 @@ void nft_meta_set_eval(const struct nft_expr *expr,
234 struct sk_buff *skb = pkt->skb; 234 struct sk_buff *skb = pkt->skb;
235 u32 *sreg = &regs->data[meta->sreg]; 235 u32 *sreg = &regs->data[meta->sreg];
236 u32 value = *sreg; 236 u32 value = *sreg;
237 u8 pkt_type; 237 u8 value8;
238 238
239 switch (meta->key) { 239 switch (meta->key) {
240 case NFT_META_MARK: 240 case NFT_META_MARK:
@@ -244,15 +244,17 @@ void nft_meta_set_eval(const struct nft_expr *expr,
244 skb->priority = value; 244 skb->priority = value;
245 break; 245 break;
246 case NFT_META_PKTTYPE: 246 case NFT_META_PKTTYPE:
247 pkt_type = nft_reg_load8(sreg); 247 value8 = nft_reg_load8(sreg);
248 248
249 if (skb->pkt_type != pkt_type && 249 if (skb->pkt_type != value8 &&
250 skb_pkt_type_ok(pkt_type) && 250 skb_pkt_type_ok(value8) &&
251 skb_pkt_type_ok(skb->pkt_type)) 251 skb_pkt_type_ok(skb->pkt_type))
252 skb->pkt_type = pkt_type; 252 skb->pkt_type = value8;
253 break; 253 break;
254 case NFT_META_NFTRACE: 254 case NFT_META_NFTRACE:
255 skb->nf_trace = !!value; 255 value8 = nft_reg_load8(sreg);
256
257 skb->nf_trace = !!value8;
256 break; 258 break;
257 default: 259 default:
258 WARN_ON(1); 260 WARN_ON(1);