View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0015428 | CentOS-7 | kernel-plus | public | 2018-11-01 12:30 | 2018-12-12 06:12 |
Reporter | kabe | ||||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 7.6.1810 | ||||
Target Version | Fixed in Version | ||||
Summary | 0015428: patches for compiling i686 kernel-3.10.0-957.el7.centos.plus.i686 | ||||
Description | As usual, i686 compile needs additional patches to baseline. Posting patches for i686 compile based on kernel-plus. | ||||
Steps To Reproduce | git checkout -b <this branch> git merge <kernel-3.10.0-862 based i686 code> then add/modify patches posted. | ||||
Additional Information | "Product version" of this report shold be 7.6.1810, but not available now. | ||||
Tags | i386 | ||||
abrt_hash | |||||
URL | |||||
Replace this with i686-7-4.patch .
i686-7-6.patch (5,154 bytes)
Replace this with i686-7-4.patch . diff -up ./arch/x86/include/asm/irq_remapping.h.7-4 ./arch/x86/include/asm/irq_remapping.h --- ./arch/x86/include/asm/irq_remapping.h.7-4 2018-10-30 19:54:34.000000000 +0900 +++ ./arch/x86/include/asm/irq_remapping.h 2018-10-30 19:56:23.000000000 +0900 @@ -35,6 +35,11 @@ enum irq_remap_cap { IRQ_POSTING_CAP = 0, }; +struct vcpu_data { + u64 pi_desc_addr; /* Physical address of PI Descriptor */ + u32 vector; /* Guest vector of the interrupt */ +}; + #ifdef CONFIG_IRQ_REMAP extern bool irq_remapping_cap(enum irq_remap_cap cap); @@ -67,11 +72,6 @@ enum { IRQ_REMAP_X2APIC_MODE, }; -struct vcpu_data { - u64 pi_desc_addr; /* Physical address of PI Descriptor */ - u32 vector; /* Guest vector of the interrupt */ -}; - #else /* CONFIG_IRQ_REMAP */ static inline bool irq_remapping_cap(enum irq_remap_cap cap) { return 0; } diff -up ./arch/x86/include/asm/kvm_host.h.7-4 ./arch/x86/include/asm/kvm_host.h --- ./arch/x86/include/asm/kvm_host.h.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/include/asm/kvm_host.h 2018-10-30 19:54:34.000000000 +0900 @@ -56,7 +56,7 @@ | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) #define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL -#define CR3_PCID_INVD (1UL << 63) +#define CR3_PCID_INVD BIT_64(63) #define CR4_RESERVED_BITS \ (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ diff -up ./arch/x86/kvm/x86.c.7-4 ./arch/x86/kvm/x86.c --- ./arch/x86/kvm/x86.c.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/kvm/x86.c 2018-10-30 19:54:34.000000000 +0900 @@ -5993,6 +5993,7 @@ int kvm_emulate_halt(struct kvm_vcpu *vc } EXPORT_SYMBOL_GPL(kvm_emulate_halt); +#ifdef CONFIG_X86_64 static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr, unsigned long clock_type) { @@ -6019,6 +6020,7 @@ static int kvm_pv_clock_pairing(struct k return ret; } +#endif /* * kvm_pv_kick_cpu_op: Kick a vcpu. @@ -6084,9 +6086,11 @@ int kvm_emulate_hypercall(struct kvm_vcp kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1); ret = 0; break; +#ifdef CONFIG_X86_64 case KVM_HC_CLOCK_PAIRING: ret = kvm_pv_clock_pairing(vcpu, a0, a1); break; +#endif default: ret = -KVM_ENOSYS; break; diff -up ./crypto/tcrypt.c.7-4 ./crypto/tcrypt.c --- ./crypto/tcrypt.c.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./crypto/tcrypt.c 2018-10-30 19:54:34.000000000 +0900 @@ -865,7 +865,7 @@ static void test_mb_ahash_speed(const ch printk("\nBlock: %lld cycles (%lld cycles/byte), %d bytes\n", (s64) (end[7]-start[0])/1, - (s64) (end[7]-start[0])/(8*speed[i].blen), + div_s64((s64) (end[7]-start[0]), (8*speed[i].blen)), 8*speed[i].blen); } ret = 0; diff -up ./drivers/misc/ioc4.c.7-4 ./drivers/misc/ioc4.c --- ./drivers/misc/ioc4.c.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/misc/ioc4.c 2018-10-30 19:54:34.000000000 +0900 @@ -168,19 +168,20 @@ ioc4_clock_calibrate(struct ioc4_driver_ mmiowb(); /* Check square wave period averaged over some number of cycles */ - do { - int_out.raw = readl(&idd->idd_misc_regs->int_out.raw); - state = int_out.fields.int_out; - if (!last_state && state) { - count++; - if (count == IOC4_CALIBRATE_END) { - ktime_get_ts(&end_ts); - break; - } else if (count == IOC4_CALIBRATE_DISCARD) - ktime_get_ts(&start_ts); - } - last_state = state; - } while (1); + ktime_get_ts(&start_ts); + state = 1; /* make sure the first read isn't a rising edge */ + for (count = 0; count <= IOC4_CALIBRATE_END; count++) { + do { /* wait for a rising edge */ + last_state = state; + int_out.raw = readl(&idd->idd_misc_regs->int_out.raw); + state = int_out.fields.int_out; + } while (last_state || !state); + + /* discard the first few cycles */ + if (count == IOC4_CALIBRATE_DISCARD) + ktime_get_ts(&start_ts); + } + ktime_get_ts(&end_ts); /* Calculation rearranged to preserve intermediate precision. * Logically: diff -up ./fs/xfs/libxfs/xfs_format.h.7-4 ./fs/xfs/libxfs/xfs_format.h --- ./fs/xfs/libxfs/xfs_format.h.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./fs/xfs/libxfs/xfs_format.h 2018-10-30 19:54:34.000000000 +0900 @@ -791,7 +791,7 @@ typedef struct xfs_agfl { __be64 agfl_lsn; __be32 agfl_crc; __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */ -} xfs_agfl_t; +} __attribute__((packed)) xfs_agfl_t; #define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc) diff -up ./fs/xfs/xfs_ondisk.h.7-4 ./fs/xfs/xfs_ondisk.h --- ./fs/xfs/xfs_ondisk.h.7-4 2018-10-05 05:18:19.000000000 +0900 +++ ./fs/xfs/xfs_ondisk.h 2018-10-30 19:54:34.000000000 +0900 @@ -34,7 +34,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_acl, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_acl_entry, 12); XFS_CHECK_STRUCT_SIZE(struct xfs_agf, 224); - XFS_CHECK_STRUCT_SIZE(struct xfs_agfl, 40); + XFS_CHECK_STRUCT_SIZE(struct xfs_agfl, 36); XFS_CHECK_STRUCT_SIZE(struct xfs_agi, 336); XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_key, 8); XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_rec, 16); |
|
Replace this with patch-copy_from_user-warning-v2.patch .
patch-copy_from_user-warning-v3.patch (4,184 bytes)
Replace this with patch-copy_from_user-warning-v2.patch . diff -up ./drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c.cfu ./drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c --- ./drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c.cfu 2018-10-30 20:06:59.000000000 +0900 +++ ./drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 2018-10-30 20:17:55.000000000 +0900 @@ -4494,12 +4494,16 @@ int vmw_execbuf_ioctl(struct drm_device return -EINVAL; } - if (arg.version > 1 && - copy_from_user(&arg.context_handle, - (void __user *) (data + copy_offset[0]), - copy_offset[arg.version - 1] - - copy_offset[0]) != 0) - return -EFAULT; + if (arg.version > 1) { + /* to make copy_from_user() happy, check bounds beforehand */ + size_t copysize = copy_offset[arg.version - 1] - copy_offset[0]; + if (copysize > sizeof(arg.context_handle)) + return -EFAULT; + if (copy_from_user(&arg.context_handle, + (void __user *) (data + copy_offset[0]), + copysize) != 0) + return -EFAULT; + } switch (arg.version) { case 1: diff -up ./drivers/isdn/hardware/avm/b1.c.cfu ./drivers/isdn/hardware/avm/b1.c --- ./drivers/isdn/hardware/avm/b1.c.cfu 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/isdn/hardware/avm/b1.c 2018-10-30 20:06:59.000000000 +0900 @@ -176,6 +176,8 @@ int b1_load_t4file(avmcard *card, capilo } if (left) { if (t4file->user) { + if (left > sizeof(buf)) /* make copy_from_user happy */ + return -EFAULT; if (copy_from_user(buf, dp, left)) return -EFAULT; } else { @@ -224,6 +226,8 @@ int b1_load_config(avmcard *card, capilo } if (left) { if (config->user) { + if (left > sizeof(buf)) /* make copy_from_user happy */ + return -EFAULT; if (copy_from_user(buf, dp, left)) return -EFAULT; } else { diff -up ./fs/binfmt_misc.c.cfu ./fs/binfmt_misc.c --- ./fs/binfmt_misc.c.cfu 2018-10-05 05:18:19.000000000 +0900 +++ ./fs/binfmt_misc.c 2018-10-30 20:06:59.000000000 +0900 @@ -396,12 +396,12 @@ static int parse_command(const char __us { char s[4]; - if (!count) - return 0; if (count > 3) return -EINVAL; if (copy_from_user(s, buffer, count)) return -EFAULT; + if (!count) + return 0; if (s[count-1] == '\n') count--; if (count == 1 && s[0] == '0') diff -up ./kernel/sys.c.cfu ./kernel/sys.c --- ./kernel/sys.c.cfu 2018-10-05 05:18:19.000000000 +0900 +++ ./kernel/sys.c 2018-10-30 20:06:59.000000000 +0900 @@ -2097,7 +2097,10 @@ static int prctl_set_mm_map(int opt, con return error; if (prctl_map.auxv_size) { + unsigned long arg4 = prctl_map.auxv_size; memset(user_auxv, 0, sizeof(user_auxv)); + if (arg4 > sizeof(user_auxv)) /* to make copy_from_user happy */ + return -EFAULT; if (copy_from_user(user_auxv, (const void __user *)prctl_map.auxv, prctl_map.auxv_size)) diff -up ./net/core/pktgen.c.cfu ./net/core/pktgen.c --- ./net/core/pktgen.c.cfu 2018-10-05 05:18:19.000000000 +0900 +++ ./net/core/pktgen.c 2018-10-30 20:06:59.000000000 +0900 @@ -881,6 +881,8 @@ static ssize_t pktgen_if_write(struct fi return len; memset(name, 0, sizeof(name)); + if (len > sizeof(name)) + return -EFAULT; if (copy_from_user(name, &user_buffer[i], len)) return -EFAULT; i += len; @@ -1798,6 +1800,8 @@ static ssize_t pktgen_thread_write(struc return len; memset(name, 0, sizeof(name)); + if (len > sizeof(name)) + return -EFAULT; if (copy_from_user(name, &user_buffer[i], len)) return -EFAULT; i += len; @@ -1828,6 +1832,8 @@ static ssize_t pktgen_thread_write(struc ret = len; goto out; } + if (len > sizeof(f)) + return -EFAULT; if (copy_from_user(f, &user_buffer[i], len)) return -EFAULT; i += len; diff -up ./sound/core/seq/seq_clientmgr.c.cfu ./sound/core/seq/seq_clientmgr.c --- ./sound/core/seq/seq_clientmgr.c.cfu 2018-10-05 05:18:19.000000000 +0900 +++ ./sound/core/seq/seq_clientmgr.c 2018-10-30 20:06:59.000000000 +0900 @@ -2136,6 +2136,8 @@ static long snd_seq_ioctl(struct file *f */ size = _IOC_SIZE(handler->cmd); if (handler->cmd & IOC_IN) { + if (size > sizeof(buf)) /* make copy_from_user happy */ + return -EFAULT; if (copy_from_user(&buf, (const void __user *)arg, size)) return -EFAULT; } |
|
Replace this with patch-zu-format-v1.patch
patch-zu-format-v2.patch (699 bytes)
Replace this with patch-zu-format-v1.patch . diff -up ./drivers/firmware/efi/efi.c.zu2 ./drivers/firmware/efi/efi.c --- ./drivers/firmware/efi/efi.c.zu2 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/firmware/efi/efi.c 2018-10-30 20:30:38.000000000 +0900 @@ -277,7 +277,7 @@ int __init efi_mem_desc_lookup(u64 phys_ map->nr_map * map->desc_size); if (!memmap) { pr_err_once("early_memremap(%#llx, %zu) failed.\n", - (unsigned long long) map->phys_map, map->nr_map * map->desc_size); + (unsigned long long) map->phys_map, (size_t) (map->nr_map * map->desc_size)); return -ENOMEM; } diff -up ./drivers/target/target_core_user.c.zu2 ./drivers/target/target_core_user.c |
|
patch-bpf-map_ids-cast.patch (500 bytes)
diff -up ./kernel/bpf/syscall.c.u32 ./kernel/bpf/syscall.c --- ./kernel/bpf/syscall.c.u32 2018-10-05 05:18:19.000000000 +0900 +++ ./kernel/bpf/syscall.c 2018-10-30 22:16:32.000000000 +0900 @@ -1576,7 +1576,7 @@ static int bpf_prog_get_info_by_fd(struc info.nr_map_ids = prog->aux->used_map_cnt; ulen = min_t(u32, info.nr_map_ids, ulen); if (ulen) { - u32 *user_map_ids = (u32 *)info.map_ids; + u32 *user_map_ids = (u32 *)(unsigned long)info.map_ids; u32 i; for (i = 0; i < ulen; i++) |
|
Replace this with ioremap.patch .
patch-ioremap-v2.patch (508 bytes)
Replace this with ioremap.patch . diff -up ./arch/x86/mm/ioremap.c.ioremap ./arch/x86/mm/ioremap.c --- ./arch/x86/mm/ioremap.c.ioremap 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/mm/ioremap.c 2018-10-30 22:59:42.000000000 +0900 @@ -167,7 +167,7 @@ static void __iomem *__ioremap_caller(re */ if (mem_flags.system_ram) { WARN_ONCE(1, "ioremap on RAM at 0x%llx - 0x%llx\n", - phys_addr, last_addr); + (unsigned long long)phys_addr, (unsigned long long)last_addr); return NULL; } |
|
patch-i686-bpf-nojit.patch (1,234 bytes)
diff -up ./kernel/bpf/verifier.c.jit ./kernel/bpf/verifier.c --- ./kernel/bpf/verifier.c.jit 2018-10-05 05:18:19.000000000 +0900 +++ ./kernel/bpf/verifier.c 2018-10-30 23:32:29.000000000 +0900 @@ -5312,7 +5312,9 @@ static int jit_subprogs(struct bpf_verif func[i]->aux->name[0] = 'F'; func[i]->aux->stack_depth = env->subprog_stack_depth[i]; func[i]->jit_requested = 1; +#ifdef CONFIG_BPF_JIT func[i] = trace_bpf_int_jit_compile(func[i]); +#endif if (!func[i]->jited) { err = -ENOTSUPP; goto out_free; @@ -5338,7 +5340,11 @@ static int jit_subprogs(struct bpf_verif } for (i = 0; i <= env->subprog_cnt; i++) { old_bpf_func = func[i]->bpf_func; +#ifdef CONFIG_BPF_JIT tmp = trace_bpf_int_jit_compile(func[i]); +#else + tmp = func[i]; +#endif if (tmp != func[i] || func[i]->bpf_func != old_bpf_func) { verbose(env, "JIT doesn't support bpf-to-bpf calls\n"); err = -EFAULT; @@ -5379,8 +5385,11 @@ static int jit_subprogs(struct bpf_verif return 0; out_free: for (i = 0; i <= env->subprog_cnt; i++) - if (func[i]) + if (func[i]) { +#ifdef CONFIG_BPF_JIT trace_bpf_jit_free(func[i]); +#endif + } kfree(func); /* cleanup main prog to be interpreted */ prog->jit_requested = 0; |
|
patch-i686-no-kaiser_active.patch (561 bytes)
diff -up ./arch/x86/include/asm/sync_core.h.pti ./arch/x86/include/asm/sync_core.h --- ./arch/x86/include/asm/sync_core.h.pti 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/include/asm/sync_core.h 2018-10-31 18:57:31.000000000 +0900 @@ -14,9 +14,11 @@ */ static inline void sync_core_before_usermode(void) { +#ifdef CONFIG_PAGE_TABLE_ISOLATION /* With PTI, we unconditionally serialize before running user code. */ if (kaiser_active()) return; +#endif /* * Return from interrupt and NMI is done through iret, which is core * serializing. |
|
patch-i686-altmap.patch (805 bytes)
diff -up ./arch/x86/mm/init_32.c.altmap ./arch/x86/mm/init_32.c --- ./arch/x86/mm/init_32.c.altmap 2018-10-31 19:01:52.000000000 +0900 +++ ./arch/x86/mm/init_32.c 2018-10-31 19:03:08.000000000 +0900 @@ -844,14 +844,14 @@ void __init mem_init(void) } #ifdef CONFIG_MEMORY_HOTPLUG -int arch_add_memory(int nid, u64 start, u64 size, bool for_device) +int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap, bool for_device) { struct pglist_data *pgdata = NODE_DATA(nid); struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM; unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - return __add_pages(nid, zone, start_pfn, nr_pages); + return __add_pages(nid, zone, start_pfn, nr_pages, altmap); } #ifdef CONFIG_MEMORY_HOTREMOVE |
|
Replace this with centos-3.10-i686-uaccess_32-h-2.patch . arch/x86/lib/usercopy_32.c is already patched in kernel-3.10.0-957.el7.
centos-3.10-i686-uaccess_32-h-3.patch (8,691 bytes)
Replace this with centos-3.10-i686-uaccess_32-h-2.patch . arch/x86/lib/usercopy_32.c is already patched in kernel-3.10.0-957.el7. From 0a2d7d9b1e63dd28baf6c8e1416b64a33f89c900 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Tue, 23 Feb 2016 14:58:52 -0800 Subject: x86: fix SMAP in 32-bit environments commit de9e478b9d49f3a0214310d921450cf5bb4a21e6 upstream. In commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space accesses") I changed how the stac/clac instructions were generated around the user space accesses, which then made it possible to do batched accesses efficiently for user string copies etc. However, in doing so, I completely spaced out, and didn't even think about the 32-bit case. And nobody really even seemed to notice, because SMAP doesn't even exist until modern Skylake processors, and you'd have to be crazy to run 32-bit kernels on a modern CPU. Which brings us to Andy Lutomirski. He actually tested the 32-bit kernel on new hardware, and noticed that it doesn't work. My bad. The trivial fix is to add the required uaccess begin/end markers around the raw accesses in <asm/uaccess_32.h>. I feel a bit bad about this patch, just because that header file really should be cleaned up to avoid all the duplicated code in it, and this commit just expands on the problem. But this just fixes the bug without any bigger cleanup surgery. Reported-and-tested-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> [bwh: Backported to 3.16: There's no 'case 8' in __copy_to_user_inatomic()] Signed-off-by: Ben Hutchings <ben@decadent.org.uk> --- arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 3c03a5de64d3..b25d109fb95a 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); + __uaccess_end(); return ret; } } @@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } @@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } @@ -164,13 +182,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, switch (n) { case 1: + __uaccess_begin(); __get_user_size(*(u8 *)to, from, 1, ret, 1); + __uaccess_end(); return ret; case 2: + __uaccess_begin(); __get_user_size(*(u16 *)to, from, 2, ret, 2); + __uaccess_end(); return ret; case 4: + __uaccess_begin(); __get_user_size(*(u32 *)to, from, 4, ret, 4); + __uaccess_end(); return ret; } } -- cgit 1.2-0.3.lf.el7 From 98ce99aa23b43c3dc736cd0354537fca029d69cb Mon Sep 17 00:00:00 2001 From: Dan Williams <dan.j.williams@intel.com> Date: Mon, 29 Jan 2018 17:02:49 -0800 Subject: x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec commit 304ec1b050310548db33063e567123fae8fd0301 upstream. Quoting Linus: I do think that it would be a good idea to very expressly document the fact that it's not that the user access itself is unsafe. I do agree that things like "get_user()" want to be protected, but not because of any direct bugs or problems with get_user() and friends, but simply because get_user() is an excellent source of a pointer that is obviously controlled from a potentially attacking user space. So it's a prime candidate for then finding _subsequent_ accesses that can then be used to perturb the cache. __uaccess_begin_nospec() covers __get_user() and copy_from_iter() where the limit check is far away from the user pointer de-reference. In those cases a barrier_nospec() prevents speculation with a potential pointer to privileged memory. uaccess_try_nospec covers get_user_try. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Suggested-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: linux-arch@vger.kernel.org Cc: Kees Cook <keescook@chromium.org> Cc: kernel-hardening@lists.openwall.com Cc: gregkh@linuxfoundation.org Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: alan@linux.intel.com Link: https://lkml.kernel.org/r/151727416953.33451.10508284228526170604.stgit@dwillia2-desk3.amr.corp.intel.com [bwh: Backported to 3.16: - Convert several more functions to use __uaccess_begin_nospec(), that are just wrappers in mainline - There's no 'case 8' in __copy_to_user_inatomic() - Adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk> --- arch/x86/include/asm/uaccess.h | 6 +++--- arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++------------ arch/x86/include/asm/uaccess_64.h | 20 ++++++++++---------- arch/x86/lib/usercopy_32.c | 10 +++++----- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index b25d109fb95a..c803818cedfb 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -48,19 +48,19 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) switch (n) { case 1: - __uaccess_begin(); + __uaccess_begin_nospec(); __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); __uaccess_end(); return ret; case 2: - __uaccess_begin(); + __uaccess_begin_nospec(); __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); __uaccess_end(); return ret; case 4: - __uaccess_begin(); + __uaccess_begin_nospec(); __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); __uaccess_end(); @@ -104,17 +104,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) switch (n) { case 1: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u8 *)to, from, 1, ret, 1); __uaccess_end(); return ret; case 2: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u16 *)to, from, 2, ret, 2); __uaccess_end(); return ret; case 4: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u32 *)to, from, 4, ret, 4); __uaccess_end(); return ret; @@ -154,17 +154,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) switch (n) { case 1: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u8 *)to, from, 1, ret, 1); __uaccess_end(); return ret; case 2: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u16 *)to, from, 2, ret, 2); __uaccess_end(); return ret; case 4: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u32 *)to, from, 4, ret, 4); __uaccess_end(); return ret; @@ -182,17 +182,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, switch (n) { case 1: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u8 *)to, from, 1, ret, 1); __uaccess_end(); return ret; case 2: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u16 *)to, from, 2, ret, 2); __uaccess_end(); return ret; case 4: - __uaccess_begin(); + __uaccess_begin_nospec(); __get_user_size(*(u32 *)to, from, 4, ret, 4); __uaccess_end(); return ret; |
|
When compiling for i686, drivers/infiniband/hw/cxgb4/device.o fails to compile: drivers/infiniband/hw/cxgb4/device.c: In function 'wr_log_show': include/linux/ktime.h:84:36: error: 'prev_time.tv64' may be used uninitialized in this function [-Werror=maybe-uninitialized] ({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; }) ^ drivers/infiniband/hw/cxgb4/device.c:133:10: note: 'prev_time.tv64' was declared here ktime_t prev_time; ^ cc1: all warnings being treated as errors make[5]: *** [drivers/infiniband/hw/cxgb4/device.o] Error 1 I don't know why x86_64 is compiling without this patch. Compiler (gcc) version dependence?
patch-cxgb4-tv64-uninit.patch (1,170 bytes)
When compiling for i686, drivers/infiniband/hw/cxgb4/device.o fails to compile: drivers/infiniband/hw/cxgb4/device.c: In function 'wr_log_show': include/linux/ktime.h:84:36: error: 'prev_time.tv64' may be used uninitialized in this function [-Werror=maybe-uninitialized] ({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; }) ^ drivers/infiniband/hw/cxgb4/device.c:133:10: note: 'prev_time.tv64' was declared here ktime_t prev_time; ^ cc1: all warnings being treated as errors make[5]: *** [drivers/infiniband/hw/cxgb4/device.o] Error 1 I don't know why x86_64 is compiling without this patch. Compiler (gcc) version dependence? diff -up ./drivers/infiniband/hw/cxgb4/device.c.tv64 ./drivers/infiniband/hw/cxgb4/device.c --- ./drivers/infiniband/hw/cxgb4/device.c.tv64 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/infiniband/hw/cxgb4/device.c 2018-11-01 09:34:48.000000000 +0900 @@ -130,7 +130,7 @@ void c4iw_log_wr_stats(struct t4_wq *wq, static int wr_log_show(struct seq_file *seq, void *v) { struct c4iw_dev *dev = seq->private; - ktime_t prev_time; + ktime_t prev_time = { .tv64 = 0 }; struct wr_log_entry *lep; int prev_time_set = 0; int idx, end; |
|
patch-md-dax-toiovecend-null.patch (783 bytes)
Without CONFIG_DAX_DRIVER, drivers/md/dm-stripe.c fails to compile: drivers/md/dm-stripe.c:515:27: error: 'stripe_dax_memcpy_toiovecend' undeclared here (not in a function) .dax_memcpy_toiovecend = stripe_dax_memcpy_toiovecend, ^ CONFIG_DAX_DRIVER will be automaticallly selected by NVDIMM support, which needs PHYS_ADDR_T_64BIT setup. diff -up ./drivers/md/dm-stripe.c.dax ./drivers/md/dm-stripe.c --- ./drivers/md/dm-stripe.c.dax 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/md/dm-stripe.c 2018-11-01 12:53:35.000000000 +0900 @@ -370,6 +370,7 @@ static int stripe_dax_memcpy_toiovecend( #define stripe_dax_direct_access NULL #define stripe_dax_memcpy_fromiovecend NULL #define stripe_dax_memcpy_fromiovecend NULL +#define stripe_dax_memcpy_toiovecend NULL #endif /* |
|
Without CONFIG_DAX_DRIVER, drivers/md/dm-stripe.c fails to compile: drivers/md/dm-stripe.c:515:27: error: 'stripe_dax_memcpy_toiovecend' undeclared here (not in a function) .dax_memcpy_toiovecend = stripe_dax_memcpy_toiovecend, ^ CONFIG_DAX_DRIVER will be automaticallly selected by NVDIMM support, which needs PHYS_ADDR_T_64BIT setup.
patch-md-dax-toiovecend-null-2.patch (783 bytes)
Without CONFIG_DAX_DRIVER, drivers/md/dm-stripe.c fails to compile: drivers/md/dm-stripe.c:515:27: error: 'stripe_dax_memcpy_toiovecend' undeclared here (not in a function) .dax_memcpy_toiovecend = stripe_dax_memcpy_toiovecend, ^ CONFIG_DAX_DRIVER will be automaticallly selected by NVDIMM support, which needs PHYS_ADDR_T_64BIT setup. diff -up ./drivers/md/dm-stripe.c.dax ./drivers/md/dm-stripe.c --- ./drivers/md/dm-stripe.c.dax 2018-10-05 05:18:19.000000000 +0900 +++ ./drivers/md/dm-stripe.c 2018-11-01 12:53:35.000000000 +0900 @@ -370,6 +370,7 @@ static int stripe_dax_memcpy_toiovecend( #define stripe_dax_direct_access NULL #define stripe_dax_memcpy_fromiovecend NULL #define stripe_dax_memcpy_fromiovecend NULL +#define stripe_dax_memcpy_toiovecend NULL #endif /* |
|
That's all I have for now. I'm posting from the real machine running kernel: Linux capricorn.five.ten 3.10.0-957.el7.centos.plus.i686 #1 SMP Thu Nov 1 15:44:20 JST 2018 i686 i686 i386 GNU/Linux |
|
You are way ahead of anyone. Thank you so much. | |
'7.6.1810' added to the product version. | |
@kabe I have a few problems. (1) patch-md-dax-toiovecend-null.patch and patch-md-dax-toiovecend-null-2.patch look identical. I used the former only. (2) patch-pcc-long-cast.patch does not apply cleanly. (3) patch-nospec_u64_i686.patch is now in the current code. (4) I commented out the above 2 patches (2 and 3) and tried to build. But it failed. <error example> ./arch/x86/include/asm/pgtable.h: In function 'native_local_pudp_get_and_clear': ./arch/x86/include/asm/pgtable.h:980:2: error: implicit declaration of function 'native_pud_clear' [-Werror=implicit-function-declaration] native_pud_clear(pudp); ^ The spec file, kernel-3.10.0-i686.config and the srpm file are in https://people.centos.org/toracat/kernel/7/plus/.pre/ [EDIT] Please note that the last line of config should be: # CONFIG_RH_KABI_SIZE_ALIGN_CHECKS is not set (the uploaded version says =y) |
|
It's weird that native_pud_clear() is undefined; its's static inlined in arch/x86/include/asm/pgtable-3level.h or arch/x86/include/asm/pgtable-2level.h. I'll post the .config file I'm using. The notable difference is mine usess CONFIG_HIGHMEM4G (non-PAE). CentOS 7.5 i686 kernel was compiled with non-PAE; which should we choose, PAE or non-PAE? (I prefer non-PAE) I'll check back with yout priminary source.rpm . kernel-3.10.0-i686.config (151,430 bytes) |
|
In earlier versions, I wanted to enable XEN, which requires PAE to be enabled. To enable PAE, high memory support must be set to 64G. Perhaps I don't need this setup? I'm not sure. | |
I changed HIGHMEM from 64G back to 4G, disabling PAE. The build still fails. Looking at the details now. | |
@kabe Could you upload your spec and config, please? |
|
There are build errors related to readq/writeq. For example, drivers/net/ethernet/netronome/nfp/nfp_net_repr.c:93:2: error: implicit declaration of function 'readq' [-Werror=implicit-function-declaration] and drivers/scsi/smartpqi/smartpqi_init.c:2411:3: error: implicit declaration of function 'readq' [-Werror=implicit-function-declaration] drivers/scsi/smartpqi/smartpqi_init.c:3445:2: error: implicit declaration of function 'writeq' [-Werror=implicit-function-declaration] In previous kernels, CONFIG_NFP and CONFIG_SCSI_SMARTPQI were disabled in 32-bit (for this reason). A possible solution is to add <asm-generic/io-64-nonatomic-lo-hi.h> to the respective code. |
|
- A patch for the nfp issue uploaded (provided by @pgreco). - CONFIG_SCSI_SMARTPQI is now disabled. With these two changes, build now succeeds.
patch-i686-nfp-2.patch (428 bytes)
i686 plus kernel patch to fix nfp build error (readq) by @pgreco --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c.bak 2018-10-04 17:18:19.000000000 -0300 +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c 2018-11-02 18:53:31.443337889 -0300 @@ -38,6 +38,7 @@ #include "nfpcore/nfp_cpp.h" #include "nfpcore/nfp_nsp.h" +#include "nfp_net.h" #include "nfp_app.h" #include "nfp_main.h" #include "nfp_net_ctrl.h" |
|
Sorry for the delay. If you need PAE support, 3 additional patches seems to be needed. Yes, CONFIG_SCSI_SMARTPQI and CONFIG_NFP should be disabled due to readq()/writeq() issue.
patch-i686-pae-kaiser_add_mapping-flags.patch (1,035 bytes)
diff -up ./arch/x86/events/intel/ds.c.kam ./arch/x86/events/intel/ds.c --- ./arch/x86/events/intel/ds.c.kam 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/events/intel/ds.c 2018-11-02 11:12:18.000000000 +0900 @@ -292,7 +292,7 @@ static void *dsalloc(size_t size, gfp_t if (!page) return NULL; addr = (unsigned long)page_address(page); - if (kaiser_add_mapping(addr, size, __PAGE_KERNEL | _PAGE_GLOBAL) < 0) { + if (kaiser_add_mapping(addr, size, (unsigned long)(__PAGE_KERNEL | _PAGE_GLOBAL)) < 0) { __free_pages(page, order); addr = 0; } diff -up ./arch/x86/kernel/ldt.c.kam ./arch/x86/kernel/ldt.c --- ./arch/x86/kernel/ldt.c.kam 2018-10-05 05:18:19.000000000 +0900 +++ ./arch/x86/kernel/ldt.c 2018-11-02 11:19:58.000000000 +0900 @@ -94,7 +94,7 @@ static struct ldt_struct *alloc_ldt_stru ret = kaiser_add_mapping((unsigned long)new_ldt->entries, alloc_size, - __PAGE_KERNEL | _PAGE_GLOBAL); + (unsigned long)(__PAGE_KERNEL | _PAGE_GLOBAL)); if (ret) { free_ldt(new_ldt, size); return NULL; |
|
The #ifdef around pud_clear() is very weird, but needed to compile bootstrapping arch/x86/boot/compressed/error.c, which arch/x86/boot/compressed/misc.h does #undef CONFIG_PARAVIRT and codepath inside arch/x86/include/asm/pgtable.h goes into generally unused codepath, which does #ifndef __PAGETABLE_PMD_FOLDED /* never defined */ #define pud_clear(pud) native_pud_clear(pud) #endif which will duplicate define pud_clear().
patch-i686-pae-native_pud_clear.patch (1,225 bytes)
The #ifdef around pud_clear() is very weird, but needed to compile bootstrapping arch/x86/boot/compressed/error.c, which arch/x86/boot/compressed/misc.h does #undef CONFIG_PARAVIRT and codepath inside arch/x86/include/asm/pgtable.h goes into generally unused codepath, which does #ifndef __PAGETABLE_PMD_FOLDED /* never defined */ #define pud_clear(pud) native_pud_clear(pud) #endif which will duplicate define pud_clear(). diff -up ./arch/x86/include/asm/pgtable-3level.h.pud ./arch/x86/include/asm/pgtable-3level.h --- ./arch/x86/include/asm/pgtable-3level.h.pud 2018-11-02 13:21:03.000000000 +0900 +++ ./arch/x86/include/asm/pgtable-3level.h 2018-11-02 13:20:08.000000000 +0900 @@ -129,12 +129,11 @@ static inline void native_pmd_clear(pmd_ *(tmp + 1) = 0; } -#ifndef CONFIG_SMP static inline void native_pud_clear(pud_t *pudp) { } -#endif +#if /*defined(__PAGETABLE_PMD_FOLDED) &&*/ defined(CONFIG_PARAVIRT) static inline void pud_clear(pud_t *pudp) { mm_track_pud(pudp); @@ -151,6 +150,7 @@ static inline void pud_clear(pud_t *pudp * pud_clear_bad()), so we don't need TLB flush here. */ } +#endif #ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear(pte_t *ptep) |
|
patch-i686-pae-pmd-init.patch (702 bytes)
diff -up ./mm/huge_memory.c.pmd ./mm/huge_memory.c --- ./mm/huge_memory.c.pmd 2018-11-02 11:12:17.000000000 +0900 +++ ./mm/huge_memory.c 2018-11-02 11:32:28.000000000 +0900 @@ -1370,7 +1370,7 @@ static int do_huge_pmd_wp_page_fallback( unsigned long haddr = address & HPAGE_PMD_MASK; spinlock_t *ptl; pgtable_t pgtable; - pmd_t _pmd = {{{0}}}; + pmd_t _pmd = {0}; int ret = 0, i; struct page **pages; unsigned long mmun_start; /* For mmu_notifiers */ @@ -2313,7 +2313,7 @@ static int __split_huge_page_map(struct { struct mm_struct *mm = vma->vm_mm; spinlock_t *ptl; - pmd_t *pmd, _pmd = {{{0}}}; + pmd_t *pmd, _pmd = {0}; int ret = 0, i; pgtable_t pgtable; unsigned long haddr; |
|
This is the last patch fpr PAE support.
patch-i686-pae-pmd-init-2.patch (702 bytes)
diff -up ./mm/huge_memory.c.pmd ./mm/huge_memory.c --- ./mm/huge_memory.c.pmd 2018-11-02 11:12:17.000000000 +0900 +++ ./mm/huge_memory.c 2018-11-02 11:32:28.000000000 +0900 @@ -1370,7 +1370,7 @@ static int do_huge_pmd_wp_page_fallback( unsigned long haddr = address & HPAGE_PMD_MASK; spinlock_t *ptl; pgtable_t pgtable; - pmd_t _pmd = {{{0}}}; + pmd_t _pmd = {0}; int ret = 0, i; struct page **pages; unsigned long mmun_start; /* For mmu_notifiers */ @@ -2313,7 +2313,7 @@ static int __split_huge_page_map(struct { struct mm_struct *mm = vma->vm_mm; spinlock_t *ptl; - pmd_t *pmd, _pmd = {{{0}}}; + pmd_t *pmd, _pmd = {0}; int ret = 0, i; pgtable_t pgtable; unsigned long haddr; |
|
Mantis seems that only file, without comment, is uploaded when 300 seconds spam detection kicks in, The above 2 patches are identical. |
|
@arrfab, could you take a look at the mantis issue @kabe mentioned? @kabe, thanks for the patches. I will try building with PAE enabled. |
|
Build of the kernel with PAE support was successful with @kabe's additional patches. CONFIG_NFP is enabled with @pgreco's patch. CONFIG_SCSI_SMARTPQ is disabled. |
|
Personally I prefer non-PAE kernel; there's numerous reports in the wild that one could not install CentOS 7 i686 on their machines because PAE support is required. CentOS 7.4 i686 and after is compiled without PAE, so if there's no objection, non-PAE has slight wider audience. |
|
if there is something with mantis itself, the best is to create another bug report (in the "Mantis BT @ CentOS" category) that we can track otherwise it can become difficult to follow discussion on *this* bug report :) | |
PAE versus non-PAE is an interesting discussion. A non-PAE kernel is not provided for RHEL/CentOS-6. ELRepo's kernel-lt/ml was originally PAE-only, like the distro kernel. Then there was a request to produce non-PAE kernels. So, ELRepo has been providing both PAE and non-PAE kernels for EL6. As @kabe pointed out, in CentOS-7, i686 kernel was PAE-enabled up to 7.3 and then non-PAE for 7.4 and 7.5. The fact there has been no request / complaint about this so far may mean "no need to switch back" ? |
|
The use case for PAE has largely been superceded by the 64 bit version. Anyone using 32 bit only hardware and needing > 4GB RAM has probably already updated to hardware able to run 64 bit and is using that. | |
I hear you. After all RH even abandoned i686 kernel in -7. | |
OK, I rebuilt the non-PAE version and uploaded this to: https://people.centos.org/toracat/kernel/7/plus/7.6.1810/957/ This is hopefully the final version. |
|
Closing as resolved. Thanks, @kabe, for all your help. | |
Date Modified | Username | Field | Change |
---|---|---|---|
2018-11-01 12:30 | kabe | New Issue | |
2018-11-01 12:33 | kabe | File Added: i686-7-6.patch | |
2018-11-01 12:33 | kabe | Note Added: 0033032 | |
2018-11-01 12:33 | kabe | Tag Attached: i386 | |
2018-11-01 12:42 | kabe | File Added: patch-copy_from_user-warning-v3.patch | |
2018-11-01 12:42 | kabe | Note Added: 0033033 | |
2018-11-01 12:43 | kabe | File Added: patch-zu-format-v2.patch | |
2018-11-01 12:43 | kabe | Note Added: 0033034 | |
2018-11-01 12:45 | kabe | File Added: patch-bpf-map_ids-cast.patch | |
2018-11-01 12:51 | kabe | File Added: patch-ioremap-v2.patch | |
2018-11-01 12:51 | kabe | Note Added: 0033035 | |
2018-11-01 12:52 | kabe | File Added: patch-i686-bpf-nojit.patch | |
2018-11-01 12:53 | kabe | File Added: patch-i686-no-kaiser_active.patch | |
2018-11-01 12:54 | kabe | File Added: patch-i686-altmap.patch | |
2018-11-01 13:02 | kabe | File Added: centos-3.10-i686-uaccess_32-h-3.patch | |
2018-11-01 13:02 | kabe | Note Added: 0033036 | |
2018-11-01 13:03 | kabe | File Added: patch-cxgb4-tv64-uninit.patch | |
2018-11-01 13:03 | kabe | Note Added: 0033037 | |
2018-11-01 13:04 | kabe | File Added: patch-md-dax-toiovecend-null.patch | |
2018-11-01 13:11 | kabe | File Added: patch-md-dax-toiovecend-null-2.patch | |
2018-11-01 13:11 | kabe | Note Added: 0033038 | |
2018-11-01 13:14 | kabe | Note Added: 0033039 | |
2018-11-01 14:03 | toracat | Note Added: 0033040 | |
2018-11-01 14:05 | toracat | Status | new => assigned |
2018-11-01 14:05 | toracat | Product Version | 7.5.1804 => 7.6.1810 |
2018-11-01 14:05 | toracat | Note Added: 0033041 | |
2018-11-01 23:32 | toracat | Note Added: 0033043 | |
2018-11-01 23:35 | toracat | Note Edited: 0033043 | View Revisions |
2018-11-01 23:45 | toracat | Note Edited: 0033043 | View Revisions |
2018-11-02 00:58 | kabe | File Added: kernel-3.10.0-i686.config | |
2018-11-02 00:58 | kabe | Note Added: 0033044 | |
2018-11-02 02:00 | toracat | Note Added: 0033045 | |
2018-11-02 16:56 | toracat | Note Added: 0033052 | |
2018-11-02 16:58 | toracat | Note Added: 0033053 | |
2018-11-03 06:42 | toracat | Note Added: 0033057 | |
2018-11-03 19:11 | toracat | File Added: patch-i686-nfp-2.patch | |
2018-11-03 19:11 | toracat | Note Added: 0033059 | |
2018-11-04 14:28 | kabe | File Added: patch-i686-pae-kaiser_add_mapping-flags.patch | |
2018-11-04 14:28 | kabe | Note Added: 0033061 | |
2018-11-04 14:30 | kabe | File Added: patch-i686-pae-native_pud_clear.patch | |
2018-11-04 14:30 | kabe | Note Added: 0033062 | |
2018-11-04 14:32 | kabe | File Added: patch-i686-pae-pmd-init.patch | |
2018-11-04 14:38 | kabe | File Added: patch-i686-pae-pmd-init-2.patch | |
2018-11-04 14:38 | kabe | Note Added: 0033063 | |
2018-11-04 14:40 | kabe | Note Added: 0033064 | |
2018-11-04 18:14 | toracat | Note Added: 0033065 | |
2018-11-05 01:04 | toracat | Note Added: 0033069 | |
2018-11-05 01:49 | kabe | Note Added: 0033070 | |
2018-11-05 06:31 | arrfab | Note Added: 0033073 | |
2018-11-05 08:51 | toracat | Note Added: 0033076 | |
2018-11-05 09:03 | TrevorH | Note Added: 0033077 | |
2018-11-05 09:16 | toracat | Note Added: 0033078 | |
2018-11-07 17:51 | toracat | Note Added: 0033088 | |
2018-12-12 06:12 | toracat | Status | assigned => resolved |
2018-12-12 06:12 | toracat | Resolution | open => fixed |
2018-12-12 06:12 | toracat | Note Added: 0033319 |