Contents of /trunk/kernel-alx/patches-4.1/0109-4.1.10-all-fixes.patch
Parent Directory | Revision Log
Revision 2748 -
(show annotations)
(download)
Mon Jan 11 12:00:45 2016 UTC (8 years, 8 months ago) by niro
File size: 40107 byte(s)
Mon Jan 11 12:00:45 2016 UTC (8 years, 8 months ago) by niro
File size: 40107 byte(s)
-linux-4.1 patches up to 4.1.15
1 | diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt |
2 | index 41b3f3f864e8..5d88f37480b6 100644 |
3 | --- a/Documentation/devicetree/bindings/net/ethernet.txt |
4 | +++ b/Documentation/devicetree/bindings/net/ethernet.txt |
5 | @@ -25,7 +25,11 @@ The following properties are common to the Ethernet controllers: |
6 | flow control thresholds. |
7 | - tx-fifo-depth: the size of the controller's transmit fifo in bytes. This |
8 | is used for components that can have configurable fifo sizes. |
9 | +- managed: string, specifies the PHY management type. Supported values are: |
10 | + "auto", "in-band-status". "auto" is the default, it usess MDIO for |
11 | + management if fixed-link is not specified. |
12 | |
13 | Child nodes of the Ethernet controller are typically the individual PHY devices |
14 | connected via the MDIO bus (sometimes the MDIO bus controller is separate). |
15 | They are described in the phy.txt file in this same directory. |
16 | +For non-MDIO PHY management see fixed-link.txt. |
17 | diff --git a/Makefile b/Makefile |
18 | index e071176b2ce6..d02f16b510dc 100644 |
19 | --- a/Makefile |
20 | +++ b/Makefile |
21 | @@ -1,6 +1,6 @@ |
22 | VERSION = 4 |
23 | PATCHLEVEL = 1 |
24 | -SUBLEVEL = 9 |
25 | +SUBLEVEL = 10 |
26 | EXTRAVERSION = |
27 | NAME = Series 4800 |
28 | |
29 | diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c |
30 | index f1ff39a3d1c1..54d946a9eee6 100644 |
31 | --- a/drivers/block/zram/zcomp.c |
32 | +++ b/drivers/block/zram/zcomp.c |
33 | @@ -325,12 +325,14 @@ void zcomp_destroy(struct zcomp *comp) |
34 | * allocate new zcomp and initialize it. return compressing |
35 | * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL) |
36 | * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in |
37 | - * case of allocation error. |
38 | + * case of allocation error, or any other error potentially |
39 | + * returned by functions zcomp_strm_{multi,single}_create. |
40 | */ |
41 | struct zcomp *zcomp_create(const char *compress, int max_strm) |
42 | { |
43 | struct zcomp *comp; |
44 | struct zcomp_backend *backend; |
45 | + int error; |
46 | |
47 | backend = find_backend(compress); |
48 | if (!backend) |
49 | @@ -342,12 +344,12 @@ struct zcomp *zcomp_create(const char *compress, int max_strm) |
50 | |
51 | comp->backend = backend; |
52 | if (max_strm > 1) |
53 | - zcomp_strm_multi_create(comp, max_strm); |
54 | + error = zcomp_strm_multi_create(comp, max_strm); |
55 | else |
56 | - zcomp_strm_single_create(comp); |
57 | - if (!comp->stream) { |
58 | + error = zcomp_strm_single_create(comp); |
59 | + if (error) { |
60 | kfree(comp); |
61 | - return ERR_PTR(-ENOMEM); |
62 | + return ERR_PTR(error); |
63 | } |
64 | return comp; |
65 | } |
66 | diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c |
67 | index cedb572bf25a..db9ebbc1a732 100644 |
68 | --- a/drivers/net/dsa/bcm_sf2.c |
69 | +++ b/drivers/net/dsa/bcm_sf2.c |
70 | @@ -417,7 +417,7 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) |
71 | core_writel(priv, port, CORE_FAST_AGE_PORT); |
72 | |
73 | reg = core_readl(priv, CORE_FAST_AGE_CTRL); |
74 | - reg |= EN_AGE_PORT | FAST_AGE_STR_DONE; |
75 | + reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE; |
76 | core_writel(priv, reg, CORE_FAST_AGE_CTRL); |
77 | |
78 | do { |
79 | @@ -431,6 +431,8 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) |
80 | if (!timeout) |
81 | return -ETIMEDOUT; |
82 | |
83 | + core_writel(priv, 0, CORE_FAST_AGE_CTRL); |
84 | + |
85 | return 0; |
86 | } |
87 | |
88 | @@ -506,7 +508,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, |
89 | u32 reg; |
90 | |
91 | reg = core_readl(priv, CORE_G_PCTL_PORT(port)); |
92 | - cur_hw_state = reg >> G_MISTP_STATE_SHIFT; |
93 | + cur_hw_state = reg & (G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT); |
94 | |
95 | switch (state) { |
96 | case BR_STATE_DISABLED: |
97 | @@ -530,10 +532,12 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, |
98 | } |
99 | |
100 | /* Fast-age ARL entries if we are moving a port from Learning or |
101 | - * Forwarding state to Disabled, Blocking or Listening state |
102 | + * Forwarding (cur_hw_state) state to Disabled, Blocking or Listening |
103 | + * state (hw_state) |
104 | */ |
105 | if (cur_hw_state != hw_state) { |
106 | - if (cur_hw_state & 4 && !(hw_state & 4)) { |
107 | + if (cur_hw_state >= G_MISTP_LEARN_STATE && |
108 | + hw_state <= G_MISTP_LISTEN_STATE) { |
109 | ret = bcm_sf2_sw_fast_age_port(ds, port); |
110 | if (ret) { |
111 | pr_err("%s: fast-ageing failed\n", __func__); |
112 | @@ -889,15 +893,11 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, |
113 | struct fixed_phy_status *status) |
114 | { |
115 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |
116 | - u32 duplex, pause, speed; |
117 | + u32 duplex, pause; |
118 | u32 reg; |
119 | |
120 | duplex = core_readl(priv, CORE_DUPSTS); |
121 | pause = core_readl(priv, CORE_PAUSESTS); |
122 | - speed = core_readl(priv, CORE_SPDSTS); |
123 | - |
124 | - speed >>= (port * SPDSTS_SHIFT); |
125 | - speed &= SPDSTS_MASK; |
126 | |
127 | status->link = 0; |
128 | |
129 | @@ -925,18 +925,6 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, |
130 | reg &= ~LINK_STS; |
131 | core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); |
132 | |
133 | - switch (speed) { |
134 | - case SPDSTS_10: |
135 | - status->speed = SPEED_10; |
136 | - break; |
137 | - case SPDSTS_100: |
138 | - status->speed = SPEED_100; |
139 | - break; |
140 | - case SPDSTS_1000: |
141 | - status->speed = SPEED_1000; |
142 | - break; |
143 | - } |
144 | - |
145 | if ((pause & (1 << port)) && |
146 | (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) { |
147 | status->asym_pause = 1; |
148 | diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h |
149 | index 22e2ebf31333..789d7b7737da 100644 |
150 | --- a/drivers/net/dsa/bcm_sf2.h |
151 | +++ b/drivers/net/dsa/bcm_sf2.h |
152 | @@ -112,8 +112,8 @@ static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off) \ |
153 | spin_unlock(&priv->indir_lock); \ |
154 | return (u64)indir << 32 | dir; \ |
155 | } \ |
156 | -static inline void name##_writeq(struct bcm_sf2_priv *priv, u32 off, \ |
157 | - u64 val) \ |
158 | +static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \ |
159 | + u32 off) \ |
160 | { \ |
161 | spin_lock(&priv->indir_lock); \ |
162 | reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE); \ |
163 | diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c |
164 | index da48e66377b5..8207877d6237 100644 |
165 | --- a/drivers/net/ethernet/altera/altera_tse_main.c |
166 | +++ b/drivers/net/ethernet/altera/altera_tse_main.c |
167 | @@ -511,8 +511,7 @@ static int tse_poll(struct napi_struct *napi, int budget) |
168 | |
169 | if (rxcomplete < budget) { |
170 | |
171 | - napi_gro_flush(napi, false); |
172 | - __napi_complete(napi); |
173 | + napi_complete(napi); |
174 | |
175 | netdev_dbg(priv->dev, |
176 | "NAPI Complete, did %d packets with budget %d\n", |
177 | diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c |
178 | index 66d47e448e4d..570390b5cd42 100644 |
179 | --- a/drivers/net/ethernet/freescale/fec_main.c |
180 | +++ b/drivers/net/ethernet/freescale/fec_main.c |
181 | @@ -1396,6 +1396,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) |
182 | if ((status & BD_ENET_RX_LAST) == 0) |
183 | netdev_err(ndev, "rcv is not +last\n"); |
184 | |
185 | + writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); |
186 | |
187 | /* Check for errors. */ |
188 | if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | |
189 | diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c |
190 | index 74d0389bf233..4d608f0117cd 100644 |
191 | --- a/drivers/net/ethernet/marvell/mvneta.c |
192 | +++ b/drivers/net/ethernet/marvell/mvneta.c |
193 | @@ -3029,8 +3029,8 @@ static int mvneta_probe(struct platform_device *pdev) |
194 | const char *dt_mac_addr; |
195 | char hw_mac_addr[ETH_ALEN]; |
196 | const char *mac_from; |
197 | + const char *managed; |
198 | int phy_mode; |
199 | - int fixed_phy = 0; |
200 | int err; |
201 | |
202 | /* Our multiqueue support is not complete, so for now, only |
203 | @@ -3064,7 +3064,6 @@ static int mvneta_probe(struct platform_device *pdev) |
204 | dev_err(&pdev->dev, "cannot register fixed PHY\n"); |
205 | goto err_free_irq; |
206 | } |
207 | - fixed_phy = 1; |
208 | |
209 | /* In the case of a fixed PHY, the DT node associated |
210 | * to the PHY is the Ethernet MAC DT node. |
211 | @@ -3088,8 +3087,10 @@ static int mvneta_probe(struct platform_device *pdev) |
212 | pp = netdev_priv(dev); |
213 | pp->phy_node = phy_node; |
214 | pp->phy_interface = phy_mode; |
215 | - pp->use_inband_status = (phy_mode == PHY_INTERFACE_MODE_SGMII) && |
216 | - fixed_phy; |
217 | + |
218 | + err = of_property_read_string(dn, "managed", &managed); |
219 | + pp->use_inband_status = (err == 0 && |
220 | + strcmp(managed, "in-band-status") == 0); |
221 | |
222 | pp->clk = devm_clk_get(&pdev->dev, NULL); |
223 | if (IS_ERR(pp->clk)) { |
224 | diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
225 | index eab4e080ebd2..80aac20104de 100644 |
226 | --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
227 | +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
228 | @@ -1256,8 +1256,6 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) |
229 | rss_context->hash_fn = MLX4_RSS_HASH_TOP; |
230 | memcpy(rss_context->rss_key, priv->rss_key, |
231 | MLX4_EN_RSS_KEY_SIZE); |
232 | - netdev_rss_key_fill(rss_context->rss_key, |
233 | - MLX4_EN_RSS_KEY_SIZE); |
234 | } else { |
235 | en_err(priv, "Unknown RSS hash function requested\n"); |
236 | err = -EINVAL; |
237 | diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c |
238 | index 8c350c5d54ad..58858c5589db 100644 |
239 | --- a/drivers/net/macvtap.c |
240 | +++ b/drivers/net/macvtap.c |
241 | @@ -1054,10 +1054,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, |
242 | return 0; |
243 | |
244 | case TUNSETSNDBUF: |
245 | - if (get_user(u, up)) |
246 | + if (get_user(s, sp)) |
247 | return -EFAULT; |
248 | |
249 | - q->sk.sk_sndbuf = u; |
250 | + q->sk.sk_sndbuf = s; |
251 | return 0; |
252 | |
253 | case TUNGETVNETHDRSZ: |
254 | diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c |
255 | index 1960b46add65..479b93f9581c 100644 |
256 | --- a/drivers/net/phy/fixed_phy.c |
257 | +++ b/drivers/net/phy/fixed_phy.c |
258 | @@ -52,6 +52,10 @@ static int fixed_phy_update_regs(struct fixed_phy *fp) |
259 | u16 lpagb = 0; |
260 | u16 lpa = 0; |
261 | |
262 | + if (!fp->status.link) |
263 | + goto done; |
264 | + bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; |
265 | + |
266 | if (fp->status.duplex) { |
267 | bmcr |= BMCR_FULLDPLX; |
268 | |
269 | @@ -96,15 +100,13 @@ static int fixed_phy_update_regs(struct fixed_phy *fp) |
270 | } |
271 | } |
272 | |
273 | - if (fp->status.link) |
274 | - bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; |
275 | - |
276 | if (fp->status.pause) |
277 | lpa |= LPA_PAUSE_CAP; |
278 | |
279 | if (fp->status.asym_pause) |
280 | lpa |= LPA_PAUSE_ASYM; |
281 | |
282 | +done: |
283 | fp->regs[MII_PHYSID1] = 0; |
284 | fp->regs[MII_PHYSID2] = 0; |
285 | |
286 | diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c |
287 | index 3c86b107275a..e0498571ae26 100644 |
288 | --- a/drivers/net/usb/usbnet.c |
289 | +++ b/drivers/net/usb/usbnet.c |
290 | @@ -778,7 +778,7 @@ int usbnet_stop (struct net_device *net) |
291 | { |
292 | struct usbnet *dev = netdev_priv(net); |
293 | struct driver_info *info = dev->driver_info; |
294 | - int retval, pm; |
295 | + int retval, pm, mpn; |
296 | |
297 | clear_bit(EVENT_DEV_OPEN, &dev->flags); |
298 | netif_stop_queue (net); |
299 | @@ -809,6 +809,8 @@ int usbnet_stop (struct net_device *net) |
300 | |
301 | usbnet_purge_paused_rxq(dev); |
302 | |
303 | + mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags); |
304 | + |
305 | /* deferred work (task, timer, softirq) must also stop. |
306 | * can't flush_scheduled_work() until we drop rtnl (later), |
307 | * else workers could deadlock; so make workers a NOP. |
308 | @@ -819,8 +821,7 @@ int usbnet_stop (struct net_device *net) |
309 | if (!pm) |
310 | usb_autopm_put_interface(dev->intf); |
311 | |
312 | - if (info->manage_power && |
313 | - !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags)) |
314 | + if (info->manage_power && mpn) |
315 | info->manage_power(dev, 0); |
316 | else |
317 | usb_autopm_put_interface(dev->intf); |
318 | diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c |
319 | index 21a0fbf1ed94..0085b8df83e2 100644 |
320 | --- a/drivers/net/vxlan.c |
321 | +++ b/drivers/net/vxlan.c |
322 | @@ -2212,6 +2212,8 @@ static int vxlan_open(struct net_device *dev) |
323 | |
324 | if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { |
325 | ret = vxlan_igmp_join(vxlan); |
326 | + if (ret == -EADDRINUSE) |
327 | + ret = 0; |
328 | if (ret) { |
329 | vxlan_sock_release(vs); |
330 | return ret; |
331 | diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c |
332 | index 0c064485d1c2..bec8ec2b31f6 100644 |
333 | --- a/drivers/of/of_mdio.c |
334 | +++ b/drivers/of/of_mdio.c |
335 | @@ -263,7 +263,8 @@ EXPORT_SYMBOL(of_phy_attach); |
336 | bool of_phy_is_fixed_link(struct device_node *np) |
337 | { |
338 | struct device_node *dn; |
339 | - int len; |
340 | + int len, err; |
341 | + const char *managed; |
342 | |
343 | /* New binding */ |
344 | dn = of_get_child_by_name(np, "fixed-link"); |
345 | @@ -272,6 +273,10 @@ bool of_phy_is_fixed_link(struct device_node *np) |
346 | return true; |
347 | } |
348 | |
349 | + err = of_property_read_string(np, "managed", &managed); |
350 | + if (err == 0 && strcmp(managed, "auto") != 0) |
351 | + return true; |
352 | + |
353 | /* Old binding */ |
354 | if (of_get_property(np, "fixed-link", &len) && |
355 | len == (5 * sizeof(__be32))) |
356 | @@ -286,8 +291,18 @@ int of_phy_register_fixed_link(struct device_node *np) |
357 | struct fixed_phy_status status = {}; |
358 | struct device_node *fixed_link_node; |
359 | const __be32 *fixed_link_prop; |
360 | - int len; |
361 | + int len, err; |
362 | struct phy_device *phy; |
363 | + const char *managed; |
364 | + |
365 | + err = of_property_read_string(np, "managed", &managed); |
366 | + if (err == 0) { |
367 | + if (strcmp(managed, "in-band-status") == 0) { |
368 | + /* status is zeroed, namely its .link member */ |
369 | + phy = fixed_phy_register(PHY_POLL, &status, np); |
370 | + return IS_ERR(phy) ? PTR_ERR(phy) : 0; |
371 | + } |
372 | + } |
373 | |
374 | /* New binding */ |
375 | fixed_link_node = of_get_child_by_name(np, "fixed-link"); |
376 | diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c |
377 | index 06697315a088..fb4dd7b3ee71 100644 |
378 | --- a/drivers/platform/x86/hp-wmi.c |
379 | +++ b/drivers/platform/x86/hp-wmi.c |
380 | @@ -54,8 +54,9 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); |
381 | #define HPWMI_HARDWARE_QUERY 0x4 |
382 | #define HPWMI_WIRELESS_QUERY 0x5 |
383 | #define HPWMI_BIOS_QUERY 0x9 |
384 | +#define HPWMI_FEATURE_QUERY 0xb |
385 | #define HPWMI_HOTKEY_QUERY 0xc |
386 | -#define HPWMI_FEATURE_QUERY 0xd |
387 | +#define HPWMI_FEATURE2_QUERY 0xd |
388 | #define HPWMI_WIRELESS2_QUERY 0x1b |
389 | #define HPWMI_POSTCODEERROR_QUERY 0x2a |
390 | |
391 | @@ -295,25 +296,33 @@ static int hp_wmi_tablet_state(void) |
392 | return (state & 0x4) ? 1 : 0; |
393 | } |
394 | |
395 | -static int __init hp_wmi_bios_2009_later(void) |
396 | +static int __init hp_wmi_bios_2008_later(void) |
397 | { |
398 | int state = 0; |
399 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, |
400 | sizeof(state), sizeof(state)); |
401 | - if (ret) |
402 | - return ret; |
403 | + if (!ret) |
404 | + return 1; |
405 | |
406 | - return (state & 0x10) ? 1 : 0; |
407 | + return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; |
408 | } |
409 | |
410 | -static int hp_wmi_enable_hotkeys(void) |
411 | +static int __init hp_wmi_bios_2009_later(void) |
412 | { |
413 | - int ret; |
414 | - int query = 0x6e; |
415 | + int state = 0; |
416 | + int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state, |
417 | + sizeof(state), sizeof(state)); |
418 | + if (!ret) |
419 | + return 1; |
420 | |
421 | - ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query), |
422 | - 0); |
423 | + return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; |
424 | +} |
425 | |
426 | +static int __init hp_wmi_enable_hotkeys(void) |
427 | +{ |
428 | + int value = 0x6e; |
429 | + int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value, |
430 | + sizeof(value), 0); |
431 | if (ret) |
432 | return -EINVAL; |
433 | return 0; |
434 | @@ -663,7 +672,7 @@ static int __init hp_wmi_input_setup(void) |
435 | hp_wmi_tablet_state()); |
436 | input_sync(hp_wmi_input_dev); |
437 | |
438 | - if (hp_wmi_bios_2009_later() == 4) |
439 | + if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) |
440 | hp_wmi_enable_hotkeys(); |
441 | |
442 | status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); |
443 | diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c |
444 | index ff667e18b2d6..9ba383f5b0c4 100644 |
445 | --- a/net/bridge/br_multicast.c |
446 | +++ b/net/bridge/br_multicast.c |
447 | @@ -980,7 +980,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, |
448 | |
449 | ih = igmpv3_report_hdr(skb); |
450 | num = ntohs(ih->ngrec); |
451 | - len = sizeof(*ih); |
452 | + len = skb_transport_offset(skb) + sizeof(*ih); |
453 | |
454 | for (i = 0; i < num; i++) { |
455 | len += sizeof(*grec); |
456 | @@ -1035,7 +1035,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, |
457 | |
458 | icmp6h = icmp6_hdr(skb); |
459 | num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); |
460 | - len = sizeof(*icmp6h); |
461 | + len = skb_transport_offset(skb) + sizeof(*icmp6h); |
462 | |
463 | for (i = 0; i < num; i++) { |
464 | __be16 *nsrcs, _nsrcs; |
465 | diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c |
466 | index 9a12668f7d62..0ad144fb0c79 100644 |
467 | --- a/net/core/fib_rules.c |
468 | +++ b/net/core/fib_rules.c |
469 | @@ -615,15 +615,17 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, |
470 | { |
471 | int idx = 0; |
472 | struct fib_rule *rule; |
473 | + int err = 0; |
474 | |
475 | rcu_read_lock(); |
476 | list_for_each_entry_rcu(rule, &ops->rules_list, list) { |
477 | if (idx < cb->args[1]) |
478 | goto skip; |
479 | |
480 | - if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
481 | - cb->nlh->nlmsg_seq, RTM_NEWRULE, |
482 | - NLM_F_MULTI, ops) < 0) |
483 | + err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
484 | + cb->nlh->nlmsg_seq, RTM_NEWRULE, |
485 | + NLM_F_MULTI, ops); |
486 | + if (err) |
487 | break; |
488 | skip: |
489 | idx++; |
490 | @@ -632,7 +634,7 @@ skip: |
491 | cb->args[1] = idx; |
492 | rules_ops_put(ops); |
493 | |
494 | - return skb->len; |
495 | + return err; |
496 | } |
497 | |
498 | static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
499 | @@ -648,7 +650,9 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
500 | if (ops == NULL) |
501 | return -EAFNOSUPPORT; |
502 | |
503 | - return dump_rules(skb, cb, ops); |
504 | + dump_rules(skb, cb, ops); |
505 | + |
506 | + return skb->len; |
507 | } |
508 | |
509 | rcu_read_lock(); |
510 | diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c |
511 | index 74dddf84adcd..556ecf96a385 100644 |
512 | --- a/net/core/sock_diag.c |
513 | +++ b/net/core/sock_diag.c |
514 | @@ -86,6 +86,9 @@ int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk, |
515 | goto out; |
516 | |
517 | fprog = filter->prog->orig_prog; |
518 | + if (!fprog) |
519 | + goto out; |
520 | + |
521 | flen = bpf_classic_proglen(fprog); |
522 | |
523 | attr = nla_reserve(skb, attrtype, flen); |
524 | diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c |
525 | index a369e8a70b2c..986440b24978 100644 |
526 | --- a/net/ipv4/tcp_output.c |
527 | +++ b/net/ipv4/tcp_output.c |
528 | @@ -2893,6 +2893,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) |
529 | skb_reserve(skb, MAX_TCP_HEADER); |
530 | tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk), |
531 | TCPHDR_ACK | TCPHDR_RST); |
532 | + skb_mstamp_get(&skb->skb_mstamp); |
533 | /* Send it off. */ |
534 | if (tcp_transmit_skb(sk, skb, 0, priority)) |
535 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED); |
536 | diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c |
537 | index 447a7fbd1bb6..f5e2ba1c18bf 100644 |
538 | --- a/net/ipv6/exthdrs_offload.c |
539 | +++ b/net/ipv6/exthdrs_offload.c |
540 | @@ -36,6 +36,6 @@ out: |
541 | return ret; |
542 | |
543 | out_rt: |
544 | - inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); |
545 | + inet6_del_offload(&rthdr_offload, IPPROTO_ROUTING); |
546 | goto out; |
547 | } |
548 | diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c |
549 | index a38d3ac0f18f..69f4f689f06a 100644 |
550 | --- a/net/ipv6/ip6_gre.c |
551 | +++ b/net/ipv6/ip6_gre.c |
552 | @@ -361,6 +361,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) |
553 | struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); |
554 | |
555 | ip6gre_tunnel_unlink(ign, t); |
556 | + ip6_tnl_dst_reset(t); |
557 | dev_put(dev); |
558 | } |
559 | |
560 | diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c |
561 | index 74ceb73c1c9a..5f36266b1f5e 100644 |
562 | --- a/net/ipv6/ip6mr.c |
563 | +++ b/net/ipv6/ip6mr.c |
564 | @@ -550,7 +550,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
565 | |
566 | if (it->cache == &mrt->mfc6_unres_queue) |
567 | spin_unlock_bh(&mfc_unres_lock); |
568 | - else if (it->cache == mrt->mfc6_cache_array) |
569 | + else if (it->cache == &mrt->mfc6_cache_array[it->ct]) |
570 | read_unlock(&mrt_lock); |
571 | } |
572 | |
573 | diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
574 | index c73ae5039e46..f371fefa7fdc 100644 |
575 | --- a/net/ipv6/route.c |
576 | +++ b/net/ipv6/route.c |
577 | @@ -1515,7 +1515,7 @@ static int ip6_convert_metrics(struct mx6_config *mxc, |
578 | return -EINVAL; |
579 | } |
580 | |
581 | -int ip6_route_add(struct fib6_config *cfg) |
582 | +int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret) |
583 | { |
584 | int err; |
585 | struct net *net = cfg->fc_nlinfo.nl_net; |
586 | @@ -1523,7 +1523,6 @@ int ip6_route_add(struct fib6_config *cfg) |
587 | struct net_device *dev = NULL; |
588 | struct inet6_dev *idev = NULL; |
589 | struct fib6_table *table; |
590 | - struct mx6_config mxc = { .mx = NULL, }; |
591 | int addr_type; |
592 | |
593 | if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128) |
594 | @@ -1719,6 +1718,32 @@ install_route: |
595 | |
596 | cfg->fc_nlinfo.nl_net = dev_net(dev); |
597 | |
598 | + *rt_ret = rt; |
599 | + |
600 | + return 0; |
601 | +out: |
602 | + if (dev) |
603 | + dev_put(dev); |
604 | + if (idev) |
605 | + in6_dev_put(idev); |
606 | + if (rt) |
607 | + dst_free(&rt->dst); |
608 | + |
609 | + *rt_ret = NULL; |
610 | + |
611 | + return err; |
612 | +} |
613 | + |
614 | +int ip6_route_add(struct fib6_config *cfg) |
615 | +{ |
616 | + struct mx6_config mxc = { .mx = NULL, }; |
617 | + struct rt6_info *rt = NULL; |
618 | + int err; |
619 | + |
620 | + err = ip6_route_info_create(cfg, &rt); |
621 | + if (err) |
622 | + goto out; |
623 | + |
624 | err = ip6_convert_metrics(&mxc, cfg); |
625 | if (err) |
626 | goto out; |
627 | @@ -1726,14 +1751,12 @@ install_route: |
628 | err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc); |
629 | |
630 | kfree(mxc.mx); |
631 | + |
632 | return err; |
633 | out: |
634 | - if (dev) |
635 | - dev_put(dev); |
636 | - if (idev) |
637 | - in6_dev_put(idev); |
638 | if (rt) |
639 | dst_free(&rt->dst); |
640 | + |
641 | return err; |
642 | } |
643 | |
644 | @@ -2496,19 +2519,78 @@ errout: |
645 | return err; |
646 | } |
647 | |
648 | -static int ip6_route_multipath(struct fib6_config *cfg, int add) |
649 | +struct rt6_nh { |
650 | + struct rt6_info *rt6_info; |
651 | + struct fib6_config r_cfg; |
652 | + struct mx6_config mxc; |
653 | + struct list_head next; |
654 | +}; |
655 | + |
656 | +static void ip6_print_replace_route_err(struct list_head *rt6_nh_list) |
657 | +{ |
658 | + struct rt6_nh *nh; |
659 | + |
660 | + list_for_each_entry(nh, rt6_nh_list, next) { |
661 | + pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6 nexthop %pI6 ifi %d\n", |
662 | + &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway, |
663 | + nh->r_cfg.fc_ifindex); |
664 | + } |
665 | +} |
666 | + |
667 | +static int ip6_route_info_append(struct list_head *rt6_nh_list, |
668 | + struct rt6_info *rt, struct fib6_config *r_cfg) |
669 | +{ |
670 | + struct rt6_nh *nh; |
671 | + struct rt6_info *rtnh; |
672 | + int err = -EEXIST; |
673 | + |
674 | + list_for_each_entry(nh, rt6_nh_list, next) { |
675 | + /* check if rt6_info already exists */ |
676 | + rtnh = nh->rt6_info; |
677 | + |
678 | + if (rtnh->dst.dev == rt->dst.dev && |
679 | + rtnh->rt6i_idev == rt->rt6i_idev && |
680 | + ipv6_addr_equal(&rtnh->rt6i_gateway, |
681 | + &rt->rt6i_gateway)) |
682 | + return err; |
683 | + } |
684 | + |
685 | + nh = kzalloc(sizeof(*nh), GFP_KERNEL); |
686 | + if (!nh) |
687 | + return -ENOMEM; |
688 | + nh->rt6_info = rt; |
689 | + err = ip6_convert_metrics(&nh->mxc, r_cfg); |
690 | + if (err) { |
691 | + kfree(nh); |
692 | + return err; |
693 | + } |
694 | + memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg)); |
695 | + list_add_tail(&nh->next, rt6_nh_list); |
696 | + |
697 | + return 0; |
698 | +} |
699 | + |
700 | +static int ip6_route_multipath_add(struct fib6_config *cfg) |
701 | { |
702 | struct fib6_config r_cfg; |
703 | struct rtnexthop *rtnh; |
704 | + struct rt6_info *rt; |
705 | + struct rt6_nh *err_nh; |
706 | + struct rt6_nh *nh, *nh_safe; |
707 | int remaining; |
708 | int attrlen; |
709 | - int err = 0, last_err = 0; |
710 | + int err = 1; |
711 | + int nhn = 0; |
712 | + int replace = (cfg->fc_nlinfo.nlh && |
713 | + (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE)); |
714 | + LIST_HEAD(rt6_nh_list); |
715 | |
716 | remaining = cfg->fc_mp_len; |
717 | -beginning: |
718 | rtnh = (struct rtnexthop *)cfg->fc_mp; |
719 | |
720 | - /* Parse a Multipath Entry */ |
721 | + /* Parse a Multipath Entry and build a list (rt6_nh_list) of |
722 | + * rt6_info structs per nexthop |
723 | + */ |
724 | while (rtnh_ok(rtnh, remaining)) { |
725 | memcpy(&r_cfg, cfg, sizeof(*cfg)); |
726 | if (rtnh->rtnh_ifindex) |
727 | @@ -2524,22 +2606,32 @@ beginning: |
728 | r_cfg.fc_flags |= RTF_GATEWAY; |
729 | } |
730 | } |
731 | - err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg); |
732 | + |
733 | + err = ip6_route_info_create(&r_cfg, &rt); |
734 | + if (err) |
735 | + goto cleanup; |
736 | + |
737 | + err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg); |
738 | if (err) { |
739 | - last_err = err; |
740 | - /* If we are trying to remove a route, do not stop the |
741 | - * loop when ip6_route_del() fails (because next hop is |
742 | - * already gone), we should try to remove all next hops. |
743 | - */ |
744 | - if (add) { |
745 | - /* If add fails, we should try to delete all |
746 | - * next hops that have been already added. |
747 | - */ |
748 | - add = 0; |
749 | - remaining = cfg->fc_mp_len - remaining; |
750 | - goto beginning; |
751 | - } |
752 | + dst_free(&rt->dst); |
753 | + goto cleanup; |
754 | + } |
755 | + |
756 | + rtnh = rtnh_next(rtnh, &remaining); |
757 | + } |
758 | + |
759 | + err_nh = NULL; |
760 | + list_for_each_entry(nh, &rt6_nh_list, next) { |
761 | + err = __ip6_ins_rt(nh->rt6_info, &cfg->fc_nlinfo, &nh->mxc); |
762 | + /* nh->rt6_info is used or freed at this point, reset to NULL*/ |
763 | + nh->rt6_info = NULL; |
764 | + if (err) { |
765 | + if (replace && nhn) |
766 | + ip6_print_replace_route_err(&rt6_nh_list); |
767 | + err_nh = nh; |
768 | + goto add_errout; |
769 | } |
770 | + |
771 | /* Because each route is added like a single route we remove |
772 | * these flags after the first nexthop: if there is a collision, |
773 | * we have already failed to add the first nexthop: |
774 | @@ -2549,6 +2641,63 @@ beginning: |
775 | */ |
776 | cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | |
777 | NLM_F_REPLACE); |
778 | + nhn++; |
779 | + } |
780 | + |
781 | + goto cleanup; |
782 | + |
783 | +add_errout: |
784 | + /* Delete routes that were already added */ |
785 | + list_for_each_entry(nh, &rt6_nh_list, next) { |
786 | + if (err_nh == nh) |
787 | + break; |
788 | + ip6_route_del(&nh->r_cfg); |
789 | + } |
790 | + |
791 | +cleanup: |
792 | + list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) { |
793 | + if (nh->rt6_info) |
794 | + dst_free(&nh->rt6_info->dst); |
795 | + if (nh->mxc.mx) |
796 | + kfree(nh->mxc.mx); |
797 | + list_del(&nh->next); |
798 | + kfree(nh); |
799 | + } |
800 | + |
801 | + return err; |
802 | +} |
803 | + |
804 | +static int ip6_route_multipath_del(struct fib6_config *cfg) |
805 | +{ |
806 | + struct fib6_config r_cfg; |
807 | + struct rtnexthop *rtnh; |
808 | + int remaining; |
809 | + int attrlen; |
810 | + int err = 1, last_err = 0; |
811 | + |
812 | + remaining = cfg->fc_mp_len; |
813 | + rtnh = (struct rtnexthop *)cfg->fc_mp; |
814 | + |
815 | + /* Parse a Multipath Entry */ |
816 | + while (rtnh_ok(rtnh, remaining)) { |
817 | + memcpy(&r_cfg, cfg, sizeof(*cfg)); |
818 | + if (rtnh->rtnh_ifindex) |
819 | + r_cfg.fc_ifindex = rtnh->rtnh_ifindex; |
820 | + |
821 | + attrlen = rtnh_attrlen(rtnh); |
822 | + if (attrlen > 0) { |
823 | + struct nlattr *nla, *attrs = rtnh_attrs(rtnh); |
824 | + |
825 | + nla = nla_find(attrs, attrlen, RTA_GATEWAY); |
826 | + if (nla) { |
827 | + nla_memcpy(&r_cfg.fc_gateway, nla, 16); |
828 | + r_cfg.fc_flags |= RTF_GATEWAY; |
829 | + } |
830 | + } |
831 | + err = ip6_route_del(&r_cfg); |
832 | + if (err) |
833 | + last_err = err; |
834 | + |
835 | rtnh = rtnh_next(rtnh, &remaining); |
836 | } |
837 | |
838 | @@ -2565,7 +2714,7 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh) |
839 | return err; |
840 | |
841 | if (cfg.fc_mp) |
842 | - return ip6_route_multipath(&cfg, 0); |
843 | + return ip6_route_multipath_del(&cfg); |
844 | else |
845 | return ip6_route_del(&cfg); |
846 | } |
847 | @@ -2580,7 +2729,7 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) |
848 | return err; |
849 | |
850 | if (cfg.fc_mp) |
851 | - return ip6_route_multipath(&cfg, 1); |
852 | + return ip6_route_multipath_add(&cfg); |
853 | else |
854 | return ip6_route_add(&cfg); |
855 | } |
856 | diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c |
857 | index 4856d975492d..980121e75d2e 100644 |
858 | --- a/net/netlink/af_netlink.c |
859 | +++ b/net/netlink/af_netlink.c |
860 | @@ -123,6 +123,24 @@ static inline u32 netlink_group_mask(u32 group) |
861 | return group ? 1 << (group - 1) : 0; |
862 | } |
863 | |
864 | +static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb, |
865 | + gfp_t gfp_mask) |
866 | +{ |
867 | + unsigned int len = skb_end_offset(skb); |
868 | + struct sk_buff *new; |
869 | + |
870 | + new = alloc_skb(len, gfp_mask); |
871 | + if (new == NULL) |
872 | + return NULL; |
873 | + |
874 | + NETLINK_CB(new).portid = NETLINK_CB(skb).portid; |
875 | + NETLINK_CB(new).dst_group = NETLINK_CB(skb).dst_group; |
876 | + NETLINK_CB(new).creds = NETLINK_CB(skb).creds; |
877 | + |
878 | + memcpy(skb_put(new, len), skb->data, len); |
879 | + return new; |
880 | +} |
881 | + |
882 | int netlink_add_tap(struct netlink_tap *nt) |
883 | { |
884 | if (unlikely(nt->dev->type != ARPHRD_NETLINK)) |
885 | @@ -204,7 +222,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, |
886 | int ret = -ENOMEM; |
887 | |
888 | dev_hold(dev); |
889 | - nskb = skb_clone(skb, GFP_ATOMIC); |
890 | + |
891 | + if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head)) |
892 | + nskb = netlink_to_full_skb(skb, GFP_ATOMIC); |
893 | + else |
894 | + nskb = skb_clone(skb, GFP_ATOMIC); |
895 | if (nskb) { |
896 | nskb->dev = dev; |
897 | nskb->protocol = htons((u16) sk->sk_protocol); |
898 | @@ -276,11 +298,6 @@ static void netlink_rcv_wake(struct sock *sk) |
899 | } |
900 | |
901 | #ifdef CONFIG_NETLINK_MMAP |
902 | -static bool netlink_skb_is_mmaped(const struct sk_buff *skb) |
903 | -{ |
904 | - return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; |
905 | -} |
906 | - |
907 | static bool netlink_rx_is_mmaped(struct sock *sk) |
908 | { |
909 | return nlk_sk(sk)->rx_ring.pg_vec != NULL; |
910 | @@ -832,7 +849,6 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) |
911 | } |
912 | |
913 | #else /* CONFIG_NETLINK_MMAP */ |
914 | -#define netlink_skb_is_mmaped(skb) false |
915 | #define netlink_rx_is_mmaped(sk) false |
916 | #define netlink_tx_is_mmaped(sk) false |
917 | #define netlink_mmap sock_no_mmap |
918 | @@ -1080,8 +1096,8 @@ static int netlink_insert(struct sock *sk, u32 portid) |
919 | |
920 | lock_sock(sk); |
921 | |
922 | - err = -EBUSY; |
923 | - if (nlk_sk(sk)->portid) |
924 | + err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY; |
925 | + if (nlk_sk(sk)->bound) |
926 | goto err; |
927 | |
928 | err = -ENOMEM; |
929 | @@ -1101,10 +1117,13 @@ static int netlink_insert(struct sock *sk, u32 portid) |
930 | err = -EOVERFLOW; |
931 | if (err == -EEXIST) |
932 | err = -EADDRINUSE; |
933 | - nlk_sk(sk)->portid = 0; |
934 | sock_put(sk); |
935 | } |
936 | |
937 | + /* We need to ensure that the socket is hashed and visible. */ |
938 | + smp_wmb(); |
939 | + nlk_sk(sk)->bound = portid; |
940 | + |
941 | err: |
942 | release_sock(sk); |
943 | return err; |
944 | @@ -1484,6 +1503,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
945 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
946 | int err; |
947 | long unsigned int groups = nladdr->nl_groups; |
948 | + bool bound; |
949 | |
950 | if (addr_len < sizeof(struct sockaddr_nl)) |
951 | return -EINVAL; |
952 | @@ -1500,9 +1520,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
953 | return err; |
954 | } |
955 | |
956 | - if (nlk->portid) |
957 | + bound = nlk->bound; |
958 | + if (bound) { |
959 | + /* Ensure nlk->portid is up-to-date. */ |
960 | + smp_rmb(); |
961 | + |
962 | if (nladdr->nl_pid != nlk->portid) |
963 | return -EINVAL; |
964 | + } |
965 | |
966 | if (nlk->netlink_bind && groups) { |
967 | int group; |
968 | @@ -1518,7 +1543,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
969 | } |
970 | } |
971 | |
972 | - if (!nlk->portid) { |
973 | + /* No need for barriers here as we return to user-space without |
974 | + * using any of the bound attributes. |
975 | + */ |
976 | + if (!bound) { |
977 | err = nladdr->nl_pid ? |
978 | netlink_insert(sk, nladdr->nl_pid) : |
979 | netlink_autobind(sock); |
980 | @@ -1566,7 +1594,10 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, |
981 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
982 | return -EPERM; |
983 | |
984 | - if (!nlk->portid) |
985 | + /* No need for barriers here as we return to user-space without |
986 | + * using any of the bound attributes. |
987 | + */ |
988 | + if (!nlk->bound) |
989 | err = netlink_autobind(sock); |
990 | |
991 | if (err == 0) { |
992 | @@ -2323,10 +2354,13 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
993 | dst_group = nlk->dst_group; |
994 | } |
995 | |
996 | - if (!nlk->portid) { |
997 | + if (!nlk->bound) { |
998 | err = netlink_autobind(sock); |
999 | if (err) |
1000 | goto out; |
1001 | + } else { |
1002 | + /* Ensure nlk is hashed and visible. */ |
1003 | + smp_rmb(); |
1004 | } |
1005 | |
1006 | /* It's a really convoluted way for userland to ask for mmaped |
1007 | diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h |
1008 | index 89008405d6b4..14437d9b1965 100644 |
1009 | --- a/net/netlink/af_netlink.h |
1010 | +++ b/net/netlink/af_netlink.h |
1011 | @@ -35,6 +35,7 @@ struct netlink_sock { |
1012 | unsigned long state; |
1013 | size_t max_recvmsg_len; |
1014 | wait_queue_head_t wait; |
1015 | + bool bound; |
1016 | bool cb_running; |
1017 | struct netlink_callback cb; |
1018 | struct mutex *cb_mutex; |
1019 | @@ -59,6 +60,15 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) |
1020 | return container_of(sk, struct netlink_sock, sk); |
1021 | } |
1022 | |
1023 | +static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb) |
1024 | +{ |
1025 | +#ifdef CONFIG_NETLINK_MMAP |
1026 | + return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; |
1027 | +#else |
1028 | + return false; |
1029 | +#endif /* CONFIG_NETLINK_MMAP */ |
1030 | +} |
1031 | + |
1032 | struct netlink_table { |
1033 | struct rhashtable hash; |
1034 | struct hlist_head mc_list; |
1035 | diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c |
1036 | index 096c6276e6b9..27e14962b504 100644 |
1037 | --- a/net/openvswitch/datapath.c |
1038 | +++ b/net/openvswitch/datapath.c |
1039 | @@ -906,7 +906,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) |
1040 | if (error) |
1041 | goto err_kfree_flow; |
1042 | |
1043 | - ovs_flow_mask_key(&new_flow->key, &key, &mask); |
1044 | + ovs_flow_mask_key(&new_flow->key, &key, true, &mask); |
1045 | |
1046 | /* Extract flow identifier. */ |
1047 | error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], |
1048 | @@ -1033,7 +1033,7 @@ static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, |
1049 | struct sw_flow_key masked_key; |
1050 | int error; |
1051 | |
1052 | - ovs_flow_mask_key(&masked_key, key, mask); |
1053 | + ovs_flow_mask_key(&masked_key, key, true, mask); |
1054 | error = ovs_nla_copy_actions(a, &masked_key, &acts, log); |
1055 | if (error) { |
1056 | OVS_NLERR(log, |
1057 | diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c |
1058 | index 4613df8c8290..aa349514e4cb 100644 |
1059 | --- a/net/openvswitch/flow_table.c |
1060 | +++ b/net/openvswitch/flow_table.c |
1061 | @@ -56,20 +56,21 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range) |
1062 | } |
1063 | |
1064 | void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, |
1065 | - const struct sw_flow_mask *mask) |
1066 | + bool full, const struct sw_flow_mask *mask) |
1067 | { |
1068 | - const long *m = (const long *)((const u8 *)&mask->key + |
1069 | - mask->range.start); |
1070 | - const long *s = (const long *)((const u8 *)src + |
1071 | - mask->range.start); |
1072 | - long *d = (long *)((u8 *)dst + mask->range.start); |
1073 | + int start = full ? 0 : mask->range.start; |
1074 | + int len = full ? sizeof *dst : range_n_bytes(&mask->range); |
1075 | + const long *m = (const long *)((const u8 *)&mask->key + start); |
1076 | + const long *s = (const long *)((const u8 *)src + start); |
1077 | + long *d = (long *)((u8 *)dst + start); |
1078 | int i; |
1079 | |
1080 | - /* The memory outside of the 'mask->range' are not set since |
1081 | - * further operations on 'dst' only uses contents within |
1082 | - * 'mask->range'. |
1083 | + /* If 'full' is true then all of 'dst' is fully initialized. Otherwise, |
1084 | + * if 'full' is false the memory outside of the 'mask->range' is left |
1085 | + * uninitialized. This can be used as an optimization when further |
1086 | + * operations on 'dst' only use contents within 'mask->range'. |
1087 | */ |
1088 | - for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long)) |
1089 | + for (i = 0; i < len; i += sizeof(long)) |
1090 | *d++ = *s++ & *m++; |
1091 | } |
1092 | |
1093 | @@ -473,7 +474,7 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti, |
1094 | u32 hash; |
1095 | struct sw_flow_key masked_key; |
1096 | |
1097 | - ovs_flow_mask_key(&masked_key, unmasked, mask); |
1098 | + ovs_flow_mask_key(&masked_key, unmasked, false, mask); |
1099 | hash = flow_hash(&masked_key, &mask->range); |
1100 | head = find_bucket(ti, hash); |
1101 | hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) { |
1102 | diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h |
1103 | index 616eda10d955..2dd9900f533d 100644 |
1104 | --- a/net/openvswitch/flow_table.h |
1105 | +++ b/net/openvswitch/flow_table.h |
1106 | @@ -86,5 +86,5 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *, |
1107 | bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *); |
1108 | |
1109 | void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, |
1110 | - const struct sw_flow_mask *mask); |
1111 | + bool full, const struct sw_flow_mask *mask); |
1112 | #endif /* flow_table.h */ |
1113 | diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c |
1114 | index 715e01e5910a..f23a3b68bba6 100644 |
1115 | --- a/net/sched/cls_fw.c |
1116 | +++ b/net/sched/cls_fw.c |
1117 | @@ -33,7 +33,6 @@ |
1118 | |
1119 | struct fw_head { |
1120 | u32 mask; |
1121 | - bool mask_set; |
1122 | struct fw_filter __rcu *ht[HTSIZE]; |
1123 | struct rcu_head rcu; |
1124 | }; |
1125 | @@ -84,7 +83,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
1126 | } |
1127 | } |
1128 | } else { |
1129 | - /* old method */ |
1130 | + /* Old method: classify the packet using its skb mark. */ |
1131 | if (id && (TC_H_MAJ(id) == 0 || |
1132 | !(TC_H_MAJ(id ^ tp->q->handle)))) { |
1133 | res->classid = id; |
1134 | @@ -114,14 +113,9 @@ static unsigned long fw_get(struct tcf_proto *tp, u32 handle) |
1135 | |
1136 | static int fw_init(struct tcf_proto *tp) |
1137 | { |
1138 | - struct fw_head *head; |
1139 | - |
1140 | - head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); |
1141 | - if (head == NULL) |
1142 | - return -ENOBUFS; |
1143 | - |
1144 | - head->mask_set = false; |
1145 | - rcu_assign_pointer(tp->root, head); |
1146 | + /* We don't allocate fw_head here, because in the old method |
1147 | + * we don't need it at all. |
1148 | + */ |
1149 | return 0; |
1150 | } |
1151 | |
1152 | @@ -252,7 +246,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, |
1153 | int err; |
1154 | |
1155 | if (!opt) |
1156 | - return handle ? -EINVAL : 0; |
1157 | + return handle ? -EINVAL : 0; /* Succeed if it is old method. */ |
1158 | |
1159 | err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy); |
1160 | if (err < 0) |
1161 | @@ -302,11 +296,17 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, |
1162 | if (!handle) |
1163 | return -EINVAL; |
1164 | |
1165 | - if (!head->mask_set) { |
1166 | - head->mask = 0xFFFFFFFF; |
1167 | + if (!head) { |
1168 | + u32 mask = 0xFFFFFFFF; |
1169 | if (tb[TCA_FW_MASK]) |
1170 | - head->mask = nla_get_u32(tb[TCA_FW_MASK]); |
1171 | - head->mask_set = true; |
1172 | + mask = nla_get_u32(tb[TCA_FW_MASK]); |
1173 | + |
1174 | + head = kzalloc(sizeof(*head), GFP_KERNEL); |
1175 | + if (!head) |
1176 | + return -ENOBUFS; |
1177 | + head->mask = mask; |
1178 | + |
1179 | + rcu_assign_pointer(tp->root, head); |
1180 | } |
1181 | |
1182 | f = kzalloc(sizeof(struct fw_filter), GFP_KERNEL); |
1183 | diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c |
1184 | index cab9e9b43967..4fbb67430ce4 100644 |
1185 | --- a/net/sched/cls_u32.c |
1186 | +++ b/net/sched/cls_u32.c |
1187 | @@ -490,6 +490,19 @@ static bool u32_destroy(struct tcf_proto *tp, bool force) |
1188 | return false; |
1189 | } |
1190 | } |
1191 | + |
1192 | + if (tp_c->refcnt > 1) |
1193 | + return false; |
1194 | + |
1195 | + if (tp_c->refcnt == 1) { |
1196 | + struct tc_u_hnode *ht; |
1197 | + |
1198 | + for (ht = rtnl_dereference(tp_c->hlist); |
1199 | + ht; |
1200 | + ht = rtnl_dereference(ht->next)) |
1201 | + if (!ht_empty(ht)) |
1202 | + return false; |
1203 | + } |
1204 | } |
1205 | |
1206 | if (root_ht && --root_ht->refcnt == 0) |
1207 | diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c |
1208 | index 53b7acde9aa3..e13c3c3ea4ac 100644 |
1209 | --- a/net/sctp/protocol.c |
1210 | +++ b/net/sctp/protocol.c |
1211 | @@ -1166,7 +1166,7 @@ static void sctp_v4_del_protocol(void) |
1212 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); |
1213 | } |
1214 | |
1215 | -static int __net_init sctp_net_init(struct net *net) |
1216 | +static int __net_init sctp_defaults_init(struct net *net) |
1217 | { |
1218 | int status; |
1219 | |
1220 | @@ -1259,12 +1259,6 @@ static int __net_init sctp_net_init(struct net *net) |
1221 | |
1222 | sctp_dbg_objcnt_init(net); |
1223 | |
1224 | - /* Initialize the control inode/socket for handling OOTB packets. */ |
1225 | - if ((status = sctp_ctl_sock_init(net))) { |
1226 | - pr_err("Failed to initialize the SCTP control sock\n"); |
1227 | - goto err_ctl_sock_init; |
1228 | - } |
1229 | - |
1230 | /* Initialize the local address list. */ |
1231 | INIT_LIST_HEAD(&net->sctp.local_addr_list); |
1232 | spin_lock_init(&net->sctp.local_addr_lock); |
1233 | @@ -1280,9 +1274,6 @@ static int __net_init sctp_net_init(struct net *net) |
1234 | |
1235 | return 0; |
1236 | |
1237 | -err_ctl_sock_init: |
1238 | - sctp_dbg_objcnt_exit(net); |
1239 | - sctp_proc_exit(net); |
1240 | err_init_proc: |
1241 | cleanup_sctp_mibs(net); |
1242 | err_init_mibs: |
1243 | @@ -1291,15 +1282,12 @@ err_sysctl_register: |
1244 | return status; |
1245 | } |
1246 | |
1247 | -static void __net_exit sctp_net_exit(struct net *net) |
1248 | +static void __net_exit sctp_defaults_exit(struct net *net) |
1249 | { |
1250 | /* Free the local address list */ |
1251 | sctp_free_addr_wq(net); |
1252 | sctp_free_local_addr_list(net); |
1253 | |
1254 | - /* Free the control endpoint. */ |
1255 | - inet_ctl_sock_destroy(net->sctp.ctl_sock); |
1256 | - |
1257 | sctp_dbg_objcnt_exit(net); |
1258 | |
1259 | sctp_proc_exit(net); |
1260 | @@ -1307,9 +1295,32 @@ static void __net_exit sctp_net_exit(struct net *net) |
1261 | sctp_sysctl_net_unregister(net); |
1262 | } |
1263 | |
1264 | -static struct pernet_operations sctp_net_ops = { |
1265 | - .init = sctp_net_init, |
1266 | - .exit = sctp_net_exit, |
1267 | +static struct pernet_operations sctp_defaults_ops = { |
1268 | + .init = sctp_defaults_init, |
1269 | + .exit = sctp_defaults_exit, |
1270 | +}; |
1271 | + |
1272 | +static int __net_init sctp_ctrlsock_init(struct net *net) |
1273 | +{ |
1274 | + int status; |
1275 | + |
1276 | + /* Initialize the control inode/socket for handling OOTB packets. */ |
1277 | + status = sctp_ctl_sock_init(net); |
1278 | + if (status) |
1279 | + pr_err("Failed to initialize the SCTP control sock\n"); |
1280 | + |
1281 | + return status; |
1282 | +} |
1283 | + |
1284 | +static void __net_init sctp_ctrlsock_exit(struct net *net) |
1285 | +{ |
1286 | + /* Free the control endpoint. */ |
1287 | + inet_ctl_sock_destroy(net->sctp.ctl_sock); |
1288 | +} |
1289 | + |
1290 | +static struct pernet_operations sctp_ctrlsock_ops = { |
1291 | + .init = sctp_ctrlsock_init, |
1292 | + .exit = sctp_ctrlsock_exit, |
1293 | }; |
1294 | |
1295 | /* Initialize the universe into something sensible. */ |
1296 | @@ -1442,8 +1453,11 @@ static __init int sctp_init(void) |
1297 | sctp_v4_pf_init(); |
1298 | sctp_v6_pf_init(); |
1299 | |
1300 | - status = sctp_v4_protosw_init(); |
1301 | + status = register_pernet_subsys(&sctp_defaults_ops); |
1302 | + if (status) |
1303 | + goto err_register_defaults; |
1304 | |
1305 | + status = sctp_v4_protosw_init(); |
1306 | if (status) |
1307 | goto err_protosw_init; |
1308 | |
1309 | @@ -1451,9 +1465,9 @@ static __init int sctp_init(void) |
1310 | if (status) |
1311 | goto err_v6_protosw_init; |
1312 | |
1313 | - status = register_pernet_subsys(&sctp_net_ops); |
1314 | + status = register_pernet_subsys(&sctp_ctrlsock_ops); |
1315 | if (status) |
1316 | - goto err_register_pernet_subsys; |
1317 | + goto err_register_ctrlsock; |
1318 | |
1319 | status = sctp_v4_add_protocol(); |
1320 | if (status) |
1321 | @@ -1469,12 +1483,14 @@ out: |
1322 | err_v6_add_protocol: |
1323 | sctp_v4_del_protocol(); |
1324 | err_add_protocol: |
1325 | - unregister_pernet_subsys(&sctp_net_ops); |
1326 | -err_register_pernet_subsys: |
1327 | + unregister_pernet_subsys(&sctp_ctrlsock_ops); |
1328 | +err_register_ctrlsock: |
1329 | sctp_v6_protosw_exit(); |
1330 | err_v6_protosw_init: |
1331 | sctp_v4_protosw_exit(); |
1332 | err_protosw_init: |
1333 | + unregister_pernet_subsys(&sctp_defaults_ops); |
1334 | +err_register_defaults: |
1335 | sctp_v4_pf_exit(); |
1336 | sctp_v6_pf_exit(); |
1337 | sctp_sysctl_unregister(); |
1338 | @@ -1507,12 +1523,14 @@ static __exit void sctp_exit(void) |
1339 | sctp_v6_del_protocol(); |
1340 | sctp_v4_del_protocol(); |
1341 | |
1342 | - unregister_pernet_subsys(&sctp_net_ops); |
1343 | + unregister_pernet_subsys(&sctp_ctrlsock_ops); |
1344 | |
1345 | /* Free protosw registrations */ |
1346 | sctp_v6_protosw_exit(); |
1347 | sctp_v4_protosw_exit(); |
1348 | |
1349 | + unregister_pernet_subsys(&sctp_defaults_ops); |
1350 | + |
1351 | /* Unregister with socket layer. */ |
1352 | sctp_v6_pf_exit(); |
1353 | sctp_v4_pf_exit(); |