已合并
Release 6.0 cve 漏洞修复 #346
何京晶创建于 4月15日
Release 6.0 cve 漏洞修复 #346
已合并
共 43 个文件变更+297-125
| @@ -396,7 +396,7 @@ int swsusp_arch_suspend(void) | |||
| 396 | * Memory allocated by get_safe_page() will be dealt with by the hibernate code, | 396 | * Memory allocated by get_safe_page() will be dealt with by the hibernate code, |
| 397 | * we don't need to free it here. | 397 | * we don't need to free it here. |
| 398 | */ | 398 | */ |
| 399 | -int swsusp_arch_resume(void) | 399 | +int __nocfi swsusp_arch_resume(void) |
| 400 | { | 400 | { |
| 401 | int rc; | 401 | int rc; |
| 402 | void *zero_page; | 402 | void *zero_page; |
| @@ -189,6 +189,9 @@ static int crypto_authenc_esn_encrypt(struct aead_request *req) | |||
| 189 | struct scatterlist *src, *dst; | 189 | struct scatterlist *src, *dst; |
| 190 | int err; | 190 | int err; |
| 191 | 191 | ||
| 192 | + if (assoclen < 8) | ||
| 193 | + return -EINVAL; | ||
| 194 | + | ||
| 192 | sg_init_table(areq_ctx->src, 2); | 195 | sg_init_table(areq_ctx->src, 2); |
| 193 | src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen); | 196 | src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen); |
| 194 | dst = src; | 197 | dst = src; |
| @@ -281,6 +284,9 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req) | |||
| 281 | u32 tmp[2]; | 284 | u32 tmp[2]; |
| 282 | int err; | 285 | int err; |
| 283 | 286 | ||
| 287 | + if (assoclen < 8) | ||
| 288 | + return -EINVAL; | ||
| 289 | + | ||
| 284 | cryptlen -= authsize; | 290 | cryptlen -= authsize; |
| 285 | 291 | ||
| 286 | if (req->src != dst) { | 292 | if (req->src != dst) { |
| @@ -96,12 +96,13 @@ static int regcache_maple_write(struct regmap *map, unsigned int reg, | |||
| 96 | 96 | ||
| 97 | mas_unlock(&mas); | 97 | mas_unlock(&mas); |
| 98 | 98 | ||
| 99 | - if (ret == 0) { | 99 | + if (ret) { |
| 100 | - kfree(lower); | 100 | + kfree(entry); |
| 101 | - kfree(upper); | 101 | + return ret; |
| 102 | } | 102 | } |
| 103 | - | 103 | + kfree(lower); |
| 104 | - return ret; | 104 | + kfree(upper); |
| 105 | + return 0; | ||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | static int regcache_maple_drop(struct regmap *map, unsigned int min, | 108 | static int regcache_maple_drop(struct regmap *map, unsigned int min, |
| @@ -408,9 +408,11 @@ static void regmap_lock_hwlock_irq(void *__map) | |||
| 408 | static void regmap_lock_hwlock_irqsave(void *__map) | 408 | static void regmap_lock_hwlock_irqsave(void *__map) |
| 409 | { | 409 | { |
| 410 | struct regmap *map = __map; | 410 | struct regmap *map = __map; |
| 411 | + unsigned long flags = 0; | ||
| 411 | 412 | ||
| 412 | hwspin_lock_timeout_irqsave(map->hwlock, UINT_MAX, | 413 | hwspin_lock_timeout_irqsave(map->hwlock, UINT_MAX, |
| 413 | - &map->spinlock_flags); | 414 | + &flags); |
| 415 | + map->spinlock_flags = flags; | ||
| 414 | } | 416 | } |
| 415 | 417 | ||
| 416 | static void regmap_unlock_hwlock(void *__map) | 418 | static void regmap_unlock_hwlock(void *__map) |
| @@ -1472,19 +1472,36 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg) | |||
| 1472 | return error; | 1472 | return error; |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | -static int loop_set_block_size(struct loop_device *lo, unsigned long arg) | 1475 | +static int loop_set_block_size(struct loop_device *lo, blk_mode_t mode, |
| 1476 | + struct block_device *bdev, unsigned long arg) | ||
| 1476 | { | 1477 | { |
| 1477 | int err = 0; | 1478 | int err = 0; |
| 1478 | 1479 | ||
| 1479 | - if (lo->lo_state != Lo_bound) | 1480 | + /* |
| 1480 | - return -ENXIO; | 1481 | + * If we don't hold exclusive handle for the device, upgrade to it |
| 1482 | + * here to avoid changing device under exclusive owner. | ||
| 1483 | + */ | ||
| 1484 | + if (!(mode & BLK_OPEN_EXCL)) { | ||
| 1485 | + err = bd_prepare_to_claim(bdev, loop_set_block_size, NULL); | ||
| 1486 | + if (err) | ||
| 1487 | + return err; | ||
| 1488 | + } | ||
| 1489 | + | ||
| 1490 | + err = mutex_lock_killable(&lo->lo_mutex); | ||
| 1491 | + if (err) | ||
| 1492 | + goto abort_claim; | ||
| 1493 | + | ||
| 1494 | + if (lo->lo_state != Lo_bound) { | ||
| 1495 | + err = -ENXIO; | ||
| 1496 | + goto unlock; | ||
| 1497 | + } | ||
| 1481 | 1498 | ||
| 1482 | err = blk_validate_block_size(arg); | 1499 | err = blk_validate_block_size(arg); |
| 1483 | if (err) | 1500 | if (err) |
| 1484 | return err; | 1501 | return err; |
| 1485 | 1502 | ||
| 1486 | if (lo->lo_queue->limits.logical_block_size == arg) | 1503 | if (lo->lo_queue->limits.logical_block_size == arg) |
| 1487 | - return 0; | 1504 | + goto unlock; |
| 1488 | 1505 | ||
| 1489 | sync_blockdev(lo->lo_device); | 1506 | sync_blockdev(lo->lo_device); |
| 1490 | invalidate_bdev(lo->lo_device); | 1507 | invalidate_bdev(lo->lo_device); |
| @@ -1496,6 +1513,11 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) | |||
| 1496 | loop_update_dio(lo); | 1513 | loop_update_dio(lo); |
| 1497 | blk_mq_unfreeze_queue(lo->lo_queue); | 1514 | blk_mq_unfreeze_queue(lo->lo_queue); |
| 1498 | 1515 | ||
| 1516 | +unlock: | ||
| 1517 | + mutex_unlock(&lo->lo_mutex); | ||
| 1518 | +abort_claim: | ||
| 1519 | + if (!(mode & BLK_OPEN_EXCL)) | ||
| 1520 | + bd_abort_claiming(bdev, loop_set_block_size); | ||
| 1499 | return err; | 1521 | return err; |
| 1500 | } | 1522 | } |
| 1501 | 1523 | ||
| @@ -1514,9 +1536,6 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd, | |||
| 1514 | case LOOP_SET_DIRECT_IO: | 1536 | case LOOP_SET_DIRECT_IO: |
| 1515 | err = loop_set_dio(lo, arg); | 1537 | err = loop_set_dio(lo, arg); |
| 1516 | break; | 1538 | break; |
| 1517 | - case LOOP_SET_BLOCK_SIZE: | ||
| 1518 | - err = loop_set_block_size(lo, arg); | ||
| 1519 | - break; | ||
| 1520 | default: | 1539 | default: |
| 1521 | err = -EINVAL; | 1540 | err = -EINVAL; |
| 1522 | } | 1541 | } |
| @@ -1571,9 +1590,12 @@ static int lo_ioctl(struct block_device *bdev, blk_mode_t mode, | |||
| 1571 | break; | 1590 | break; |
| 1572 | case LOOP_GET_STATUS64: | 1591 | case LOOP_GET_STATUS64: |
| 1573 | return loop_get_status64(lo, argp); | 1592 | return loop_get_status64(lo, argp); |
| 1593 | + case LOOP_SET_BLOCK_SIZE: | ||
| 1594 | + if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) | ||
| 1595 | + return -EPERM; | ||
| 1596 | + return loop_set_block_size(lo, mode, bdev, arg); | ||
| 1574 | case LOOP_SET_CAPACITY: | 1597 | case LOOP_SET_CAPACITY: |
| 1575 | case LOOP_SET_DIRECT_IO: | 1598 | case LOOP_SET_DIRECT_IO: |
| 1576 | - case LOOP_SET_BLOCK_SIZE: | ||
| 1577 | if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) | 1599 | if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) |
| 1578 | return -EPERM; | 1600 | return -EPERM; |
| 1579 | fallthrough; | 1601 | fallthrough; |
| @@ -278,6 +278,11 @@ davinci_lpsc_clk_register(struct device *dev, const char *name, | |||
| 278 | 278 | ||
| 279 | lpsc->pm_domain.name = devm_kasprintf(dev, GFP_KERNEL, "%s: %s", | 279 | lpsc->pm_domain.name = devm_kasprintf(dev, GFP_KERNEL, "%s: %s", |
| 280 | best_dev_name(dev), name); | 280 | best_dev_name(dev), name); |
| 281 | + if (!lpsc->pm_domain.name) { | ||
| 282 | + clk_hw_unregister(&lpsc->hw); | ||
| 283 | + kfree(lpsc); | ||
| 284 | + return ERR_PTR(-ENOMEM); | ||
| 285 | + } | ||
| 281 | lpsc->pm_domain.attach_dev = davinci_psc_genpd_attach_dev; | 286 | lpsc->pm_domain.attach_dev = davinci_psc_genpd_attach_dev; |
| 282 | lpsc->pm_domain.detach_dev = davinci_psc_genpd_detach_dev; | 287 | lpsc->pm_domain.detach_dev = davinci_psc_genpd_detach_dev; |
| 283 | lpsc->pm_domain.flags = GENPD_FLAG_PM_CLK; | 288 | lpsc->pm_domain.flags = GENPD_FLAG_PM_CLK; |
| @@ -1382,15 +1382,11 @@ int devfreq_remove_governor(struct devfreq_governor *governor) | |||
| 1382 | int ret; | 1382 | int ret; |
| 1383 | struct device *dev = devfreq->dev.parent; | 1383 | struct device *dev = devfreq->dev.parent; |
| 1384 | 1384 | ||
| 1385 | + if (!devfreq->governor) | ||
| 1386 | + continue; | ||
| 1387 | + | ||
| 1385 | if (!strncmp(devfreq->governor->name, governor->name, | 1388 | if (!strncmp(devfreq->governor->name, governor->name, |
| 1386 | DEVFREQ_NAME_LEN)) { | 1389 | DEVFREQ_NAME_LEN)) { |
| 1387 | - /* we should have a devfreq governor! */ | ||
| 1388 | - if (!devfreq->governor) { | ||
| 1389 | - dev_warn(dev, "%s: Governor %s NOT present\n", | ||
| 1390 | - __func__, governor->name); | ||
| 1391 | - continue; | ||
| 1392 | - /* Fall through */ | ||
| 1393 | - } | ||
| 1394 | ret = devfreq->governor->event_handler(devfreq, | 1390 | ret = devfreq->governor->event_handler(devfreq, |
| 1395 | DEVFREQ_GOV_STOP, NULL); | 1391 | DEVFREQ_GOV_STOP, NULL); |
| 1396 | if (ret) { | 1392 | if (ret) { |
| @@ -546,11 +546,6 @@ int led_classdev_register_ext(struct device *parent, | |||
| 546 | 546 | ||
| 547 | led_cdev->brightness_hw_changed = -1; | 547 | led_cdev->brightness_hw_changed = -1; |
| 548 | 548 | ||
| 549 | - /* add to the list of leds */ | ||
| 550 | - down_write(&leds_list_lock); | ||
| 551 | - list_add_tail(&led_cdev->node, &leds_list); | ||
| 552 | - up_write(&leds_list_lock); | ||
| 553 | - | ||
| 554 | if (!led_cdev->max_brightness) | 549 | if (!led_cdev->max_brightness) |
| 555 | led_cdev->max_brightness = LED_FULL; | 550 | led_cdev->max_brightness = LED_FULL; |
| 556 | 551 | ||
| @@ -558,6 +553,11 @@ int led_classdev_register_ext(struct device *parent, | |||
| 558 | 553 | ||
| 559 | led_init_core(led_cdev); | 554 | led_init_core(led_cdev); |
| 560 | 555 | ||
| 556 | + /* add to the list of leds */ | ||
| 557 | + down_write(&leds_list_lock); | ||
| 558 | + list_add_tail(&led_cdev->node, &leds_list); | ||
| 559 | + up_write(&leds_list_lock); | ||
| 560 | + | ||
| 561 | 561 | ||
| 562 | led_trigger_set_default(led_cdev); | 562 | led_trigger_set_default(led_cdev); |
| 563 | 563 | ||
| @@ -168,7 +168,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | |||
| 168 | mutex_unlock(&dmxdev->mutex); | 168 | mutex_unlock(&dmxdev->mutex); |
| 169 | return -ENOMEM; | 169 | return -ENOMEM; |
| 170 | } | 170 | } |
| 171 | - dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | 171 | + dmxdev->dvr_buffer.data = mem; |
| 172 | + dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; | ||
| 173 | + dvb_ringbuffer_reset(&dmxdev->dvr_buffer); | ||
| 172 | if (dmxdev->may_do_mmap) | 174 | if (dmxdev->may_do_mmap) |
| 173 | dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", | 175 | dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", |
| 174 | file->f_flags & O_NONBLOCK); | 176 | file->f_flags & O_NONBLOCK); |
| @@ -2198,6 +2198,8 @@ static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_ms | |||
| 2198 | struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); | 2198 | struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); |
| 2199 | u8 n_overflow = 1; | 2199 | u8 n_overflow = 1; |
| 2200 | u16 i = 1000; | 2200 | u16 i = 1000; |
| 2201 | + if (msg[0].len < 3) | ||
| 2202 | + return -EOPNOTSUPP; | ||
| 2201 | u16 serpar_num = msg[0].buf[0]; | 2203 | u16 serpar_num = msg[0].buf[0]; |
| 2202 | 2204 | ||
| 2203 | while (n_overflow == 1 && i) { | 2205 | while (n_overflow == 1 && i) { |
| @@ -2217,6 +2219,8 @@ static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg | |||
| 2217 | struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); | 2219 | struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); |
| 2218 | u8 n_overflow = 1, n_empty = 1; | 2220 | u8 n_overflow = 1, n_empty = 1; |
| 2219 | u16 i = 1000; | 2221 | u16 i = 1000; |
| 2222 | + if (msg[0].len < 1 || msg[1].len < 2) | ||
| 2223 | + return -EOPNOTSUPP; | ||
| 2220 | u16 serpar_num = msg[0].buf[0]; | 2224 | u16 serpar_num = msg[0].buf[0]; |
| 2221 | u16 read_word; | 2225 | u16 read_word; |
| 2222 | 2226 | ||
| @@ -2261,8 +2265,12 @@ static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, | |||
| 2261 | u16 word; | 2265 | u16 word; |
| 2262 | 2266 | ||
| 2263 | if (num == 1) { /* write */ | 2267 | if (num == 1) { /* write */ |
| 2268 | + if (msg[0].len < 3) | ||
| 2269 | + return -EOPNOTSUPP; | ||
| 2264 | dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); | 2270 | dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); |
| 2265 | } else { | 2271 | } else { |
| 2272 | + if (msg[1].len < 2) | ||
| 2273 | + return -EOPNOTSUPP; | ||
| 2266 | word = dib7000p_read_word(state, apb_address); | 2274 | word = dib7000p_read_word(state, apb_address); |
| 2267 | msg[1].buf[0] = (word >> 8) & 0xff; | 2275 | msg[1].buf[0] = (word >> 8) & 0xff; |
| 2268 | msg[1].buf[1] = (word) & 0xff; | 2276 | msg[1].buf[1] = (word) & 0xff; |
| @@ -235,6 +235,9 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
| 235 | unsigned int i, n; | 235 | unsigned int i, n; |
| 236 | u8 ftype; | 236 | u8 ftype; |
| 237 | 237 | ||
| 238 | + if (buflen < 4) | ||
| 239 | + return -EINVAL; | ||
| 240 | + | ||
| 238 | format->type = buffer[2]; | 241 | format->type = buffer[2]; |
| 239 | format->index = buffer[3]; | 242 | format->index = buffer[3]; |
| 240 | format->frames = frames; | 243 | format->frames = frames; |
| @@ -244,6 +244,13 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock | |||
| 244 | sdhci_writel(host, extra, reg); | 244 | sdhci_writel(host, extra, reg); |
| 245 | 245 | ||
| 246 | if (clock <= 52000000) { | 246 | if (clock <= 52000000) { |
| 247 | + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 || | ||
| 248 | + host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { | ||
| 249 | + dev_err(mmc_dev(host->mmc), | ||
| 250 | + "Can't reduce the clock below 52MHz in HS200/HS400 mode"); | ||
| 251 | + return; | ||
| 252 | + } | ||
| 253 | + | ||
| 247 | /* | 254 | /* |
| 248 | * Disable DLL and reset both of sample and drive clock. | 255 | * Disable DLL and reset both of sample and drive clock. |
| 249 | * The bypass bit and start bit need to be set if DLL is not locked. | 256 | * The bypass bit and start bit need to be set if DLL is not locked. |
| @@ -87,6 +87,7 @@ MODULE_PARM_DESC(phyaddr, "Physical device address"); | |||
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | 89 | ||
| 90 | + | ||
| 90 | 91 | ||
| 91 | static int flow_ctrl = FLOW_AUTO; | 92 | static int flow_ctrl = FLOW_AUTO; |
| 92 | module_param(flow_ctrl, int, 0644); | 93 | module_param(flow_ctrl, int, 0644); |
| @@ -4873,6 +4874,7 @@ static int stmmac_xdp_get_tx_queue(struct stmmac_priv *priv, | |||
| 4873 | static int stmmac_xdp_xmit_back(struct stmmac_priv *priv, | 4874 | static int stmmac_xdp_xmit_back(struct stmmac_priv *priv, |
| 4874 | struct xdp_buff *xdp) | 4875 | struct xdp_buff *xdp) |
| 4875 | { | 4876 | { |
| 4877 | + bool zc = !!(xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL); | ||
| 4876 | struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); | 4878 | struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); |
| 4877 | int cpu = smp_processor_id(); | 4879 | int cpu = smp_processor_id(); |
| 4878 | struct netdev_queue *nq; | 4880 | struct netdev_queue *nq; |
| @@ -4889,9 +4891,18 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv, | |||
| 4889 | /* Avoids TX time-out as we are sharing with slow path */ | 4891 | /* Avoids TX time-out as we are sharing with slow path */ |
| 4890 | txq_trans_cond_update(nq); | 4892 | txq_trans_cond_update(nq); |
| 4891 | 4893 | ||
| 4892 | - res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, false); | 4894 | + /* For zero copy XDP_TX action, dma_map is true */ |
| 4893 | - if (res == STMMAC_XDP_TX) | 4895 | + res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, zc); |
| 4896 | + if (res == STMMAC_XDP_TX) { | ||
| 4894 | stmmac_flush_tx_descriptors(priv, queue); | 4897 | stmmac_flush_tx_descriptors(priv, queue); |
| 4898 | + } else if (res == STMMAC_XDP_CONSUMED && zc) { | ||
| 4899 | + /* xdp has been freed by xdp_convert_buff_to_frame(), | ||
| 4900 | + * no need to call xsk_buff_free() again, so return | ||
| 4901 | + * STMMAC_XSK_CONSUMED. | ||
| 4902 | + */ | ||
| 4903 | + res = STMMAC_XSK_CONSUMED; | ||
| 4904 | + xdp_return_frame(xdpf); | ||
| 4905 | + } | ||
| 4895 | 4906 | ||
| 4896 | __netif_tx_unlock(nq); | 4907 | __netif_tx_unlock(nq); |
| 4897 | 4908 | ||
| @@ -5237,6 +5248,8 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) | |||
| 5237 | break; | 5248 | break; |
| 5238 | case STMMAC_XDP_CONSUMED: | 5249 | case STMMAC_XDP_CONSUMED: |
| 5239 | xsk_buff_free(buf->xdp); | 5250 | xsk_buff_free(buf->xdp); |
| 5251 | + fallthrough; | ||
| 5252 | + case STMMAC_XSK_CONSUMED: | ||
| 5240 | rx_dropped++; | 5253 | rx_dropped++; |
| 5241 | break; | 5254 | break; |
| 5242 | case STMMAC_XDP_TX: | 5255 | case STMMAC_XDP_TX: |
| @@ -676,6 +676,7 @@ static int ax88772_init_mdio(struct usbnet *dev) | |||
| 676 | priv->mdio->read = &asix_mdio_bus_read; | 676 | priv->mdio->read = &asix_mdio_bus_read; |
| 677 | priv->mdio->write = &asix_mdio_bus_write; | 677 | priv->mdio->write = &asix_mdio_bus_write; |
| 678 | priv->mdio->name = "Asix MDIO Bus"; | 678 | priv->mdio->name = "Asix MDIO Bus"; |
| 679 | + priv->mdio->phy_mask = ~(BIT(priv->phy_addr) | BIT(AX_EMBD_PHY_ADDR)); | ||
| 679 | /* mii bus name is usb-<usb bus number>-<usb device number> */ | 680 | /* mii bus name is usb-<usb bus number>-<usb device number> */ |
| 680 | snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", | 681 | snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", |
| 681 | dev->udev->bus->busnum, dev->udev->devnum); | 682 | dev->udev->bus->busnum, dev->udev->devnum); |
| @@ -238,6 +238,15 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
| 238 | if (desc->mux_usecount) | 238 | if (desc->mux_usecount) |
| 239 | return NULL; | 239 | return NULL; |
| 240 | } | 240 | } |
| 241 | + | ||
| 242 | + if (gpio_range) { | ||
| 243 | + owner = desc->gpio_owner; | ||
| 244 | + desc->gpio_owner = NULL; | ||
| 245 | + } else { | ||
| 246 | + owner = desc->mux_owner; | ||
| 247 | + desc->mux_owner = NULL; | ||
| 248 | + desc->mux_setting = NULL; | ||
| 249 | + } | ||
| 241 | } | 250 | } |
| 242 | 251 | ||
| 243 | /* | 252 | /* |
| @@ -249,17 +258,6 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
| 249 | else if (ops->free) | 258 | else if (ops->free) |
| 250 | ops->free(pctldev, pin); | 259 | ops->free(pctldev, pin); |
| 251 | 260 | ||
| 252 | - scoped_guard(mutex, &desc->mux_lock) { | ||
| 253 | - if (gpio_range) { | ||
| 254 | - owner = desc->gpio_owner; | ||
| 255 | - desc->gpio_owner = NULL; | ||
| 256 | - } else { | ||
| 257 | - owner = desc->mux_owner; | ||
| 258 | - desc->mux_owner = NULL; | ||
| 259 | - desc->mux_setting = NULL; | ||
| 260 | - } | ||
| 261 | - } | ||
| 262 | - | ||
| 263 | module_put(pctldev->owner); | 261 | module_put(pctldev->owner); |
| 264 | 262 | ||
| 265 | return owner; | 263 | return owner; |
| @@ -2489,6 +2489,11 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, | |||
| 2489 | if (!cdev->os_desc_req->buf) { | 2489 | if (!cdev->os_desc_req->buf) { |
| 2490 | ret = -ENOMEM; | 2490 | ret = -ENOMEM; |
| 2491 | usb_ep_free_request(ep0, cdev->os_desc_req); | 2491 | usb_ep_free_request(ep0, cdev->os_desc_req); |
| 2492 | + /* | ||
| 2493 | + * Set os_desc_req to NULL so that composite_dev_cleanup() | ||
| 2494 | + * will not try to free it again. | ||
| 2495 | + */ | ||
| 2496 | + cdev->os_desc_req = NULL; | ||
| 2492 | goto end; | 2497 | goto end; |
| 2493 | } | 2498 | } |
| 2494 | cdev->os_desc_req->context = cdev; | 2499 | cdev->os_desc_req->context = cdev; |
| @@ -804,4 +804,5 @@ int exfat_create_upcase_table(struct super_block *sb) | |||
| 804 | void exfat_free_upcase_table(struct exfat_sb_info *sbi) | 804 | void exfat_free_upcase_table(struct exfat_sb_info *sbi) |
| 805 | { | 805 | { |
| 806 | kvfree(sbi->vol_utbl); | 806 | kvfree(sbi->vol_utbl); |
| 807 | + sbi->vol_utbl = NULL; | ||
| 807 | } | 808 | } |
| @@ -298,7 +298,11 @@ static int ext4_create_inline_data(handle_t *handle, | |||
| 298 | if (error) | 298 | if (error) |
| 299 | goto out; | 299 | goto out; |
| 300 | 300 | ||
| 301 | - BUG_ON(!is.s.not_found); | 301 | + if (!is.s.not_found) { |
| 302 | + EXT4_ERROR_INODE(inode, "unexpected inline data xattr"); | ||
| 303 | + error = -EFSCORRUPTED; | ||
| 304 | + goto out; | ||
| 305 | + } | ||
| 302 | 306 | ||
| 303 | error = ext4_xattr_ibody_set(handle, inode, &i, &is); | 307 | error = ext4_xattr_ibody_set(handle, inode, &i, &is); |
| 304 | if (error) { | 308 | if (error) { |
| @@ -349,7 +353,11 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode, | |||
| 349 | if (error) | 353 | if (error) |
| 350 | goto out; | 354 | goto out; |
| 351 | 355 | ||
| 352 | - BUG_ON(is.s.not_found); | 356 | + if (is.s.not_found) { |
| 357 | + EXT4_ERROR_INODE(inode, "missing inline data xattr"); | ||
| 358 | + error = -EFSCORRUPTED; | ||
| 359 | + goto out; | ||
| 360 | + } | ||
| 353 | 361 | ||
| 354 | len -= EXT4_MIN_INLINE_DATA_SIZE; | 362 | len -= EXT4_MIN_INLINE_DATA_SIZE; |
| 355 | value = kzalloc(len, GFP_NOFS); | 363 | value = kzalloc(len, GFP_NOFS); |
| @@ -1966,7 +1974,12 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline) | |||
| 1966 | if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) | 1974 | if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) |
| 1967 | goto out_error; | 1975 | goto out_error; |
| 1968 | 1976 | ||
| 1969 | - BUG_ON(is.s.not_found); | 1977 | + if (is.s.not_found) { |
| 1978 | + EXT4_ERROR_INODE(inode, | ||
| 1979 | + "missing inline data xattr"); | ||
| 1980 | + err = -EFSCORRUPTED; | ||
| 1981 | + goto out_error; | ||
| 1982 | + } | ||
| 1970 | 1983 | ||
| 1971 | value_len = le32_to_cpu(is.s.here->e_value_size); | 1984 | value_len = le32_to_cpu(is.s.here->e_value_size); |
| 1972 | value = kmalloc(value_len, GFP_NOFS); | 1985 | value = kmalloc(value_len, GFP_NOFS); |
| @@ -382,7 +382,7 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) | |||
| 382 | struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; | 382 | struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; |
| 383 | struct extent_tree *et; | 383 | struct extent_tree *et; |
| 384 | struct extent_node *en; | 384 | struct extent_node *en; |
| 385 | - struct extent_info ei; | 385 | + struct extent_info ei = {0}; |
| 386 | 386 | ||
| 387 | if (!__may_extent_tree(inode, EX_READ)) { | 387 | if (!__may_extent_tree(inode, EX_READ)) { |
| 388 | /* drop largest read extent */ | 388 | /* drop largest read extent */ |
| @@ -934,8 +934,12 @@ void f2fs_evict_inode(struct inode *inode) | |||
| 934 | if (likely(!f2fs_cp_error(sbi) && | 934 | if (likely(!f2fs_cp_error(sbi) && |
| 935 | !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | 935 | !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) |
| 936 | f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); | 936 | f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); |
| 937 | - else | 937 | + |
| 938 | - f2fs_inode_synced(inode); | 938 | + /* |
| 939 | + * anyway, it needs to remove the inode from sbi->inode_list[DIRTY_META] | ||
| 940 | + * list to avoid UAF in f2fs_sync_inode_meta() during checkpoint. | ||
| 941 | + */ | ||
| 942 | + f2fs_inode_synced(inode); | ||
| 939 | 943 | ||
| 940 | /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ | 944 | /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ |
| 941 | if (inode->i_ino) | 945 | if (inode->i_ino) |
| @@ -567,6 +567,8 @@ static void pde_set_flags(struct proc_dir_entry *pde) | |||
| 567 | if (pde->proc_ops->proc_compat_ioctl) | 567 | if (pde->proc_ops->proc_compat_ioctl) |
| 568 | pde->flags |= PROC_ENTRY_proc_compat_ioctl; | 568 | pde->flags |= PROC_ENTRY_proc_compat_ioctl; |
| 569 | 569 | ||
| 570 | + if (pde->proc_ops->proc_lseek) | ||
| 571 | + pde->flags |= PROC_ENTRY_proc_lseek; | ||
| 570 | } | 572 | } |
| 571 | 573 | ||
| 572 | struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, | 574 | struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, |
| @@ -494,7 +494,7 @@ static int proc_reg_open(struct inode *inode, struct file *file) | |||
| 494 | typeof_member(struct proc_ops, proc_release) release; | 494 | typeof_member(struct proc_ops, proc_release) release; |
| 495 | struct pde_opener *pdeo; | 495 | struct pde_opener *pdeo; |
| 496 | 496 | ||
| 497 | - if (!pde->proc_ops->proc_lseek) | 497 | + if (!pde_has_proc_lseek(pde)) |
| 498 | file->f_mode &= ~FMODE_LSEEK; | 498 | file->f_mode &= ~FMODE_LSEEK; |
| 499 | 499 | ||
| 500 | if (pde_is_permanent(pde)) { | 500 | if (pde_is_permanent(pde)) { |
| @@ -98,6 +98,11 @@ static inline bool pde_has_proc_compat_ioctl(const struct proc_dir_entry *pde) | |||
| 98 | 98 | ||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | +static inline bool pde_has_proc_lseek(const struct proc_dir_entry *pde) | ||
| 102 | +{ | ||
| 103 | + return pde->flags & PROC_ENTRY_proc_lseek; | ||
| 104 | +} | ||
| 105 | + | ||
| 101 | extern struct kmem_cache *proc_dir_entry_cache; | 106 | extern struct kmem_cache *proc_dir_entry_cache; |
| 102 | void pde_free(struct proc_dir_entry *pde); | 107 | void pde_free(struct proc_dir_entry *pde); |
| 103 | 108 | ||
| @@ -27,6 +27,7 @@ enum { | |||
| 27 | 27 | ||
| 28 | PROC_ENTRY_proc_read_iter = 1U << 1, | 28 | PROC_ENTRY_proc_read_iter = 1U << 1, |
| 29 | PROC_ENTRY_proc_compat_ioctl = 1U << 2, | 29 | PROC_ENTRY_proc_compat_ioctl = 1U << 2, |
| 30 | + PROC_ENTRY_proc_lseek = 1U << 3, | ||
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | struct proc_ops { | 33 | struct proc_ops { |
| @@ -466,6 +466,16 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk, | |||
| 466 | { | 466 | { |
| 467 | netdev_features_t features = NETIF_F_SG; | 467 | netdev_features_t features = NETIF_F_SG; |
| 468 | struct sk_buff *segs; | 468 | struct sk_buff *segs; |
| 469 | + int drop_count; | ||
| 470 | + | ||
| 471 | + /* | ||
| 472 | + * Segmentation in UDP receive path is only for UDP GRO, drop udp | ||
| 473 | + * fragmentation offload (UFO) packets. | ||
| 474 | + */ | ||
| 475 | + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) { | ||
| 476 | + drop_count = 1; | ||
| 477 | + goto drop; | ||
| 478 | + } | ||
| 469 | 479 | ||
| 470 | /* Avoid csum recalculation by skb_segment unless userspace explicitly | 480 | /* Avoid csum recalculation by skb_segment unless userspace explicitly |
| 471 | * asks for the final checksum values | 481 | * asks for the final checksum values |
| @@ -489,16 +499,18 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk, | |||
| 489 | */ | 499 | */ |
| 490 | segs = __skb_gso_segment(skb, features, false); | 500 | segs = __skb_gso_segment(skb, features, false); |
| 491 | if (IS_ERR_OR_NULL(segs)) { | 501 | if (IS_ERR_OR_NULL(segs)) { |
| 492 | - int segs_nr = skb_shinfo(skb)->gso_segs; | 502 | + drop_count = skb_shinfo(skb)->gso_segs; |
| 493 | - | 503 | + goto drop; |
| 494 | - atomic_add(segs_nr, &sk->sk_drops); | ||
| 495 | - SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, segs_nr); | ||
| 496 | - kfree_skb(skb); | ||
| 497 | - return NULL; | ||
| 498 | } | 504 | } |
| 499 | 505 | ||
| 500 | consume_skb(skb); | 506 | consume_skb(skb); |
| 501 | return segs; | 507 | return segs; |
| 508 | + | ||
| 509 | +drop: | ||
| 510 | + atomic_add(drop_count, &sk->sk_drops); | ||
| 511 | + SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, drop_count); | ||
| 512 | + kfree_skb(skb); | ||
| 513 | + return NULL; | ||
| 502 | } | 514 | } |
| 503 | 515 | ||
| 504 | static inline void udp_post_segment_fix_csum(struct sk_buff *skb) | 516 | static inline void udp_post_segment_fix_csum(struct sk_buff *skb) |
| @@ -4058,13 +4058,17 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 4058 | } else { | 4058 | } else { |
| 4059 | iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); | 4059 | iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); |
| 4060 | } | 4060 | } |
| 4061 | + } else { | ||
| 4062 | + if (hash) | ||
| 4063 | + iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash); | ||
| 4064 | + else | ||
| 4065 | + iter->hash = EMPTY_HASH; | ||
| 4066 | + } | ||
| 4061 | 4067 | ||
| 4062 | - if (!iter->hash) { | 4068 | + if (!iter->hash) { |
| 4063 | - trace_parser_put(&iter->parser); | 4069 | + trace_parser_put(&iter->parser); |
| 4064 | - goto out_unlock; | 4070 | + goto out_unlock; |
| 4065 | - } | 4071 | + } |
| 4066 | - } else | ||
| 4067 | - iter->hash = hash; | ||
| 4068 | 4072 | ||
| 4069 | ret = 0; | 4073 | ret = 0; |
| 4070 | 4074 | ||
| @@ -5922,9 +5926,6 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 5922 | ftrace_hash_move_and_update_ops(iter->ops, orig_hash, | 5926 | ftrace_hash_move_and_update_ops(iter->ops, orig_hash, |
| 5923 | iter->hash, filter_hash); | 5927 | iter->hash, filter_hash); |
| 5924 | mutex_unlock(&ftrace_lock); | 5928 | mutex_unlock(&ftrace_lock); |
| 5925 | - } else { | ||
| 5926 | - /* For read only, the hash is the ops hash */ | ||
| 5927 | - iter->hash = NULL; | ||
| 5928 | } | 5929 | } |
| 5929 | 5930 | ||
| 5930 | mutex_unlock(&iter->ops->func_hash->regex_lock); | 5931 | mutex_unlock(&iter->ops->func_hash->regex_lock); |
| @@ -64,13 +64,14 @@ void fprop_global_destroy(struct fprop_global *p) | |||
| 64 | bool fprop_new_period(struct fprop_global *p, int periods) | 64 | bool fprop_new_period(struct fprop_global *p, int periods) |
| 65 | { | 65 | { |
| 66 | s64 events = percpu_counter_sum(&p->events); | 66 | s64 events = percpu_counter_sum(&p->events); |
| 67 | + unsigned long flags; | ||
| 67 | 68 | ||
| 68 | /* | 69 | /* |
| 69 | * Don't do anything if there are no events. | 70 | * Don't do anything if there are no events. |
| 70 | */ | 71 | */ |
| 71 | if (events <= 1) | 72 | if (events <= 1) |
| 72 | return false; | 73 | return false; |
| 73 | - preempt_disable_nested(); | 74 | + local_irq_save(flags); |
| 74 | write_seqcount_begin(&p->sequence); | 75 | write_seqcount_begin(&p->sequence); |
| 75 | if (periods < 64) | 76 | if (periods < 64) |
| 76 | events -= events >> periods; | 77 | events -= events >> periods; |
| @@ -78,7 +79,7 @@ bool fprop_new_period(struct fprop_global *p, int periods) | |||
| 78 | percpu_counter_add(&p->events, -events); | 79 | percpu_counter_add(&p->events, -events); |
| 79 | p->period += periods; | 80 | p->period += periods; |
| 80 | write_seqcount_end(&p->sequence); | 81 | write_seqcount_end(&p->sequence); |
| 81 | - preempt_enable_nested(); | 82 | + local_irq_restore(flags); |
| 82 | 83 | ||
| 83 | return true; | 84 | return true; |
| 84 | } | 85 | } |
| @@ -1684,17 +1684,15 @@ static void l2cap_info_timeout(struct work_struct *work) | |||
| 1684 | 1684 | ||
| 1685 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1685 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1686 | { | 1686 | { |
| 1687 | - struct hci_dev *hdev = conn->hcon->hdev; | ||
| 1688 | int ret; | 1687 | int ret; |
| 1689 | 1688 | ||
| 1690 | /* We need to check whether l2cap_conn is registered. If it is not, we | 1689 | /* We need to check whether l2cap_conn is registered. If it is not, we |
| 1691 | - * must not register the l2cap_user. l2cap_conn_del() is unregisters | 1690 | + * must not register the l2cap_user. l2cap_conn_del() unregisters |
| 1692 | - * l2cap_conn objects, but doesn't provide its own locking. Instead, it | 1691 | + * l2cap_conn objects under conn->lock, and we use the same lock here |
| 1693 | - * relies on the parent hci_conn object to be locked. This itself relies | 1692 | + * to protect access to conn->users and conn->hchan. |
| 1694 | - * on the hci_dev object to be locked. So we must lock the hci device | 1693 | + */ |
| 1695 | - * here, too. */ | ||
| 1696 | 1694 | ||
| 1697 | - hci_dev_lock(hdev); | 1695 | + mutex_lock(&conn->lock); |
| 1698 | 1696 | ||
| 1699 | if (!list_empty(&user->list)) { | 1697 | if (!list_empty(&user->list)) { |
| 1700 | ret = -EINVAL; | 1698 | ret = -EINVAL; |
| @@ -1715,16 +1713,14 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) | |||
| 1715 | ret = 0; | 1713 | ret = 0; |
| 1716 | 1714 | ||
| 1717 | out_unlock: | 1715 | out_unlock: |
| 1718 | - hci_dev_unlock(hdev); | 1716 | + mutex_unlock(&conn->lock); |
| 1719 | return ret; | 1717 | return ret; |
| 1720 | } | 1718 | } |
| 1721 | EXPORT_SYMBOL(l2cap_register_user); | 1719 | EXPORT_SYMBOL(l2cap_register_user); |
| 1722 | 1720 | ||
| 1723 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1721 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1724 | { | 1722 | { |
| 1725 | - struct hci_dev *hdev = conn->hcon->hdev; | 1723 | + mutex_lock(&conn->lock); |
| 1726 | - | ||
| 1727 | - hci_dev_lock(hdev); | ||
| 1728 | 1724 | ||
| 1729 | if (list_empty(&user->list)) | 1725 | if (list_empty(&user->list)) |
| 1730 | goto out_unlock; | 1726 | goto out_unlock; |
| @@ -1733,7 +1729,7 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) | |||
| 1733 | user->remove(conn, user); | 1729 | user->remove(conn, user); |
| 1734 | 1730 | ||
| 1735 | out_unlock: | 1731 | out_unlock: |
| 1736 | - hci_dev_unlock(hdev); | 1732 | + mutex_unlock(&conn->lock); |
| 1737 | } | 1733 | } |
| 1738 | EXPORT_SYMBOL(l2cap_unregister_user); | 1734 | EXPORT_SYMBOL(l2cap_unregister_user); |
| 1739 | 1735 | ||
| @@ -243,6 +243,8 @@ static void napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb) | |||
| 243 | goto out; | 243 | goto out; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | + /* NICs can feed encapsulated packets into GRO */ | ||
| 247 | + skb->encapsulation = 0; | ||
| 246 | rcu_read_lock(); | 248 | rcu_read_lock(); |
| 247 | list_for_each_entry_rcu(ptype, head, list) { | 249 | list_for_each_entry_rcu(ptype, head, list) { |
| 248 | if (ptype->type != type || !ptype->callbacks.gro_complete) | 250 | if (ptype->type != type || !ptype->callbacks.gro_complete) |
| @@ -4340,12 +4340,14 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, | |||
| 4340 | { | 4340 | { |
| 4341 | struct sk_buff *list_skb = skb_shinfo(skb)->frag_list; | 4341 | struct sk_buff *list_skb = skb_shinfo(skb)->frag_list; |
| 4342 | unsigned int tnl_hlen = skb_tnl_header_len(skb); | 4342 | unsigned int tnl_hlen = skb_tnl_header_len(skb); |
| 4343 | - unsigned int delta_truesize = 0; | ||
| 4344 | unsigned int delta_len = 0; | 4343 | unsigned int delta_len = 0; |
| 4345 | struct sk_buff *tail = NULL; | 4344 | struct sk_buff *tail = NULL; |
| 4346 | struct sk_buff *nskb, *tmp; | 4345 | struct sk_buff *nskb, *tmp; |
| 4347 | int len_diff, err; | 4346 | int len_diff, err; |
| 4348 | 4347 | ||
| 4348 | + /* Only skb_gro_receive_list generated skbs arrive here */ | ||
| 4349 | + DEBUG_NET_WARN_ON_ONCE(!(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)); | ||
| 4350 | + | ||
| 4349 | skb_push(skb, -skb_network_offset(skb) + offset); | 4351 | skb_push(skb, -skb_network_offset(skb) + offset); |
| 4350 | 4352 | ||
| 4351 | /* Ensure the head is writeable before touching the shared info */ | 4353 | /* Ensure the head is writeable before touching the shared info */ |
| @@ -4359,8 +4361,9 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, | |||
| 4359 | nskb = list_skb; | 4361 | nskb = list_skb; |
| 4360 | list_skb = list_skb->next; | 4362 | list_skb = list_skb->next; |
| 4361 | 4363 | ||
| 4364 | + DEBUG_NET_WARN_ON_ONCE(nskb->sk); | ||
| 4365 | + | ||
| 4362 | err = 0; | 4366 | err = 0; |
| 4363 | - delta_truesize += nskb->truesize; | ||
| 4364 | if (skb_shared(nskb)) { | 4367 | if (skb_shared(nskb)) { |
| 4365 | tmp = skb_clone(nskb, GFP_ATOMIC); | 4368 | tmp = skb_clone(nskb, GFP_ATOMIC); |
| 4366 | if (tmp) { | 4369 | if (tmp) { |
| @@ -4403,7 +4406,6 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, | |||
| 4403 | goto err_linearize; | 4406 | goto err_linearize; |
| 4404 | } | 4407 | } |
| 4405 | 4408 | ||
| 4406 | - skb->truesize = skb->truesize - delta_truesize; | ||
| 4407 | skb->data_len = skb->data_len - delta_len; | 4409 | skb->data_len = skb->data_len - delta_len; |
| 4408 | skb->len = skb->len - delta_len; | 4410 | skb->len = skb->len - delta_len; |
| 4409 | 4411 | ||
| @@ -1240,7 +1240,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, | |||
| 1240 | &rt->fib6_siblings, | 1240 | &rt->fib6_siblings, |
| 1241 | fib6_siblings) | 1241 | fib6_siblings) |
| 1242 | sibling->fib6_nsiblings--; | 1242 | sibling->fib6_nsiblings--; |
| 1243 | - rt->fib6_nsiblings = 0; | 1243 | + WRITE_ONCE(rt->fib6_nsiblings, 0); |
| 1244 | list_del_rcu(&rt->fib6_siblings); | 1244 | list_del_rcu(&rt->fib6_siblings); |
| 1245 | rt6_multipath_rebalance(next_sibling); | 1245 | rt6_multipath_rebalance(next_sibling); |
| 1246 | return err; | 1246 | return err; |
| @@ -1953,7 +1953,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn, | |||
| 1953 | list_for_each_entry_safe(sibling, next_sibling, | 1953 | list_for_each_entry_safe(sibling, next_sibling, |
| 1954 | &rt->fib6_siblings, fib6_siblings) | 1954 | &rt->fib6_siblings, fib6_siblings) |
| 1955 | sibling->fib6_nsiblings--; | 1955 | sibling->fib6_nsiblings--; |
| 1956 | - rt->fib6_nsiblings = 0; | 1956 | + WRITE_ONCE(rt->fib6_nsiblings, 0); |
| 1957 | list_del_rcu(&rt->fib6_siblings); | 1957 | list_del_rcu(&rt->fib6_siblings); |
| 1958 | rt6_multipath_rebalance(next_sibling); | 1958 | rt6_multipath_rebalance(next_sibling); |
| 1959 | } | 1959 | } |
| @@ -1566,8 +1566,8 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) | |||
| 1566 | memcpy(&n, ((u8 *)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); | 1566 | memcpy(&n, ((u8 *)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); |
| 1567 | mtu = ntohl(n); | 1567 | mtu = ntohl(n); |
| 1568 | 1568 | ||
| 1569 | - if (in6_dev->ra_mtu != mtu) { | 1569 | + if (READ_ONCE(in6_dev->ra_mtu) != mtu) { |
| 1570 | - in6_dev->ra_mtu = mtu; | 1570 | + WRITE_ONCE(in6_dev->ra_mtu, mtu); |
| 1571 | send_ifinfo_notify = true; | 1571 | send_ifinfo_notify = true; |
| 1572 | } | 1572 | } |
| 1573 | 1573 | ||
| @@ -5577,32 +5577,34 @@ static int rt6_nh_nlmsg_size(struct fib6_nh *nh, void *arg) | |||
| 5577 | 5577 | ||
| 5578 | static size_t rt6_nlmsg_size(struct fib6_info *f6i) | 5578 | static size_t rt6_nlmsg_size(struct fib6_info *f6i) |
| 5579 | { | 5579 | { |
| 5580 | + struct fib6_info *sibling; | ||
| 5581 | + struct fib6_nh *nh; | ||
| 5580 | int nexthop_len; | 5582 | int nexthop_len; |
| 5581 | 5583 | ||
| 5582 | if (f6i->nh) { | 5584 | if (f6i->nh) { |
| 5583 | nexthop_len = nla_total_size(4); /* RTA_NH_ID */ | 5585 | nexthop_len = nla_total_size(4); /* RTA_NH_ID */ |
| 5584 | nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size, | 5586 | nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size, |
| 5585 | &nexthop_len); | 5587 | &nexthop_len); |
| 5586 | - } else { | 5588 | + goto common; |
| 5587 | - struct fib6_nh *nh = f6i->fib6_nh; | ||
| 5588 | - struct fib6_info *sibling; | ||
| 5589 | - | ||
| 5590 | - nexthop_len = 0; | ||
| 5591 | - if (f6i->fib6_nsiblings) { | ||
| 5592 | - rt6_nh_nlmsg_size(nh, &nexthop_len); | ||
| 5593 | - | ||
| 5594 | - rcu_read_lock(); | ||
| 5595 | - | ||
| 5596 | - list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, | ||
| 5597 | - fib6_siblings) { | ||
| 5598 | - rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); | ||
| 5599 | - } | ||
| 5600 | - | ||
| 5601 | - rcu_read_unlock(); | ||
| 5602 | - } | ||
| 5603 | - nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); | ||
| 5604 | } | 5589 | } |
| 5605 | 5590 | ||
| 5591 | + rcu_read_lock(); | ||
| 5592 | +retry: | ||
| 5593 | + nh = f6i->fib6_nh; | ||
| 5594 | + nexthop_len = 0; | ||
| 5595 | + if (READ_ONCE(f6i->fib6_nsiblings)) { | ||
| 5596 | + rt6_nh_nlmsg_size(nh, &nexthop_len); | ||
| 5597 | + | ||
| 5598 | + list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, | ||
| 5599 | + fib6_siblings) { | ||
| 5600 | + rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); | ||
| 5601 | + if (!READ_ONCE(f6i->fib6_nsiblings)) | ||
| 5602 | + goto retry; | ||
| 5603 | + } | ||
| 5604 | + } | ||
| 5605 | + rcu_read_unlock(); | ||
| 5606 | + nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); | ||
| 5607 | +common: | ||
| 5606 | return NLMSG_ALIGN(sizeof(struct rtmsg)) | 5608 | return NLMSG_ALIGN(sizeof(struct rtmsg)) |
| 5607 | + nla_total_size(16) /* RTA_SRC */ | 5609 | + nla_total_size(16) /* RTA_SRC */ |
| 5608 | + nla_total_size(16) /* RTA_DST */ | 5610 | + nla_total_size(16) /* RTA_DST */ |
| @@ -1253,8 +1253,6 @@ static void l2tp_tunnel_del_work(struct work_struct *work) | |||
| 1253 | { | 1253 | { |
| 1254 | struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel, | 1254 | struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel, |
| 1255 | del_work); | 1255 | del_work); |
| 1256 | - struct sock *sk = tunnel->sock; | ||
| 1257 | - struct socket *sock = sk->sk_socket; | ||
| 1258 | 1256 | ||
| 1259 | l2tp_tunnel_closeall(tunnel); | 1257 | l2tp_tunnel_closeall(tunnel); |
| 1260 | 1258 | ||
| @@ -1262,6 +1260,8 @@ static void l2tp_tunnel_del_work(struct work_struct *work) | |||
| 1262 | * the sk API to release it here. | 1260 | * the sk API to release it here. |
| 1263 | */ | 1261 | */ |
| 1264 | if (tunnel->fd < 0) { | 1262 | if (tunnel->fd < 0) { |
| 1263 | + struct socket *sock = tunnel->sock->sk_socket; | ||
| 1264 | + | ||
| 1265 | if (sock) { | 1265 | if (sock) { |
| 1266 | kernel_sock_shutdown(sock, SHUT_RDWR); | 1266 | kernel_sock_shutdown(sock, SHUT_RDWR); |
| 1267 | sock_release(sock); | 1267 | sock_release(sock); |
| @@ -5847,6 +5847,9 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata, | |||
| 5847 | control = le16_to_cpu(prof->control); | 5847 | control = le16_to_cpu(prof->control); |
| 5848 | link_id = control & IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID; | 5848 | link_id = control & IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID; |
| 5849 | 5849 | ||
| 5850 | + if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) | ||
| 5851 | + continue; | ||
| 5852 | + | ||
| 5850 | removed_links |= BIT(link_id); | 5853 | removed_links |= BIT(link_id); |
| 5851 | 5854 | ||
| 5852 | /* the MAC address should not be included, but handle it */ | 5855 | /* the MAC address should not be included, but handle it */ |
| @@ -48,6 +48,9 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
| 48 | struct sta_info *sta; | 48 | struct sta_info *sta; |
| 49 | int band; | 49 | int band; |
| 50 | 50 | ||
| 51 | + if (!ifocb->joined) | ||
| 52 | + return; | ||
| 53 | + | ||
| 51 | /* XXX: Consider removing the least recently used entry and | 54 | /* XXX: Consider removing the least recently used entry and |
| 52 | * allow new one to be added. | 55 | * allow new one to be added. |
| 53 | */ | 56 | */ |
| @@ -1450,7 +1450,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
| 1450 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | 1450 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) |
| 1451 | return -ENOTSUPP; | 1451 | return -ENOTSUPP; |
| 1452 | 1452 | ||
| 1453 | - if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1453 | + if (sdata->vif.type != NL80211_IFTYPE_STATION || !sdata->vif.cfg.assoc) |
| 1454 | return -EINVAL; | 1454 | return -EINVAL; |
| 1455 | 1455 | ||
| 1456 | switch (oper) { | 1456 | switch (oper) { |
| @@ -17,7 +17,7 @@ static unsigned int nf_hook_run_bpf(void *bpf_prog, struct sk_buff *skb, | |||
| 17 | .skb = skb, | 17 | .skb = skb, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | - return bpf_prog_run(prog, &ctx); | 20 | + return bpf_prog_run_pin_on_cpu(prog, &ctx); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | struct bpf_nf_link { | 23 | struct bpf_nf_link { |
| @@ -1205,7 +1205,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx) | |||
| 1205 | if (flags & ~NFT_TABLE_F_MASK) | 1205 | if (flags & ~NFT_TABLE_F_MASK) |
| 1206 | return -EOPNOTSUPP; | 1206 | return -EOPNOTSUPP; |
| 1207 | 1207 | ||
| 1208 | - if (flags == ctx->table->flags) | 1208 | + if (flags == (ctx->table->flags & NFT_TABLE_F_MASK)) |
| 1209 | return 0; | 1209 | return 0; |
| 1210 | 1210 | ||
| 1211 | if ((nft_table_has_owner(ctx->table) && | 1211 | if ((nft_table_has_owner(ctx->table) && |
| @@ -257,20 +257,47 @@ svc_tcp_sock_process_cmsg(struct socket *sock, struct msghdr *msg, | |||
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static int | 259 | static int |
| 260 | -svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg) | 260 | +svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags) |
| 261 | { | 261 | { |
| 262 | union { | 262 | union { |
| 263 | struct cmsghdr cmsg; | 263 | struct cmsghdr cmsg; |
| 264 | u8 buf[CMSG_SPACE(sizeof(u8))]; | 264 | u8 buf[CMSG_SPACE(sizeof(u8))]; |
| 265 | } u; | 265 | } u; |
| 266 | - struct socket *sock = svsk->sk_sock; | 266 | + u8 alert[2]; |
| 267 | + struct kvec alert_kvec = { | ||
| 268 | + .iov_base = alert, | ||
| 269 | + .iov_len = sizeof(alert), | ||
| 270 | + }; | ||
| 271 | + struct msghdr msg = { | ||
| 272 | + .msg_flags = *msg_flags, | ||
| 273 | + .msg_control = &u, | ||
| 274 | + .msg_controllen = sizeof(u), | ||
| 275 | + }; | ||
| 267 | int ret; | 276 | int ret; |
| 268 | 277 | ||
| 269 | - msg->msg_control = &u; | 278 | + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1, |
| 270 | - msg->msg_controllen = sizeof(u); | 279 | + alert_kvec.iov_len); |
| 280 | + ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT); | ||
| 281 | + if (ret > 0 && | ||
| 282 | + tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) { | ||
| 283 | + iov_iter_revert(&msg.msg_iter, ret); | ||
| 284 | + ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN); | ||
| 285 | + } | ||
| 286 | + return ret; | ||
| 287 | +} | ||
| 288 | + | ||
| 289 | +static int | ||
| 290 | +svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg) | ||
| 291 | +{ | ||
| 292 | + int ret; | ||
| 293 | + struct socket *sock = svsk->sk_sock; | ||
| 294 | + | ||
| 271 | ret = sock_recvmsg(sock, msg, MSG_DONTWAIT); | 295 | ret = sock_recvmsg(sock, msg, MSG_DONTWAIT); |
| 272 | - if (unlikely(msg->msg_controllen != sizeof(u))) | 296 | + if (msg->msg_flags & MSG_CTRUNC) { |
| 273 | - ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret); | 297 | + msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); |
| 298 | + if (ret == 0 || ret == -EIO) | ||
| 299 | + ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags); | ||
| 300 | + } | ||
| 274 | return ret; | 301 | return ret; |
| 275 | } | 302 | } |
| 276 | 303 | ||
| @@ -321,7 +348,7 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen, | |||
| 321 | iov_iter_advance(&msg.msg_iter, seek); | 348 | iov_iter_advance(&msg.msg_iter, seek); |
| 322 | buflen -= seek; | 349 | buflen -= seek; |
| 323 | } | 350 | } |
| 324 | - len = svc_tcp_sock_recv_cmsg(svsk, &msg); | 351 | + len = svc_tcp_sock_recvmsg(svsk, &msg); |
| 325 | if (len > 0) | 352 | if (len > 0) |
| 326 | svc_flush_bvec(bvec, len, seek); | 353 | svc_flush_bvec(bvec, len, seek); |
| 327 | 354 | ||
| @@ -1019,7 +1046,7 @@ static ssize_t svc_tcp_read_marker(struct svc_sock *svsk, | |||
| 1019 | iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen; | 1046 | iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen; |
| 1020 | iov.iov_len = want; | 1047 | iov.iov_len = want; |
| 1021 | iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want); | 1048 | iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want); |
| 1022 | - len = svc_tcp_sock_recv_cmsg(svsk, &msg); | 1049 | + len = svc_tcp_sock_recvmsg(svsk, &msg); |
| 1023 | if (len < 0) | 1050 | if (len < 0) |
| 1024 | return len; | 1051 | return len; |
| 1025 | svsk->sk_tcplen += len; | 1052 | svsk->sk_tcplen += len; |
| @@ -358,7 +358,7 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp) | |||
| 358 | 358 | ||
| 359 | static int | 359 | static int |
| 360 | xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, | 360 | xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, |
| 361 | - struct cmsghdr *cmsg, int ret) | 361 | + unsigned int *msg_flags, struct cmsghdr *cmsg, int ret) |
| 362 | { | 362 | { |
| 363 | u8 content_type = tls_get_record_type(sock->sk, cmsg); | 363 | u8 content_type = tls_get_record_type(sock->sk, cmsg); |
| 364 | u8 level, description; | 364 | u8 level, description; |
| @@ -371,7 +371,7 @@ xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, | |||
| 371 | * record, even though there might be more frames | 371 | * record, even though there might be more frames |
| 372 | * waiting to be decrypted. | 372 | * waiting to be decrypted. |
| 373 | */ | 373 | */ |
| 374 | - msg->msg_flags &= ~MSG_EOR; | 374 | + *msg_flags &= ~MSG_EOR; |
| 375 | break; | 375 | break; |
| 376 | case TLS_RECORD_TYPE_ALERT: | 376 | case TLS_RECORD_TYPE_ALERT: |
| 377 | tls_alert_recv(sock->sk, msg, &level, &description); | 377 | tls_alert_recv(sock->sk, msg, &level, &description); |
| @@ -386,19 +386,33 @@ xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, | |||
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | static int | 388 | static int |
| 389 | -xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags) | 389 | +xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) |
| 390 | { | 390 | { |
| 391 | union { | 391 | union { |
| 392 | struct cmsghdr cmsg; | 392 | struct cmsghdr cmsg; |
| 393 | u8 buf[CMSG_SPACE(sizeof(u8))]; | 393 | u8 buf[CMSG_SPACE(sizeof(u8))]; |
| 394 | } u; | 394 | } u; |
| 395 | + u8 alert[2]; | ||
| 396 | + struct kvec alert_kvec = { | ||
| 397 | + .iov_base = alert, | ||
| 398 | + .iov_len = sizeof(alert), | ||
| 399 | + }; | ||
| 400 | + struct msghdr msg = { | ||
| 401 | + .msg_flags = *msg_flags, | ||
| 402 | + .msg_control = &u, | ||
| 403 | + .msg_controllen = sizeof(u), | ||
| 404 | + }; | ||
| 395 | int ret; | 405 | int ret; |
| 396 | 406 | ||
| 397 | - msg->msg_control = &u; | 407 | + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1, |
| 398 | - msg->msg_controllen = sizeof(u); | 408 | + alert_kvec.iov_len); |
| 399 | - ret = sock_recvmsg(sock, msg, flags); | 409 | + ret = sock_recvmsg(sock, &msg, flags); |
| 400 | - if (msg->msg_controllen != sizeof(u)) | 410 | + if (ret > 0 && |
| 401 | - ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret); | 411 | + tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) { |
| 412 | + iov_iter_revert(&msg.msg_iter, ret); | ||
| 413 | + ret = xs_sock_process_cmsg(sock, &msg, msg_flags, &u.cmsg, | ||
| 414 | + -EAGAIN); | ||
| 415 | + } | ||
| 402 | return ret; | 416 | return ret; |
| 403 | } | 417 | } |
| 404 | 418 | ||
| @@ -408,7 +422,13 @@ xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek) | |||
| 408 | ssize_t ret; | 422 | ssize_t ret; |
| 409 | if (seek != 0) | 423 | if (seek != 0) |
| 410 | iov_iter_advance(&msg->msg_iter, seek); | 424 | iov_iter_advance(&msg->msg_iter, seek); |
| 411 | - ret = xs_sock_recv_cmsg(sock, msg, flags); | 425 | + ret = sock_recvmsg(sock, msg, flags); |
| 426 | + /* Handle TLS inband control message lazily */ | ||
| 427 | + if (msg->msg_flags & MSG_CTRUNC) { | ||
| 428 | + msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); | ||
| 429 | + if (ret == 0 || ret == -EIO) | ||
| 430 | + ret = xs_sock_recv_cmsg(sock, &msg->msg_flags, flags); | ||
| 431 | + } | ||
| 412 | return ret > 0 ? ret + seek : ret; | 432 | return ret > 0 ? ret + seek : ret; |
| 413 | } | 433 | } |
| 414 | 434 | ||
| @@ -434,7 +454,7 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags, | |||
| 434 | size_t count) | 454 | size_t count) |
| 435 | { | 455 | { |
| 436 | iov_iter_discard(&msg->msg_iter, ITER_DEST, count); | 456 | iov_iter_discard(&msg->msg_iter, ITER_DEST, count); |
| 437 | - return xs_sock_recv_cmsg(sock, msg, flags); | 457 | + return xs_sock_recvmsg(sock, msg, flags, 0); |
| 438 | } | 458 | } |
| 439 | 459 | ||
| 440 | 460 | ||
| @@ -1103,6 +1103,10 @@ static int compat_standard_call(struct net_device *dev, | |||
| 1103 | return ioctl_standard_call(dev, iwr, cmd, info, handler); | 1103 | return ioctl_standard_call(dev, iwr, cmd, info, handler); |
| 1104 | 1104 | ||
| 1105 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | 1105 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; |
| 1106 | + | ||
| 1107 | + /* struct iw_point has a 32bit hole on 64bit arches. */ | ||
| 1108 | + memset(&iwp, 0, sizeof(iwp)); | ||
| 1109 | + | ||
| 1106 | iwp.pointer = compat_ptr(iwp_compat->pointer); | 1110 | iwp.pointer = compat_ptr(iwp_compat->pointer); |
| 1107 | iwp.length = iwp_compat->length; | 1111 | iwp.length = iwp_compat->length; |
| 1108 | iwp.flags = iwp_compat->flags; | 1112 | iwp.flags = iwp_compat->flags; |
| @@ -228,6 +228,10 @@ int compat_private_call(struct net_device *dev, struct iwreq *iwr, | |||
| 228 | struct iw_point iwp; | 228 | struct iw_point iwp; |
| 229 | 229 | ||
| 230 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | 230 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; |
| 231 | + | ||
| 232 | + /* struct iw_point has a 32bit hole on 64bit arches. */ | ||
| 233 | + memset(&iwp, 0, sizeof(iwp)); | ||
| 234 | + | ||
| 231 | iwp.pointer = compat_ptr(iwp_compat->pointer); | 235 | iwp.pointer = compat_ptr(iwp_compat->pointer); |
| 232 | iwp.length = iwp_compat->length; | 236 | iwp.length = iwp_compat->length; |
| 233 | iwp.flags = iwp_compat->flags; | 237 | iwp.flags = iwp_compat->flags; |