summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--4.2.3/0000_README2
-rw-r--r--4.2.3/4420_grsecurity-3.1-4.2.3-201510111839.patch (renamed from 4.2.3/4420_grsecurity-3.1-4.2.3-201510092347.patch)534
2 files changed, 500 insertions, 36 deletions
diff --git a/4.2.3/0000_README b/4.2.3/0000_README
index 1d05b9f..f4ca83e 100644
--- a/4.2.3/0000_README
+++ b/4.2.3/0000_README
@@ -2,7 +2,7 @@ README
-----------------------------------------------------------------------------
Individual Patch Descriptions:
-----------------------------------------------------------------------------
-Patch: 4420_grsecurity-3.1-4.2.3-201510092347.patch
+Patch: 4420_grsecurity-3.1-4.2.3-201510111839.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/4.2.3/4420_grsecurity-3.1-4.2.3-201510092347.patch b/4.2.3/4420_grsecurity-3.1-4.2.3-201510111839.patch
index 5075ca5..3eeb3c5 100644
--- a/4.2.3/4420_grsecurity-3.1-4.2.3-201510092347.patch
+++ b/4.2.3/4420_grsecurity-3.1-4.2.3-201510111839.patch
@@ -2834,6 +2834,29 @@ index 29e2991..7bc5757 100644
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
#endif
+diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c
+index 097e2e2..3927085 100644
+--- a/arch/arm/kernel/module-plts.c
++++ b/arch/arm/kernel/module-plts.c
+@@ -30,17 +30,12 @@ struct plt_entries {
+ u32 lit[PLT_ENT_COUNT];
+ };
+
+-static bool in_init(const struct module *mod, u32 addr)
+-{
+- return addr - (u32)mod->module_init < mod->init_size;
+-}
+-
+ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
+ {
+ struct plt_entries *plt, *plt_end;
+ int c, *count;
+
+- if (in_init(mod, loc)) {
++ if (within_module_init(loc, mod)) {
+ plt = (void *)mod->arch.init_plt->sh_addr;
+ plt_end = (void *)plt + mod->arch.init_plt->sh_size;
+ count = &mod->arch.init_plt_count;
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index efdddcb..35e58f6 100644
--- a/arch/arm/kernel/module.c
@@ -5045,6 +5068,20 @@ index 07e1ba44..ec8cbbb 100644
#define access_ok(type, addr, size) __range_ok(addr, size)
#define user_addr_max get_fs
+diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
+index e8ca6ea..13671a9 100644
+--- a/arch/arm64/kernel/efi.c
++++ b/arch/arm64/kernel/efi.c
+@@ -258,7 +258,8 @@ static bool __init efi_virtmap_init(void)
+ */
+ if (!is_normal_ram(md))
+ prot = __pgprot(PROT_DEVICE_nGnRE);
+- else if (md->type == EFI_RUNTIME_SERVICES_CODE)
++ else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
++ !PAGE_ALIGNED(md->phys_addr))
+ prot = PAGE_KERNEL_EXEC;
+ else
+ prot = PAGE_KERNEL;
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index d16a1ce..a5acc60 100644
--- a/arch/arm64/mm/dma-mapping.c
@@ -7201,6 +7238,30 @@ index 5c81fdd..db158d3 100644
int __virt_addr_valid(const volatile void *kaddr)
{
return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+diff --git a/arch/mips/net/bpf_jit_asm.S b/arch/mips/net/bpf_jit_asm.S
+index e927260..552e6ea 100644
+--- a/arch/mips/net/bpf_jit_asm.S
++++ b/arch/mips/net/bpf_jit_asm.S
+@@ -62,7 +62,9 @@ sk_load_word_positive:
+ is_offset_in_header(4, word)
+ /* Offset within header boundaries */
+ PTR_ADDU t1, $r_skb_data, offset
++ .set reorder
+ lw $r_A, 0(t1)
++ .set noreorder
+ #ifdef CONFIG_CPU_LITTLE_ENDIAN
+ wsbh t0, $r_A
+ rotr $r_A, t0, 16
+@@ -78,7 +80,9 @@ sk_load_half_positive:
+ is_offset_in_header(2, half)
+ /* Offset within header boundaries */
+ PTR_ADDU t1, $r_skb_data, offset
++ .set reorder
+ lh $r_A, 0(t1)
++ .set noreorder
+ #ifdef CONFIG_CPU_LITTLE_ENDIAN
+ wsbh t0, $r_A
+ seh $r_A, t0
diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c
index a2358b4..7cead4f 100644
--- a/arch/mips/sgi-ip27/ip27-nmi.c
@@ -24508,6 +24569,32 @@ index 83741a7..bd3507d 100644
{
.notifier_call = cpuid_class_cpu_callback,
};
+diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
+index e068d66..74ca2fe 100644
+--- a/arch/x86/kernel/crash.c
++++ b/arch/x86/kernel/crash.c
+@@ -185,10 +185,9 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
+ }
+
+ #ifdef CONFIG_KEXEC_FILE
+-static int get_nr_ram_ranges_callback(unsigned long start_pfn,
+- unsigned long nr_pfn, void *arg)
++static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg)
+ {
+- int *nr_ranges = arg;
++ unsigned int *nr_ranges = arg;
+
+ (*nr_ranges)++;
+ return 0;
+@@ -214,7 +213,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
+
+ ced->image = image;
+
+- walk_system_ram_range(0, -1, &nr_ranges,
++ walk_system_ram_res(0, -1, &nr_ranges,
+ get_nr_ram_ranges_callback);
+
+ ced->max_nr_ranges = nr_ranges;
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c
index afa64ad..dce67dd 100644
--- a/arch/x86/kernel/crash_dump_64.c
@@ -34759,7 +34846,7 @@ index 9f0614d..92ae64a 100644
p += get_opcode(p, &opcode);
for (i = 0; i < ARRAY_SIZE(imm_wop); i++)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
-index fb0a9dd..6fc86ab 100644
+index fb0a9dd..8560f52 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -98,10 +98,75 @@ static inline void pgd_list_del(pgd_t *pgd)
@@ -35047,7 +35134,7 @@ index fb0a9dd..6fc86ab 100644
pgd_dtor(pgd);
paravirt_pgd_free(mm, pgd);
_pgd_free(pgd);
-@@ -544,6 +616,40 @@ void __init reserve_top_address(unsigned long reserve)
+@@ -544,6 +616,55 @@ void __init reserve_top_address(unsigned long reserve)
int fixmaps_set;
@@ -35064,16 +35151,31 @@ index fb0a9dd..6fc86ab 100644
+
+#ifdef CONFIG_X86_VSYSCALL_EMULATION
+ case VSYSCALL_PAGE:
++ break;
+#endif
++
+#ifdef CONFIG_PARAVIRT_CLOCK
+ case PVCLOCK_FIXMAP_BEGIN ... PVCLOCK_FIXMAP_END:
-+#endif
+ break;
++#endif
+ }
+
+ pgd = pgd_offset_k(address);
-+ if (!(pgd_val(*pgd) & _PAGE_USER))
++ if (!(pgd_val(*pgd) & _PAGE_USER)) {
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ unsigned int cpu;
++ pgd_t *pgd_cpu;
++
++ for_each_possible_cpu(cpu) {
++ pgd_cpu = pgd_offset_cpu(cpu, kernel, address);
++ set_pgd(pgd_cpu, __pgd(pgd_val(*pgd_cpu) | _PAGE_USER));
++
++ pgd_cpu = pgd_offset_cpu(cpu, user, address);
++ set_pgd(pgd_cpu, __pgd(pgd_val(*pgd_cpu) | _PAGE_USER));
++ }
++#endif
+ set_pgd(pgd, __pgd(pgd_val(*pgd) | _PAGE_USER));
++ }
+
+ pud = pud_offset(pgd, address);
+ if (!(pud_val(*pud) & _PAGE_USER))
@@ -35088,7 +35190,7 @@ index fb0a9dd..6fc86ab 100644
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
{
unsigned long address = __fix_to_virt(idx);
-@@ -554,6 +660,7 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
+@@ -554,6 +675,7 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
}
set_pte_vaddr(address, pte);
fixmaps_set++;
@@ -35801,6 +35903,91 @@ index 9b83b90..2c256c5 100644
return !(ret & 0xff00);
}
EXPORT_SYMBOL(pcibios_set_irq_routing);
+diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
+index e4308fe..c6835bf 100644
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -705,6 +705,70 @@ out:
+ }
+
+ /*
++ * Iterate the EFI memory map in reverse order because the regions
++ * will be mapped top-down. The end result is the same as if we had
++ * mapped things forward, but doesn't require us to change the
++ * existing implementation of efi_map_region().
++ */
++static inline void *efi_map_next_entry_reverse(void *entry)
++{
++ /* Initial call */
++ if (!entry)
++ return memmap.map_end - memmap.desc_size;
++
++ entry -= memmap.desc_size;
++ if (entry < memmap.map)
++ return NULL;
++
++ return entry;
++}
++
++/*
++ * efi_map_next_entry - Return the next EFI memory map descriptor
++ * @entry: Previous EFI memory map descriptor
++ *
++ * This is a helper function to iterate over the EFI memory map, which
++ * we do in different orders depending on the current configuration.
++ *
++ * To begin traversing the memory map @entry must be %NULL.
++ *
++ * Returns %NULL when we reach the end of the memory map.
++ */
++static void *efi_map_next_entry(void *entry)
++{
++ if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
++ /*
++ * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
++ * config table feature requires us to map all entries
++ * in the same order as they appear in the EFI memory
++ * map. That is to say, entry N must have a lower
++ * virtual address than entry N+1. This is because the
++ * firmware toolchain leaves relative references in
++ * the code/data sections, which are split and become
++ * separate EFI memory regions. Mapping things
++ * out-of-order leads to the firmware accessing
++ * unmapped addresses.
++ *
++ * Since we need to map things this way whether or not
++ * the kernel actually makes use of
++ * EFI_PROPERTIES_TABLE, let's just switch to this
++ * scheme by default for 64-bit.
++ */
++ return efi_map_next_entry_reverse(entry);
++ }
++
++ /* Initial call */
++ if (!entry)
++ return memmap.map;
++
++ entry += memmap.desc_size;
++ if (entry >= memmap.map_end)
++ return NULL;
++
++ return entry;
++}
++
++/*
+ * Map the efi memory ranges of the runtime services and update new_mmap with
+ * virtual addresses.
+ */
+@@ -714,7 +778,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
+ unsigned long left = 0;
+ efi_memory_desc_t *md;
+
+- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
++ p = NULL;
++ while ((p = efi_map_next_entry(p))) {
+ md = p;
+ if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
+ #ifdef CONFIG_X86_64
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index ed5b673..24d2d53 100644
--- a/arch/x86/platform/efi/efi_32.c
@@ -41269,6 +41456,130 @@ index 756eca8..2336d08 100644
int error;
/* new_var */
+diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
+index e29560e..950c87f 100644
+--- a/drivers/firmware/efi/libstub/arm-stub.c
++++ b/drivers/firmware/efi/libstub/arm-stub.c
+@@ -13,6 +13,7 @@
+ */
+
+ #include <linux/efi.h>
++#include <linux/sort.h>
+ #include <asm/efi.h>
+
+ #include "efistub.h"
+@@ -305,6 +306,44 @@ fail:
+ */
+ #define EFI_RT_VIRTUAL_BASE 0x40000000
+
++static int cmp_mem_desc(const void *l, const void *r)
++{
++ const efi_memory_desc_t *left = l, *right = r;
++
++ return (left->phys_addr > right->phys_addr) ? 1 : -1;
++}
++
++/*
++ * Returns whether region @left ends exactly where region @right starts,
++ * or false if either argument is NULL.
++ */
++static bool regions_are_adjacent(efi_memory_desc_t *left,
++ efi_memory_desc_t *right)
++{
++ u64 left_end;
++
++ if (left == NULL || right == NULL)
++ return false;
++
++ left_end = left->phys_addr + left->num_pages * EFI_PAGE_SIZE;
++
++ return left_end == right->phys_addr;
++}
++
++/*
++ * Returns whether region @left and region @right have compatible memory type
++ * mapping attributes, and are both EFI_MEMORY_RUNTIME regions.
++ */
++static bool regions_have_compatible_memory_type_attrs(efi_memory_desc_t *left,
++ efi_memory_desc_t *right)
++{
++ static const u64 mem_type_mask = EFI_MEMORY_WB | EFI_MEMORY_WT |
++ EFI_MEMORY_WC | EFI_MEMORY_UC |
++ EFI_MEMORY_RUNTIME;
++
++ return ((left->attribute ^ right->attribute) & mem_type_mask) == 0;
++}
++
+ /*
+ * efi_get_virtmap() - create a virtual mapping for the EFI memory map
+ *
+@@ -317,33 +356,52 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
+ int *count)
+ {
+ u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
+- efi_memory_desc_t *out = runtime_map;
++ efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
+ int l;
+
+- for (l = 0; l < map_size; l += desc_size) {
+- efi_memory_desc_t *in = (void *)memory_map + l;
++ /*
++ * To work around potential issues with the Properties Table feature
++ * introduced in UEFI 2.5, which may split PE/COFF executable images
++ * in memory into several RuntimeServicesCode and RuntimeServicesData
++ * regions, we need to preserve the relative offsets between adjacent
++ * EFI_MEMORY_RUNTIME regions with the same memory type attributes.
++ * The easiest way to find adjacent regions is to sort the memory map
++ * before traversing it.
++ */
++ sort(memory_map, map_size / desc_size, desc_size, cmp_mem_desc, NULL);
++
++ for (l = 0; l < map_size; l += desc_size, prev = in) {
+ u64 paddr, size;
+
++ in = (void *)memory_map + l;
+ if (!(in->attribute & EFI_MEMORY_RUNTIME))
+ continue;
+
++ paddr = in->phys_addr;
++ size = in->num_pages * EFI_PAGE_SIZE;
++
+ /*
+ * Make the mapping compatible with 64k pages: this allows
+ * a 4k page size kernel to kexec a 64k page size kernel and
+ * vice versa.
+ */
+- paddr = round_down(in->phys_addr, SZ_64K);
+- size = round_up(in->num_pages * EFI_PAGE_SIZE +
+- in->phys_addr - paddr, SZ_64K);
++ if (!regions_are_adjacent(prev, in) ||
++ !regions_have_compatible_memory_type_attrs(prev, in)) {
+
+- /*
+- * Avoid wasting memory on PTEs by choosing a virtual base that
+- * is compatible with section mappings if this region has the
+- * appropriate size and physical alignment. (Sections are 2 MB
+- * on 4k granule kernels)
+- */
+- if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
+- efi_virt_base = round_up(efi_virt_base, SZ_2M);
++ paddr = round_down(in->phys_addr, SZ_64K);
++ size += in->phys_addr - paddr;
++
++ /*
++ * Avoid wasting memory on PTEs by choosing a virtual
++ * base that is compatible with section mappings if this
++ * region has the appropriate size and physical
++ * alignment. (Sections are 2 MB on 4k granule kernels)
++ */
++ if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
++ efi_virt_base = round_up(efi_virt_base, SZ_2M);
++ else
++ efi_virt_base = round_up(efi_virt_base, SZ_64K);
++ }
+
+ in->virt_addr = efi_virt_base + in->phys_addr - paddr;
+ efi_virt_base += size;
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
index 5c55227..97f4978 100644
--- a/drivers/firmware/efi/runtime-map.c
@@ -79778,7 +80089,7 @@ index 14db05d..687f6d8 100644
#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
diff --git a/fs/namei.c b/fs/namei.c
-index 1c2105e..79d9ccb 100644
+index 1c2105e..e54c8ab 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -336,17 +336,32 @@ int generic_permission(struct inode *inode, int mask)
@@ -79945,7 +80256,29 @@ index 1c2105e..79d9ccb 100644
nd->last_type = LAST_BIND;
res = inode->i_link;
if (!res) {
-@@ -1665,6 +1737,23 @@ static int pick_link(struct nameidata *nd, struct path *link,
+@@ -1535,8 +1607,6 @@ static int lookup_fast(struct nameidata *nd,
+ negative = d_is_negative(dentry);
+ if (read_seqcount_retry(&dentry->d_seq, seq))
+ return -ECHILD;
+- if (negative)
+- return -ENOENT;
+
+ /*
+ * This sequence count validates that the parent had no
+@@ -1557,6 +1627,12 @@ static int lookup_fast(struct nameidata *nd,
+ goto unlazy;
+ }
+ }
++ /*
++ * Note: do negative dentry check after revalidation in
++ * case that drops it.
++ */
++ if (negative)
++ return -ENOENT;
+ path->mnt = mnt;
+ path->dentry = dentry;
+ if (likely(__follow_mount_rcu(nd, path, inode, seqp)))
+@@ -1665,6 +1741,23 @@ static int pick_link(struct nameidata *nd, struct path *link,
}
}
@@ -79969,7 +80302,7 @@ index 1c2105e..79d9ccb 100644
last = nd->stack + nd->depth++;
last->link = *link;
last->cookie = NULL;
-@@ -1804,7 +1893,7 @@ EXPORT_SYMBOL(full_name_hash);
+@@ -1804,7 +1897,7 @@ EXPORT_SYMBOL(full_name_hash);
static inline u64 hash_name(const char *name)
{
unsigned long a, b, adata, bdata, mask, hash, len;
@@ -79978,7 +80311,7 @@ index 1c2105e..79d9ccb 100644
hash = a = 0;
len = -sizeof(unsigned long);
-@@ -1973,6 +2062,9 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
+@@ -1973,6 +2066,9 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
nd->depth = 0;
nd->total_link_count = 0;
@@ -79988,7 +80321,7 @@ index 1c2105e..79d9ccb 100644
if (flags & LOOKUP_ROOT) {
struct dentry *root = nd->root.dentry;
struct inode *inode = root->d_inode;
-@@ -2110,6 +2202,11 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
+@@ -2110,6 +2206,11 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
if (!err)
err = complete_walk(nd);
@@ -80000,7 +80333,7 @@ index 1c2105e..79d9ccb 100644
if (!err && nd->flags & LOOKUP_DIRECTORY)
if (!d_can_lookup(nd->path.dentry))
err = -ENOTDIR;
-@@ -2158,6 +2255,10 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
+@@ -2158,6 +2259,10 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
err = link_path_walk(s, nd);
if (!err)
err = complete_walk(nd);
@@ -80011,7 +80344,7 @@ index 1c2105e..79d9ccb 100644
if (!err) {
*parent = nd->path;
nd->path.mnt = NULL;
-@@ -2689,6 +2790,13 @@ static int may_open(struct path *path, int acc_mode, int flag)
+@@ -2689,6 +2794,13 @@ static int may_open(struct path *path, int acc_mode, int flag)
if (flag & O_NOATIME && !inode_owner_or_capable(inode))
return -EPERM;
@@ -80025,7 +80358,7 @@ index 1c2105e..79d9ccb 100644
return 0;
}
-@@ -2955,6 +3063,18 @@ static int lookup_open(struct nameidata *nd, struct path *path,
+@@ -2955,6 +3067,18 @@ static int lookup_open(struct nameidata *nd, struct path *path,
/* Negative dentry, just create the file */
if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
umode_t mode = op->mode;
@@ -80044,7 +80377,7 @@ index 1c2105e..79d9ccb 100644
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current_umask();
/*
-@@ -2976,6 +3096,8 @@ static int lookup_open(struct nameidata *nd, struct path *path,
+@@ -2976,6 +3100,8 @@ static int lookup_open(struct nameidata *nd, struct path *path,
nd->flags & LOOKUP_EXCL);
if (error)
goto out_dput;
@@ -80053,7 +80386,7 @@ index 1c2105e..79d9ccb 100644
}
out_no_open:
path->dentry = dentry;
-@@ -3039,6 +3161,9 @@ static int do_last(struct nameidata *nd,
+@@ -3039,6 +3165,9 @@ static int do_last(struct nameidata *nd,
if (error)
return error;
@@ -80063,7 +80396,7 @@ index 1c2105e..79d9ccb 100644
audit_inode(nd->name, dir, LOOKUP_PARENT);
/* trailing slashes? */
if (unlikely(nd->last.name[nd->last.len]))
-@@ -3081,11 +3206,24 @@ retry_lookup:
+@@ -3081,11 +3210,24 @@ retry_lookup:
goto finish_open_created;
}
@@ -80089,7 +80422,7 @@ index 1c2105e..79d9ccb 100644
/*
* If atomic_open() acquired write access it is dropped now due to
-@@ -3121,6 +3259,11 @@ finish_lookup:
+@@ -3121,6 +3263,11 @@ finish_lookup:
if (unlikely(error))
return error;
@@ -80101,7 +80434,7 @@ index 1c2105e..79d9ccb 100644
if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
path_to_nameidata(&path, nd);
return -ELOOP;
-@@ -3143,6 +3286,12 @@ finish_open:
+@@ -3143,6 +3290,12 @@ finish_open:
path_put(&save_parent);
return error;
}
@@ -80114,7 +80447,7 @@ index 1c2105e..79d9ccb 100644
audit_inode(nd->name, nd->path.dentry, 0);
error = -EISDIR;
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
-@@ -3409,9 +3558,11 @@ static struct dentry *filename_create(int dfd, struct filename *name,
+@@ -3409,9 +3562,11 @@ static struct dentry *filename_create(int dfd, struct filename *name,
goto unlock;
error = -EEXIST;
@@ -80128,7 +80461,7 @@ index 1c2105e..79d9ccb 100644
/*
* Special case - lookup gave negative, but... we had foo/bar/
* From the vfs_mknod() POV we just have a negative dentry -
-@@ -3465,6 +3616,20 @@ inline struct dentry *user_path_create(int dfd, const char __user *pathname,
+@@ -3465,6 +3620,20 @@ inline struct dentry *user_path_create(int dfd, const char __user *pathname,
}
EXPORT_SYMBOL(user_path_create);
@@ -80149,7 +80482,7 @@ index 1c2105e..79d9ccb 100644
int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
int error = may_create(dir, dentry);
-@@ -3528,6 +3693,17 @@ retry:
+@@ -3528,6 +3697,17 @@ retry:
if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
@@ -80167,7 +80500,7 @@ index 1c2105e..79d9ccb 100644
error = security_path_mknod(&path, dentry, mode, dev);
if (error)
goto out;
-@@ -3543,6 +3719,8 @@ retry:
+@@ -3543,6 +3723,8 @@ retry:
error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
break;
}
@@ -80176,7 +80509,7 @@ index 1c2105e..79d9ccb 100644
out:
done_path_create(&path, dentry);
if (retry_estale(error, lookup_flags)) {
-@@ -3597,9 +3775,16 @@ retry:
+@@ -3597,9 +3779,16 @@ retry:
if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
@@ -80193,7 +80526,7 @@ index 1c2105e..79d9ccb 100644
done_path_create(&path, dentry);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
-@@ -3632,7 +3817,7 @@ void dentry_unhash(struct dentry *dentry)
+@@ -3632,7 +3821,7 @@ void dentry_unhash(struct dentry *dentry)
{
shrink_dcache_parent(dentry);
spin_lock(&dentry->d_lock);
@@ -80202,7 +80535,7 @@ index 1c2105e..79d9ccb 100644
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
}
-@@ -3685,6 +3870,8 @@ static long do_rmdir(int dfd, const char __user *pathname)
+@@ -3685,6 +3874,8 @@ static long do_rmdir(int dfd, const char __user *pathname)
struct path path;
struct qstr last;
int type;
@@ -80211,7 +80544,7 @@ index 1c2105e..79d9ccb 100644
unsigned int lookup_flags = 0;
retry:
name = user_path_parent(dfd, pathname,
-@@ -3717,10 +3904,20 @@ retry:
+@@ -3717,10 +3908,20 @@ retry:
error = -ENOENT;
goto exit3;
}
@@ -80232,7 +80565,7 @@ index 1c2105e..79d9ccb 100644
exit3:
dput(dentry);
exit2:
-@@ -3815,6 +4012,8 @@ static long do_unlinkat(int dfd, const char __user *pathname)
+@@ -3815,6 +4016,8 @@ static long do_unlinkat(int dfd, const char __user *pathname)
int type;
struct inode *inode = NULL;
struct inode *delegated_inode = NULL;
@@ -80241,7 +80574,7 @@ index 1c2105e..79d9ccb 100644
unsigned int lookup_flags = 0;
retry:
name = user_path_parent(dfd, pathname,
-@@ -3841,10 +4040,21 @@ retry_deleg:
+@@ -3841,10 +4044,21 @@ retry_deleg:
if (d_is_negative(dentry))
goto slashes;
ihold(inode);
@@ -80263,7 +80596,7 @@ index 1c2105e..79d9ccb 100644
exit2:
dput(dentry);
}
-@@ -3933,9 +4143,17 @@ retry:
+@@ -3933,9 +4147,17 @@ retry:
if (IS_ERR(dentry))
goto out_putname;
@@ -80281,7 +80614,7 @@ index 1c2105e..79d9ccb 100644
done_path_create(&path, dentry);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
-@@ -4039,6 +4257,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
+@@ -4039,6 +4261,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
struct dentry *new_dentry;
struct path old_path, new_path;
struct inode *delegated_inode = NULL;
@@ -80289,7 +80622,7 @@ index 1c2105e..79d9ccb 100644
int how = 0;
int error;
-@@ -4062,7 +4281,7 @@ retry:
+@@ -4062,7 +4285,7 @@ retry:
if (error)
return error;
@@ -80298,7 +80631,7 @@ index 1c2105e..79d9ccb 100644
(how & LOOKUP_REVAL));
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
-@@ -4074,11 +4293,26 @@ retry:
+@@ -4074,11 +4297,26 @@ retry:
error = may_linkat(&old_path);
if (unlikely(error))
goto out_dput;
@@ -80325,7 +80658,7 @@ index 1c2105e..79d9ccb 100644
done_path_create(&new_path, new_dentry);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
-@@ -4393,6 +4627,20 @@ retry_deleg:
+@@ -4393,6 +4631,20 @@ retry_deleg:
if (new_dentry == trap)
goto exit5;
@@ -80346,7 +80679,7 @@ index 1c2105e..79d9ccb 100644
error = security_path_rename(&old_path, old_dentry,
&new_path, new_dentry, flags);
if (error)
-@@ -4400,6 +4648,9 @@ retry_deleg:
+@@ -4400,6 +4652,9 @@ retry_deleg:
error = vfs_rename(old_path.dentry->d_inode, old_dentry,
new_path.dentry->d_inode, new_dentry,
&delegated_inode, flags);
@@ -80356,7 +80689,7 @@ index 1c2105e..79d9ccb 100644
exit5:
dput(new_dentry);
exit4:
-@@ -4456,14 +4707,24 @@ EXPORT_SYMBOL(vfs_whiteout);
+@@ -4456,14 +4711,24 @@ EXPORT_SYMBOL(vfs_whiteout);
int readlink_copy(char __user *buffer, int buflen, const char *link)
{
@@ -121671,6 +122004,137 @@ index 338b404..839dcb0 100644
.pf = PF_INET,
.get_optmin = SO_IP_SET,
.get_optmax = SO_IP_SET + 1,
+diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
+index 3c862c0..a93dfeb 100644
+--- a/net/netfilter/ipset/ip_set_hash_netnet.c
++++ b/net/netfilter/ipset/ip_set_hash_netnet.c
+@@ -131,6 +131,13 @@ hash_netnet4_data_next(struct hash_netnet4_elem *next,
+ #define HOST_MASK 32
+ #include "ip_set_hash_gen.h"
+
++static void
++hash_netnet4_init(struct hash_netnet4_elem *e)
++{
++ e->cidr[0] = HOST_MASK;
++ e->cidr[1] = HOST_MASK;
++}
++
+ static int
+ hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+@@ -160,7 +167,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
+ {
+ const struct hash_netnet *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+- struct hash_netnet4_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, };
++ struct hash_netnet4_elem e = { };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ u32 ip = 0, ip_to = 0, last;
+ u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2;
+@@ -169,6 +176,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
++ hash_netnet4_init(&e);
+ if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+ return -IPSET_ERR_PROTOCOL;
+@@ -357,6 +365,13 @@ hash_netnet6_data_next(struct hash_netnet4_elem *next,
+ #define IP_SET_EMIT_CREATE
+ #include "ip_set_hash_gen.h"
+
++static void
++hash_netnet6_init(struct hash_netnet6_elem *e)
++{
++ e->cidr[0] = HOST_MASK;
++ e->cidr[1] = HOST_MASK;
++}
++
+ static int
+ hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+@@ -385,13 +400,14 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+ {
+ ipset_adtfn adtfn = set->variant->adt[adt];
+- struct hash_netnet6_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, };
++ struct hash_netnet6_elem e = { };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ int ret;
+
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
++ hash_netnet6_init(&e);
+ if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+ return -IPSET_ERR_PROTOCOL;
+diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
+index 0c68734..9a14c23 100644
+--- a/net/netfilter/ipset/ip_set_hash_netportnet.c
++++ b/net/netfilter/ipset/ip_set_hash_netportnet.c
+@@ -142,6 +142,13 @@ hash_netportnet4_data_next(struct hash_netportnet4_elem *next,
+ #define HOST_MASK 32
+ #include "ip_set_hash_gen.h"
+
++static void
++hash_netportnet4_init(struct hash_netportnet4_elem *e)
++{
++ e->cidr[0] = HOST_MASK;
++ e->cidr[1] = HOST_MASK;
++}
++
+ static int
+ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+@@ -175,7 +182,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
+ {
+ const struct hash_netportnet *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+- struct hash_netportnet4_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, };
++ struct hash_netportnet4_elem e = { };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to;
+ u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
+@@ -185,6 +192,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
++ hash_netportnet4_init(&e);
+ if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+ !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+@@ -412,6 +420,13 @@ hash_netportnet6_data_next(struct hash_netportnet4_elem *next,
+ #define IP_SET_EMIT_CREATE
+ #include "ip_set_hash_gen.h"
+
++static void
++hash_netportnet6_init(struct hash_netportnet6_elem *e)
++{
++ e->cidr[0] = HOST_MASK;
++ e->cidr[1] = HOST_MASK;
++}
++
+ static int
+ hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+@@ -445,7 +460,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
+ {
+ const struct hash_netportnet *h = set->data;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+- struct hash_netportnet6_elem e = { .cidr = { HOST_MASK, HOST_MASK, }, };
++ struct hash_netportnet6_elem e = { };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ u32 port, port_to;
+ bool with_ports = false;
+@@ -454,6 +469,7 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
++ hash_netportnet6_init(&e);
+ if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+ !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index b0f7b62..0541842 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c