diff options
-rw-r--r-- | 4.2.3/0000_README | 2 | ||||
-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 |