diff options
author | Mike Pagano <mpagano@gentoo.org> | 2016-01-23 13:58:32 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2016-01-23 13:58:32 -0500 |
commit | 01da9642fbcd26b4b893cdf36b9b8cfab0fa192b (patch) | |
tree | 2a70d4e2036a7fc98c7fd0833dce25c6428dacba | |
parent | Ensure that thread joining a session keyring does not leak the keyring refere... (diff) | |
download | linux-patches-01da9642fbcd26b4b893cdf36b9b8cfab0fa192b.tar.gz linux-patches-01da9642fbcd26b4b893cdf36b9b8cfab0fa192b.tar.bz2 linux-patches-01da9642fbcd26b4b893cdf36b9b8cfab0fa192b.zip |
Linux 3.14.59. Includes patch for CVE-2016-07283.14-66
-rw-r--r-- | 0000_README | 8 | ||||
-rw-r--r-- | 1058_linux-3.14.59.patch | 1464 | ||||
-rw-r--r-- | 1520_keyring-refleak-in-join-session-CVE-2016-0728.patch | 81 |
3 files changed, 1468 insertions, 85 deletions
diff --git a/0000_README b/0000_README index a31da20b..767949fb 100644 --- a/0000_README +++ b/0000_README @@ -274,6 +274,10 @@ Patch: 1057_linux-3.14.58.patch From: http://www.kernel.org Desc: Linux 3.14.58 +Patch: 1058_linux-3.14.59.patch +From: http://www.kernel.org +Desc: Linux 3.14.59 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. @@ -282,10 +286,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_enable-thinkpad-micled.patch From: https://bugs.gentoo.org/show_bug.cgi?id=449248 Desc: Enable mic mute led in thinkpads diff --git a/1058_linux-3.14.59.patch b/1058_linux-3.14.59.patch new file mode 100644 index 00000000..800aa75b --- /dev/null +++ b/1058_linux-3.14.59.patch @@ -0,0 +1,1464 @@ +diff --git a/Makefile b/Makefile +index 48a4d0b37c10..c2a6ec4d8803 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 58 ++SUBLEVEL = 59 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c +index 586f2f7f6993..df420af7e2ae 100644 +--- a/drivers/firewire/ohci.c ++++ b/drivers/firewire/ohci.c +@@ -3675,6 +3675,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 4d3258dd0a88..2c535fc5887d 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -1018,13 +1018,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/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 957f0ffe31c4..58f1a09d6f1d 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1424,6 +1424,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++; +@@ -1439,12 +1440,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/phy/broadcom.c b/drivers/net/phy/broadcom.c +index f8c90ea75108..7a1ff5797f12 100644 +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -848,7 +848,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = { + { PHY_ID_BCM5421, 0xfffffff0 }, + { PHY_ID_BCM5461, 0xfffffff0 }, + { PHY_ID_BCM5464, 0xfffffff0 }, +- { PHY_ID_BCM5482, 0xfffffff0 }, ++ { PHY_ID_BCM5481, 0xfffffff0 }, + { PHY_ID_BCM5482, 0xfffffff0 }, + { PHY_ID_BCM50610, 0xfffffff0 }, + { PHY_ID_BCM50610M, 0xfffffff0 }, +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/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index db21af8de9f6..3580938246b0 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -755,6 +755,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ + {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ + {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ ++ {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ + {QMI_FIXED_INTF(0x0b3c, 0xc000, 4)}, /* Olivetti Olicard 100 */ + {QMI_FIXED_INTF(0x0b3c, 0xc001, 4)}, /* Olivetti Olicard 120 */ + {QMI_FIXED_INTF(0x0b3c, 0xc002, 4)}, /* Olivetti Olicard 140 */ +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index d7049c393a33..2aca88715632 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1810,6 +1810,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 3ecc887eea27..12d14f91c4d3 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -116,7 +116,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 1847a7d38026..fa114bcedabf 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -130,6 +130,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. + */ +@@ -4350,6 +4354,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) { +@@ -4595,7 +4601,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, + if (status < 0) + goto loop; + +- usb_detect_quirks(udev); + if (udev->quirks & USB_QUIRK_DELAY_INIT) + msleep(1000); + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 804acc700327..00addda9ad53 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -205,6 +205,12 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { + /* Logitech Optical Mouse M90/M100 */ + { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* 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/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/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index d11335d4395d..c2bdc5f2a4b1 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 fb79775447b0..efb727a49262 100644 +--- a/drivers/usb/serial/usb-serial-simple.c ++++ b/drivers/usb/serial/usb-serial-simple.c +@@ -47,6 +47,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 0a841ddd6843..17bc3b5ac263 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -751,8 +751,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], +@@ -771,8 +779,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(); + } + + if (extent_end <= search_start) { +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index eaf8699ed559..7f0dcfc58cbf 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -1238,8 +1238,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/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index ff42208417b9..0b3af57acaef 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -88,13 +88,13 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) + return 0; + } + ++ err = handle->h_err; + if (!handle->h_transaction) { +- err = jbd2_journal_stop(handle); +- return handle->h_err ? handle->h_err : err; ++ rc = jbd2_journal_stop(handle); ++ return err ? err : rc; + } + + sb = handle->h_transaction->t_journal->j_private; +- err = handle->h_err; + rc = jbd2_journal_stop(handle); + + if (!err) +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a07af5b7a575..c05fc3aef69f 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 3b607a8609c4..ef5f39a73c51 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -2088,8 +2088,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 6659ce545f15..b6b426c75e4c 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -1675,7 +1675,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 d3f606255b99..d4fbaaee993a 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/ocfs2/namei.c b/fs/ocfs2/namei.c +index b2427623dd6c..cc0aeb9e81a2 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -345,6 +345,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 385593d748f6..e137e962834b 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 8b96ae2a38fe..5ef39160bd47 100644 +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -36,4 +36,7 @@ + /* device can't handle device_qualifier descriptor requests */ + #define USB_QUIRK_DEVICE_QUALIFIER 0x00000100 + ++/* 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/ip6_tunnel.h b/include/net/ip6_tunnel.h +index a5593dab6af7..ef9557683fec 100644 +--- a/include/net/ip6_tunnel.h ++++ b/include/net/ip6_tunnel.h +@@ -79,11 +79,12 @@ static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev) + err = ip6_local_out(skb); + + if (net_xmit_eval(err) == 0) { +- struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); ++ struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); + u64_stats_update_begin(&tstats->syncp); + tstats->tx_bytes += pkt_len; + tstats->tx_packets++; + u64_stats_update_end(&tstats->syncp); ++ put_cpu_ptr(tstats); + } else { + stats->tx_errors++; + stats->tx_aborted_errors++; +diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h +index 7b9ec5837496..62d2b169df01 100644 +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -166,12 +166,13 @@ static inline void iptunnel_xmit_stats(int err, + struct pcpu_sw_netstats __percpu *stats) + { + if (err > 0) { +- struct pcpu_sw_netstats *tstats = this_cpu_ptr(stats); ++ struct pcpu_sw_netstats *tstats = get_cpu_ptr(stats); + + u64_stats_update_begin(&tstats->syncp); + tstats->tx_bytes += err; + tstats->tx_packets++; + u64_stats_update_end(&tstats->syncp); ++ put_cpu_ptr(tstats); + } else if (err < 0) { + err_stats->tx_errors++; + err_stats->tx_aborted_errors++; +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index a60948d7bcea..30a8da3bb259 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -489,6 +489,7 @@ struct ip6_create_arg { + u32 user; + const struct in6_addr *src; + const struct in6_addr *dst; ++ int iif; + u8 ecn; + }; + +diff --git a/include/net/sock.h b/include/net/sock.h +index ff4f825647a5..031717ab68cb 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -374,6 +374,7 @@ struct sock { + sk_no_check : 2, + sk_userlocks : 4, + sk_protocol : 8, ++#define SK_PROTOCOL_MAX U8_MAX + sk_type : 16; + kmemcheck_bitfield_end(flags); + int sk_wmem_queued; +@@ -700,6 +701,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; +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 316dd4e0af39..cd7d93d3ef7a 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -459,6 +459,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/scm.c b/net/core/scm.c +index b442e7e25e60..d30eb057fa7b 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -306,6 +306,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) { + cmlen = CMSG_SPACE(i*sizeof(int)); ++ if (msg->msg_controllen < cmlen) ++ cmlen = msg->msg_controllen; + msg->msg_control += cmlen; + msg->msg_controllen -= cmlen; + } +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 366f7ff741b7..9ac664d8da33 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3997,7 +3997,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 8ebfa52e5d70..3b687b3c28b4 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) { +diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c +index 4c04848953bd..630f972c20d2 100644 +--- a/net/decnet/af_decnet.c ++++ b/net/decnet/af_decnet.c +@@ -677,6 +677,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 f4c804dbd3b4..a91e465b7449 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -260,6 +260,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/ipmr.c b/net/ipv4/ipmr.c +index a3d7ccfe154d..42809cf91488 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -136,7 +136,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, + struct mfc_cache *c, struct rtmsg *rtm); + static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, + int cmd); +-static void mroute_clean_tables(struct mr_table *mrt); ++static void mroute_clean_tables(struct mr_table *mrt, bool all); + static void ipmr_expire_process(unsigned long arg); + + #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES +@@ -348,7 +348,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) + static void ipmr_free_table(struct mr_table *mrt) + { + del_timer_sync(&mrt->ipmr_expire_timer); +- mroute_clean_tables(mrt); ++ mroute_clean_tables(mrt, true); + kfree(mrt); + } + +@@ -1201,7 +1201,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, + * Close the multicast socket, and clear the vif tables etc + */ + +-static void mroute_clean_tables(struct mr_table *mrt) ++static void mroute_clean_tables(struct mr_table *mrt, bool all) + { + int i; + LIST_HEAD(list); +@@ -1210,8 +1210,9 @@ static void mroute_clean_tables(struct mr_table *mrt) + /* Shut down all active vif entries */ + + for (i = 0; i < mrt->maxvif; i++) { +- if (!(mrt->vif_table[i].flags & VIFF_STATIC)) +- vif_delete(mrt, i, 0, &list); ++ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC)) ++ continue; ++ vif_delete(mrt, i, 0, &list); + } + unregister_netdevice_many(&list); + +@@ -1219,7 +1220,7 @@ static void mroute_clean_tables(struct mr_table *mrt) + + for (i = 0; i < MFC_LINES; i++) { + list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) { +- if (c->mfc_flags & MFC_STATIC) ++ if (!all && (c->mfc_flags & MFC_STATIC)) + continue; + list_del_rcu(&c->list); + mroute_netlink_event(mrt, c, RTM_DELROUTE); +@@ -1254,7 +1255,7 @@ static void mrtsock_destruct(struct sock *sk) + NETCONFA_IFINDEX_ALL, + net->ipv4.devconf_all); + RCU_INIT_POINTER(mrt->mroute_sk, NULL); +- mroute_clean_tables(mrt); ++ mroute_clean_tables(mrt, false); + } + } + rtnl_unlock(); +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 9fbd69efa999..5b10c59ba8a9 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5577,6 +5577,7 @@ discard: + } + + tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; ++ tp->copied_seq = tp->rcv_nxt; + tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; + + /* RFC1323: The window in SYN & SYN/ACK segments is +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index e2f8bd0d35ed..1b2a53e625cc 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -998,7 +998,8 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, + } + + md5sig = rcu_dereference_protected(tp->md5sig_info, +- sock_owned_by_user(sk)); ++ sock_owned_by_user(sk) || ++ lockdep_is_held(&sk->sk_lock.slock)); + if (!md5sig) { + md5sig = kmalloc(sizeof(*md5sig), gfp); + if (!md5sig) +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index d935889f1008..e56aa09f04d1 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -110,6 +110,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 baffa3b7a328..bbc5e64ee984 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1558,13 +1558,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/ip6mr.c b/net/ipv6/ip6mr.c +index 821d8dfb2ddd..9ad561152eb6 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -120,7 +120,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc, + int cmd); + static int ip6mr_rtm_dumproute(struct sk_buff *skb, + struct netlink_callback *cb); +-static void mroute_clean_tables(struct mr6_table *mrt); ++static void mroute_clean_tables(struct mr6_table *mrt, bool all); + static void ipmr_expire_process(unsigned long arg); + + #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES +@@ -337,7 +337,7 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id) + static void ip6mr_free_table(struct mr6_table *mrt) + { + del_timer(&mrt->ipmr_expire_timer); +- mroute_clean_tables(mrt); ++ mroute_clean_tables(mrt, true); + kfree(mrt); + } + +@@ -1536,7 +1536,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, + * Close the multicast socket, and clear the vif tables etc + */ + +-static void mroute_clean_tables(struct mr6_table *mrt) ++static void mroute_clean_tables(struct mr6_table *mrt, bool all) + { + int i; + LIST_HEAD(list); +@@ -1546,8 +1546,9 @@ static void mroute_clean_tables(struct mr6_table *mrt) + * Shut down all active vif entries + */ + for (i = 0; i < mrt->maxvif; i++) { +- if (!(mrt->vif6_table[i].flags & VIFF_STATIC)) +- mif6_delete(mrt, i, &list); ++ if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC)) ++ continue; ++ mif6_delete(mrt, i, &list); + } + unregister_netdevice_many(&list); + +@@ -1556,7 +1557,7 @@ static void mroute_clean_tables(struct mr6_table *mrt) + */ + for (i = 0; i < MFC6_LINES; i++) { + list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { +- if (c->mfc_flags & MFC_STATIC) ++ if (!all && (c->mfc_flags & MFC_STATIC)) + continue; + write_lock_bh(&mrt_lock); + list_del(&c->list); +@@ -1619,7 +1620,7 @@ int ip6mr_sk_done(struct sock *sk) + net->ipv6.devconf_all); + write_unlock_bh(&mrt_lock); + +- mroute_clean_tables(mrt); ++ mroute_clean_tables(mrt, false); + err = 0; + break; + } +diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c +index 761e4586ab5f..0b1bf2d17abf 100644 +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@ -1636,7 +1636,6 @@ out: + if (!err) { + ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); + ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); +- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); + } else { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); + } +@@ -2000,7 +1999,6 @@ out: + if (!err) { + ICMP6MSGOUT_INC_STATS(net, idev, type); + ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); +- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len); + } else + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); + +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index 767ab8da8218..883d62362a9f 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -184,7 +184,7 @@ static void nf_ct_frag6_expire(unsigned long data) + /* Creation primitives. */ + static inline struct frag_queue *fq_find(struct net *net, __be32 id, + u32 user, struct in6_addr *src, +- struct in6_addr *dst, u8 ecn) ++ struct in6_addr *dst, int iif, u8 ecn) + { + struct inet_frag_queue *q; + struct ip6_create_arg arg; +@@ -194,6 +194,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, + arg.user = user; + arg.src = src; + arg.dst = dst; ++ arg.iif = iif; + arg.ecn = ecn; + + read_lock_bh(&nf_frags.lock); +@@ -602,7 +603,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) + local_bh_enable(); + + fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, +- ip6_frag_ecn(hdr)); ++ skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr)); + if (fq == NULL) { + pr_debug("Can't find and can't create new queue\n"); + goto ret_orig; +diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c +index cc85a9ba5010..9c15250eac1d 100644 +--- a/net/ipv6/reassembly.c ++++ b/net/ipv6/reassembly.c +@@ -111,7 +111,10 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a) + return fq->id == arg->id && + fq->user == arg->user && + ipv6_addr_equal(&fq->saddr, arg->src) && +- ipv6_addr_equal(&fq->daddr, arg->dst); ++ ipv6_addr_equal(&fq->daddr, arg->dst) && ++ (arg->iif == fq->iif || ++ !(ipv6_addr_type(arg->dst) & (IPV6_ADDR_MULTICAST | ++ IPV6_ADDR_LINKLOCAL))); + } + EXPORT_SYMBOL(ip6_frag_match); + +@@ -180,7 +183,7 @@ static void ip6_frag_expire(unsigned long data) + + static __inline__ struct frag_queue * + fq_find(struct net *net, __be32 id, const struct in6_addr *src, +- const struct in6_addr *dst, u8 ecn) ++ const struct in6_addr *dst, int iif, u8 ecn) + { + struct inet_frag_queue *q; + struct ip6_create_arg arg; +@@ -190,6 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, + arg.user = IP6_DEFRAG_LOCAL_DELIVER; + arg.src = src; + arg.dst = dst; ++ arg.iif = iif; + arg.ecn = ecn; + + read_lock(&ip6_frags.lock); +@@ -558,7 +562,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) + IPSTATS_MIB_REASMFAILS, evicted); + + fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, +- ip6_frag_ecn(hdr)); ++ skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr)); + if (fq != NULL) { + int ret; + +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index 54747c25c86c..f945293c17f0 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1103,6 +1103,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/packet/af_packet.c b/net/packet/af_packet.c +index c53684eeddb3..25d329a18616 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2091,6 +2091,15 @@ static void tpacket_destruct_skb(struct sk_buff *skb) + sock_wfree(skb); + } + ++static void tpacket_set_protocol(const struct net_device *dev, ++ struct sk_buff *skb) ++{ ++ if (dev->type == ARPHRD_ETHER) { ++ skb_reset_mac_header(skb); ++ skb->protocol = eth_hdr(skb)->h_proto; ++ } ++} ++ + static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, + void *frame, struct net_device *dev, int size_max, + __be16 proto, unsigned char *addr, int hlen) +@@ -2127,8 +2136,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, + skb_reserve(skb, hlen); + skb_reset_network_header(skb); + +- if (!packet_use_direct_xmit(po)) +- skb_probe_transport_header(skb, 0); + if (unlikely(po->tp_tx_has_off)) { + int off_min, off_max, off; + off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll); +@@ -2178,6 +2185,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, + dev->hard_header_len); + if (unlikely(err)) + return err; ++ if (!skb->protocol) ++ tpacket_set_protocol(dev, skb); + + data += dev->hard_header_len; + to_write -= dev->hard_header_len; +@@ -2212,6 +2221,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, + len = ((to_write > len_max) ? len_max : to_write); + } + ++ skb_probe_transport_header(skb, 0); ++ + return tp_len; + } + +@@ -2537,8 +2548,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) + len += vnet_hdr_len; + } + +- if (!packet_use_direct_xmit(po)) +- skb_probe_transport_header(skb, reserve); ++ skb_probe_transport_header(skb, reserve); ++ + if (unlikely(extra_len == 4)) + skb->no_fcs = 1; + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index fb7976aee61c..603c3bbc5923 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -800,8 +800,8 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, + if (!has_sha1) + return -EINVAL; + +- memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0], +- hmacs->shmac_num_idents * sizeof(__u16)); ++ for (i = 0; i < hmacs->shmac_num_idents; i++) ++ ep->auth_hmacs_list->hmac_ids[i] = htons(hmacs->shmac_idents[i]); + ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) + + hmacs->shmac_num_idents * sizeof(__u16)); + return 0; +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 2b1738ef9394..1b9b4528b5f3 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -638,6 +638,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) +@@ -657,6 +658,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 df06b13a50f6..557d7a7d95b0 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_compare(bear_cookie->expiration, kt) < 0) { + /* +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index f940fdc540f5..a7400f65b9b5 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -6985,6 +6985,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, +@@ -7165,6 +7168,13 @@ struct proto sctp_prot = { + + #if IS_ENABLED(CONFIG_IPV6) + ++#include <net/transp_v6.h> ++static void sctp_v6_destroy_sock(struct sock *sk) ++{ ++ sctp_destroy_sock(sk); ++ inet6_destroy_sock(sk); ++} ++ + struct proto sctpv6_prot = { + .name = "SCTPv6", + .owner = THIS_MODULE, +@@ -7174,7 +7184,7 @@ struct proto sctpv6_prot = { + .accept = sctp_accept, + .ioctl = sctp_ioctl, + .init = sctp_init_sock, +- .destroy = sctp_destroy_sock, ++ .destroy = sctp_v6_destroy_sock, + .shutdown = sctp_shutdown, + .setsockopt = sctp_setsockopt, + .getsockopt = sctp_getsockopt, +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 4affedbe0206..ae0d0654f8c4 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; +@@ -1536,12 +1654,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 +@@ -1549,10 +1669,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); +@@ -1578,21 +1702,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); +@@ -1606,6 +1747,8 @@ restart: + return len; + + out_unlock: ++ if (sk_locked) ++ unix_state_unlock(sk); + unix_state_unlock(other); + out_free: + kfree_skb(skb); +@@ -1947,14 +2090,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); +@@ -1995,12 +2131,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); +@@ -2263,14 +2399,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/gc.c b/security/keys/gc.c +index 009d9370c8fd..4a780333c22c 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -143,6 +143,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + kdebug("- %u", key->serial); + key_check(key); + ++ /* Throw away the key data if the key is instantiated */ ++ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && ++ !test_bit(KEY_FLAG_NEGATIVE, &key->flags) && ++ key->type->destroy) ++ key->type->destroy(key); ++ + security_key_free(key); + + /* deal with the user's key tracking and quota */ +@@ -157,10 +163,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) + atomic_dec(&key->user->nikeys); + +- /* now throw away the key memory */ +- if (key->type->destroy) +- key->type->destroy(key); +- + key_user_put(key->user); + + kfree(key->description); +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index cee72ce64222..cb1eef9ed4fd 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -744,16 +744,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 0cf8a130a267..4e56371f239f 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -793,6 +793,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/tools/net/Makefile b/tools/net/Makefile +index ee577ea03ba5..ddf888010652 100644 +--- a/tools/net/Makefile ++++ b/tools/net/Makefile +@@ -4,6 +4,9 @@ CC = gcc + LEX = flex + YACC = bison + ++CFLAGS += -Wall -O2 ++CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include ++ + %.yacc.c: %.y + $(YACC) -o $@ -d $< + +@@ -12,15 +15,13 @@ YACC = bison + + all : bpf_jit_disasm bpf_dbg bpf_asm + +-bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm' ++bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm' + bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl + bpf_jit_disasm : bpf_jit_disasm.o + +-bpf_dbg : CFLAGS = -Wall -O2 + bpf_dbg : LDLIBS = -lreadline + bpf_dbg : bpf_dbg.o + +-bpf_asm : CFLAGS = -Wall -O2 -I. + bpf_asm : LDLIBS = + bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o + bpf_exp.lex.o : bpf_exp.yacc.c 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 - |