diff options
author | 2017-02-26 15:45:07 -0500 | |
---|---|---|
committer | 2017-02-26 15:45:07 -0500 | |
commit | f0aebc3668307cc523caedc3499d401990fcacbc (patch) | |
tree | 5b33497d5c7bce3e84f20dcfb1f740c5ea2d9d15 | |
parent | dccp: fix freeing skb too early for IPV6_RECVPKTINFO. CVE-2017-6074 (diff) | |
download | linux-patches-f0aebc3668307cc523caedc3499d401990fcacbc.tar.gz linux-patches-f0aebc3668307cc523caedc3499d401990fcacbc.tar.bz2 linux-patches-f0aebc3668307cc523caedc3499d401990fcacbc.zip |
Linux patch 4.4.52. Removal of redundant patch.4.4-56
-rw-r--r-- | 0000_README | 8 | ||||
-rw-r--r-- | 1051_linux-4.4.52.patch | 817 | ||||
-rw-r--r-- | 1520_CVE-2017-6074-dccp-skb-freeing-fix.patch | 47 |
3 files changed, 821 insertions, 51 deletions
diff --git a/0000_README b/0000_README index 0bee2eb0..747896bd 100644 --- a/0000_README +++ b/0000_README @@ -247,6 +247,10 @@ Patch: 1050_linux-4.4.51.patch From: http://www.kernel.org Desc: Linux 4.4.51 +Patch: 1051_linux-4.4.52.patch +From: http://www.kernel.org +Desc: Linux 4.4.52 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. @@ -255,10 +259,6 @@ Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/ Desc: Enable link security restrictions by default. -Patch: 1520_CVE-2017-6074-dccp-skb-freeing-fix.patch -From: https://bugs.gentoo.org/show_bug.cgi?id=610600 -Desc: dccp: fix freeing skb too early for IPV6_RECVPKTINFO. CVE-2017-6074 - Patch: 1900_xfs-fix-suspend-to-memory.patch From: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/patch/fs/xfs/xfs_trans_ail.c?id=18f1df4e00cea2eae41f3e5515b94d1e7127b2b6 Desc: xfs: Make xfsaild freezeable again. See bug #575034. diff --git a/1051_linux-4.4.52.patch b/1051_linux-4.4.52.patch new file mode 100644 index 00000000..63d6ed79 --- /dev/null +++ b/1051_linux-4.4.52.patch @@ -0,0 +1,817 @@ +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index c360f80c3473..ca64ca566099 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1255,6 +1255,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + When zero, profiling data is discarded and associated + debugfs files are removed at module unload time. + ++ goldfish [X86] Enable the goldfish android emulator platform. ++ Don't use this when you are not running on the ++ android emulator ++ + gpt [EFI] Forces disk with valid GPT signature but + invalid Protective MBR to be treated as GPT. If the + primary GPT is corrupted, it enables the backup/alternate +diff --git a/Makefile b/Makefile +index 117357188f01..671e183bd507 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 51 ++SUBLEVEL = 52 + EXTRAVERSION = + NAME = Blurry Fish Butt + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index bb620df05d0d..64f60a48def1 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -4867,6 +4867,12 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) + if (vmx_xsaves_supported()) + vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP); + ++ if (enable_pml) { ++ ASSERT(vmx->pml_pg); ++ vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); ++ vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); ++ } ++ + return 0; + } + +@@ -7839,22 +7845,6 @@ static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2) + *info2 = vmcs_read32(VM_EXIT_INTR_INFO); + } + +-static int vmx_create_pml_buffer(struct vcpu_vmx *vmx) +-{ +- struct page *pml_pg; +- +- pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO); +- if (!pml_pg) +- return -ENOMEM; +- +- vmx->pml_pg = pml_pg; +- +- vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); +- vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); +- +- return 0; +-} +- + static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx) + { + if (vmx->pml_pg) { +@@ -8789,14 +8779,26 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) + if (err) + goto free_vcpu; + ++ err = -ENOMEM; ++ ++ /* ++ * If PML is turned on, failure on enabling PML just results in failure ++ * of creating the vcpu, therefore we can simplify PML logic (by ++ * avoiding dealing with cases, such as enabling PML partially on vcpus ++ * for the guest, etc. ++ */ ++ if (enable_pml) { ++ vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO); ++ if (!vmx->pml_pg) ++ goto uninit_vcpu; ++ } ++ + vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL); + BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0]) + > PAGE_SIZE); + +- err = -ENOMEM; +- if (!vmx->guest_msrs) { +- goto uninit_vcpu; +- } ++ if (!vmx->guest_msrs) ++ goto free_pml; + + vmx->loaded_vmcs = &vmx->vmcs01; + vmx->loaded_vmcs->vmcs = alloc_vmcs(); +@@ -8840,18 +8842,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) + vmx->nested.current_vmptr = -1ull; + vmx->nested.current_vmcs12 = NULL; + +- /* +- * If PML is turned on, failure on enabling PML just results in failure +- * of creating the vcpu, therefore we can simplify PML logic (by +- * avoiding dealing with cases, such as enabling PML partially on vcpus +- * for the guest, etc. +- */ +- if (enable_pml) { +- err = vmx_create_pml_buffer(vmx); +- if (err) +- goto free_vmcs; +- } +- + return &vmx->vcpu; + + free_vmcs: +@@ -8859,6 +8849,8 @@ free_vmcs: + free_loaded_vmcs(vmx->loaded_vmcs); + free_msrs: + kfree(vmx->guest_msrs); ++free_pml: ++ vmx_destroy_pml_buffer(vmx); + uninit_vcpu: + kvm_vcpu_uninit(&vmx->vcpu); + free_vcpu: +diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c +index 1693107a518e..0d17c0aafeb1 100644 +--- a/arch/x86/platform/goldfish/goldfish.c ++++ b/arch/x86/platform/goldfish/goldfish.c +@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = { + } + }; + ++static bool goldfish_enable __initdata; ++ ++static int __init goldfish_setup(char *str) ++{ ++ goldfish_enable = true; ++ return 0; ++} ++__setup("goldfish", goldfish_setup); ++ + static int __init goldfish_init(void) + { ++ if (!goldfish_enable) ++ return -ENODEV; ++ + platform_device_register_simple("goldfish_pdev_bus", -1, +- goldfish_pdev_bus_resources, 2); ++ goldfish_pdev_bus_resources, 2); + return 0; + } + device_initcall(goldfish_init); +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 6cfc6b200366..d8d63c38bf29 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1259,12 +1259,9 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) + + blk_queue_split(q, &bio, q->bio_split); + +- if (!is_flush_fua && !blk_queue_nomerges(q)) { +- if (blk_attempt_plug_merge(q, bio, &request_count, +- &same_queue_rq)) +- return BLK_QC_T_NONE; +- } else +- request_count = blk_plug_queued_count(q); ++ if (!is_flush_fua && !blk_queue_nomerges(q) && ++ blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq)) ++ return BLK_QC_T_NONE; + + rq = blk_mq_map_request(q, bio, &data); + if (unlikely(!rq)) +@@ -1355,9 +1352,11 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) + + blk_queue_split(q, &bio, q->bio_split); + +- if (!is_flush_fua && !blk_queue_nomerges(q) && +- blk_attempt_plug_merge(q, bio, &request_count, NULL)) +- return BLK_QC_T_NONE; ++ if (!is_flush_fua && !blk_queue_nomerges(q)) { ++ if (blk_attempt_plug_merge(q, bio, &request_count, NULL)) ++ return BLK_QC_T_NONE; ++ } else ++ request_count = blk_plug_queued_count(q); + + rq = blk_mq_map_request(q, bio, &data); + if (unlikely(!rq)) +diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c +index aac1ed3f7bb4..ad8390d2997b 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/usb.c ++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c +@@ -834,12 +834,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw) + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); ++ struct urb *urb; + + /* should after adapter start and interrupt enable. */ + set_hal_stop(rtlhal); + cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); + /* Enable software */ + SET_USB_STOP(rtlusb); ++ ++ /* free pre-allocated URBs from rtl_usb_start() */ ++ usb_kill_anchored_urbs(&rtlusb->rx_submitted); ++ ++ tasklet_kill(&rtlusb->rx_work_tasklet); ++ cancel_work_sync(&rtlpriv->works.lps_change_work); ++ ++ flush_workqueue(rtlpriv->works.rtl_wq); ++ ++ skb_queue_purge(&rtlusb->rx_queue); ++ ++ while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { ++ usb_free_coherent(urb->dev, urb->transfer_buffer_length, ++ urb->transfer_buffer, urb->transfer_dma); ++ usb_free_urb(urb); ++ } ++ + rtlpriv->cfg->ops->hw_disable(hw); + } + +@@ -1073,6 +1091,7 @@ int rtl_usb_probe(struct usb_interface *intf, + return -ENOMEM; + } + rtlpriv = hw->priv; ++ rtlpriv->hw = hw; + rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + GFP_KERNEL); + if (!rtlpriv->usb_data) +diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c +index 1f52462f4cdd..dd9ea463c2a4 100644 +--- a/drivers/platform/goldfish/pdev_bus.c ++++ b/drivers/platform/goldfish/pdev_bus.c +@@ -157,23 +157,26 @@ static int goldfish_new_pdev(void) + static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id) + { + irqreturn_t ret = IRQ_NONE; ++ + while (1) { + u32 op = readl(pdev_bus_base + PDEV_BUS_OP); +- switch (op) { +- case PDEV_BUS_OP_DONE: +- return IRQ_NONE; + ++ switch (op) { + case PDEV_BUS_OP_REMOVE_DEV: + goldfish_pdev_remove(); ++ ret = IRQ_HANDLED; + break; + + case PDEV_BUS_OP_ADD_DEV: + goldfish_new_pdev(); ++ ret = IRQ_HANDLED; + break; ++ ++ case PDEV_BUS_OP_DONE: ++ default: ++ return ret; + } +- ret = IRQ_HANDLED; + } +- return ret; + } + + static int goldfish_pdev_bus_probe(struct platform_device *pdev) +diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c +index 5836751b8203..9bb934ed2a7a 100644 +--- a/drivers/rtc/interface.c ++++ b/drivers/rtc/interface.c +@@ -748,9 +748,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); + */ + static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) + { ++ struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); ++ struct rtc_time tm; ++ ktime_t now; ++ + timer->enabled = 1; ++ __rtc_read_time(rtc, &tm); ++ now = rtc_tm_to_ktime(tm); ++ ++ /* Skip over expired timers */ ++ while (next) { ++ if (next->expires.tv64 >= now.tv64) ++ break; ++ next = timerqueue_iterate_next(next); ++ } ++ + timerqueue_add(&rtc->timerqueue, &timer->node); +- if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { ++ if (!next) { + struct rtc_wkalrm alarm; + int err; + alarm.time = rtc_ktime_to_tm(timer->node.expires); +diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c +index e1de4944e0ce..8c4707d5778e 100644 +--- a/drivers/tty/serial/msm_serial.c ++++ b/drivers/tty/serial/msm_serial.c +@@ -1615,6 +1615,7 @@ static const struct of_device_id msm_match_table[] = { + { .compatible = "qcom,msm-uartdm" }, + {} + }; ++MODULE_DEVICE_TABLE(of, msm_match_table); + + static struct platform_driver msm_platform_driver = { + .remove = msm_serial_remove, +diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c +index 5a048b7b92e8..2949289bb3c5 100644 +--- a/drivers/usb/chipidea/ci_hdrc_imx.c ++++ b/drivers/usb/chipidea/ci_hdrc_imx.c +@@ -244,7 +244,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + struct ci_hdrc_platform_data pdata = { + .name = dev_name(&pdev->dev), + .capoffset = DEF_CAPOFFSET, +- .flags = CI_HDRC_SET_NON_ZERO_TTHA, + }; + int ret; + const struct of_device_id *of_id; +diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c +index 1532cde8a437..7812052dc700 100644 +--- a/drivers/usb/serial/ark3116.c ++++ b/drivers/usb/serial/ark3116.c +@@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial, + usb_rcvctrlpipe(serial->dev, 0), + 0xfe, 0xc0, 0, reg, + buf, 1, ARK_TIMEOUT); +- if (result < 0) ++ if (result < 1) { ++ dev_err(&serial->interface->dev, ++ "failed to read register %u: %d\n", ++ reg, result); ++ if (result >= 0) ++ result = -EIO; ++ + return result; +- else +- return buf[0]; ++ } ++ ++ return buf[0]; + } + + static inline int calc_divisor(int bps) +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index fe7452f0f38a..33cec50978b8 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -171,6 +171,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ + { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ + { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ ++ { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ ++ { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ + { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index d3d6ec455151..19a98116c2ab 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -1807,8 +1807,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) + + mutex_init(&priv->cfg_lock); + +- priv->flags = ASYNC_LOW_LATENCY; +- + if (quirk && quirk->port_probe) + quirk->port_probe(priv); + +@@ -2072,6 +2070,20 @@ static int ftdi_process_packet(struct usb_serial_port *port, + priv->prev_status = status; + } + ++ /* save if the transmitter is empty or not */ ++ if (packet[1] & FTDI_RS_TEMT) ++ priv->transmit_empty = 1; ++ else ++ priv->transmit_empty = 0; ++ ++ len -= 2; ++ if (!len) ++ return 0; /* status only */ ++ ++ /* ++ * Break and error status must only be processed for packets with ++ * data payload to avoid over-reporting. ++ */ + flag = TTY_NORMAL; + if (packet[1] & FTDI_RS_ERR_MASK) { + /* Break takes precedence over parity, which takes precedence +@@ -2094,15 +2106,6 @@ static int ftdi_process_packet(struct usb_serial_port *port, + } + } + +- /* save if the transmitter is empty or not */ +- if (packet[1] & FTDI_RS_TEMT) +- priv->transmit_empty = 1; +- else +- priv->transmit_empty = 0; +- +- len -= 2; +- if (!len) +- return 0; /* status only */ + port->icount.rx += len; + ch = packet + 2; + +@@ -2433,8 +2436,12 @@ static int ftdi_get_modem_status(struct usb_serial_port *port, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, priv->interface, + buf, len, WDR_TIMEOUT); +- if (ret < 0) { ++ ++ /* NOTE: We allow short responses and handle that below. */ ++ if (ret < 1) { + dev_err(&port->dev, "failed to get modem status: %d\n", ret); ++ if (ret >= 0) ++ ret = -EIO; + ret = usb_translate_errors(ret); + goto out; + } +diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c +index 97ea52b5cfd4..d17685cc00c9 100644 +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -1024,6 +1024,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) + * (can't set it up in mos7840_startup as the structures * + * were not set up at that time.) */ + if (port0->open_ports == 1) { ++ /* FIXME: Buffer never NULL, so URB is not submitted. */ + if (serial->port[0]->interrupt_in_buffer == NULL) { + /* set up interrupt urb */ + usb_fill_int_urb(serial->port[0]->interrupt_in_urb, +@@ -2119,7 +2120,8 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) + static int mos7840_attach(struct usb_serial *serial) + { + if (serial->num_bulk_in < serial->num_ports || +- serial->num_bulk_out < serial->num_ports) { ++ serial->num_bulk_out < serial->num_ports || ++ serial->num_interrupt_in < 1) { + dev_err(&serial->interface->dev, "missing endpoints\n"); + return -ENODEV; + } +diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c +index 4b7bfb394a32..64bf258e7e00 100644 +--- a/drivers/usb/serial/opticon.c ++++ b/drivers/usb/serial/opticon.c +@@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) + usb_clear_halt(port->serial->dev, port->read_urb->pipe); + + res = usb_serial_generic_open(tty, port); +- if (!res) ++ if (res) + return res; + + /* Request CTS line state, sometimes during opening the current +diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c +index 475e6c31b266..ddfd787c461c 100644 +--- a/drivers/usb/serial/spcp8x5.c ++++ b/drivers/usb/serial/spcp8x5.c +@@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + GET_UART_STATUS, GET_UART_STATUS_TYPE, + 0, GET_UART_STATUS_MSR, buf, 1, 100); +- if (ret < 0) ++ if (ret < 1) { + dev_err(&port->dev, "failed to get modem status: %d\n", ret); ++ if (ret >= 0) ++ ret = -EIO; ++ goto out; ++ } + + dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf); + *status = *buf; ++ ret = 0; ++out: + kfree(buf); + + return ret; +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 9ef80bf441b3..a988d4ef39da 100644 +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -757,15 +757,20 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) + if (!bdi->wb_congested) + return -ENOMEM; + ++ atomic_set(&bdi->wb_congested->refcnt, 1); ++ + err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); + if (err) { +- kfree(bdi->wb_congested); ++ wb_congested_put(bdi->wb_congested); + return err; + } + return 0; + } + +-static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { } ++static void cgwb_bdi_destroy(struct backing_dev_info *bdi) ++{ ++ wb_congested_put(bdi->wb_congested); ++} + + #endif /* CONFIG_CGROUP_WRITEBACK */ + +diff --git a/net/dccp/input.c b/net/dccp/input.c +index 3bd14e885396..dbe2573f6ba1 100644 +--- a/net/dccp/input.c ++++ b/net/dccp/input.c +@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, + if (inet_csk(sk)->icsk_af_ops->conn_request(sk, + skb) < 0) + return 1; +- goto discard; ++ consume_skb(skb); ++ return 0; + } + if (dh->dccph_type == DCCP_PKT_RESET) + goto discard; +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index bc14c5bb124b..f300d1cbfa91 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -105,10 +105,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, + if (skb->ip_summed != CHECKSUM_COMPLETE) + return; + +- if (offset != 0) +- csum = csum_sub(csum, +- csum_partial(skb->data + tlen, +- offset, 0)); ++ if (offset != 0) { ++ int tend_off = skb_transport_offset(skb) + tlen; ++ csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); ++ } + + put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); + } +diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c +index acbe61c7e683..160dc89335e2 100644 +--- a/net/irda/irqueue.c ++++ b/net/irda/irqueue.c +@@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new); + * for deallocating this structure if it's complex. If not the user can + * just supply kfree, which should take care of the job. + */ +-#ifdef CONFIG_LOCKDEP +-static int hashbin_lock_depth = 0; +-#endif + int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + { + irda_queue_t* queue; +@@ -396,22 +393,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); + + /* Synchronize */ +- if ( hashbin->hb_type & HB_LOCK ) { +- spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, +- hashbin_lock_depth++); +- } ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); + + /* + * Free the entries in the hashbin, TODO: use hashbin_clear when + * it has been shown to work + */ + for (i = 0; i < HASHBIN_SIZE; i ++ ) { +- queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); +- while (queue ) { +- if (free_func) +- (*free_func)(queue); +- queue = dequeue_first( +- (irda_queue_t**) &hashbin->hb_queue[i]); ++ while (1) { ++ queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); ++ ++ if (!queue) ++ break; ++ ++ if (free_func) { ++ if (hashbin->hb_type & HB_LOCK) ++ spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); ++ free_func(queue); ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); ++ } + } + } + +@@ -420,12 +422,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + hashbin->magic = ~HB_MAGIC; + + /* Release lock */ +- if ( hashbin->hb_type & HB_LOCK) { ++ if (hashbin->hb_type & HB_LOCK) + spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); +-#ifdef CONFIG_LOCKDEP +- hashbin_lock_depth--; +-#endif +- } + + /* + * Free the hashbin structure +diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c +index 3e821daf9dd4..8bc5a1bd2d45 100644 +--- a/net/llc/llc_conn.c ++++ b/net/llc/llc_conn.c +@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) + * another trick required to cope with how the PROCOM state + * machine works. -acme + */ ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + } + if (!sock_owned_by_user(sk)) + llc_conn_rcv(sk, skb); +diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c +index d0e1e804ebd7..5404d0d195cc 100644 +--- a/net/llc/llc_sap.c ++++ b/net/llc/llc_sap.c +@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, + + ev->type = LLC_SAP_EV_TYPE_PDU; + ev->reason = 0; ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + llc_sap_state_process(sap, skb); + } + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index f2d28ed74a0a..d805cd577a60 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po) + f->arr[f->num_members] = sk; + smp_wmb(); + f->num_members++; ++ if (f->num_members == 1) ++ dev_add_pack(&f->prot_hook); + spin_unlock(&f->lock); + } + +@@ -1513,6 +1515,8 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) + BUG_ON(i >= f->num_members); + f->arr[i] = f->arr[f->num_members - 1]; + f->num_members--; ++ if (f->num_members == 0) ++ __dev_remove_pack(&f->prot_hook); + spin_unlock(&f->lock); + } + +@@ -1623,6 +1627,7 @@ static void fanout_release_data(struct packet_fanout *f) + + static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + { ++ struct packet_rollover *rollover = NULL; + struct packet_sock *po = pkt_sk(sk); + struct packet_fanout *f, *match; + u8 type = type_flags & 0xff; +@@ -1645,23 +1650,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + return -EINVAL; + } + ++ mutex_lock(&fanout_mutex); ++ ++ err = -EINVAL; + if (!po->running) +- return -EINVAL; ++ goto out; + ++ err = -EALREADY; + if (po->fanout) +- return -EALREADY; ++ goto out; + + if (type == PACKET_FANOUT_ROLLOVER || + (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) { +- po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); +- if (!po->rollover) +- return -ENOMEM; +- atomic_long_set(&po->rollover->num, 0); +- atomic_long_set(&po->rollover->num_huge, 0); +- atomic_long_set(&po->rollover->num_failed, 0); ++ err = -ENOMEM; ++ rollover = kzalloc(sizeof(*rollover), GFP_KERNEL); ++ if (!rollover) ++ goto out; ++ atomic_long_set(&rollover->num, 0); ++ atomic_long_set(&rollover->num_huge, 0); ++ atomic_long_set(&rollover->num_failed, 0); ++ po->rollover = rollover; + } + +- mutex_lock(&fanout_mutex); + match = NULL; + list_for_each_entry(f, &fanout_list, list) { + if (f->id == id && +@@ -1691,7 +1701,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + match->prot_hook.func = packet_rcv_fanout; + match->prot_hook.af_packet_priv = match; + match->prot_hook.id_match = match_fanout_group; +- dev_add_pack(&match->prot_hook); + list_add(&match->list, &fanout_list); + } + err = -EINVAL; +@@ -1708,36 +1717,40 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + } + } + out: +- mutex_unlock(&fanout_mutex); +- if (err) { +- kfree(po->rollover); ++ if (err && rollover) { ++ kfree(rollover); + po->rollover = NULL; + } ++ mutex_unlock(&fanout_mutex); + return err; + } + +-static void fanout_release(struct sock *sk) ++/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes ++ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout. ++ * It is the responsibility of the caller to call fanout_release_data() and ++ * free the returned packet_fanout (after synchronize_net()) ++ */ ++static struct packet_fanout *fanout_release(struct sock *sk) + { + struct packet_sock *po = pkt_sk(sk); + struct packet_fanout *f; + ++ mutex_lock(&fanout_mutex); + f = po->fanout; +- if (!f) +- return; ++ if (f) { ++ po->fanout = NULL; + +- mutex_lock(&fanout_mutex); +- po->fanout = NULL; ++ if (atomic_dec_and_test(&f->sk_ref)) ++ list_del(&f->list); ++ else ++ f = NULL; + +- if (atomic_dec_and_test(&f->sk_ref)) { +- list_del(&f->list); +- dev_remove_pack(&f->prot_hook); +- fanout_release_data(f); +- kfree(f); ++ if (po->rollover) ++ kfree_rcu(po->rollover, rcu); + } + mutex_unlock(&fanout_mutex); + +- if (po->rollover) +- kfree_rcu(po->rollover, rcu); ++ return f; + } + + static bool packet_extra_vlan_len_allowed(const struct net_device *dev, +@@ -2846,6 +2859,7 @@ static int packet_release(struct socket *sock) + { + struct sock *sk = sock->sk; + struct packet_sock *po; ++ struct packet_fanout *f; + struct net *net; + union tpacket_req_u req_u; + +@@ -2885,9 +2899,14 @@ static int packet_release(struct socket *sock) + packet_set_ring(sk, &req_u, 1, 1); + } + +- fanout_release(sk); ++ f = fanout_release(sk); + + synchronize_net(); ++ ++ if (f) { ++ fanout_release_data(f); ++ kfree(f); ++ } + /* + * Now the socket is dead. No more input will appear. + */ +@@ -3861,7 +3880,6 @@ static int packet_notifier(struct notifier_block *this, + } + if (msg == NETDEV_UNREGISTER) { + packet_cached_dev_reset(po); +- fanout_release(sk); + po->ifindex = -1; + if (po->prot_hook.dev) + dev_put(po->prot_hook.dev); +diff --git a/net/socket.c b/net/socket.c +index 0090225eeb1e..fbfa9d2492cf 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2185,8 +2185,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, + return err; + + err = sock_error(sock->sk); +- if (err) ++ if (err) { ++ datagrams = err; + goto out_put; ++ } + + entry = mmsg; + compat_entry = (struct compat_mmsghdr __user *)mmsg; diff --git a/1520_CVE-2017-6074-dccp-skb-freeing-fix.patch b/1520_CVE-2017-6074-dccp-skb-freeing-fix.patch deleted file mode 100644 index 433fd4b2..00000000 --- a/1520_CVE-2017-6074-dccp-skb-freeing-fix.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4 Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andreyknvl@google.com> -Date: Thu, 16 Feb 2017 17:22:46 +0100 -Subject: dccp: fix freeing skb too early for IPV6_RECVPKTINFO - -In the current DCCP implementation an skb for a DCCP_PKT_REQUEST packet -is forcibly freed via __kfree_skb in dccp_rcv_state_process if -dccp_v6_conn_request successfully returns. - -However, if IPV6_RECVPKTINFO is set on a socket, the address of the skb -is saved to ireq->pktopts and the ref count for skb is incremented in -dccp_v6_conn_request, so skb is still in use. Nevertheless, it gets freed -in dccp_rcv_state_process. - -Fix by calling consume_skb instead of doing goto discard and therefore -calling __kfree_skb. - -Similar fixes for TCP: - -fb7e2399ec17f1004c0e0ccfd17439f8759ede01 [TCP]: skb is unexpectedly freed. -0aea76d35c9651d55bbaf746e7914e5f9ae5a25d tcp: SYN packets are now -simply consumed - -Signed-off-by: Andrey Konovalov <andreyknvl@google.com> -Acked-by: Eric Dumazet <edumazet@google.com> -Signed-off-by: David S. Miller <davem@davemloft.net> ---- - net/dccp/input.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/net/dccp/input.c b/net/dccp/input.c -index ba34718..8fedc2d 100644 ---- a/net/dccp/input.c -+++ b/net/dccp/input.c -@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - if (inet_csk(sk)->icsk_af_ops->conn_request(sk, - skb) < 0) - return 1; -- goto discard; -+ consume_skb(skb); -+ return 0; - } - if (dh->dccph_type == DCCP_PKT_RESET) - goto discard; --- -cgit v0.12 - |