diff options
author | Mike Pagano <mpagano@gentoo.org> | 2016-01-31 10:36:20 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2016-01-31 10:36:20 -0500 |
commit | 41033c2db3e1f066508325a49e17c53e24013843 (patch) | |
tree | 18eff7e92d7ab46a79fe6bc517f02f6c382a71a0 | |
parent | Ensure that thread joining a session keyring does not leak the keyring refere... (diff) | |
download | linux-patches-41033c2db3e1f066508325a49e17c53e24013843.tar.gz linux-patches-41033c2db3e1f066508325a49e17c53e24013843.tar.bz2 linux-patches-41033c2db3e1f066508325a49e17c53e24013843.zip |
Linux patch 3.18.26. Removal of redundant patchset.3.18-27
-rw-r--r-- | 0000_README | 8 | ||||
-rw-r--r-- | 1025_linux-3.18.26.patch | 1763 | ||||
-rw-r--r-- | 1520_keyring-refleak-in-join-session-CVE-2016-0728.patch | 81 |
3 files changed, 1767 insertions, 85 deletions
diff --git a/0000_README b/0000_README index 3fe5eecd..728c863c 100644 --- a/0000_README +++ b/0000_README @@ -143,6 +143,10 @@ Patch: 1024_linux-3.18.25.patch From: http://www.kernel.org Desc: Linux 3.18.25 +Patch: 1025_linux-3.18.26.patch +From: http://www.kernel.org +Desc: Linux 3.18.26 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. @@ -151,10 +155,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_keyring-refleak-in-join-session-CVE-2016-0728.patch -From: https://bugs.gentoo.org/show_bug.cgi?id=572384 -Desc: Ensure that thread joining a session keyring does not leak the keyring reference. CVE-2016-0728. - Patch: 1700_ARM-dts-patch-to-support-popoplug-e02.patch From: https://bugs.gentoo.org/show_bug.cgi?id=508248 Desc: ARM: dts: Add support for Pogoplug E02. diff --git a/1025_linux-3.18.26.patch b/1025_linux-3.18.26.patch new file mode 100644 index 00000000..5ad05b03 --- /dev/null +++ b/1025_linux-3.18.26.patch @@ -0,0 +1,1763 @@ +diff --git a/Makefile b/Makefile +index 6df25277ea44..03b0c3fb5bfd 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 18 +-SUBLEVEL = 25 ++SUBLEVEL = 26 + EXTRAVERSION = + NAME = Diseased Newt + +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 8f51d6e3883e..c546a93c0f8a 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -3394,6 +3394,7 @@ static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq) + goto err_rq; + } + img_request->rq = rq; ++ snapc = NULL; /* img_request consumes a ref */ + + if (op_type == OBJ_OP_DISCARD) + result = rbd_img_request_fill(img_request, OBJ_REQUEST_NODATA, +@@ -5172,41 +5173,36 @@ out_err: + static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) + { + struct rbd_device *parent = NULL; +- struct rbd_spec *parent_spec; +- struct rbd_client *rbdc; + int ret; + + if (!rbd_dev->parent_spec) + return 0; +- /* +- * We need to pass a reference to the client and the parent +- * spec when creating the parent rbd_dev. Images related by +- * parent/child relationships always share both. +- */ +- parent_spec = rbd_spec_get(rbd_dev->parent_spec); +- rbdc = __rbd_get_client(rbd_dev->rbd_client); + +- ret = -ENOMEM; +- parent = rbd_dev_create(rbdc, parent_spec); +- if (!parent) ++ parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec); ++ if (!parent) { ++ ret = -ENOMEM; + goto out_err; ++ } ++ ++ /* ++ * Images related by parent/child relationships always share ++ * rbd_client and spec/parent_spec, so bump their refcounts. ++ */ ++ __rbd_get_client(rbd_dev->rbd_client); ++ rbd_spec_get(rbd_dev->parent_spec); + + ret = rbd_dev_image_probe(parent, false); + if (ret < 0) + goto out_err; ++ + rbd_dev->parent = parent; + atomic_set(&rbd_dev->parent_ref, 1); +- + return 0; ++ + out_err: +- if (parent) { +- rbd_dev_unparent(rbd_dev); ++ rbd_dev_unparent(rbd_dev); ++ if (parent) + rbd_dev_destroy(parent); +- } else { +- rbd_put_client(rbdc); +- rbd_spec_put(parent_spec); +- } +- + return ret; + } + +diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c +index a66a3217f1d9..f047d7c2b643 100644 +--- a/drivers/firewire/ohci.c ++++ b/drivers/firewire/ohci.c +@@ -3682,6 +3682,11 @@ static int pci_probe(struct pci_dev *dev, + + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); + ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); ++ /* JMicron JMB38x often shows 0 at first read, just ignore it */ ++ if (!ohci->it_context_support) { ++ ohci_notice(ohci, "overriding IsoXmitIntMask\n"); ++ ohci->it_context_support = 0xf; ++ } + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); + ohci->it_context_mask = ohci->it_context_support; + ohci->n_it = hweight32(ohci->it_context_mask); +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +index 72fb86b9aa24..067f2cb9b215 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -1014,13 +1014,12 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + sizeof(struct atl1c_recv_ret_status) * rx_desc_count + + 8 * 4; + +- ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, +- &ring_header->dma); ++ ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size, ++ &ring_header->dma, GFP_KERNEL); + if (unlikely(!ring_header->desc)) { +- dev_err(&pdev->dev, "pci_alloc_consistend failed\n"); ++ dev_err(&pdev->dev, "could not get memory for DMA buffer\n"); + goto err_nomem; + } +- memset(ring_header->desc, 0, ring_header->size); + /* init TPD ring */ + + tpd_ring[0].dma = roundup(ring_header->dma, 8); +diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c +index 2c811f66d5ac..f77b58911558 100644 +--- a/drivers/net/ethernet/qualcomm/qca_spi.c ++++ b/drivers/net/ethernet/qualcomm/qca_spi.c +@@ -737,9 +737,8 @@ qcaspi_netdev_tx_timeout(struct net_device *dev) + netdev_info(qca->net_dev, "Transmit timeout at %ld, latency %ld\n", + jiffies, jiffies - dev->trans_start); + qca->net_dev->stats.tx_errors++; +- /* wake the queue if there is room */ +- if (qcaspi_tx_ring_has_space(&qca->txr)) +- netif_wake_queue(dev); ++ /* Trigger tx queue flush and QCA7000 reset */ ++ qca->sync = QCASPI_SYNC_UNKNOWN; + } + + static int +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index b5db6b3f939f..b474dbfcdb4f 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1417,6 +1417,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) + if (mdp->cd->shift_rd0) + desc_status >>= 16; + ++ skb = mdp->rx_skbuff[entry]; + if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | + RD_RFS5 | RD_RFS6 | RD_RFS10)) { + ndev->stats.rx_errors++; +@@ -1432,12 +1433,11 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) + ndev->stats.rx_missed_errors++; + if (desc_status & RD_RFS10) + ndev->stats.rx_over_errors++; +- } else { ++ } else if (skb) { + if (!mdp->cd->hw_swap) + sh_eth_soft_swap( + phys_to_virt(ALIGN(rxdesc->addr, 4)), + pkt_len + 2); +- skb = mdp->rx_skbuff[entry]; + mdp->rx_skbuff[entry] = NULL; + if (mdp->cd->rpadir) + skb_reserve(skb, NET_IP_ALIGN); +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 1dc628ffce2b..0710214df2bf 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -420,6 +420,9 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, + struct pptp_opt *opt = &po->proto.pptp; + int error = 0; + ++ if (sockaddr_len < sizeof(struct sockaddr_pppox)) ++ return -EINVAL; ++ + lock_sock(sk); + + opt->src_addr = sp->sa_addr.pptp; +@@ -441,6 +444,9 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + struct flowi4 fl4; + int error = 0; + ++ if (sockaddr_len < sizeof(struct sockaddr_pppox)) ++ return -EINVAL; ++ + if (sp->sa_protocol != PX_PROTO_PPTP) + return -EINVAL; + +diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c +index 9dfd1d1106d7..655ecf982394 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-7000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-7000.c +@@ -69,8 +69,8 @@ + #include "iwl-agn-hw.h" + + /* Highest firmware API version supported */ +-#define IWL7260_UCODE_API_MAX 10 +-#define IWL3160_UCODE_API_MAX 10 ++#define IWL7260_UCODE_API_MAX 12 ++#define IWL3160_UCODE_API_MAX 12 + + /* Oldest version we won't warn about */ + #define IWL7260_UCODE_API_OK 9 +@@ -103,7 +103,7 @@ + #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" + + #define IWL7265D_FW_PRE "iwlwifi-7265D-" +-#define IWL7265D_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" ++#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode" + + #define NVM_HW_SECTION_NUM_FAMILY_7000 0 + +diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c +index d2b7234b1c73..d727ad324d17 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-8000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-8000.c +@@ -69,7 +69,7 @@ + #include "iwl-agn-hw.h" + + /* Highest firmware API version supported */ +-#define IWL8000_UCODE_API_MAX 10 ++#define IWL8000_UCODE_API_MAX 12 + + /* Oldest version we won't warn about */ + #define IWL8000_UCODE_API_OK 8 +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 7d8c3d4ede20..0ecf393a7973 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1860,6 +1860,11 @@ static const struct usb_device_id acm_ids[] = { + }, + #endif + ++ /* Exclude Infineon Flash Loader utility */ ++ { USB_DEVICE(0x058b, 0x0041), ++ .driver_info = IGNORE_DEVICE, ++ }, ++ + /* control interfaces without any protocol set */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTO_NONE) }, +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index b9ddf0c1ffe5..894894f2ff93 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -115,7 +115,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, + USB_SS_MULT(desc->bmAttributes) > 3) { + dev_warn(ddev, "Isoc endpoint has Mult of %d in " + "config %d interface %d altsetting %d ep %d: " +- "setting to 3\n", desc->bmAttributes + 1, ++ "setting to 3\n", ++ USB_SS_MULT(desc->bmAttributes), + cfgno, inum, asnum, ep->desc.bEndpointAddress); + ep->ss_ep_comp.bmAttributes = 2; + } +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 2222899c4b69..88e6e5debbe9 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -124,6 +124,10 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) + + static int usb_device_supports_lpm(struct usb_device *udev) + { ++ /* Some devices have trouble with LPM */ ++ if (udev->quirks & USB_QUIRK_NO_LPM) ++ return 0; ++ + /* USB 2.1 (and greater) devices indicate LPM support through + * their USB 2.0 Extended Capabilities BOS descriptor. + */ +@@ -4498,6 +4502,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, + goto fail; + } + ++ usb_detect_quirks(udev); ++ + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(udev); + if (!retval) { +@@ -4692,7 +4698,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + if (status < 0) + goto loop; + +- usb_detect_quirks(udev); + if (udev->quirks & USB_QUIRK_DELAY_INIT) + msleep(1000); + +@@ -5324,9 +5329,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + if (udev->usb2_hw_lpm_enabled == 1) + usb_set_usb2_hardware_lpm(udev, 0); + +- bos = udev->bos; +- udev->bos = NULL; +- + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency + * settings are cleared when the device is reset, so we have to set +@@ -5335,15 +5337,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + ret = usb_unlocked_disable_lpm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); +- goto re_enumerate; ++ goto re_enumerate_no_bos; + } + ret = usb_disable_ltm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LTM\n.", + __func__); +- goto re_enumerate; ++ goto re_enumerate_no_bos; + } + ++ bos = udev->bos; ++ udev->bos = NULL; ++ + for (i = 0; i < SET_CONFIG_TRIES; ++i) { + + /* ep0 maxpacket size may change; let the HCD know about it. +@@ -5440,10 +5445,11 @@ done: + return 0; + + re_enumerate: +- /* LPM state doesn't matter when we're about to destroy the device. */ +- hub_port_logical_disconnect(parent_hub, port1); + usb_release_bos_descriptor(udev); + udev->bos = bos; ++re_enumerate_no_bos: ++ /* LPM state doesn't matter when we're about to destroy the device. */ ++ hub_port_logical_disconnect(parent_hub, port1); + return -ENODEV; + } + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 8a77a417ccfd..6b53fc3ec636 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -196,6 +196,12 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x1a0a, 0x0200), .driver_info = + USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, + ++ /* Blackmagic Design Intensity Shuttle */ ++ { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM }, ++ ++ /* Blackmagic Design UltraStudio SDI */ ++ { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, ++ + { } /* terminating entry must be last */ + }; + +diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c +index 4868369eeec6..69456811ec11 100644 +--- a/drivers/usb/gadget/udc/pxa27x_udc.c ++++ b/drivers/usb/gadget/udc/pxa27x_udc.c +@@ -2564,6 +2564,9 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state) + udc->pullup_resume = udc->pullup_on; + dplus_pullup(udc, 0); + ++ if (udc->driver) ++ udc->driver->disconnect(&udc->gadget); ++ + return 0; + } + +diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c +index dc31c425ce01..9f1c0538b211 100644 +--- a/drivers/usb/host/whci/qset.c ++++ b/drivers/usb/host/whci/qset.c +@@ -377,6 +377,10 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f + if (std->pl_virt == NULL) + return -ENOMEM; + std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE); ++ if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) { ++ kfree(std->pl_virt); ++ return -EFAULT; ++ } + + for (p = 0; p < std->num_pointers; p++) { + std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index 06cc5d6ea681..dbc56eb5eee4 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -140,7 +140,7 @@ config USB_TI_CPPI_DMA + + config USB_TI_CPPI41_DMA + bool 'TI CPPI 4.1 (AM335x)' +- depends on ARCH_OMAP ++ depends on ARCH_OMAP && DMADEVICES + select TI_CPPI41 + + config USB_TUSB_OMAP_DMA +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index eac7ccaa3c85..7d4f51a32e66 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -132,7 +132,6 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +- { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ +diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c +index 7064eb8d6142..a1f2e2a05bc5 100644 +--- a/drivers/usb/serial/usb-serial-simple.c ++++ b/drivers/usb/serial/usb-serial-simple.c +@@ -53,6 +53,7 @@ DEVICE(funsoft, FUNSOFT_IDS); + + /* Infineon Flashloader driver */ + #define FLASHLOADER_IDS() \ ++ { USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \ + { USB_DEVICE(0x8087, 0x0716) } + DEVICE(flashloader, FLASHLOADER_IDS); + +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 5193c7844315..e557e4ca0392 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -760,8 +760,16 @@ next_slot: + } + + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); +- if (key.objectid > ino || +- key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end) ++ ++ if (key.objectid > ino) ++ break; ++ if (WARN_ON_ONCE(key.objectid < ino) || ++ key.type < BTRFS_EXTENT_DATA_KEY) { ++ ASSERT(del_nr == 0); ++ path->slots[0]++; ++ goto next_slot; ++ } ++ if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end) + break; + + fi = btrfs_item_ptr(leaf, path->slots[0], +@@ -780,8 +788,8 @@ next_slot: + btrfs_file_extent_inline_len(leaf, + path->slots[0], fi); + } else { +- WARN_ON(1); +- extent_end = search_start; ++ /* can't happen */ ++ BUG(); + } + + /* +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 0be09bb34b75..5db50e8bf52e 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -1268,8 +1268,14 @@ next_slot: + num_bytes = 0; + btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); + +- if (found_key.objectid > ino || +- found_key.type > BTRFS_EXTENT_DATA_KEY || ++ if (found_key.objectid > ino) ++ break; ++ if (WARN_ON_ONCE(found_key.objectid < ino) || ++ found_key.type < BTRFS_EXTENT_DATA_KEY) { ++ path->slots[0]++; ++ goto next_slot; ++ } ++ if (found_key.type > BTRFS_EXTENT_DATA_KEY || + found_key.offset > end) + break; + +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index 3d50f1ee51ba..31c9f6471ce7 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -3187,6 +3187,150 @@ static void clone_update_extent_map(struct inode *inode, + &BTRFS_I(inode)->runtime_flags); + } + ++/* ++ * Make sure we do not end up inserting an inline extent into a file that has ++ * already other (non-inline) extents. If a file has an inline extent it can ++ * not have any other extents and the (single) inline extent must start at the ++ * file offset 0. Failing to respect these rules will lead to file corruption, ++ * resulting in EIO errors on read/write operations, hitting BUG_ON's in mm, etc ++ * ++ * We can have extents that have been already written to disk or we can have ++ * dirty ranges still in delalloc, in which case the extent maps and items are ++ * created only when we run delalloc, and the delalloc ranges might fall outside ++ * the range we are currently locking in the inode's io tree. So we check the ++ * inode's i_size because of that (i_size updates are done while holding the ++ * i_mutex, which we are holding here). ++ * We also check to see if the inode has a size not greater than "datal" but has ++ * extents beyond it, due to an fallocate with FALLOC_FL_KEEP_SIZE (and we are ++ * protected against such concurrent fallocate calls by the i_mutex). ++ * ++ * If the file has no extents but a size greater than datal, do not allow the ++ * copy because we would need turn the inline extent into a non-inline one (even ++ * with NO_HOLES enabled). If we find our destination inode only has one inline ++ * extent, just overwrite it with the source inline extent if its size is less ++ * than the source extent's size, or we could copy the source inline extent's ++ * data into the destination inode's inline extent if the later is greater then ++ * the former. ++ */ ++static int clone_copy_inline_extent(struct inode *src, ++ struct inode *dst, ++ struct btrfs_trans_handle *trans, ++ struct btrfs_path *path, ++ struct btrfs_key *new_key, ++ const u64 drop_start, ++ const u64 datal, ++ const u64 skip, ++ const u64 size, ++ char *inline_data) ++{ ++ struct btrfs_root *root = BTRFS_I(dst)->root; ++ const u64 aligned_end = ALIGN(new_key->offset + datal, ++ root->sectorsize); ++ int ret; ++ struct btrfs_key key; ++ ++ if (new_key->offset > 0) ++ return -EOPNOTSUPP; ++ ++ key.objectid = btrfs_ino(dst); ++ key.type = BTRFS_EXTENT_DATA_KEY; ++ key.offset = 0; ++ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ++ if (ret < 0) { ++ return ret; ++ } else if (ret > 0) { ++ if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) { ++ ret = btrfs_next_leaf(root, path); ++ if (ret < 0) ++ return ret; ++ else if (ret > 0) ++ goto copy_inline_extent; ++ } ++ btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); ++ if (key.objectid == btrfs_ino(dst) && ++ key.type == BTRFS_EXTENT_DATA_KEY) { ++ ASSERT(key.offset > 0); ++ return -EOPNOTSUPP; ++ } ++ } else if (i_size_read(dst) <= datal) { ++ struct btrfs_file_extent_item *ei; ++ u64 ext_len; ++ ++ /* ++ * If the file size is <= datal, make sure there are no other ++ * extents following (can happen do to an fallocate call with ++ * the flag FALLOC_FL_KEEP_SIZE). ++ */ ++ ei = btrfs_item_ptr(path->nodes[0], path->slots[0], ++ struct btrfs_file_extent_item); ++ /* ++ * If it's an inline extent, it can not have other extents ++ * following it. ++ */ ++ if (btrfs_file_extent_type(path->nodes[0], ei) == ++ BTRFS_FILE_EXTENT_INLINE) ++ goto copy_inline_extent; ++ ++ ext_len = btrfs_file_extent_num_bytes(path->nodes[0], ei); ++ if (ext_len > aligned_end) ++ return -EOPNOTSUPP; ++ ++ ret = btrfs_next_item(root, path); ++ if (ret < 0) { ++ return ret; ++ } else if (ret == 0) { ++ btrfs_item_key_to_cpu(path->nodes[0], &key, ++ path->slots[0]); ++ if (key.objectid == btrfs_ino(dst) && ++ key.type == BTRFS_EXTENT_DATA_KEY) ++ return -EOPNOTSUPP; ++ } ++ } ++ ++copy_inline_extent: ++ /* ++ * We have no extent items, or we have an extent at offset 0 which may ++ * or may not be inlined. All these cases are dealt the same way. ++ */ ++ if (i_size_read(dst) > datal) { ++ /* ++ * If the destination inode has an inline extent... ++ * This would require copying the data from the source inline ++ * extent into the beginning of the destination's inline extent. ++ * But this is really complex, both extents can be compressed ++ * or just one of them, which would require decompressing and ++ * re-compressing data (which could increase the new compressed ++ * size, not allowing the compressed data to fit anymore in an ++ * inline extent). ++ * So just don't support this case for now (it should be rare, ++ * we are not really saving space when cloning inline extents). ++ */ ++ return -EOPNOTSUPP; ++ } ++ ++ btrfs_release_path(path); ++ ret = btrfs_drop_extents(trans, root, dst, drop_start, aligned_end, 1); ++ if (ret) ++ return ret; ++ ret = btrfs_insert_empty_item(trans, root, path, new_key, size); ++ if (ret) ++ return ret; ++ ++ if (skip) { ++ const u32 start = btrfs_file_extent_calc_inline_size(0); ++ ++ memmove(inline_data + start, inline_data + start + skip, datal); ++ } ++ ++ write_extent_buffer(path->nodes[0], inline_data, ++ btrfs_item_ptr_offset(path->nodes[0], ++ path->slots[0]), ++ size); ++ inode_add_bytes(dst, datal); ++ ++ return 0; ++} ++ + /** + * btrfs_clone() - clone a range from inode file to another + * +@@ -3451,7 +3595,6 @@ process_slot: + } else if (type == BTRFS_FILE_EXTENT_INLINE) { + u64 skip = 0; + u64 trim = 0; +- u64 aligned_end = 0; + + if (off > key.offset) { + skip = off - key.offset; +@@ -3469,42 +3612,22 @@ process_slot: + size -= skip + trim; + datal -= skip + trim; + +- aligned_end = ALIGN(new_key.offset + datal, +- root->sectorsize); +- ret = btrfs_drop_extents(trans, root, inode, +- drop_start, +- aligned_end, +- 1); ++ ret = clone_copy_inline_extent(src, inode, ++ trans, path, ++ &new_key, ++ drop_start, ++ datal, ++ skip, size, buf); + if (ret) { + if (ret != -EOPNOTSUPP) + btrfs_abort_transaction(trans, +- root, ret); +- btrfs_end_transaction(trans, root); +- goto out; +- } +- +- ret = btrfs_insert_empty_item(trans, root, path, +- &new_key, size); +- if (ret) { +- btrfs_abort_transaction(trans, root, +- ret); ++ root, ++ ret); + btrfs_end_transaction(trans, root); + goto out; + } +- +- if (skip) { +- u32 start = +- btrfs_file_extent_calc_inline_size(0); +- memmove(buf+start, buf+start+skip, +- datal); +- } +- + leaf = path->nodes[0]; + slot = path->slots[0]; +- write_extent_buffer(leaf, buf, +- btrfs_item_ptr_offset(leaf, slot), +- size); +- inode_add_bytes(inode, datal); + } + + /* If we have an implicit hole (NO_HOLES feature). */ +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index 01bad724b5f7..fbb0533e977f 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -309,8 +309,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) + /* check to make sure this item is what we want */ + if (found_key.objectid != key.objectid) + break; +- if (found_key.type != BTRFS_XATTR_ITEM_KEY) ++ if (found_key.type > BTRFS_XATTR_ITEM_KEY) + break; ++ if (found_key.type < BTRFS_XATTR_ITEM_KEY) ++ goto next; + + di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); + if (verify_dir_item(root, leaf, di)) +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index a92d3f5c6c12..6f29455c03fe 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1857,7 +1857,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, + + len = sizeof(*head) + + pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) + +- sizeof(struct timespec); ++ sizeof(struct ceph_timespec); + + /* calculate (max) length for cap releases */ + len += sizeof(struct ceph_mds_request_release) * +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index b5a2c29a8db8..b16ba5239dcf 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -404,9 +404,13 @@ static void ext4_handle_error(struct super_block *sb) + smp_wmb(); + sb->s_flags |= MS_RDONLY; + } +- if (test_opt(sb, ERRORS_PANIC)) ++ if (test_opt(sb, ERRORS_PANIC)) { ++ if (EXT4_SB(sb)->s_journal && ++ !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) ++ return; + panic("EXT4-fs (device %s): panic forced after error\n", + sb->s_id); ++ } + } + + #define ext4_error_ratelimit(sb) \ +@@ -595,8 +599,12 @@ void __ext4_abort(struct super_block *sb, const char *function, + jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); + save_error_info(sb, function, line); + } +- if (test_opt(sb, ERRORS_PANIC)) ++ if (test_opt(sb, ERRORS_PANIC)) { ++ if (EXT4_SB(sb)->s_journal && ++ !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) ++ return; + panic("EXT4-fs panic from previous error\n"); ++ } + } + + void __ext4_msg(struct super_block *sb, +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 2540324f084b..07e87ec45709 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -2087,8 +2087,12 @@ static void __journal_abort_soft (journal_t *journal, int errno) + + __jbd2_journal_abort_hard(journal); + +- if (errno) ++ if (errno) { + jbd2_journal_update_sb_errno(journal); ++ write_lock(&journal->j_state_lock); ++ journal->j_flags |= JBD2_REC_ERR; ++ write_unlock(&journal->j_state_lock); ++ } + } + + /** +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 00689a8a85e4..d7cfc6e42b5e 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -1717,7 +1717,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) + nfsi->attrtimeo_timestamp = now; + } + } +- invalid &= ~NFS_INO_INVALID_ATTR; ++ ++ /* Don't declare attrcache up to date if there were no attrs! */ ++ if (fattr->valid != 0) ++ invalid &= ~NFS_INO_INVALID_ATTR; ++ + /* Don't invalidate the data if we were to blame */ + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) + || S_ISLNK(inode->i_mode))) +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 368a6b72290c..0e11fe80e5b9 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -33,7 +33,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) + return ret; + idr_preload(GFP_KERNEL); + spin_lock(&nn->nfs_client_lock); +- ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT); ++ ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT); + if (ret >= 0) + clp->cl_cb_ident = ret; + spin_unlock(&nn->nfs_client_lock); +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index eda99c8ec3ed..b6c3a8792358 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -3241,6 +3241,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, + stp->st_access_bmap = 0; + stp->st_deny_bmap = 0; + stp->st_openstp = NULL; ++ init_rwsem(&stp->st_rwsem); + spin_lock(&oo->oo_owner.so_client->cl_lock); + list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); + spin_lock(&fp->fi_lock); +@@ -4057,21 +4058,27 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf + */ + if (stp) { + /* Stateid was found, this is an OPEN upgrade */ ++ down_read(&stp->st_rwsem); + status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); +- if (status) ++ if (status) { ++ up_read(&stp->st_rwsem); + goto out; ++ } + } else { + stp = open->op_stp; + open->op_stp = NULL; + init_open_stateid(stp, fp, open); ++ down_read(&stp->st_rwsem); + status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); + if (status) { ++ up_read(&stp->st_rwsem); + release_open_stateid(stp); + goto out; + } + } + update_stateid(&stp->st_stid.sc_stateid); + memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); ++ up_read(&stp->st_rwsem); + + if (nfsd4_has_session(&resp->cstate)) { + if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { +@@ -4647,10 +4654,13 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_ + * revoked delegations are kept only for free_stateid. + */ + return nfserr_bad_stateid; ++ down_write(&stp->st_rwsem); + status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); +- if (status) +- return status; +- return nfs4_check_fh(current_fh, &stp->st_stid); ++ if (status == nfs_ok) ++ status = nfs4_check_fh(current_fh, &stp->st_stid); ++ if (status != nfs_ok) ++ up_write(&stp->st_rwsem); ++ return status; + } + + /* +@@ -4697,6 +4707,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs + return status; + oo = openowner(stp->st_stateowner); + if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { ++ up_write(&stp->st_rwsem); + nfs4_put_stid(&stp->st_stid); + return nfserr_bad_stateid; + } +@@ -4727,11 +4738,14 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + goto out; + oo = openowner(stp->st_stateowner); + status = nfserr_bad_stateid; +- if (oo->oo_flags & NFS4_OO_CONFIRMED) ++ if (oo->oo_flags & NFS4_OO_CONFIRMED) { ++ up_write(&stp->st_rwsem); + goto put_stateid; ++ } + oo->oo_flags |= NFS4_OO_CONFIRMED; + update_stateid(&stp->st_stid.sc_stateid); + memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); ++ up_write(&stp->st_rwsem); + dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", + __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); + +@@ -4810,6 +4824,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, + memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); + status = nfs_ok; + put_stateid: ++ up_write(&stp->st_rwsem); + nfs4_put_stid(&stp->st_stid); + out: + nfsd4_bump_seqid(cstate, status); +@@ -4860,6 +4875,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + goto out; + update_stateid(&stp->st_stid.sc_stateid); + memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); ++ up_write(&stp->st_rwsem); + + nfsd4_close_open_stateid(stp); + +@@ -5088,6 +5104,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, + stp->st_access_bmap = 0; + stp->st_deny_bmap = open_stp->st_deny_bmap; + stp->st_openstp = open_stp; ++ init_rwsem(&stp->st_rwsem); + list_add(&stp->st_locks, &open_stp->st_locks); + list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); + spin_lock(&fp->fi_lock); +@@ -5256,6 +5273,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + &open_stp, nn); + if (status) + goto out; ++ up_write(&open_stp->st_rwsem); + open_sop = openowner(open_stp->st_stateowner); + status = nfserr_bad_stateid; + if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, +@@ -5263,6 +5281,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + goto out; + status = lookup_or_create_lock_state(cstate, open_stp, lock, + &lock_stp, &new); ++ if (status == nfs_ok) ++ down_write(&lock_stp->st_rwsem); + } else { + status = nfs4_preprocess_seqid_op(cstate, + lock->lk_old_lock_seqid, +@@ -5368,6 +5388,8 @@ out: + seqid_mutating_err(ntohl(status))) + lock_sop->lo_owner.so_seqid++; + ++ up_write(&lock_stp->st_rwsem); ++ + /* + * If this is a new, never-before-used stateid, and we are + * returning an error, then just go ahead and release it. +@@ -5538,6 +5560,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + fput: + fput(filp); + put_stateid: ++ up_write(&stp->st_rwsem); + nfs4_put_stid(&stp->st_stid); + out: + nfsd4_bump_seqid(cstate, status); +diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h +index 2712042a66b1..3ccb1046a2f9 100644 +--- a/fs/nfsd/state.h ++++ b/fs/nfsd/state.h +@@ -506,14 +506,15 @@ struct nfs4_file { + * Better suggestions welcome. + */ + struct nfs4_ol_stateid { +- struct nfs4_stid st_stid; /* must be first field */ +- struct list_head st_perfile; +- struct list_head st_perstateowner; +- struct list_head st_locks; +- struct nfs4_stateowner * st_stateowner; +- unsigned char st_access_bmap; +- unsigned char st_deny_bmap; +- struct nfs4_ol_stateid * st_openstp; ++ struct nfs4_stid st_stid; ++ struct list_head st_perfile; ++ struct list_head st_perstateowner; ++ struct list_head st_locks; ++ struct nfs4_stateowner *st_stateowner; ++ unsigned char st_access_bmap; ++ unsigned char st_deny_bmap; ++ struct nfs4_ol_stateid *st_openstp; ++ struct rw_semaphore st_rwsem; + }; + + static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) +diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c +index 914c121ec890..9fc1daecdfb3 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -361,6 +361,8 @@ static int ocfs2_mknod(struct inode *dir, + mlog_errno(status); + goto leave; + } ++ /* update inode->i_mode after mask with "umask". */ ++ inode->i_mode = mode; + + handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, + S_ISDIR(mode), +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 4caf8acfef11..c035001df223 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1007,6 +1007,7 @@ struct journal_s + #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file + * data write error in ordered + * mode */ ++#define JBD2_REC_ERR 0x080 /* The errno in the sb has been recorded */ + + /* + * Function declarations for the journaling transaction and buffer +diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h +index 9948c874e3f1..1d0043dc34e4 100644 +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -47,4 +47,7 @@ + /* device generates spurious wakeup, ignore remote wakeup capability */ + #define USB_QUIRK_IGNORE_REMOTE_WAKEUP BIT(9) + ++/* device can't handle Link Power Management */ ++#define USB_QUIRK_NO_LPM BIT(10) ++ + #endif /* __LINUX_USB_QUIRKS_H */ +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index dfe4ddfbb43c..e830c3dff61a 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -63,6 +63,7 @@ struct unix_sock { + #define UNIX_GC_CANDIDATE 0 + #define UNIX_GC_MAYBE_CYCLE 1 + struct socket_wq peer_wq; ++ wait_queue_t peer_wake; + }; + + static inline struct unix_sock *unix_sk(struct sock *sk) +diff --git a/include/net/dst.h b/include/net/dst.h +index 0fb99a26e973..182b812d45e1 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -312,6 +312,39 @@ static inline void skb_dst_force(struct sk_buff *skb) + } + } + ++/** ++ * dst_hold_safe - Take a reference on a dst if possible ++ * @dst: pointer to dst entry ++ * ++ * This helper returns false if it could not safely ++ * take a reference on a dst. ++ */ ++static inline bool dst_hold_safe(struct dst_entry *dst) ++{ ++ if (dst->flags & DST_NOCACHE) ++ return atomic_inc_not_zero(&dst->__refcnt); ++ dst_hold(dst); ++ return true; ++} ++ ++/** ++ * skb_dst_force_safe - makes sure skb dst is refcounted ++ * @skb: buffer ++ * ++ * If dst is not yet refcounted and not destroyed, grab a ref on it. ++ */ ++static inline void skb_dst_force_safe(struct sk_buff *skb) ++{ ++ if (skb_dst_is_noref(skb)) { ++ struct dst_entry *dst = skb_dst(skb); ++ ++ if (!dst_hold_safe(dst)) ++ dst = NULL; ++ ++ skb->_skb_refdst = (unsigned long)dst; ++ } ++} ++ + + /** + * __skb_tunnel_rx - prepare skb for rx reinsert +diff --git a/include/net/sock.h b/include/net/sock.h +index a098ce3cd242..a40bc8c0af4b 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -379,6 +379,7 @@ struct sock { + sk_no_check_rx : 1, + sk_userlocks : 4, + sk_protocol : 8, ++#define SK_PROTOCOL_MAX U8_MAX + sk_type : 16; + kmemcheck_bitfield_end(flags); + int sk_wmem_queued; +@@ -715,6 +716,8 @@ enum sock_flags { + SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ + }; + ++#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) ++ + static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) + { + nsk->sk_flags = osk->sk_flags; +@@ -789,7 +792,7 @@ void sk_stream_write_space(struct sock *sk); + static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) + { + /* dont let skb dst not refcounted, we are going to leave rcu lock */ +- skb_dst_force(skb); ++ skb_dst_force_safe(skb); + + if (!sk->sk_backlog.tail) + sk->sk_backlog.head = skb; +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index bd3c41d4ec07..2273f534b01a 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1442,13 +1442,13 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq, + timer_stats_timer_set_start_info(&dwork->timer); + + dwork->wq = wq; +- /* timer isn't guaranteed to run in this cpu, record earlier */ +- if (cpu == WORK_CPU_UNBOUND) +- cpu = raw_smp_processor_id(); + dwork->cpu = cpu; + timer->expires = jiffies + delay; + +- add_timer_on(timer, cpu); ++ if (unlikely(cpu != WORK_CPU_UNBOUND)) ++ add_timer_on(timer, cpu); ++ else ++ add_timer(timer); + } + + /** +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index c35c3f48fc0f..1428c3ff3341 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -806,6 +806,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol, + struct sock *sk; + ax25_cb *ax25; + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 7ee9e4ab00f8..b3ef78a644ed 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -520,6 +520,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le + if (!addr || addr->sa_family != AF_BLUETOOTH) + return -EINVAL; + ++ if (addr_len < sizeof(struct sockaddr_sco)) ++ return -EINVAL; ++ + lock_sock(sk); + + if (sk->sk_state != BT_OPEN) { +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index ea0bcc4a9657..b2921c0d5608 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3599,7 +3599,8 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb, + serr->ee.ee_info = tstype; + if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { + serr->ee.ee_data = skb_shinfo(skb)->tskey; +- if (sk->sk_protocol == IPPROTO_TCP) ++ if (sk->sk_protocol == IPPROTO_TCP && ++ sk->sk_type == SOCK_STREAM) + serr->ee.ee_data -= sk->sk_tskey; + } + +@@ -4108,7 +4109,8 @@ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) + return NULL; + } + +- memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); ++ memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN, ++ 2 * ETH_ALEN); + skb->mac_header += VLAN_HLEN; + return skb; + } +diff --git a/net/core/sock.c b/net/core/sock.c +index 1e5130de31b6..b1a6ff0a9041 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -422,8 +422,6 @@ static void sock_warn_obsolete_bsdism(const char *name) + } + } + +-#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) +- + static void sock_disable_timestamp(struct sock *sk, unsigned long flags) + { + if (sk->sk_flags & flags) { +@@ -861,7 +859,8 @@ set_rcvbuf: + } + if (val & SOF_TIMESTAMPING_OPT_ID && + !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { +- if (sk->sk_protocol == IPPROTO_TCP) { ++ if (sk->sk_protocol == IPPROTO_TCP && ++ sk->sk_type == SOCK_STREAM) { + if (sk->sk_state != TCP_ESTABLISHED) { + ret = -EINVAL; + break; +diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c +index 25733d538147..2aeeb4f22e9d 100644 +--- a/net/decnet/af_decnet.c ++++ b/net/decnet/af_decnet.c +@@ -678,6 +678,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol, + { + struct sock *sk; + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 9a173577a790..6cf020ea4f46 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -259,6 +259,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, + int try_loading_module = 0; + int err; + ++ if (protocol < 0 || protocol >= IPPROTO_MAX) ++ return -EINVAL; ++ + sock->state = SS_UNCONNECTED; + + /* Look for the requested type/protocol pair. */ +diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c +index 606c520ffd5a..8ce8e82d1abb 100644 +--- a/net/ipv4/fou.c ++++ b/net/ipv4/fou.c +@@ -25,6 +25,7 @@ struct fou { + u16 port; + struct udp_offload udp_offloads; + struct list_head list; ++ struct rcu_head rcu; + }; + + struct fou_cfg { +@@ -287,7 +288,7 @@ static void fou_release(struct fou *fou) + + sock_release(sock); + +- kfree(fou); ++ kfree_rcu(fou, rcu); + } + + static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 6cd9f696d9c6..5d5390299277 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1553,7 +1553,7 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) + if (likely(sk->sk_rx_dst)) + skb_dst_drop(skb); + else +- skb_dst_force(skb); ++ skb_dst_force_safe(skb); + + __skb_queue_tail(&tp->ucopy.prequeue, skb); + tp->ucopy.memory += skb->truesize; +@@ -1758,8 +1758,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); + +- if (dst) { +- dst_hold(dst); ++ if (dst && dst_hold_safe(dst)) { + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + } +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 05417c330f4e..ad95905e7a70 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -109,6 +109,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, + int try_loading_module = 0; + int err; + ++ if (protocol < 0 || protocol >= IPPROTO_MAX) ++ return -EINVAL; ++ + /* Look for the requested type/protocol pair. */ + lookup_protocol: + err = -ESOCKTNOSUPPORT; +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 28d7a245ea34..25cd22c1ddee 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1563,13 +1563,11 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], + return -EEXIST; + } else { + t = nt; +- +- ip6gre_tunnel_unlink(ign, t); +- ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); +- ip6gre_tunnel_link(ign, t); +- netdev_state_change(dev); + } + ++ ip6gre_tunnel_unlink(ign, t); ++ ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); ++ ip6gre_tunnel_link(ign, t); + return 0; + } + +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 26feadd0b763..b5a4ac8ce4b1 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -93,10 +93,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); + +- if (dst) { ++ if (dst && dst_hold_safe(dst)) { + const struct rt6_info *rt = (const struct rt6_info *)dst; + +- dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + if (rt->rt6i_node) +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index 3f3a6cbdceb7..b3f6ec0df426 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1100,6 +1100,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol, + + IRDA_DEBUG(2, "%s()\n", __func__); + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (net != &init_net) + return -EAFNOSUPPORT; + +diff --git a/net/rds/send.c b/net/rds/send.c +index 0a64541020b0..0bae8d43b012 100644 +--- a/net/rds/send.c ++++ b/net/rds/send.c +@@ -958,11 +958,13 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + release_sock(sk); + } + +- /* racing with another thread binding seems ok here */ ++ lock_sock(sk); + if (daddr == 0 || rs->rs_bound_addr == 0) { ++ release_sock(sk); + ret = -ENOTCONN; /* XXX not a great errno */ + goto out; + } ++ release_sock(sk); + + /* size of rm including all sgs */ + ret = rds_rm_size(msg, payload_len); +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 0e4198ee2370..3267a5cbb3e8 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -634,6 +634,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, + struct sock *newsk; + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); + struct sctp6_sock *newsctp6sk; ++ struct ipv6_txoptions *opt; + + newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot); + if (!newsk) +@@ -653,6 +654,13 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, + + memcpy(newnp, np, sizeof(struct ipv6_pinfo)); + ++ rcu_read_lock(); ++ opt = rcu_dereference(np->opt); ++ if (opt) ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ rcu_read_unlock(); ++ + /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() + * and getpeername(). + */ +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index 371a152d9759..642c11570285 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -1652,7 +1652,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, + + /* Set an expiration time for the cookie. */ + cookie->c.expiration = ktime_add(asoc->cookie_life, +- ktime_get()); ++ ktime_get_real()); + + /* Copy the peer's init packet. */ + memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr, +@@ -1780,7 +1780,7 @@ no_hmac: + if (sock_flag(ep->base.sk, SOCK_TIMESTAMP)) + kt = skb_get_ktime(skb); + else +- kt = ktime_get(); ++ kt = ktime_get_real(); + + if (!asoc && ktime_before(bear_cookie->expiration, kt)) { + /* +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index fb082aa4d656..4130c1b87dd6 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -7181,6 +7181,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, + newsk->sk_type = sk->sk_type; + newsk->sk_bound_dev_if = sk->sk_bound_dev_if; + newsk->sk_flags = sk->sk_flags; ++ newsk->sk_tsflags = sk->sk_tsflags; + newsk->sk_no_check_tx = sk->sk_no_check_tx; + newsk->sk_no_check_rx = sk->sk_no_check_rx; + newsk->sk_reuse = sk->sk_reuse; +@@ -7213,6 +7214,9 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, + newinet->mc_ttl = 1; + newinet->mc_index = 0; + newinet->mc_list = NULL; ++ ++ if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) ++ net_enable_timestamp(); + } + + static inline void sctp_copy_descendant(struct sock *sk_to, +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 2ae4a5915aa7..7229794c1419 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -316,6 +316,118 @@ found: + return s; + } + ++/* Support code for asymmetrically connected dgram sockets ++ * ++ * If a datagram socket is connected to a socket not itself connected ++ * to the first socket (eg, /dev/log), clients may only enqueue more ++ * messages if the present receive queue of the server socket is not ++ * "too large". This means there's a second writeability condition ++ * poll and sendmsg need to test. The dgram recv code will do a wake ++ * up on the peer_wait wait queue of a socket upon reception of a ++ * datagram which needs to be propagated to sleeping would-be writers ++ * since these might not have sent anything so far. This can't be ++ * accomplished via poll_wait because the lifetime of the server ++ * socket might be less than that of its clients if these break their ++ * association with it or if the server socket is closed while clients ++ * are still connected to it and there's no way to inform "a polling ++ * implementation" that it should let go of a certain wait queue ++ * ++ * In order to propagate a wake up, a wait_queue_t of the client ++ * socket is enqueued on the peer_wait queue of the server socket ++ * whose wake function does a wake_up on the ordinary client socket ++ * wait queue. This connection is established whenever a write (or ++ * poll for write) hit the flow control condition and broken when the ++ * association to the server socket is dissolved or after a wake up ++ * was relayed. ++ */ ++ ++static int unix_dgram_peer_wake_relay(wait_queue_t *q, unsigned mode, int flags, ++ void *key) ++{ ++ struct unix_sock *u; ++ wait_queue_head_t *u_sleep; ++ ++ u = container_of(q, struct unix_sock, peer_wake); ++ ++ __remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait, ++ q); ++ u->peer_wake.private = NULL; ++ ++ /* relaying can only happen while the wq still exists */ ++ u_sleep = sk_sleep(&u->sk); ++ if (u_sleep) ++ wake_up_interruptible_poll(u_sleep, key); ++ ++ return 0; ++} ++ ++static int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other) ++{ ++ struct unix_sock *u, *u_other; ++ int rc; ++ ++ u = unix_sk(sk); ++ u_other = unix_sk(other); ++ rc = 0; ++ spin_lock(&u_other->peer_wait.lock); ++ ++ if (!u->peer_wake.private) { ++ u->peer_wake.private = other; ++ __add_wait_queue(&u_other->peer_wait, &u->peer_wake); ++ ++ rc = 1; ++ } ++ ++ spin_unlock(&u_other->peer_wait.lock); ++ return rc; ++} ++ ++static void unix_dgram_peer_wake_disconnect(struct sock *sk, ++ struct sock *other) ++{ ++ struct unix_sock *u, *u_other; ++ ++ u = unix_sk(sk); ++ u_other = unix_sk(other); ++ spin_lock(&u_other->peer_wait.lock); ++ ++ if (u->peer_wake.private == other) { ++ __remove_wait_queue(&u_other->peer_wait, &u->peer_wake); ++ u->peer_wake.private = NULL; ++ } ++ ++ spin_unlock(&u_other->peer_wait.lock); ++} ++ ++static void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk, ++ struct sock *other) ++{ ++ unix_dgram_peer_wake_disconnect(sk, other); ++ wake_up_interruptible_poll(sk_sleep(sk), ++ POLLOUT | ++ POLLWRNORM | ++ POLLWRBAND); ++} ++ ++/* preconditions: ++ * - unix_peer(sk) == other ++ * - association is stable ++ */ ++static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other) ++{ ++ int connected; ++ ++ connected = unix_dgram_peer_wake_connect(sk, other); ++ ++ if (unix_recvq_full(other)) ++ return 1; ++ ++ if (connected) ++ unix_dgram_peer_wake_disconnect(sk, other); ++ ++ return 0; ++} ++ + static inline int unix_writable(struct sock *sk) + { + return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf; +@@ -420,6 +532,8 @@ static void unix_release_sock(struct sock *sk, int embrion) + skpair->sk_state_change(skpair); + sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); + } ++ ++ unix_dgram_peer_wake_disconnect(sk, skpair); + sock_put(skpair); /* It may now die */ + unix_peer(sk) = NULL; + } +@@ -653,6 +767,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) + INIT_LIST_HEAD(&u->link); + mutex_init(&u->readlock); /* single task reading lock */ + init_waitqueue_head(&u->peer_wait); ++ init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); + unix_insert_socket(unix_sockets_unbound(sk), sk); + out: + if (sk == NULL) +@@ -1020,6 +1135,8 @@ restart: + if (unix_peer(sk)) { + struct sock *old_peer = unix_peer(sk); + unix_peer(sk) = other; ++ unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer); ++ + unix_state_double_unlock(sk, other); + + if (other != old_peer) +@@ -1459,6 +1576,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, + struct scm_cookie tmp_scm; + int max_level; + int data_len = 0; ++ int sk_locked; + + if (NULL == siocb->scm) + siocb->scm = &tmp_scm; +@@ -1540,12 +1658,14 @@ restart: + goto out_free; + } + ++ sk_locked = 0; + unix_state_lock(other); ++restart_locked: + err = -EPERM; + if (!unix_may_send(sk, other)) + goto out_unlock; + +- if (sock_flag(other, SOCK_DEAD)) { ++ if (unlikely(sock_flag(other, SOCK_DEAD))) { + /* + * Check with 1003.1g - what should + * datagram error +@@ -1553,10 +1673,14 @@ restart: + unix_state_unlock(other); + sock_put(other); + ++ if (!sk_locked) ++ unix_state_lock(sk); ++ + err = 0; +- unix_state_lock(sk); + if (unix_peer(sk) == other) { + unix_peer(sk) = NULL; ++ unix_dgram_peer_wake_disconnect_wakeup(sk, other); ++ + unix_state_unlock(sk); + + unix_dgram_disconnected(sk, other); +@@ -1582,21 +1706,38 @@ restart: + goto out_unlock; + } + +- if (unix_peer(other) != sk && unix_recvq_full(other)) { +- if (!timeo) { +- err = -EAGAIN; +- goto out_unlock; ++ if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { ++ if (timeo) { ++ timeo = unix_wait_for_peer(other, timeo); ++ ++ err = sock_intr_errno(timeo); ++ if (signal_pending(current)) ++ goto out_free; ++ ++ goto restart; + } + +- timeo = unix_wait_for_peer(other, timeo); ++ if (!sk_locked) { ++ unix_state_unlock(other); ++ unix_state_double_lock(sk, other); ++ } + +- err = sock_intr_errno(timeo); +- if (signal_pending(current)) +- goto out_free; ++ if (unix_peer(sk) != other || ++ unix_dgram_peer_wake_me(sk, other)) { ++ err = -EAGAIN; ++ sk_locked = 1; ++ goto out_unlock; ++ } + +- goto restart; ++ if (!sk_locked) { ++ sk_locked = 1; ++ goto restart_locked; ++ } + } + ++ if (unlikely(sk_locked)) ++ unix_state_unlock(sk); ++ + if (sock_flag(other, SOCK_RCVTSTAMP)) + __net_timestamp(skb); + maybe_add_creds(skb, sock, other); +@@ -1610,6 +1751,8 @@ restart: + return len; + + out_unlock: ++ if (sk_locked) ++ unix_state_unlock(sk); + unix_state_unlock(other); + out_free: + kfree_skb(skb); +@@ -1953,14 +2096,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + memset(&tmp_scm, 0, sizeof(tmp_scm)); + } + +- err = mutex_lock_interruptible(&u->readlock); +- if (unlikely(err)) { +- /* recvmsg() in non blocking mode is supposed to return -EAGAIN +- * sk_rcvtimeo is not honored by mutex_lock_interruptible() +- */ +- err = noblock ? -EAGAIN : -ERESTARTSYS; +- goto out; +- } ++ mutex_lock(&u->readlock); + + if (flags & MSG_PEEK) + skip = sk_peek_offset(sk, flags); +@@ -2001,12 +2137,12 @@ again: + + timeo = unix_stream_data_wait(sk, timeo, last); + +- if (signal_pending(current) +- || mutex_lock_interruptible(&u->readlock)) { ++ if (signal_pending(current)) { + err = sock_intr_errno(timeo); + goto out; + } + ++ mutex_lock(&u->readlock); + continue; + unlock: + unix_state_unlock(sk); +@@ -2269,14 +2405,16 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, + return mask; + + writable = unix_writable(sk); +- other = unix_peer_get(sk); +- if (other) { +- if (unix_peer(other) != sk) { +- sock_poll_wait(file, &unix_sk(other)->peer_wait, wait); +- if (unix_recvq_full(other)) +- writable = 0; +- } +- sock_put(other); ++ if (writable) { ++ unix_state_lock(sk); ++ ++ other = unix_peer(sk); ++ if (other && unix_peer(other) != sk && ++ unix_recvq_full(other) && ++ unix_dgram_peer_wake_me(sk, other)) ++ writable = 0; ++ ++ unix_state_unlock(sk); + } + + if (writable) +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 4743d71e4aa6..fee27fe2b30f 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -757,16 +757,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) + + /* the key is probably readable - now try to read it */ + can_read_key: +- ret = key_validate(key); +- if (ret == 0) { +- ret = -EOPNOTSUPP; +- if (key->type->read) { +- /* read the data with the semaphore held (since we +- * might sleep) */ +- down_read(&key->sem); ++ ret = -EOPNOTSUPP; ++ if (key->type->read) { ++ /* Read the data with the semaphore held (since we might sleep) ++ * to protect against the key being updated or revoked. ++ */ ++ down_read(&key->sem); ++ ret = key_validate(key); ++ if (ret == 0) + ret = key->type->read(key, buffer, buflen); +- up_read(&key->sem); +- } ++ up_read(&key->sem); + } + + error2: +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index bd536cb221e2..db91639c81e3 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -794,6 +794,7 @@ long join_session_keyring(const char *name) + ret = PTR_ERR(keyring); + goto error2; + } else if (keyring == new->session_keyring) { ++ key_put(keyring); + ret = 0; + goto error2; + } +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index b422e406a9cb..99e952293498 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -48,8 +48,9 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); + #define is_haswell(codec) ((codec)->vendor_id == 0x80862807) + #define is_broadwell(codec) ((codec)->vendor_id == 0x80862808) + #define is_skylake(codec) ((codec)->vendor_id == 0x80862809) ++#define is_broxton(codec) ((codec)->vendor_id == 0x8086280a) + #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \ +- || is_skylake(codec)) ++ || is_skylake(codec) || is_broxton(codec)) + + #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882) + #define is_cherryview(codec) ((codec)->vendor_id == 0x80862883) diff --git a/1520_keyring-refleak-in-join-session-CVE-2016-0728.patch b/1520_keyring-refleak-in-join-session-CVE-2016-0728.patch deleted file mode 100644 index 49020d7d..00000000 --- a/1520_keyring-refleak-in-join-session-CVE-2016-0728.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 23567fd052a9abb6d67fe8e7a9ccdd9800a540f2 Mon Sep 17 00:00:00 2001 -From: Yevgeny Pats <yevgeny@perception-point.io> -Date: Tue, 19 Jan 2016 22:09:04 +0000 -Subject: KEYS: Fix keyring ref leak in join_session_keyring() - -This fixes CVE-2016-0728. - -If a thread is asked to join as a session keyring the keyring that's already -set as its session, we leak a keyring reference. - -This can be tested with the following program: - - #include <stddef.h> - #include <stdio.h> - #include <sys/types.h> - #include <keyutils.h> - - int main(int argc, const char *argv[]) - { - int i = 0; - key_serial_t serial; - - serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, - "leaked-keyring"); - if (serial < 0) { - perror("keyctl"); - return -1; - } - - if (keyctl(KEYCTL_SETPERM, serial, - KEY_POS_ALL | KEY_USR_ALL) < 0) { - perror("keyctl"); - return -1; - } - - for (i = 0; i < 100; i++) { - serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, - "leaked-keyring"); - if (serial < 0) { - perror("keyctl"); - return -1; - } - } - - return 0; - } - -If, after the program has run, there something like the following line in -/proc/keys: - -3f3d898f I--Q--- 100 perm 3f3f0000 0 0 keyring leaked-keyring: empty - -with a usage count of 100 * the number of times the program has been run, -then the kernel is malfunctioning. If leaked-keyring has zero usages or -has been garbage collected, then the problem is fixed. - -Reported-by: Yevgeny Pats <yevgeny@perception-point.io> -Signed-off-by: David Howells <dhowells@redhat.com> -Acked-by: Don Zickus <dzickus@redhat.com> -Acked-by: Prarit Bhargava <prarit@redhat.com> -Acked-by: Jarod Wilson <jarod@redhat.com> -Signed-off-by: James Morris <james.l.morris@oracle.com> ---- - security/keys/process_keys.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index a3f85d2..e6d50172 100644 ---- a/security/keys/process_keys.c -+++ b/security/keys/process_keys.c -@@ -794,6 +794,7 @@ long join_session_keyring(const char *name) - ret = PTR_ERR(keyring); - goto error2; - } else if (keyring == new->session_keyring) { -+ key_put(keyring); - ret = 0; - goto error2; - } --- -cgit v0.12 - |