mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-22 14:51:41 +00:00
1464 lines
46 KiB
Diff
1464 lines
46 KiB
Diff
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
|