summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2015-08-11 22:13:21 -0400
committerAnthony G. Basile <blueness@gentoo.org>2015-08-11 22:13:21 -0400
commit1de11cdd8e7748bb66eca924f709d2055f64efe0 (patch)
tree7a7097d1c05ab726e674e737b5708fc4a9eeda3b /3.2.69/1056_linux-3.2.57.patch
parentgrsecurity-{3.14.49,4.1.4}-201508032312 (diff)
downloadhardened-patchset-1de11cdd8e7748bb66eca924f709d2055f64efe0.tar.gz
hardened-patchset-1de11cdd8e7748bb66eca924f709d2055f64efe0.tar.bz2
hardened-patchset-1de11cdd8e7748bb66eca924f709d2055f64efe0.zip
grsecurity-{3.2.70,3.14.50,4.1.5}-20150810212920150810
Diffstat (limited to '3.2.69/1056_linux-3.2.57.patch')
-rw-r--r--3.2.69/1056_linux-3.2.57.patch905
1 files changed, 0 insertions, 905 deletions
diff --git a/3.2.69/1056_linux-3.2.57.patch b/3.2.69/1056_linux-3.2.57.patch
deleted file mode 100644
index 7b8f174..0000000
--- a/3.2.69/1056_linux-3.2.57.patch
+++ /dev/null
@@ -1,905 +0,0 @@
-diff --git a/Makefile b/Makefile
-index ec90bfb..c92db9b 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 3
- PATCHLEVEL = 2
--SUBLEVEL = 56
-+SUBLEVEL = 57
- EXTRAVERSION =
- NAME = Saber-toothed Squirrel
-
-diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
-index 99348c0..78be245 100644
---- a/arch/s390/kernel/head64.S
-+++ b/arch/s390/kernel/head64.S
-@@ -61,7 +61,7 @@ ENTRY(startup_continue)
- .quad 0 # cr12: tracing off
- .quad 0 # cr13: home space segment table
- .quad 0xc0000000 # cr14: machine check handling off
-- .quad 0 # cr15: linkage stack operations
-+ .quad .Llinkage_stack # cr15: linkage stack operations
- .Lpcmsk:.quad 0x0000000180000000
- .L4malign:.quad 0xffffffffffc00000
- .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
-@@ -69,12 +69,15 @@ ENTRY(startup_continue)
- .Lparmaddr:
- .quad PARMAREA
- .align 64
--.Lduct: .long 0,0,0,0,.Lduald,0,0,0
-+.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0
- .long 0,0,0,0,0,0,0,0
-+.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0
- .align 128
- .Lduald:.rept 8
- .long 0x80000000,0,0,0 # invalid access-list entries
- .endr
-+.Llinkage_stack:
-+ .long 0,0,0x89000000,0,0,0,0x8a000000,0
-
- ENTRY(_ehead)
-
-diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
-index f1b36cf..db2ffef 100644
---- a/arch/x86/kvm/mmu.c
-+++ b/arch/x86/kvm/mmu.c
-@@ -2451,6 +2451,9 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
- int emulate = 0;
- gfn_t pseudo_gfn;
-
-+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
-+ return 0;
-+
- for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
- if (iterator.level == level) {
- unsigned pte_access = ACC_ALL;
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index aac5ea7..a4f6bda 100644
---- a/arch/x86/kvm/vmx.c
-+++ b/arch/x86/kvm/vmx.c
-@@ -6273,8 +6273,8 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- free_vpid(vmx);
-- free_nested(vmx);
- free_loaded_vmcs(vmx->loaded_vmcs);
-+ free_nested(vmx);
- kfree(vmx->guest_msrs);
- kvm_vcpu_uninit(vcpu);
- kmem_cache_free(kvm_vcpu_cache, vmx);
-diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
-index 7be5fd9..bc35070 100644
---- a/drivers/input/mouse/synaptics.c
-+++ b/drivers/input/mouse/synaptics.c
-@@ -237,11 +237,22 @@ static int synaptics_identify(struct psmouse *psmouse)
- * Read touchpad resolution and maximum reported coordinates
- * Resolution is left zero if touchpad does not support the query
- */
-+
-+static const int *quirk_min_max;
-+
- static int synaptics_resolution(struct psmouse *psmouse)
- {
- struct synaptics_data *priv = psmouse->private;
- unsigned char resp[3];
-
-+ if (quirk_min_max) {
-+ priv->x_min = quirk_min_max[0];
-+ priv->x_max = quirk_min_max[1];
-+ priv->y_min = quirk_min_max[2];
-+ priv->y_max = quirk_min_max[3];
-+ return 0;
-+ }
-+
- if (SYN_ID_MAJOR(priv->identity) < 4)
- return 0;
-
-@@ -1364,10 +1375,54 @@ static const struct dmi_system_id __initconst olpc_dmi_table[] = {
- { }
- };
-
-+static const struct dmi_system_id min_max_dmi_table[] __initconst = {
-+#if defined(CONFIG_DMI)
-+ {
-+ /* Lenovo ThinkPad Helix */
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
-+ },
-+ .driver_data = (int []){1024, 5052, 2258, 4832},
-+ },
-+ {
-+ /* Lenovo ThinkPad X240 */
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
-+ },
-+ .driver_data = (int []){1232, 5710, 1156, 4696},
-+ },
-+ {
-+ /* Lenovo ThinkPad T440s */
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
-+ },
-+ .driver_data = (int []){1024, 5112, 2024, 4832},
-+ },
-+ {
-+ /* Lenovo ThinkPad T540p */
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
-+ },
-+ .driver_data = (int []){1024, 5056, 2058, 4832},
-+ },
-+#endif
-+ { }
-+};
-+
- void __init synaptics_module_init(void)
- {
-+ const struct dmi_system_id *min_max_dmi;
-+
- impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
- broken_olpc_ec = dmi_check_system(olpc_dmi_table);
-+
-+ min_max_dmi = dmi_first_match(min_max_dmi_table);
-+ if (min_max_dmi)
-+ quirk_min_max = min_max_dmi->driver_data;
- }
-
- int synaptics_init(struct psmouse *psmouse)
-diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
-index 6729585..98ab759 100644
---- a/drivers/net/usb/asix.c
-+++ b/drivers/net/usb/asix.c
-@@ -183,6 +183,17 @@ struct ax88172_int_data {
- __le16 res3;
- } __packed;
-
-+struct asix_rx_fixup_info {
-+ struct sk_buff *ax_skb;
-+ u32 header;
-+ u16 size;
-+ bool split_head;
-+};
-+
-+struct asix_common_private {
-+ struct asix_rx_fixup_info rx_fixup_info;
-+};
-+
- static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
- {
-@@ -304,97 +315,89 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- }
- }
-
--static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+static int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
-+ struct asix_rx_fixup_info *rx)
- {
-- u8 *head;
-- u32 header;
-- char *packet;
-- struct sk_buff *ax_skb;
-- u16 size;
-+ int offset = 0;
-+
-+ while (offset + sizeof(u16) <= skb->len) {
-+ u16 remaining = 0;
-+ unsigned char *data;
-+
-+ if (!rx->size) {
-+ if ((skb->len - offset == sizeof(u16)) ||
-+ rx->split_head) {
-+ if(!rx->split_head) {
-+ rx->header = get_unaligned_le16(
-+ skb->data + offset);
-+ rx->split_head = true;
-+ offset += sizeof(u16);
-+ break;
-+ } else {
-+ rx->header |= (get_unaligned_le16(
-+ skb->data + offset)
-+ << 16);
-+ rx->split_head = false;
-+ offset += sizeof(u16);
-+ }
-+ } else {
-+ rx->header = get_unaligned_le32(skb->data +
-+ offset);
-+ offset += sizeof(u32);
-+ }
-
-- head = (u8 *) skb->data;
-- memcpy(&header, head, sizeof(header));
-- le32_to_cpus(&header);
-- packet = head + sizeof(header);
--
-- skb_pull(skb, 4);
--
-- while (skb->len > 0) {
-- if ((header & 0x07ff) != ((~header >> 16) & 0x07ff))
-- netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n");
--
-- /* get the packet length */
-- size = (u16) (header & 0x000007ff);
--
-- if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
-- u8 alignment = (unsigned long)skb->data & 0x3;
-- if (alignment != 0x2) {
-- /*
-- * not 16bit aligned so use the room provided by
-- * the 32 bit header to align the data
-- *
-- * note we want 16bit alignment as MAC header is
-- * 14bytes thus ip header will be aligned on
-- * 32bit boundary so accessing ipheader elements
-- * using a cast to struct ip header wont cause
-- * an unaligned accesses.
-- */
-- u8 realignment = (alignment + 2) & 0x3;
-- memmove(skb->data - realignment,
-- skb->data,
-- size);
-- skb->data -= realignment;
-- skb_set_tail_pointer(skb, size);
-+ /* get the packet length */
-+ rx->size = (u16) (rx->header & 0x7ff);
-+ if (rx->size != ((~rx->header >> 16) & 0x7ff)) {
-+ netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
-+ rx->header, offset);
-+ rx->size = 0;
-+ return 0;
- }
-- return 2;
-+ rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
-+ rx->size);
-+ if (!rx->ax_skb)
-+ return 0;
- }
-
-- if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
-+ if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
- netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
-- size);
-- return 0;
-- }
-- ax_skb = skb_clone(skb, GFP_ATOMIC);
-- if (ax_skb) {
-- u8 alignment = (unsigned long)packet & 0x3;
-- ax_skb->len = size;
--
-- if (alignment != 0x2) {
-- /*
-- * not 16bit aligned use the room provided by
-- * the 32 bit header to align the data
-- */
-- u8 realignment = (alignment + 2) & 0x3;
-- memmove(packet - realignment, packet, size);
-- packet -= realignment;
-- }
-- ax_skb->data = packet;
-- skb_set_tail_pointer(ax_skb, size);
-- usbnet_skb_return(dev, ax_skb);
-- } else {
-+ rx->size);
-+ kfree_skb(rx->ax_skb);
- return 0;
- }
-
-- skb_pull(skb, (size + 1) & 0xfffe);
-+ if (rx->size > skb->len - offset) {
-+ remaining = rx->size - (skb->len - offset);
-+ rx->size = skb->len - offset;
-+ }
-
-- if (skb->len < sizeof(header))
-- break;
-+ data = skb_put(rx->ax_skb, rx->size);
-+ memcpy(data, skb->data + offset, rx->size);
-+ if (!remaining)
-+ usbnet_skb_return(dev, rx->ax_skb);
-
-- head = (u8 *) skb->data;
-- memcpy(&header, head, sizeof(header));
-- le32_to_cpus(&header);
-- packet = head + sizeof(header);
-- skb_pull(skb, 4);
-+ offset += (rx->size + 1) & 0xfffe;
-+ rx->size = remaining;
- }
-
-- if (skb->len < 0) {
-- netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n",
-- skb->len);
-+ if (skb->len != offset) {
-+ netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n",
-+ skb->len, offset);
- return 0;
- }
-+
- return 1;
- }
-
-+static int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb)
-+{
-+ struct asix_common_private *dp = dev->driver_priv;
-+ struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
-+
-+ return asix_rx_fixup_internal(dev, skb, rx);
-+}
-+
- static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- gfp_t flags)
- {
-@@ -1154,9 +1157,19 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
- dev->rx_urb_size = 2048;
- }
-
-+ dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
-+ if (!dev->driver_priv)
-+ return -ENOMEM;
-+
- return 0;
- }
-
-+static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+ if (dev->driver_priv)
-+ kfree(dev->driver_priv);
-+}
-+
- static struct ethtool_ops ax88178_ethtool_ops = {
- .get_drvinfo = asix_get_drvinfo,
- .get_link = asix_get_link,
-@@ -1489,6 +1502,10 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
- dev->rx_urb_size = 2048;
- }
-
-+ dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
-+ if (!dev->driver_priv)
-+ return -ENOMEM;
-+
- return 0;
- }
-
-@@ -1535,22 +1552,25 @@ static const struct driver_info hawking_uf200_info = {
- static const struct driver_info ax88772_info = {
- .description = "ASIX AX88772 USB 2.0 Ethernet",
- .bind = ax88772_bind,
-+ .unbind = ax88772_unbind,
- .status = asix_status,
- .link_reset = ax88772_link_reset,
- .reset = ax88772_reset,
-- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
-- .rx_fixup = asix_rx_fixup,
-+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
-+ .rx_fixup = asix_rx_fixup_common,
- .tx_fixup = asix_tx_fixup,
- };
-
- static const struct driver_info ax88178_info = {
- .description = "ASIX AX88178 USB 2.0 Ethernet",
- .bind = ax88178_bind,
-+ .unbind = ax88772_unbind,
- .status = asix_status,
- .link_reset = ax88178_link_reset,
- .reset = ax88178_reset,
-- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
-- .rx_fixup = asix_rx_fixup,
-+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
-+ FLAG_MULTI_PACKET,
-+ .rx_fixup = asix_rx_fixup_common,
- .tx_fixup = asix_tx_fixup,
- };
-
-diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
-index 07a7f54..6829195 100644
---- a/drivers/staging/speakup/kobjects.c
-+++ b/drivers/staging/speakup/kobjects.c
-@@ -521,9 +521,9 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
- spk_lock(flags);
-
- if (*punc_buf == 'd' || *punc_buf == 'r')
-- x = set_mask_bits(0, var->value, 3);
-+ x = spk_set_mask_bits(0, var->value, 3);
- else
-- x = set_mask_bits(punc_buf, var->value, 3);
-+ x = spk_set_mask_bits(punc_buf, var->value, 3);
-
- spk_unlock(flags);
- return count;
-diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
-index 0d70f68..a076351 100644
---- a/drivers/staging/speakup/main.c
-+++ b/drivers/staging/speakup/main.c
-@@ -2265,7 +2265,7 @@ static int __init speakup_init(void)
- (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
- speakup_register_var(var);
- for (i = 1; punc_info[i].mask != 0; i++)
-- set_mask_bits(0, i, 2);
-+ spk_set_mask_bits(0, i, 2);
-
- set_key_info(key_defaults, key_buf);
- if (quiet_boot)
-diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
-index 412b879..f39c0a2 100644
---- a/drivers/staging/speakup/speakup.h
-+++ b/drivers/staging/speakup/speakup.h
-@@ -71,7 +71,7 @@ extern struct st_var_header *var_header_by_name(const char *name);
- extern struct punc_var_t *get_punc_var(enum var_id_t var_id);
- extern int set_num_var(int val, struct st_var_header *var, int how);
- extern int set_string_var(const char *page, struct st_var_header *var, int len);
--extern int set_mask_bits(const char *input, const int which, const int how);
-+extern int spk_set_mask_bits(const char *input, const int which, const int how);
- extern special_func special_handler;
- extern int handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key);
- extern int synth_init(char *name);
-diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
-index ab7de93..75eaf27 100644
---- a/drivers/staging/speakup/varhandlers.c
-+++ b/drivers/staging/speakup/varhandlers.c
-@@ -267,11 +267,11 @@ int set_string_var(const char *page, struct st_var_header *var, int len)
- return ret;
- }
-
--/* set_mask_bits sets or clears the punc/delim/repeat bits,
-+/* spk_set_mask_bits sets or clears the punc/delim/repeat bits,
- * if input is null uses the defaults.
- * values for how: 0 clears bits of chars supplied,
- * 1 clears allk, 2 sets bits for chars */
--int set_mask_bits(const char *input, const int which, const int how)
-+int spk_set_mask_bits(const char *input, const int which, const int how)
- {
- u_char *cp;
- short mask = punc_info[which].mask;
-diff --git a/fs/cifs/file.c b/fs/cifs/file.c
-index c55808e..aa05d5e 100644
---- a/fs/cifs/file.c
-+++ b/fs/cifs/file.c
-@@ -2107,7 +2107,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
- {
- unsigned int written;
- unsigned long num_pages, npages, i;
-- size_t copied, len, cur_len;
-+ size_t bytes, copied, len, cur_len;
- ssize_t total_written = 0;
- struct kvec *to_send;
- struct page **pages;
-@@ -2165,17 +2165,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
- do {
- size_t save_len = cur_len;
- for (i = 0; i < npages; i++) {
-- copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
-+ bytes = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
- copied = iov_iter_copy_from_user(pages[i], &it, 0,
-- copied);
-+ bytes);
- cur_len -= copied;
- iov_iter_advance(&it, copied);
- to_send[i+1].iov_base = kmap(pages[i]);
- to_send[i+1].iov_len = copied;
-+ /*
-+ * If we didn't copy as much as we expected, then that
-+ * may mean we trod into an unmapped area. Stop copying
-+ * at that point. On the next pass through the big
-+ * loop, we'll likely end up getting a zero-length
-+ * write and bailing out of it.
-+ */
-+ if (copied < bytes)
-+ break;
- }
-
- cur_len = save_len - cur_len;
-
-+ /*
-+ * If we have no data to send, then that probably means that
-+ * the copy above failed altogether. That's most likely because
-+ * the address in the iovec was bogus. Set the rc to -EFAULT,
-+ * free anything we allocated and bail out.
-+ */
-+ if (!cur_len) {
-+ kunmap(pages[0]);
-+ if (!total_written)
-+ total_written = -EFAULT;
-+ break;
-+ }
-+
-+ /*
-+ * i + 1 now represents the number of pages we actually used in
-+ * the copy phase above.
-+ */
-+ npages = min(npages, i + 1);
-+
- do {
- if (open_file->invalidHandle) {
- rc = cifs_reopen_file(open_file, false);
-diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
-index 45778a6..dc9f0ec 100644
---- a/fs/ext4/inode.c
-+++ b/fs/ext4/inode.c
-@@ -38,6 +38,7 @@
- #include <linux/printk.h>
- #include <linux/slab.h>
- #include <linux/ratelimit.h>
-+#include <linux/bitops.h>
-
- #include "ext4_jbd2.h"
- #include "xattr.h"
-@@ -3694,18 +3695,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
- void ext4_set_inode_flags(struct inode *inode)
- {
- unsigned int flags = EXT4_I(inode)->i_flags;
-+ unsigned int new_fl = 0;
-
-- inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
- if (flags & EXT4_SYNC_FL)
-- inode->i_flags |= S_SYNC;
-+ new_fl |= S_SYNC;
- if (flags & EXT4_APPEND_FL)
-- inode->i_flags |= S_APPEND;
-+ new_fl |= S_APPEND;
- if (flags & EXT4_IMMUTABLE_FL)
-- inode->i_flags |= S_IMMUTABLE;
-+ new_fl |= S_IMMUTABLE;
- if (flags & EXT4_NOATIME_FL)
-- inode->i_flags |= S_NOATIME;
-+ new_fl |= S_NOATIME;
- if (flags & EXT4_DIRSYNC_FL)
-- inode->i_flags |= S_DIRSYNC;
-+ new_fl |= S_DIRSYNC;
-+ set_mask_bits(&inode->i_flags,
-+ S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl);
- }
-
- /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
-diff --git a/include/linux/bitops.h b/include/linux/bitops.h
-index fc8a3ff..87a375f 100644
---- a/include/linux/bitops.h
-+++ b/include/linux/bitops.h
-@@ -168,6 +168,21 @@ static inline unsigned long __ffs64(u64 word)
-
- #ifdef __KERNEL__
-
-+#ifndef set_mask_bits
-+#define set_mask_bits(ptr, _mask, _bits) \
-+({ \
-+ const typeof(*ptr) mask = (_mask), bits = (_bits); \
-+ typeof(*ptr) old, new; \
-+ \
-+ do { \
-+ old = ACCESS_ONCE(*ptr); \
-+ new = (old & ~mask) | bits; \
-+ } while (cmpxchg(ptr, old, new) != old); \
-+ \
-+ new; \
-+})
-+#endif
-+
- #ifndef find_last_bit
- /**
- * find_last_bit - find the last set bit in a memory region
-diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index 85180bf..13bd6d0 100644
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -2143,6 +2143,8 @@ extern int skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
-
- extern struct sk_buff *skb_segment(struct sk_buff *skb, u32 features);
-
-+unsigned int skb_gso_transport_seglen(const struct sk_buff *skb);
-+
- static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
- int len, void *buffer)
- {
-@@ -2555,5 +2557,22 @@ static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
-
- return true;
- }
-+
-+/**
-+ * skb_gso_network_seglen - Return length of individual segments of a gso packet
-+ *
-+ * @skb: GSO skb
-+ *
-+ * skb_gso_network_seglen is used to determine the real size of the
-+ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
-+ *
-+ * The MAC/L2 header is not accounted for.
-+ */
-+static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
-+{
-+ unsigned int hdr_len = skb_transport_header(skb) -
-+ skb_network_header(skb);
-+ return hdr_len + skb_gso_transport_seglen(skb);
-+}
- #endif /* __KERNEL__ */
- #endif /* _LINUX_SKBUFF_H */
-diff --git a/ipc/msg.c b/ipc/msg.c
-index 7385de2..25f1a61 100644
---- a/ipc/msg.c
-+++ b/ipc/msg.c
-@@ -296,7 +296,9 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
- }
- atomic_sub(msq->q_cbytes, &ns->msg_bytes);
- security_msg_queue_free(msq);
-+ ipc_lock_by_ptr(&msq->q_perm);
- ipc_rcu_putref(msq);
-+ ipc_unlock(&msq->q_perm);
- }
-
- /*
-diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 5d6cb54..8ac4a0f 100644
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -45,6 +45,8 @@
- #include <linux/in.h>
- #include <linux/inet.h>
- #include <linux/slab.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
- #include <linux/netdevice.h>
- #ifdef CONFIG_NET_CLS_ACT
- #include <net/pkt_sched.h>
-@@ -3181,3 +3183,26 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb)
- " while LRO is enabled\n", skb->dev->name);
- }
- EXPORT_SYMBOL(__skb_warn_lro_forwarding);
-+
-+/**
-+ * skb_gso_transport_seglen - Return length of individual segments of a gso packet
-+ *
-+ * @skb: GSO skb
-+ *
-+ * skb_gso_transport_seglen is used to determine the real size of the
-+ * individual segments, including Layer4 headers (TCP/UDP).
-+ *
-+ * The MAC/L2 or network (IP, IPv6) headers are not accounted for.
-+ */
-+unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
-+{
-+ const struct skb_shared_info *shinfo = skb_shinfo(skb);
-+ unsigned int hdr_len;
-+
-+ if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-+ hdr_len = tcp_hdrlen(skb);
-+ else
-+ hdr_len = sizeof(struct udphdr);
-+ return hdr_len + shinfo->gso_size;
-+}
-+EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
-diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
-index 29a07b6..e0d9f02 100644
---- a/net/ipv4/ip_forward.c
-+++ b/net/ipv4/ip_forward.c
-@@ -39,6 +39,68 @@
- #include <net/route.h>
- #include <net/xfrm.h>
-
-+static bool ip_may_fragment(const struct sk_buff *skb)
-+{
-+ return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
-+ !skb->local_df;
-+}
-+
-+static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
-+{
-+ if (skb->len <= mtu || skb->local_df)
-+ return false;
-+
-+ if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
-+ return false;
-+
-+ return true;
-+}
-+
-+static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
-+{
-+ unsigned int mtu;
-+
-+ if (skb->local_df || !skb_is_gso(skb))
-+ return false;
-+
-+ mtu = dst_mtu(skb_dst(skb));
-+
-+ /* if seglen > mtu, do software segmentation for IP fragmentation on
-+ * output. DF bit cannot be set since ip_forward would have sent
-+ * icmp error.
-+ */
-+ return skb_gso_network_seglen(skb) > mtu;
-+}
-+
-+/* called if GSO skb needs to be fragmented on forward */
-+static int ip_forward_finish_gso(struct sk_buff *skb)
-+{
-+ struct sk_buff *segs;
-+ int ret = 0;
-+
-+ segs = skb_gso_segment(skb, 0);
-+ if (IS_ERR(segs)) {
-+ kfree_skb(skb);
-+ return -ENOMEM;
-+ }
-+
-+ consume_skb(skb);
-+
-+ do {
-+ struct sk_buff *nskb = segs->next;
-+ int err;
-+
-+ segs->next = NULL;
-+ err = dst_output(segs);
-+
-+ if (err && ret == 0)
-+ ret = err;
-+ segs = nskb;
-+ } while (segs);
-+
-+ return ret;
-+}
-+
- static int ip_forward_finish(struct sk_buff *skb)
- {
- struct ip_options * opt = &(IPCB(skb)->opt);
-@@ -48,6 +110,9 @@ static int ip_forward_finish(struct sk_buff *skb)
- if (unlikely(opt->optlen))
- ip_forward_options(skb);
-
-+ if (ip_gso_exceeds_dst_mtu(skb))
-+ return ip_forward_finish_gso(skb);
-+
- return dst_output(skb);
- }
-
-@@ -87,8 +152,7 @@ int ip_forward(struct sk_buff *skb)
- if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
- goto sr_failed;
-
-- if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
-- (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
-+ if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, dst_mtu(&rt->dst))) {
- IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(dst_mtu(&rt->dst)));
-diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index d3fde7e..cd4b529 100644
---- a/net/ipv6/ip6_output.c
-+++ b/net/ipv6/ip6_output.c
-@@ -381,6 +381,17 @@ static inline int ip6_forward_finish(struct sk_buff *skb)
- return dst_output(skb);
- }
-
-+static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
-+{
-+ if (skb->len <= mtu || skb->local_df)
-+ return false;
-+
-+ if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
-+ return false;
-+
-+ return true;
-+}
-+
- int ip6_forward(struct sk_buff *skb)
- {
- struct dst_entry *dst = skb_dst(skb);
-@@ -504,7 +515,7 @@ int ip6_forward(struct sk_buff *skb)
- if (mtu < IPV6_MIN_MTU)
- mtu = IPV6_MIN_MTU;
-
-- if (skb->len > mtu && !skb_is_gso(skb)) {
-+ if (ip6_pkt_too_big(skb, mtu)) {
- /* Again, force OUTPUT device used as source address */
- skb->dev = dst->dev;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
-index 2e664a6..8aa94ee 100644
---- a/net/netfilter/nf_conntrack_proto_dccp.c
-+++ b/net/netfilter/nf_conntrack_proto_dccp.c
-@@ -431,7 +431,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
- const char *msg;
- u_int8_t state;
-
-- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
-+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
- BUG_ON(dh == NULL);
-
- state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
-@@ -483,7 +483,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
- u_int8_t type, old_state, new_state;
- enum ct_dccp_roles role;
-
-- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
-+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
- BUG_ON(dh == NULL);
- type = dh->dccph_type;
-
-@@ -575,7 +575,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
- unsigned int cscov;
- const char *msg;
-
-- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
-+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
- if (dh == NULL) {
- msg = "nf_ct_dccp: short packet ";
- goto out_invalid;
-diff --git a/scripts/package/builddeb b/scripts/package/builddeb
-index 3c6c0b1..bee55f6 100644
---- a/scripts/package/builddeb
-+++ b/scripts/package/builddeb
-@@ -41,9 +41,9 @@ create_package() {
- parisc*)
- debarch=hppa ;;
- mips*)
-- debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
-+ debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;;
- arm*)
-- debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
-+ debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;;
- *)
- echo "" >&2
- echo "** ** ** WARNING ** ** **" >&2
-@@ -62,7 +62,7 @@ create_package() {
- fi
-
- # Create the package
-- dpkg-gencontrol -isp $forcearch -p$pname -P"$pdir"
-+ dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir"
- dpkg --build "$pdir" ..
- }
-
-@@ -105,12 +105,12 @@ fi
- if [ "$ARCH" = "um" ] ; then
- $MAKE linux
- cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
-- cp .config "$tmpdir/usr/share/doc/$packagename/config"
-+ cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config"
- gzip "$tmpdir/usr/share/doc/$packagename/config"
- cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version"
- else
- cp System.map "$tmpdir/boot/System.map-$version"
-- cp .config "$tmpdir/boot/config-$version"
-+ cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
- # Not all arches include the boot path in KBUILD_IMAGE
- if [ -e $KBUILD_IMAGE ]; then
- cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
-@@ -119,7 +119,7 @@ else
- fi
- fi
-
--if grep -q '^CONFIG_MODULES=y' .config ; then
-+if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
- INSTALL_MOD_PATH="$tmpdir" make KBUILD_SRC= modules_install
- if [ "$ARCH" = "um" ] ; then
- mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
-@@ -240,21 +240,21 @@ fi
- # Build header package
- (cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles")
- (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles")
--(cd $objtree; find .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles")
-+(cd $objtree; find Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles")
- destdir=$kernel_headers_dir/usr/src/linux-headers-$version
- mkdir -p "$destdir"
- (cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -)
- (cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -)
-+(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
- rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
--arch=$(dpkg --print-architecture)
-
- cat <<EOF >> debian/control
-
- Package: $kernel_headers_packagename
- Provides: linux-headers, linux-headers-2.6
--Architecture: $arch
--Description: Linux kernel headers for $KERNELRELEASE on $arch
-- This package provides kernel header files for $KERNELRELEASE on $arch
-+Architecture: any
-+Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch}
-+ This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch}
- .
- This is useful for people who need to build external modules
- EOF