diff options
-rw-r--r-- | 4.5.7/0000_README | 2 | ||||
-rw-r--r-- | 4.5.7/4420_grsecurity-3.1-4.5.7-201606142010.patch (renamed from 4.5.7/4420_grsecurity-3.1-4.5.7-201606080852.patch) | 1324 |
2 files changed, 1056 insertions, 270 deletions
diff --git a/4.5.7/0000_README b/4.5.7/0000_README index 67f12a7..7dd453b 100644 --- a/4.5.7/0000_README +++ b/4.5.7/0000_README @@ -2,7 +2,7 @@ README ----------------------------------------------------------------------------- Individual Patch Descriptions: ----------------------------------------------------------------------------- -Patch: 4420_grsecurity-3.1-4.5.7-201606080852.patch +Patch: 4420_grsecurity-3.1-4.5.7-201606142010.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/4.5.7/4420_grsecurity-3.1-4.5.7-201606080852.patch b/4.5.7/4420_grsecurity-3.1-4.5.7-201606142010.patch index 65f5e28..b46e7cf 100644 --- a/4.5.7/4420_grsecurity-3.1-4.5.7-201606080852.patch +++ b/4.5.7/4420_grsecurity-3.1-4.5.7-201606142010.patch @@ -3631,6 +3631,68 @@ index 549f6d3..909a9dc 100644 default y if ARM_ARCH_TIMER select GENERIC_TIME_VSYSCALL help +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index 7d5f4c7..c6a0816 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -778,6 +778,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + u16 tinstr = 0; + int isize = 4; + int thumb2_32b = 0; ++ bool is_user_mode = user_mode(regs); + + if (interrupts_enabled(regs)) + local_irq_enable(); +@@ -786,14 +787,24 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + + if (thumb_mode(regs)) { + u16 *ptr = (u16 *)(instrptr & ~1); +- fault = probe_kernel_address(ptr, tinstr); ++ if (is_user_mode) { ++ pax_open_userland(); ++ fault = probe_kernel_address(ptr, tinstr); ++ pax_close_userland(); ++ } else ++ fault = probe_kernel_address(ptr, tinstr); + tinstr = __mem_to_opcode_thumb16(tinstr); + if (!fault) { + if (cpu_architecture() >= CPU_ARCH_ARMv7 && + IS_T32(tinstr)) { + /* Thumb-2 32-bit */ + u16 tinst2 = 0; +- fault = probe_kernel_address(ptr + 1, tinst2); ++ if (is_user_mode) { ++ pax_open_userland(); ++ fault = probe_kernel_address(ptr + 1, tinst2); ++ pax_close_userland(); ++ } else ++ fault = probe_kernel_address(ptr + 1, tinst2); + tinst2 = __mem_to_opcode_thumb16(tinst2); + instr = __opcode_thumb32_compose(tinstr, tinst2); + thumb2_32b = 1; +@@ -803,7 +814,12 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + } + } + } else { +- fault = probe_kernel_address((void *)instrptr, instr); ++ if (is_user_mode) { ++ pax_open_userland(); ++ fault = probe_kernel_address((void *)instrptr, instr); ++ pax_close_userland(); ++ } else ++ fault = probe_kernel_address((void *)instrptr, instr); + instr = __mem_to_opcode_arm(instr); + } + +@@ -812,7 +828,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + goto bad_or_fault; + } + +- if (user_mode(regs)) ++ if (is_user_mode) + goto user; + + ai_sys += 1; diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 9f9d542..5189649 100644 --- a/arch/arm/mm/cache-l2x0.c @@ -97446,6 +97508,123 @@ index 8580831..36166e5 100644 retval = sysfs_create_mount_point(kernel_kobj, "debug"); if (retval) return retval; +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index feef8a9..f024040 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -112,7 +112,6 @@ static int ecryptfs_readdir(struct file *file, struct dir_context *ctx) + .sb = inode->i_sb, + }; + lower_file = ecryptfs_file_to_lower(file); +- lower_file->f_pos = ctx->pos; + rc = iterate_dir(lower_file, &buf.ctx); + ctx->pos = buf.ctx.pos; + if (rc < 0) +@@ -223,14 +222,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file) + } + ecryptfs_set_file_lower( + file, ecryptfs_inode_to_private(inode)->lower_file); +- if (d_is_dir(ecryptfs_dentry)) { +- ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); +- mutex_lock(&crypt_stat->cs_mutex); +- crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); +- mutex_unlock(&crypt_stat->cs_mutex); +- rc = 0; +- goto out; +- } + rc = read_or_initialize_metadata(ecryptfs_dentry); + if (rc) + goto out_put; +@@ -247,6 +238,45 @@ out: + return rc; + } + ++/** ++ * ecryptfs_dir_open ++ * @inode: inode speciying file to open ++ * @file: Structure to return filled in ++ * ++ * Opens the file specified by inode. ++ * ++ * Returns zero on success; non-zero otherwise ++ */ ++static int ecryptfs_dir_open(struct inode *inode, struct file *file) ++{ ++ struct dentry *ecryptfs_dentry = file->f_path.dentry; ++ /* Private value of ecryptfs_dentry allocated in ++ * ecryptfs_lookup() */ ++ struct ecryptfs_file_info *file_info; ++ struct file *lower_file; ++ ++ /* Released in ecryptfs_release or end of function if failure */ ++ file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); ++ ecryptfs_set_file_private(file, file_info); ++ if (unlikely(!file_info)) { ++ ecryptfs_printk(KERN_ERR, ++ "Error attempting to allocate memory\n"); ++ return -ENOMEM; ++ } ++ lower_file = dentry_open(ecryptfs_dentry_to_lower_path(ecryptfs_dentry), ++ file->f_flags, current_cred()); ++ if (IS_ERR(lower_file)) { ++ printk(KERN_ERR "%s: Error attempting to initialize " ++ "the lower file for the dentry with name " ++ "[%pd]; rc = [%ld]\n", __func__, ++ ecryptfs_dentry, PTR_ERR(lower_file)); ++ kmem_cache_free(ecryptfs_file_info_cache, file_info); ++ return PTR_ERR(lower_file); ++ } ++ ecryptfs_set_file_lower(file, lower_file); ++ return 0; ++} ++ + static int ecryptfs_flush(struct file *file, fl_owner_t td) + { + struct file *lower_file = ecryptfs_file_to_lower(file); +@@ -267,6 +297,19 @@ static int ecryptfs_release(struct inode *inode, struct file *file) + return 0; + } + ++static int ecryptfs_dir_release(struct inode *inode, struct file *file) ++{ ++ fput(ecryptfs_file_to_lower(file)); ++ kmem_cache_free(ecryptfs_file_info_cache, ++ ecryptfs_file_to_private(file)); ++ return 0; ++} ++ ++static loff_t ecryptfs_dir_llseek(struct file *file, loff_t offset, int whence) ++{ ++ return vfs_llseek(ecryptfs_file_to_lower(file), offset, whence); ++} ++ + static int + ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) + { +@@ -346,20 +389,16 @@ const struct file_operations ecryptfs_dir_fops = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, + #endif +- .open = ecryptfs_open, +- .flush = ecryptfs_flush, +- .release = ecryptfs_release, ++ .open = ecryptfs_dir_open, ++ .release = ecryptfs_dir_release, + .fsync = ecryptfs_fsync, +- .fasync = ecryptfs_fasync, +- .splice_read = generic_file_splice_read, +- .llseek = default_llseek, ++ .llseek = ecryptfs_dir_llseek, + }; + + const struct file_operations ecryptfs_main_fops = { + .llseek = generic_file_llseek, + .read_iter = ecryptfs_read_update_atime, + .write_iter = generic_file_write_iter, +- .iterate = ecryptfs_readdir, + .unlocked_ioctl = ecryptfs_unlocked_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 4e685ac..462fc20 100644 --- a/fs/ecryptfs/inode.c @@ -97483,6 +97662,45 @@ index 6bd67e2..1d71a4b 100644 } s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { +diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c +index 866bb18..e818f5a 100644 +--- a/fs/ecryptfs/kthread.c ++++ b/fs/ecryptfs/kthread.c +@@ -25,6 +25,7 @@ + #include <linux/slab.h> + #include <linux/wait.h> + #include <linux/mount.h> ++#include <linux/file.h> + #include "ecryptfs_kernel.h" + + struct ecryptfs_open_req { +@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file, + flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR; + (*lower_file) = dentry_open(&req.path, flags, cred); + if (!IS_ERR(*lower_file)) +- goto out; ++ goto have_file; + if ((flags & O_ACCMODE) == O_RDONLY) { + rc = PTR_ERR((*lower_file)); + goto out; +@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file, + mutex_unlock(&ecryptfs_kthread_ctl.mux); + wake_up(&ecryptfs_kthread_ctl.wait); + wait_for_completion(&req.done); +- if (IS_ERR(*lower_file)) ++ if (IS_ERR(*lower_file)) { + rc = PTR_ERR(*lower_file); ++ goto out; ++ } ++have_file: ++ if ((*lower_file)->f_op->mmap == NULL) { ++ fput(*lower_file); ++ *lower_file = NULL; ++ rc = -EMEDIUMTYPE; ++ } + out: + return rc; + } diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index e4141f2..d8263e8 100644 --- a/fs/ecryptfs/miscdev.c @@ -97497,7 +97715,7 @@ index e4141f2..d8263e8 100644 i += packet_length_size; if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size)) diff --git a/fs/exec.c b/fs/exec.c -index dcd4ac7..b1bb7fa 100644 +index dcd4ac7..50eef0a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -56,8 +56,20 @@ @@ -97835,15 +98053,7 @@ index dcd4ac7..b1bb7fa 100644 set_fs(old_fs); return result; } -@@ -869,6 +959,7 @@ static int exec_mmap(struct mm_struct *mm) - tsk->mm = mm; - tsk->active_mm = mm; - activate_mm(active_mm, mm); -+ populate_stack(); - tsk->mm->vmacache_seqnum = 0; - vmacache_flush(tsk); - task_unlock(tsk); -@@ -1277,7 +1368,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm) +@@ -1277,7 +1367,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm) } rcu_read_unlock(); @@ -97852,7 +98062,7 @@ index dcd4ac7..b1bb7fa 100644 bprm->unsafe |= LSM_UNSAFE_SHARE; else p->fs->in_exec = 1; -@@ -1478,6 +1569,31 @@ static int exec_binprm(struct linux_binprm *bprm) +@@ -1478,6 +1568,31 @@ static int exec_binprm(struct linux_binprm *bprm) return ret; } @@ -97884,7 +98094,7 @@ index dcd4ac7..b1bb7fa 100644 /* * sys_execve() executes a new program. */ -@@ -1486,6 +1602,11 @@ static int do_execveat_common(int fd, struct filename *filename, +@@ -1486,6 +1601,11 @@ static int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr envp, int flags) { @@ -97896,7 +98106,7 @@ index dcd4ac7..b1bb7fa 100644 char *pathbuf = NULL; struct linux_binprm *bprm; struct file *file; -@@ -1495,6 +1616,8 @@ static int do_execveat_common(int fd, struct filename *filename, +@@ -1495,6 +1615,8 @@ static int do_execveat_common(int fd, struct filename *filename, if (IS_ERR(filename)) return PTR_ERR(filename); @@ -97905,7 +98115,7 @@ index dcd4ac7..b1bb7fa 100644 /* * We move the actual failure in case of RLIMIT_NPROC excess from * set*uid() to execve() because too many poorly written programs -@@ -1558,6 +1681,11 @@ static int do_execveat_common(int fd, struct filename *filename, +@@ -1558,6 +1680,11 @@ static int do_execveat_common(int fd, struct filename *filename, } bprm->interp = bprm->filename; @@ -97917,7 +98127,7 @@ index dcd4ac7..b1bb7fa 100644 retval = bprm_mm_init(bprm); if (retval) goto out_unmark; -@@ -1574,24 +1702,70 @@ static int do_execveat_common(int fd, struct filename *filename, +@@ -1574,24 +1701,70 @@ static int do_execveat_common(int fd, struct filename *filename, if (retval < 0) goto out; @@ -97992,7 +98202,7 @@ index dcd4ac7..b1bb7fa 100644 current->fs->in_exec = 0; current->in_execve = 0; acct_update_integrals(current); -@@ -1603,6 +1777,14 @@ static int do_execveat_common(int fd, struct filename *filename, +@@ -1603,6 +1776,14 @@ static int do_execveat_common(int fd, struct filename *filename, put_files_struct(displaced); return retval; @@ -98007,7 +98217,7 @@ index dcd4ac7..b1bb7fa 100644 out: if (bprm->mm) { acct_arg_size(bprm, 0); -@@ -1749,3 +1931,319 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd, +@@ -1749,3 +1930,319 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd, argv, envp, flags); } #endif @@ -98163,7 +98373,7 @@ index dcd4ac7..b1bb7fa 100644 + +#ifdef CONFIG_PAX_USERCOPY +/* 0: not at all, 1: fully, 2: fully inside frame, -1: partially (implies an error) */ -+static noinline int check_stack_object(const void *obj, unsigned long len) ++static noinline int check_stack_object(unsigned long obj, unsigned long len) +{ + const void * const stack = task_stack_page(current); + const void * const stackend = stack + THREAD_SIZE; @@ -98176,10 +98386,10 @@ index dcd4ac7..b1bb7fa 100644 + if (obj + len < obj) + return -1; + -+ if (obj + len <= stack || stackend <= obj) ++ if (obj + len <= (unsigned long)stack || (unsigned long)stackend <= obj) + return 0; + -+ if (obj < stack || stackend < obj + len) ++ if (obj < (unsigned long)stack || (unsigned long)stackend < obj + len) + return -1; + +#if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86) @@ -98198,8 +98408,8 @@ index dcd4ac7..b1bb7fa 100644 + causing us to bail out and correctly report + the copy as invalid + */ -+ if (obj + len <= frame) -+ return obj >= oldframe + 2 * sizeof(void *) ? 2 : -1; ++ if (obj + len <= (unsigned long)frame) ++ return obj >= (unsigned long)oldframe + 2 * sizeof(void *) ? 2 : -1; + oldframe = frame; + frame = *(const void * const *)frame; + } @@ -98280,7 +98490,7 @@ index dcd4ac7..b1bb7fa 100644 + + type = check_heap_object(ptr, n); + if (!type) { -+ int ret = check_stack_object(ptr, n); ++ int ret = check_stack_object((unsigned long)ptr, n); + if (ret == 1 || ret == 2) + return; + if (ret == 0) { @@ -113366,10 +113576,24 @@ index fe5b6e6..cd2913c 100644 kfree(ctl_table_arg); goto out; diff --git a/fs/proc/root.c b/fs/proc/root.c -index 361ab4e..9720b97 100644 +index 361ab4e..55e45e9 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c -@@ -187,7 +187,15 @@ void __init proc_root_init(void) +@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + if (IS_ERR(sb)) + return ERR_CAST(sb); + ++ /* ++ * procfs isn't actually a stacking filesystem; however, there is ++ * too much magic going on inside it to permit stacking things on ++ * top of it ++ */ ++ sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH; ++ + if (!proc_parse_options(options, ns)) { + deactivate_locked_super(sb); + return ERR_PTR(-EINVAL); +@@ -187,7 +194,15 @@ void __init proc_root_init(void) proc_create_mount_point("openprom"); #endif proc_tty_init(); @@ -115023,6 +115247,157 @@ index 642d55d..d8ccf82 100644 xfs_dir3_get_dtype(dp->i_mount, filetype))) return 0; sfep = dp->d_ops->sf_nextentry(sfp, sfep); +diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c +index d7a490f..59a8848 100644 +--- a/fs/xfs/xfs_icache.c ++++ b/fs/xfs/xfs_icache.c +@@ -91,13 +91,6 @@ xfs_inode_free_callback( + struct inode *inode = container_of(head, struct inode, i_rcu); + struct xfs_inode *ip = XFS_I(inode); + +- kmem_zone_free(xfs_inode_zone, ip); +-} +- +-void +-xfs_inode_free( +- struct xfs_inode *ip) +-{ + switch (ip->i_d.di_mode & S_IFMT) { + case S_IFREG: + case S_IFDIR: +@@ -115,6 +108,25 @@ xfs_inode_free( + ip->i_itemp = NULL; + } + ++ kmem_zone_free(xfs_inode_zone, ip); ++} ++ ++static void ++__xfs_inode_free( ++ struct xfs_inode *ip) ++{ ++ /* asserts to verify all state is correct here */ ++ ASSERT(atomic_read(&ip->i_pincount) == 0); ++ ASSERT(!xfs_isiflocked(ip)); ++ XFS_STATS_DEC(ip->i_mount, vn_active); ++ ++ call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); ++} ++ ++void ++xfs_inode_free( ++ struct xfs_inode *ip) ++{ + /* + * Because we use RCU freeing we need to ensure the inode always + * appears to be reclaimed with an invalid inode number when in the +@@ -126,12 +138,7 @@ xfs_inode_free( + ip->i_ino = 0; + spin_unlock(&ip->i_flags_lock); + +- /* asserts to verify all state is correct here */ +- ASSERT(atomic_read(&ip->i_pincount) == 0); +- ASSERT(!xfs_isiflocked(ip)); +- XFS_STATS_DEC(ip->i_mount, vn_active); +- +- call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); ++ __xfs_inode_free(ip); + } + + /* +@@ -741,8 +748,7 @@ __xfs_inode_set_reclaim_tag( + if (!pag->pag_ici_reclaimable) { + /* propagate the reclaim tag up into the perag radix tree */ + spin_lock(&ip->i_mount->m_perag_lock); +- radix_tree_tag_set(&ip->i_mount->m_perag_tree, +- XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), ++ radix_tree_tag_set(&ip->i_mount->m_perag_tree, pag->pag_agno, + XFS_ICI_RECLAIM_TAG); + spin_unlock(&ip->i_mount->m_perag_lock); + +@@ -786,8 +792,7 @@ __xfs_inode_clear_reclaim( + if (!pag->pag_ici_reclaimable) { + /* clear the reclaim tag from the perag radix tree */ + spin_lock(&ip->i_mount->m_perag_lock); +- radix_tree_tag_clear(&ip->i_mount->m_perag_tree, +- XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), ++ radix_tree_tag_clear(&ip->i_mount->m_perag_tree, pag->pag_agno, + XFS_ICI_RECLAIM_TAG); + spin_unlock(&ip->i_mount->m_perag_lock); + trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno, +@@ -898,6 +903,7 @@ xfs_reclaim_inode( + int sync_mode) + { + struct xfs_buf *bp = NULL; ++ xfs_ino_t ino = ip->i_ino; /* for radix_tree_delete */ + int error; + + restart: +@@ -962,6 +968,22 @@ restart: + + xfs_iflock(ip); + reclaim: ++ /* ++ * Because we use RCU freeing we need to ensure the inode always appears ++ * to be reclaimed with an invalid inode number when in the free state. ++ * We do this as early as possible under the ILOCK and flush lock so ++ * that xfs_iflush_cluster() can be guaranteed to detect races with us ++ * here. By doing this, we guarantee that once xfs_iflush_cluster has ++ * locked both the XFS_ILOCK and the flush lock that it will see either ++ * a valid, flushable inode that will serialise correctly against the ++ * locks below, or it will see a clean (and invalid) inode that it can ++ * skip. ++ */ ++ spin_lock(&ip->i_flags_lock); ++ ip->i_flags = XFS_IRECLAIM; ++ ip->i_ino = 0; ++ spin_unlock(&ip->i_flags_lock); ++ + xfs_ifunlock(ip); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + +@@ -975,7 +997,7 @@ reclaim: + */ + spin_lock(&pag->pag_ici_lock); + if (!radix_tree_delete(&pag->pag_ici_root, +- XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino))) ++ XFS_INO_TO_AGINO(ip->i_mount, ino))) + ASSERT(0); + __xfs_inode_clear_reclaim(pag, ip); + spin_unlock(&pag->pag_ici_lock); +@@ -992,7 +1014,7 @@ reclaim: + xfs_qm_dqdetach(ip); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + +- xfs_inode_free(ip); ++ __xfs_inode_free(ip); + return error; + + out_ifunlock: +diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c +index c738a52..658eea8 100644 +--- a/fs/xfs/xfs_inode.c ++++ b/fs/xfs/xfs_inode.c +@@ -3259,6 +3259,19 @@ xfs_iflush_cluster( + continue; + } + ++ ++ /* ++ * Check the inode number again, just to be certain we are not ++ * racing with freeing in xfs_reclaim_inode(). See the comments ++ * in that function for more information as to why the initial ++ * check is not sufficient. ++ */ ++ if (!iq->i_ino) { ++ xfs_ifunlock(iq); ++ xfs_iunlock(iq, XFS_ILOCK_SHARED); ++ continue; ++ } ++ + /* + * arriving here means that this inode can be flushed. First + * re-check that it's dirty before flushing. diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 478d04e..3d6a86b 100644 --- a/fs/xfs/xfs_ioctl.c @@ -132656,7 +133031,7 @@ index 556ec1e..38c19c9 100644 /* diff --git a/include/linux/sched.h b/include/linux/sched.h -index a10494a..9f25fd6 100644 +index a10494a..2d7faf1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -7,7 +7,7 @@ @@ -132929,17 +133304,16 @@ index a10494a..9f25fd6 100644 { return tsk->pid; } -@@ -2289,6 +2397,26 @@ extern u64 sched_clock_cpu(int cpu); +@@ -2289,6 +2397,25 @@ extern u64 sched_clock_cpu(int cpu); extern void sched_clock_init(void); +#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW -+static inline void populate_stack(void) ++static inline void populate_stack(void *stack) +{ -+ struct task_struct *curtask = current; + int c; -+ int *ptr = curtask->stack; -+ int *end = curtask->stack + THREAD_SIZE; ++ int *ptr = stack; ++ int *end = stack + THREAD_SIZE; + + while (ptr < end) { + c = *(volatile int *)ptr; @@ -132948,7 +133322,7 @@ index a10494a..9f25fd6 100644 + } +} +#else -+static inline void populate_stack(void) ++static inline void populate_stack(void *stack) +{ +} +#endif @@ -132956,7 +133330,7 @@ index a10494a..9f25fd6 100644 #ifndef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK static inline void sched_clock_tick(void) { -@@ -2417,7 +2545,9 @@ extern void set_curr_task(int cpu, struct task_struct *p); +@@ -2417,7 +2544,9 @@ extern void set_curr_task(int cpu, struct task_struct *p); void yield(void); union thread_union { @@ -132966,7 +133340,7 @@ index a10494a..9f25fd6 100644 unsigned long stack[THREAD_SIZE/sizeof(long)]; }; -@@ -2450,6 +2580,7 @@ extern struct pid_namespace init_pid_ns; +@@ -2450,6 +2579,7 @@ extern struct pid_namespace init_pid_ns; */ extern struct task_struct *find_task_by_vpid(pid_t nr); @@ -132974,7 +133348,7 @@ index a10494a..9f25fd6 100644 extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns); -@@ -2481,7 +2612,7 @@ extern void proc_caches_init(void); +@@ -2481,7 +2611,7 @@ extern void proc_caches_init(void); extern void flush_signals(struct task_struct *); extern void ignore_signals(struct task_struct *); extern void flush_signal_handlers(struct task_struct *, int force_default); @@ -132983,7 +133357,7 @@ index a10494a..9f25fd6 100644 static inline int kernel_dequeue_signal(siginfo_t *info) { -@@ -2635,7 +2766,7 @@ extern void __cleanup_sighand(struct sighand_struct *); +@@ -2635,7 +2765,7 @@ extern void __cleanup_sighand(struct sighand_struct *); extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); @@ -132992,7 +133366,7 @@ index a10494a..9f25fd6 100644 extern int do_execve(struct filename *, const char __user * const __user *, -@@ -2750,11 +2881,13 @@ static inline int thread_group_empty(struct task_struct *p) +@@ -2750,11 +2880,13 @@ static inline int thread_group_empty(struct task_struct *p) * It must not be nested with write_lock_irq(&tasklist_lock), * neither inside nor outside. */ @@ -133006,7 +133380,7 @@ index a10494a..9f25fd6 100644 static inline void task_unlock(struct task_struct *p) { spin_unlock(&p->alloc_lock); -@@ -2840,9 +2973,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) +@@ -2840,9 +2972,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) #define task_stack_end_corrupted(task) \ (*(end_of_stack(task)) != STACK_END_MAGIC) @@ -138371,10 +138745,10 @@ index c112abb..49d919f 100644 if (wo->wo_flags & __WNOTHREAD) break; diff --git a/kernel/fork.c b/kernel/fork.c -index 2e391c7..555531a 100644 +index 2e391c7..4af22a9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -188,12 +188,54 @@ static void free_thread_info(struct thread_info *ti) +@@ -188,12 +188,55 @@ static void free_thread_info(struct thread_info *ti) void thread_info_cache_init(void) { thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, @@ -138405,7 +138779,8 @@ index 2e391c7..555531a 100644 + if (ret == NULL) { + free_thread_info(*lowmem_stack); + *lowmem_stack = NULL; -+ } ++ } else ++ populate_stack(ret); + +out: + return ret; @@ -138430,7 +138805,7 @@ index 2e391c7..555531a 100644 /* SLAB cache for signal_struct structures (tsk->signal) */ static struct kmem_cache *signal_cachep; -@@ -212,18 +254,22 @@ struct kmem_cache *vm_area_cachep; +@@ -212,18 +255,22 @@ struct kmem_cache *vm_area_cachep; /* SLAB cache for mm_struct structures (tsk->mm) */ static struct kmem_cache *mm_cachep; @@ -138456,7 +138831,7 @@ index 2e391c7..555531a 100644 rt_mutex_debug_task_free(tsk); ftrace_graph_exit_task(tsk); put_seccomp_filter(tsk); -@@ -290,7 +336,7 @@ static void set_max_threads(unsigned int max_threads_suggested) +@@ -290,7 +337,7 @@ static void set_max_threads(unsigned int max_threads_suggested) #ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT /* Initialized by the architecture: */ @@ -138465,7 +138840,7 @@ index 2e391c7..555531a 100644 #endif void __init fork_init(void) -@@ -335,6 +381,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -335,6 +382,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; @@ -138473,7 +138848,7 @@ index 2e391c7..555531a 100644 int node = tsk_fork_get_node(orig); int err; -@@ -342,7 +389,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -342,7 +390,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) if (!tsk) return NULL; @@ -138482,7 +138857,7 @@ index 2e391c7..555531a 100644 if (!ti) goto free_tsk; -@@ -351,6 +398,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -351,6 +399,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) goto free_ti; tsk->stack = ti; @@ -138492,7 +138867,7 @@ index 2e391c7..555531a 100644 #ifdef CONFIG_SECCOMP /* * We must handle setting up seccomp filters once we're under -@@ -367,7 +417,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -367,7 +418,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) set_task_stack_end_magic(tsk); #ifdef CONFIG_CC_STACKPROTECTOR @@ -138501,7 +138876,7 @@ index 2e391c7..555531a 100644 #endif /* -@@ -382,24 +432,90 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -382,24 +433,90 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) tsk->task_frag.page = NULL; tsk->wake_q.next = NULL; @@ -138596,7 +138971,7 @@ index 2e391c7..555531a 100644 uprobe_start_dup_mmap(); down_write(&oldmm->mmap_sem); -@@ -430,52 +546,14 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -430,52 +547,14 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) prev = NULL; for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { @@ -138653,7 +139028,7 @@ index 2e391c7..555531a 100644 } /* -@@ -507,6 +585,38 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -507,6 +586,38 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; } @@ -138692,7 +139067,7 @@ index 2e391c7..555531a 100644 /* a new mm has just been created */ arch_dup_mmap(oldmm, mm); retval = 0; -@@ -516,14 +626,6 @@ out: +@@ -516,14 +627,6 @@ out: up_write(&oldmm->mmap_sem); uprobe_end_dup_mmap(); return retval; @@ -138707,7 +139082,7 @@ index 2e391c7..555531a 100644 } static inline int mm_alloc_pgd(struct mm_struct *mm) -@@ -798,8 +900,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +@@ -798,8 +901,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) return ERR_PTR(err); mm = get_task_mm(task); @@ -138718,7 +139093,7 @@ index 2e391c7..555531a 100644 mmput(mm); mm = ERR_PTR(-EACCES); } -@@ -1000,13 +1102,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) +@@ -1000,13 +1103,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) spin_unlock(&fs->lock); return -EAGAIN; } @@ -138740,7 +139115,7 @@ index 2e391c7..555531a 100644 return 0; } -@@ -1239,7 +1348,7 @@ init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) +@@ -1239,7 +1349,7 @@ init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ @@ -138749,7 +139124,7 @@ index 2e391c7..555531a 100644 unsigned long stack_start, unsigned long stack_size, int __user *child_tidptr, -@@ -1310,6 +1419,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1310,6 +1420,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif retval = -EAGAIN; @@ -138759,7 +139134,7 @@ index 2e391c7..555531a 100644 if (atomic_read(&p->real_cred->user->processes) >= task_rlimit(p, RLIMIT_NPROC)) { if (p->real_cred->user != INIT_USER && -@@ -1568,6 +1680,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1568,6 +1681,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, goto bad_fork_cancel_cgroup; } @@ -138771,7 +139146,7 @@ index 2e391c7..555531a 100644 if (likely(p->pid)) { ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); -@@ -1657,6 +1774,8 @@ bad_fork_cleanup_count: +@@ -1657,6 +1775,8 @@ bad_fork_cleanup_count: bad_fork_free: free_task(p); fork_out: @@ -138780,7 +139155,7 @@ index 2e391c7..555531a 100644 return ERR_PTR(retval); } -@@ -1719,6 +1838,7 @@ long _do_fork(unsigned long clone_flags, +@@ -1719,6 +1839,7 @@ long _do_fork(unsigned long clone_flags, p = copy_process(clone_flags, stack_start, stack_size, child_tidptr, NULL, trace, tls); @@ -138788,7 +139163,7 @@ index 2e391c7..555531a 100644 /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. -@@ -1735,6 +1855,8 @@ long _do_fork(unsigned long clone_flags, +@@ -1735,6 +1856,8 @@ long _do_fork(unsigned long clone_flags, if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); @@ -138797,7 +139172,7 @@ index 2e391c7..555531a 100644 if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); -@@ -1871,7 +1993,7 @@ void __init proc_caches_init(void) +@@ -1871,7 +1994,7 @@ void __init proc_caches_init(void) sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK|SLAB_ACCOUNT, NULL); @@ -138806,7 +139181,7 @@ index 2e391c7..555531a 100644 mmap_init(); nsproxy_cache_init(); } -@@ -1919,7 +2041,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) +@@ -1919,7 +2042,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) return 0; /* don't need lock here; in the worst case we'll do useless copy */ @@ -138815,7 +139190,7 @@ index 2e391c7..555531a 100644 return 0; *new_fsp = copy_fs_struct(fs); -@@ -2032,7 +2154,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) +@@ -2032,7 +2155,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) fs = current->fs; spin_lock(&fs->lock); current->fs = new_fs; @@ -138825,7 +139200,7 @@ index 2e391c7..555531a 100644 new_fs = NULL; else new_fs = fs; -@@ -2096,7 +2219,7 @@ int unshare_files(struct files_struct **displaced) +@@ -2096,7 +2220,7 @@ int unshare_files(struct files_struct **displaced) int sysctl_max_threads(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -141676,7 +142051,7 @@ index a5d966c..9c2d28b 100644 #ifdef CONFIG_RT_GROUP_SCHED /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index 1c1d2a0..a8b297a 100644 +index 1c1d2a0..1b7307c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2263,7 +2263,7 @@ void set_numabalancing_state(bool enabled) @@ -141706,18 +142081,27 @@ index 1c1d2a0..a8b297a 100644 next = head->next; head->next = NULL; head = next; -@@ -2784,8 +2784,10 @@ context_switch(struct rq *rq, struct task_struct *prev, +@@ -2784,8 +2784,9 @@ context_switch(struct rq *rq, struct task_struct *prev, next->active_mm = oldmm; atomic_inc(&oldmm->mm_count); enter_lazy_tlb(oldmm, next); - } else + } else { switch_mm(oldmm, mm, next); -+ populate_stack(); + } if (!prev->mm) { prev->active_mm = NULL; +@@ -3109,7 +3110,8 @@ static noinline void __schedule_bug(struct task_struct *prev) + static inline void schedule_debug(struct task_struct *prev) + { + #ifdef CONFIG_SCHED_STACK_END_CHECK +- BUG_ON(task_stack_end_corrupted(prev)); ++ if (task_stack_end_corrupted(prev)) ++ panic("corrupted stack end detected inside scheduler\n"); + #endif + + if (unlikely(in_atomic_preempt_off())) { @@ -3609,6 +3611,8 @@ int can_nice(const struct task_struct *p, const int nice) /* convert nice value [19,-20] to rlimit style value [1,40] */ int nice_rlim = nice_to_rlimit(nice); @@ -141745,15 +142129,7 @@ index 1c1d2a0..a8b297a 100644 /* can't increase priority */ if (attr->sched_priority > p->rt_priority && attr->sched_priority > rlim_rtprio) -@@ -5285,6 +5291,7 @@ void idle_task_exit(void) - - if (mm != &init_mm) { - switch_mm(mm, &init_mm, current); -+ populate_stack(); - finish_arch_post_lock_switch(); - } - mmdrop(mm); -@@ -5410,7 +5417,7 @@ static void migrate_tasks(struct rq *dead_rq) +@@ -5410,7 +5416,7 @@ static void migrate_tasks(struct rq *dead_rq) #if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) @@ -141762,7 +142138,7 @@ index 1c1d2a0..a8b297a 100644 { .procname = "sched_domain", .mode = 0555, -@@ -5427,17 +5434,17 @@ static struct ctl_table sd_ctl_root[] = { +@@ -5427,17 +5433,17 @@ static struct ctl_table sd_ctl_root[] = { {} }; @@ -141784,7 +142160,7 @@ index 1c1d2a0..a8b297a 100644 /* * In the intermediate directories, both the child directory and -@@ -5445,22 +5452,25 @@ static void sd_free_ctl_entry(struct ctl_table **tablep) +@@ -5445,22 +5451,25 @@ static void sd_free_ctl_entry(struct ctl_table **tablep) * will always be set. In the lowest directory the names are * static strings and all have proc handlers. */ @@ -141816,7 +142192,7 @@ index 1c1d2a0..a8b297a 100644 const char *procname, void *data, int maxlen, umode_t mode, proc_handler *proc_handler, bool load_idx) -@@ -5480,7 +5490,7 @@ set_table_entry(struct ctl_table *entry, +@@ -5480,7 +5489,7 @@ set_table_entry(struct ctl_table *entry, static struct ctl_table * sd_alloc_ctl_domain_table(struct sched_domain *sd) { @@ -141825,7 +142201,7 @@ index 1c1d2a0..a8b297a 100644 if (table == NULL) return NULL; -@@ -5518,9 +5528,9 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) +@@ -5518,9 +5527,9 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) return table; } @@ -141837,7 +142213,7 @@ index 1c1d2a0..a8b297a 100644 struct sched_domain *sd; int domain_num = 0, i; char buf[32]; -@@ -5547,11 +5557,13 @@ static struct ctl_table_header *sd_sysctl_header; +@@ -5547,11 +5556,13 @@ static struct ctl_table_header *sd_sysctl_header; static void register_sched_domain_sysctl(void) { int i, cpu_num = num_possible_cpus(); @@ -141852,7 +142228,7 @@ index 1c1d2a0..a8b297a 100644 if (entry == NULL) return; -@@ -5573,8 +5585,12 @@ static void unregister_sched_domain_sysctl(void) +@@ -5573,8 +5584,12 @@ static void unregister_sched_domain_sysctl(void) { unregister_sysctl_table(sd_sysctl_header); sd_sysctl_header = NULL; @@ -142205,10 +142581,18 @@ index d903c02..c3efd35 100644 unsigned long flags; int ret = 0; diff --git a/kernel/smpboot.c b/kernel/smpboot.c -index d264f59..48b8da3 100644 +index d264f59..fd4da04 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c -@@ -301,7 +301,7 @@ int smpboot_register_percpu_thread_cpumask(struct smp_hotplug_thread *plug_threa +@@ -13,6 +13,7 @@ + #include <linux/percpu.h> + #include <linux/kthread.h> + #include <linux/smpboot.h> ++#include <asm/pgtable.h> + + #include "smpboot.h" + +@@ -301,7 +302,7 @@ int smpboot_register_percpu_thread_cpumask(struct smp_hotplug_thread *plug_threa if (cpumask_test_cpu(cpu, cpumask)) smpboot_unpark_thread(plug_thread, cpu); } @@ -142217,7 +142601,7 @@ index d264f59..48b8da3 100644 out: mutex_unlock(&smpboot_threads_lock); put_online_cpus(); -@@ -319,7 +319,7 @@ void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread) +@@ -319,7 +320,7 @@ void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread) { get_online_cpus(); mutex_lock(&smpboot_threads_lock); @@ -142226,6 +142610,16 @@ index d264f59..48b8da3 100644 smpboot_destroy_threads(plug_thread); mutex_unlock(&smpboot_threads_lock); put_online_cpus(); +@@ -359,7 +360,9 @@ int smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread, + for_each_cpu_and(cpu, tmp, cpu_online_mask) + smpboot_unpark_thread(plug_thread, cpu); + ++ pax_open_kernel(); + cpumask_copy(old, new); ++ pax_close_kernel(); + + mutex_unlock(&smpboot_threads_lock); + put_online_cpus(); diff --git a/kernel/softirq.c b/kernel/softirq.c index 479e443..4072c49 100644 --- a/kernel/softirq.c @@ -148702,9 +149096,18 @@ index 1d11790..1cc6074 100644 spin_unlock_irqrestore(&zone->lock, flags); } diff --git a/mm/percpu.c b/mm/percpu.c -index 998607a..4854f93 100644 +index 998607a..389e6ba 100644 --- a/mm/percpu.c +++ b/mm/percpu.c +@@ -110,7 +110,7 @@ struct pcpu_chunk { + int map_used; /* # of map entries used before the sentry */ + int map_alloc; /* # of map entries allocated */ + int *map; /* allocation map */ +- struct work_struct map_extend_work;/* async ->map[] extension */ ++ struct list_head map_extend_list;/* on pcpu_map_extend_chunks */ + + void *data; /* chunk data */ + int first_free; /* no free below this */ @@ -131,7 +131,7 @@ static unsigned int pcpu_low_unit_cpu __read_mostly; static unsigned int pcpu_high_unit_cpu __read_mostly; @@ -148714,6 +149117,192 @@ index 998607a..4854f93 100644 EXPORT_SYMBOL_GPL(pcpu_base_addr); static const int *pcpu_unit_map __read_mostly; /* cpu -> unit */ +@@ -160,10 +160,13 @@ static struct pcpu_chunk *pcpu_reserved_chunk; + static int pcpu_reserved_chunk_limit; + + static DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */ +-static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */ ++static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */ + + static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ + ++/* chunks which need their map areas extended, protected by pcpu_lock */ ++static LIST_HEAD(pcpu_map_extend_chunks); ++ + /* + * The number of empty populated pages, protected by pcpu_lock. The + * reserved chunk doesn't contribute to the count. +@@ -393,13 +396,19 @@ static int pcpu_need_to_extend(struct pcpu_chunk *chunk, bool is_atomic) + { + int margin, new_alloc; + ++ lockdep_assert_held(&pcpu_lock); ++ + if (is_atomic) { + margin = 3; + + if (chunk->map_alloc < +- chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW && +- pcpu_async_enabled) +- schedule_work(&chunk->map_extend_work); ++ chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW) { ++ if (list_empty(&chunk->map_extend_list)) { ++ list_add_tail(&chunk->map_extend_list, ++ &pcpu_map_extend_chunks); ++ pcpu_schedule_balance_work(); ++ } ++ } + } else { + margin = PCPU_ATOMIC_MAP_MARGIN_HIGH; + } +@@ -433,6 +442,8 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc) + size_t old_size = 0, new_size = new_alloc * sizeof(new[0]); + unsigned long flags; + ++ lockdep_assert_held(&pcpu_alloc_mutex); ++ + new = pcpu_mem_zalloc(new_size); + if (!new) + return -ENOMEM; +@@ -465,20 +476,6 @@ out_unlock: + return 0; + } + +-static void pcpu_map_extend_workfn(struct work_struct *work) +-{ +- struct pcpu_chunk *chunk = container_of(work, struct pcpu_chunk, +- map_extend_work); +- int new_alloc; +- +- spin_lock_irq(&pcpu_lock); +- new_alloc = pcpu_need_to_extend(chunk, false); +- spin_unlock_irq(&pcpu_lock); +- +- if (new_alloc) +- pcpu_extend_area_map(chunk, new_alloc); +-} +- + /** + * pcpu_fit_in_area - try to fit the requested allocation in a candidate area + * @chunk: chunk the candidate area belongs to +@@ -738,7 +735,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void) + chunk->map_used = 1; + + INIT_LIST_HEAD(&chunk->list); +- INIT_WORK(&chunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&chunk->map_extend_list); + chunk->free_size = pcpu_unit_size; + chunk->contig_hint = pcpu_unit_size; + +@@ -893,6 +890,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved, + return NULL; + } + ++ if (!is_atomic) ++ mutex_lock(&pcpu_alloc_mutex); ++ + spin_lock_irqsave(&pcpu_lock, flags); + + /* serve reserved allocations from the reserved chunk if available */ +@@ -965,12 +965,9 @@ restart: + if (is_atomic) + goto fail; + +- mutex_lock(&pcpu_alloc_mutex); +- + if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) { + chunk = pcpu_create_chunk(); + if (!chunk) { +- mutex_unlock(&pcpu_alloc_mutex); + err = "failed to allocate new chunk"; + goto fail; + } +@@ -981,7 +978,6 @@ restart: + spin_lock_irqsave(&pcpu_lock, flags); + } + +- mutex_unlock(&pcpu_alloc_mutex); + goto restart; + + area_found: +@@ -991,8 +987,6 @@ area_found: + if (!is_atomic) { + int page_start, page_end, rs, re; + +- mutex_lock(&pcpu_alloc_mutex); +- + page_start = PFN_DOWN(off); + page_end = PFN_UP(off + size); + +@@ -1003,7 +997,6 @@ area_found: + + spin_lock_irqsave(&pcpu_lock, flags); + if (ret) { +- mutex_unlock(&pcpu_alloc_mutex); + pcpu_free_area(chunk, off, &occ_pages); + err = "failed to populate"; + goto fail_unlock; +@@ -1043,6 +1036,8 @@ fail: + /* see the flag handling in pcpu_blance_workfn() */ + pcpu_atomic_alloc_failed = true; + pcpu_schedule_balance_work(); ++ } else { ++ mutex_unlock(&pcpu_alloc_mutex); + } + return NULL; + } +@@ -1127,6 +1122,7 @@ static void pcpu_balance_workfn(struct work_struct *work) + if (chunk == list_first_entry(free_head, struct pcpu_chunk, list)) + continue; + ++ list_del_init(&chunk->map_extend_list); + list_move(&chunk->list, &to_free); + } + +@@ -1144,6 +1140,25 @@ static void pcpu_balance_workfn(struct work_struct *work) + pcpu_destroy_chunk(chunk); + } + ++ /* service chunks which requested async area map extension */ ++ do { ++ int new_alloc = 0; ++ ++ spin_lock_irq(&pcpu_lock); ++ ++ chunk = list_first_entry_or_null(&pcpu_map_extend_chunks, ++ struct pcpu_chunk, map_extend_list); ++ if (chunk) { ++ list_del_init(&chunk->map_extend_list); ++ new_alloc = pcpu_need_to_extend(chunk, false); ++ } ++ ++ spin_unlock_irq(&pcpu_lock); ++ ++ if (new_alloc) ++ pcpu_extend_area_map(chunk, new_alloc); ++ } while (chunk); ++ + /* + * Ensure there are certain number of free populated pages for + * atomic allocs. Fill up from the most packed so that atomic +@@ -1642,7 +1657,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + */ + schunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0); + INIT_LIST_HEAD(&schunk->list); +- INIT_WORK(&schunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&schunk->map_extend_list); + schunk->base_addr = base_addr; + schunk->map = smap; + schunk->map_alloc = ARRAY_SIZE(smap); +@@ -1671,7 +1686,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + if (dyn_size) { + dchunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0); + INIT_LIST_HEAD(&dchunk->list); +- INIT_WORK(&dchunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&dchunk->map_extend_list); + dchunk->base_addr = base_addr; + dchunk->map = dmap; + dchunk->map_alloc = ARRAY_SIZE(dmap); diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 5d453e5..4043093 100644 --- a/mm/process_vm_access.c @@ -148966,7 +149555,7 @@ index 440e2a7..9091191 100644 return -ENOMEM; diff --git a/mm/slab.c b/mm/slab.c -index 621fbcb..272a1f3 100644 +index 621fbcb..9bf872e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -116,6 +116,7 @@ @@ -149039,7 +149628,16 @@ index 621fbcb..272a1f3 100644 /* * Adjust the object sizes so that we clear -@@ -3367,6 +3372,20 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, +@@ -2123,6 +2128,8 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + BUG_ON(flags & SLAB_POISON); + #endif + ++ flags = pax_sanitize_slab_flags(flags); ++ + /* + * Check that size is in terms of words. This is needed to avoid + * unaligned accesses for some archs when redzoning is used, and makes +@@ -3367,6 +3374,20 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, struct array_cache *ac = cpu_cache_get(cachep); check_irq_off(); @@ -149060,7 +149658,7 @@ index 621fbcb..272a1f3 100644 kmemleak_free_recursive(objp, cachep->flags); objp = cache_free_debugcheck(cachep, objp, caller); -@@ -3492,7 +3511,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller) +@@ -3492,7 +3513,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller) return kmem_cache_alloc_node_trace(cachep, flags, node, size); } @@ -149069,7 +149667,7 @@ index 621fbcb..272a1f3 100644 { return __do_kmalloc_node(size, flags, node, _RET_IP_); } -@@ -3512,7 +3531,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller); +@@ -3512,7 +3533,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller); * @flags: the type of memory to allocate (see kmalloc). * @caller: function caller for debug tracking of the caller */ @@ -149078,7 +149676,7 @@ index 621fbcb..272a1f3 100644 unsigned long caller) { struct kmem_cache *cachep; -@@ -3585,6 +3604,7 @@ void kfree(const void *objp) +@@ -3585,6 +3606,7 @@ void kfree(const void *objp) if (unlikely(ZERO_OR_NULL_PTR(objp))) return; @@ -149086,7 +149684,7 @@ index 621fbcb..272a1f3 100644 local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); -@@ -4004,14 +4024,22 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) +@@ -4004,14 +4026,22 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) } /* cpu stats */ { @@ -149113,7 +149711,7 @@ index 621fbcb..272a1f3 100644 #endif } -@@ -4219,13 +4247,80 @@ static const struct file_operations proc_slabstats_operations = { +@@ -4219,13 +4249,80 @@ static const struct file_operations proc_slabstats_operations = { static int __init slab_proc_init(void) { #ifdef CONFIG_DEBUG_SLAB_LEAK @@ -149196,7 +149794,7 @@ index 621fbcb..272a1f3 100644 * ksize - get the actual amount of memory allocated for a given object * @objp: Pointer to the object diff --git a/mm/slab.h b/mm/slab.h -index 2eedace..cd94091 100644 +index 2eedace..7de6f9b 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -22,7 +22,7 @@ struct kmem_cache { @@ -149208,7 +149806,7 @@ index 2eedace..cd94091 100644 void (*ctor)(void *); /* Called on object slot creation */ struct list_head list; /* List of all slab caches on the system */ }; -@@ -66,6 +66,20 @@ extern struct list_head slab_caches; +@@ -66,6 +66,35 @@ extern struct list_head slab_caches; /* The slab cache that manages slab cache information */ extern struct kmem_cache *kmem_cache; @@ -149223,13 +149821,28 @@ index 2eedace..cd94091 100644 + PAX_SANITIZE_SLAB_FAST, + PAX_SANITIZE_SLAB_FULL, +}; ++ +extern enum pax_sanitize_mode pax_sanitize_slab; ++ ++static inline unsigned long pax_sanitize_slab_flags(unsigned long flags) ++{ ++ if (pax_sanitize_slab == PAX_SANITIZE_SLAB_OFF || (flags & SLAB_DESTROY_BY_RCU)) ++ flags |= SLAB_NO_SANITIZE; ++ else if (pax_sanitize_slab == PAX_SANITIZE_SLAB_FULL) ++ flags &= ~SLAB_NO_SANITIZE; ++ return flags; ++} ++#else ++static inline unsigned long pax_sanitize_slab_flags(unsigned long flags) ++{ ++ return flags; ++} +#endif + unsigned long calculate_alignment(unsigned long flags, unsigned long align, unsigned long size); -@@ -115,7 +129,8 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size, +@@ -115,7 +144,8 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size, /* Legal flag mask for kmem_cache_create(), for various configurations */ #define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | SLAB_PANIC | \ @@ -149239,7 +149852,7 @@ index 2eedace..cd94091 100644 #if defined(CONFIG_DEBUG_SLAB) #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER) -@@ -311,6 +326,9 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) +@@ -311,6 +341,9 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) return s; page = virt_to_head_page(x); @@ -149250,7 +149863,7 @@ index 2eedace..cd94091 100644 if (slab_equal_or_root(cachep, s)) return cachep; diff --git a/mm/slab_common.c b/mm/slab_common.c -index 065b7bd..3c2c410 100644 +index 065b7bd..185af36 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -25,11 +25,35 @@ @@ -149317,21 +149930,7 @@ index 065b7bd..3c2c410 100644 list_add(&s->list, &slab_caches); out: if (err) -@@ -408,6 +432,13 @@ kmem_cache_create(const char *name, size_t size, size_t align, - */ - flags &= CACHE_CREATE_MASK; - -+#ifdef CONFIG_PAX_MEMORY_SANITIZE -+ if (pax_sanitize_slab == PAX_SANITIZE_SLAB_OFF || (flags & SLAB_DESTROY_BY_RCU)) -+ flags |= SLAB_NO_SANITIZE; -+ else if (pax_sanitize_slab == PAX_SANITIZE_SLAB_FULL) -+ flags &= ~SLAB_NO_SANITIZE; -+#endif -+ - s = __kmem_cache_alias(name, size, align, flags, ctor); - if (s) - goto out_unlock; -@@ -469,7 +500,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier) +@@ -469,7 +493,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier) rcu_barrier(); list_for_each_entry_safe(s, s2, release, list) { @@ -149340,7 +149939,7 @@ index 065b7bd..3c2c410 100644 sysfs_slab_remove(s); #else slab_kmem_cache_release(s); -@@ -713,8 +744,7 @@ void kmem_cache_destroy(struct kmem_cache *s) +@@ -713,8 +737,7 @@ void kmem_cache_destroy(struct kmem_cache *s) mutex_lock(&slab_mutex); @@ -149350,7 +149949,7 @@ index 065b7bd..3c2c410 100644 goto out_unlock; err = shutdown_memcg_caches(s, &release, &need_rcu_barrier); -@@ -780,7 +810,7 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz +@@ -780,7 +803,7 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz panic("Creation of kmalloc slab %s size=%zu failed. Reason %d\n", name, size, err); @@ -149359,7 +149958,7 @@ index 065b7bd..3c2c410 100644 } struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, -@@ -793,7 +823,7 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, +@@ -793,7 +816,7 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, create_boot_cache(s, name, size, flags); list_add(&s->list, &slab_caches); @@ -149368,7 +149967,7 @@ index 065b7bd..3c2c410 100644 return s; } -@@ -805,6 +835,11 @@ struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1]; +@@ -805,6 +828,11 @@ struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1]; EXPORT_SYMBOL(kmalloc_dma_caches); #endif @@ -149380,7 +149979,7 @@ index 065b7bd..3c2c410 100644 /* * Conversion table for small slabs sizes / 8 to the index in the * kmalloc array. This is necessary for slabs < 192 since we have non power -@@ -869,6 +904,13 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags) +@@ -869,6 +897,13 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags) return kmalloc_dma_caches[index]; #endif @@ -149394,7 +149993,7 @@ index 065b7bd..3c2c410 100644 return kmalloc_caches[index]; } -@@ -961,7 +1003,7 @@ void __init create_kmalloc_caches(unsigned long flags) +@@ -961,7 +996,7 @@ void __init create_kmalloc_caches(unsigned long flags) for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) { if (!kmalloc_caches[i]) @@ -149403,7 +150002,7 @@ index 065b7bd..3c2c410 100644 /* * Caches that are not of the two-to-the-power-of size. -@@ -969,9 +1011,9 @@ void __init create_kmalloc_caches(unsigned long flags) +@@ -969,9 +1004,9 @@ void __init create_kmalloc_caches(unsigned long flags) * earlier power of two caches */ if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[1] && i == 6) @@ -149415,7 +150014,7 @@ index 065b7bd..3c2c410 100644 } /* Kmalloc array is now usable */ -@@ -992,6 +1034,23 @@ void __init create_kmalloc_caches(unsigned long flags) +@@ -992,6 +1027,23 @@ void __init create_kmalloc_caches(unsigned long flags) } } #endif @@ -149439,7 +150038,7 @@ index 065b7bd..3c2c410 100644 } #endif /* !CONFIG_SLOB */ -@@ -1051,6 +1110,9 @@ static void print_slabinfo_header(struct seq_file *m) +@@ -1051,6 +1103,9 @@ static void print_slabinfo_header(struct seq_file *m) seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); @@ -149449,7 +150048,7 @@ index 065b7bd..3c2c410 100644 #endif seq_putc(m, '\n'); } -@@ -1180,7 +1242,7 @@ static int __init slab_proc_init(void) +@@ -1180,7 +1235,7 @@ static int __init slab_proc_init(void) module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */ @@ -149459,7 +150058,7 @@ index 065b7bd..3c2c410 100644 { void *ret; diff --git a/mm/slob.c b/mm/slob.c -index 5ec1580..017a002 100644 +index 5ec1580..93f3beb 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -67,6 +67,7 @@ @@ -149641,7 +150240,7 @@ index 5ec1580..017a002 100644 { return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, _RET_IP_); } -@@ -491,34 +516,123 @@ void kfree(const void *block) +@@ -491,39 +516,130 @@ void kfree(const void *block) return; kmemleak_free(block); @@ -149774,7 +150373,14 @@ index 5ec1580..017a002 100644 } EXPORT_SYMBOL(ksize); -@@ -534,23 +648,33 @@ int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) + int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) + { ++ flags = pax_sanitize_slab_flags(flags); ++ + if (flags & SLAB_DESTROY_BY_RCU) { + /* leave room for rcu footer at the end of object */ + c->size += sizeof(struct slob_rcu); +@@ -534,23 +650,33 @@ int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) static void *slob_alloc_node(struct kmem_cache *c, gfp_t flags, int node) { @@ -149810,7 +150416,7 @@ index 5ec1580..017a002 100644 if (b && c->ctor) c->ctor(b); -@@ -566,7 +690,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) +@@ -566,7 +692,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_NUMA @@ -149819,7 +150425,7 @@ index 5ec1580..017a002 100644 { return __do_kmalloc_node(size, gfp, node, _RET_IP_); } -@@ -579,12 +703,16 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t gfp, int node) +@@ -579,12 +705,16 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t gfp, int node) EXPORT_SYMBOL(kmem_cache_alloc_node); #endif @@ -149840,7 +150446,7 @@ index 5ec1580..017a002 100644 } static void kmem_rcu_free(struct rcu_head *head) -@@ -592,22 +720,36 @@ static void kmem_rcu_free(struct rcu_head *head) +@@ -592,22 +722,36 @@ static void kmem_rcu_free(struct rcu_head *head) struct slob_rcu *slob_rcu = (struct slob_rcu *)head; void *b = (void *)slob_rcu - (slob_rcu->size - sizeof(struct slob_rcu)); @@ -149882,7 +150488,7 @@ index 5ec1580..017a002 100644 EXPORT_SYMBOL(kmem_cache_free); diff --git a/mm/slub.c b/mm/slub.c -index 2a722e1..1e5e2f8 100644 +index 2a722e1..af44068 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -34,6 +34,7 @@ @@ -149911,16 +150517,17 @@ index 2a722e1..1e5e2f8 100644 s, (void *)t->addr, jiffies - t->when, t->cpu, t->pid); #ifdef CONFIG_STACKTRACE { -@@ -2767,6 +2768,21 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page, +@@ -2767,6 +2768,22 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page, slab_free_freelist_hook(s, head, tail); +#ifdef CONFIG_PAX_MEMORY_SANITIZE + if (!(s->flags & SLAB_NO_SANITIZE)) { ++ int offset = s->offset ? 0 : sizeof(void *); + void *x = head; + + while (1) { -+ memset(x, PAX_MEMORY_SANITIZE_VALUE, s->object_size); ++ memset(x + offset, PAX_MEMORY_SANITIZE_VALUE, s->object_size - offset); + if (s->ctor) + s->ctor(x); + if (x == tail_obj) @@ -149933,17 +150540,7 @@ index 2a722e1..1e5e2f8 100644 redo: /* * Determine the currently cpus per cpu slab. -@@ -3264,6 +3280,9 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) - s->inuse = size; - - if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) || -+#ifdef CONFIG_PAX_MEMORY_SANITIZE -+ (!(flags & SLAB_NO_SANITIZE)) || -+#endif - s->ctor)) { - /* - * Relocate free pointer after the object if it is not -@@ -3514,7 +3533,7 @@ static int __init setup_slub_min_objects(char *str) +@@ -3514,7 +3531,7 @@ static int __init setup_slub_min_objects(char *str) __setup("slub_min_objects=", setup_slub_min_objects); @@ -149952,7 +150549,7 @@ index 2a722e1..1e5e2f8 100644 { struct kmem_cache *s; void *ret; -@@ -3552,7 +3571,7 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node) +@@ -3552,7 +3569,7 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node) return ptr; } @@ -149961,7 +150558,7 @@ index 2a722e1..1e5e2f8 100644 { struct kmem_cache *s; void *ret; -@@ -3600,6 +3619,70 @@ static size_t __ksize(const void *object) +@@ -3600,6 +3617,70 @@ static size_t __ksize(const void *object) return slab_ksize(page->slab_cache); } @@ -150032,7 +150629,7 @@ index 2a722e1..1e5e2f8 100644 size_t ksize(const void *object) { size_t size = __ksize(object); -@@ -3620,6 +3703,7 @@ void kfree(const void *x) +@@ -3620,6 +3701,7 @@ void kfree(const void *x) if (unlikely(ZERO_OR_NULL_PTR(x))) return; @@ -150040,7 +150637,7 @@ index 2a722e1..1e5e2f8 100644 page = virt_to_head_page(x); if (unlikely(!PageSlab(page))) { BUG_ON(!PageCompound(page)); -@@ -3937,7 +4021,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, +@@ -3937,7 +4019,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, s = find_mergeable(size, align, flags, name, ctor); if (s) { @@ -150049,7 +150646,7 @@ index 2a722e1..1e5e2f8 100644 /* * Adjust the object sizes so that we clear -@@ -3953,7 +4037,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, +@@ -3953,7 +4035,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, } if (sysfs_slab_alias(s, name)) { @@ -150058,6 +150655,15 @@ index 2a722e1..1e5e2f8 100644 s = NULL; } } +@@ -3965,6 +4047,8 @@ int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) + { + int err; + ++ flags = pax_sanitize_slab_flags(flags); ++ + err = kmem_cache_open(s, flags); + if (err) + return err; @@ -4070,7 +4154,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, } #endif @@ -165468,12 +166074,13 @@ index 0000000..e31e92f +} diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c new file mode 100644 -index 0000000..f08a221 +index 0000000..be3978c --- /dev/null +++ b/scripts/gcc-plugins/latent_entropy_plugin.c -@@ -0,0 +1,438 @@ +@@ -0,0 +1,613 @@ +/* + * Copyright 2012-2016 by the PaX Team <pageexec@freemail.hu> ++ * Copyright 2016 by Emese Revfy <re.emese@gmail.com> + * Licensed under the GPL v2 + * + * Note: the choice of the license means that the compilation process is @@ -165481,32 +166088,89 @@ index 0000000..f08a221 + * but for the kernel it doesn't matter since it doesn't link against + * any of the gcc libraries + * -+ * gcc plugin to help generate a little bit of entropy from program state, -+ * used throughout the uptime of the kernel ++ * This gcc plugin helps generate a little bit of entropy from program state, ++ * used throughout the uptime of the kernel. Here is an instrumentation example: ++ * ++ * before: ++ * void __latent_entropy test(int argc, char *argv[]) ++ * { ++ * printf("%u %s\n", argc, *argv); ++ * } ++ * ++ * after: ++ * void __latent_entropy test(int argc, char *argv[]) ++ * { ++ * // latent_entropy_execute() 1. ++ * unsigned long local_entropy; ++ * // init_local_entropy() 1. ++ * void *local_entropy_frame_addr; ++ * // init_local_entropy() 3. ++ * unsigned long temp_latent_entropy; ++ * ++ * // init_local_entropy() 2. ++ * local_entropy_frame_addr = __builtin_frame_address(0); ++ * local_entropy = (unsigned long) local_entropy_frame_addr; ++ * ++ * // init_local_entropy() 4. ++ * temp_latent_entropy = latent_entropy; ++ * // init_local_entropy() 5. ++ * local_entropy ^= temp_latent_entropy; ++ * ++ * // latent_entropy_execute() 3. ++ * local_entropy += 4623067384293424948; ++ * ++ * printf("%u %s\n", argc, *argv); ++ * ++ * // latent_entropy_execute() 4. ++ * temp_latent_entropy = rol(temp_latent_entropy, local_entropy); ++ * latent_entropy = temp_latent_entropy; ++ * } ++ * ++ * It would look like this in C: ++ * ++ * unsigned long local_entropy = latent_entropy; ++ * local_entropy ^= 1234567890; ++ * local_entropy ^= (unsigned long)__builtin_frame_address(0); ++ * local_entropy += 9876543210; ++ * latent_entropy = rol(local_entropy, 6); + * + * TODO: + * - add ipa pass to identify not explicitly marked candidate functions -+ * - mix in more program state (function arguments/return values, loop variables, etc) ++ * - mix in more program state (function arguments/return values, ++ * loop variables, etc) + * - more instrumentation control via attribute parameters + * + * BUGS: + * - none known ++ * ++ * Options: ++ * -fplugin-arg-latent_entropy_plugin-disable ++ * ++ * Attribute: __attribute__((latent_entropy)) ++ * The latent_entropy gcc attribute can be only on functions and variables. ++ * If it is on a function then the plugin will instrument it. If the attribute ++ * is on a variable then the plugin will initialize it with a random value. ++ * The variable must be an integer, an integer array type or a structure ++ * with integer fields. + */ + +#include "gcc-common.h" + +int plugin_is_GPL_compatible; + -+static bool enabled = true; -+ +static GTY(()) tree latent_entropy_decl; + +static struct plugin_info latent_entropy_plugin_info = { -+ .version = "201605212030", ++ .version = "201606141920", + .help = "disable\tturn off latent entropy instrumentation\n", +}; + +static unsigned HOST_WIDE_INT seed; ++/* ++ * get_random_seed() (this is a GCC function) generates the seed. ++ * This is a simple random generator without any cryptographic security because ++ * the entropy doesn't come from here. ++ */ +static unsigned HOST_WIDE_INT get_random_const(void) +{ + unsigned int i; @@ -165522,10 +166186,21 @@ index 0000000..f08a221 + return ret; +} + -+static tree handle_latent_entropy_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs) ++static tree tree_get_random_const(tree type) +{ -+ tree type; + unsigned long long mask; ++ ++ mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); ++ mask = 2 * (mask - 1) + 1; ++ ++ if (TYPE_UNSIGNED(type)) ++ return build_int_cstu(type, mask & get_random_const()); ++ return build_int_cst(type, mask & get_random_const()); ++} ++ ++static tree handle_latent_entropy_attribute(tree *node, tree name, tree args __unused, int flags __unused, bool *no_add_attrs) ++{ ++ tree type; +#if BUILDING_GCC_VERSION <= 4007 + VEC(constructor_elt, gc) *vals; +#else @@ -165555,8 +166230,9 @@ index 0000000..f08a221 + switch (TREE_CODE(type)) { + default: + *no_add_attrs = true; -+ error("variable %qD with %qE attribute must be an integer or a fixed length integer array type" -+ "or a fixed sized structure with integer fields", *node, name); ++ error("variable %qD with %qE attribute must be an integer" ++ " or a fixed length integer array type" ++ " or a fixed sized structure with integer fields", *node, name); + break; + + case RECORD_TYPE: { @@ -165567,11 +166243,13 @@ index 0000000..f08a221 + tree fieldtype; + + fieldtype = TREE_TYPE(field); -+ if (TREE_CODE(fieldtype) != INTEGER_TYPE) { -+ *no_add_attrs = true; -+ error("structure variable %qD with %qE attribute has a non-integer field %qE", *node, name, field); -+ break; -+ } ++ if (TREE_CODE(fieldtype) == INTEGER_TYPE) ++ continue; ++ ++ *no_add_attrs = true; ++ error("structure variable %qD with %qE attribute has" ++ " a non-integer field %qE", *node, name, field); ++ break; + } + + if (field) @@ -165584,31 +166262,21 @@ index 0000000..f08a221 +#endif + + for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) { -+ tree fieldtype; -+ -+ fieldtype = TREE_TYPE(field); -+ mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(fieldtype)) - 1); -+ mask = 2 * (mask - 1) + 1; ++ tree random_const; + -+ if (TYPE_UNSIGNED(fieldtype)) -+ CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cstu(fieldtype, mask & get_random_const())); -+ else -+ CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cst(fieldtype, mask & get_random_const())); ++ random_const = tree_get_random_const(TREE_TYPE(field)); ++ CONSTRUCTOR_APPEND_ELT(vals, field, random_const); + } + ++ /* Initialize the fields with random constants */ + DECL_INITIAL(*node) = build_constructor(type, vals); +//debug_tree(DECL_INITIAL(*node)); + break; + } + ++ /* Initialize the variable with a random constant */ + case INTEGER_TYPE: -+ mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); -+ mask = 2 * (mask - 1) + 1; -+ -+ if (TYPE_UNSIGNED(type)) -+ DECL_INITIAL(*node) = build_int_cstu(type, mask & get_random_const()); -+ else -+ DECL_INITIAL(*node) = build_int_cst(type, mask & get_random_const()); ++ DECL_INITIAL(*node) = tree_get_random_const(type); + break; + + case ARRAY_TYPE: { @@ -165621,7 +166289,8 @@ index 0000000..f08a221 + + if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size || TREE_CODE(array_size) != INTEGER_CST) { + *no_add_attrs = true; -+ error("array variable %qD with %qE attribute must be a fixed length integer array type", *node, name); ++ error("array variable %qD with %qE attribute must be" ++ " a fixed length integer array type", *node, name); + break; + } + @@ -165632,15 +166301,13 @@ index 0000000..f08a221 + vec_alloc(vals, nelt); +#endif + -+ mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(elt_type)) - 1); -+ mask = 2 * (mask - 1) + 1; ++ for (i = 0; i < nelt; i++) { ++ tree random_const = tree_get_random_const(elt_type); + -+ for (i = 0; i < nelt; i++) -+ if (TYPE_UNSIGNED(elt_type)) -+ CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cstu(elt_type, mask & get_random_const())); -+ else -+ CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cst(elt_type, mask & get_random_const())); ++ CONSTRUCTOR_APPEND_ELT(vals, size_int(i), random_const); ++ } + ++ /* Initialize the elements of the array with random constants */ + DECL_INITIAL(*node) = build_constructor(type, vals); +//debug_tree(DECL_INITIAL(*node)); + break; @@ -165668,7 +166335,7 @@ index 0000000..f08a221 +#endif +}; + -+static void register_attributes(void *event_data, void *data) ++static void register_attributes(void *event_data __unused, void *data __unused) +{ + register_attribute(&latent_entropy_attr); +} @@ -165686,6 +166353,28 @@ index 0000000..f08a221 + return lookup_attribute("latent_entropy", DECL_ATTRIBUTES(current_function_decl)) != NULL_TREE; +} + ++static tree create_a_tmp_var(tree type, const char *name) ++{ ++ tree var; ++ ++ var = create_tmp_var(type, name); ++ add_referenced_var(var); ++ mark_sym_for_renaming(var); ++ return var; ++} ++ ++/* ++ * Set up the next operation and its constant operand to use in the latent ++ * entropy PRNG. When RHS is specified, the request is for perturbing the ++ * local latent entropy variable, otherwise it is for perturbing the global ++ * latent entropy variable where the two operands are already given by the ++ * local and global latent entropy variables themselves. ++ * ++ * The operation is one of add/xor/rol when instrumenting the local entropy ++ * variable and one of add/xor when perturbing the global entropy variable. ++ * Rotation is not used for the latter case because it would transmit less ++ * entropy to the global variable than the other two operations. ++ */ +static enum tree_code get_op(tree *rhs) +{ + static enum tree_code op; @@ -165701,6 +166390,10 @@ index 0000000..f08a221 + case PLUS_EXPR: + if (rhs) { + op = LROTATE_EXPR; ++ /* ++ * This code limits the value of random_const to ++ * the size of a wide int for the rotation ++ */ + random_const &= HOST_BITS_PER_WIDE_INT - 1; + break; + } @@ -165719,85 +166412,174 @@ index 0000000..f08a221 +{ + gimple_stmt_iterator gsi; + gimple assign; -+ tree addxorrol, rhs; ++ tree rhs; + enum tree_code op; + + op = get_op(&rhs); -+ addxorrol = fold_build2_loc(UNKNOWN_LOCATION, op, unsigned_intDI_type_node, local_entropy, rhs); -+ assign = gimple_build_assign(local_entropy, addxorrol); ++ assign = gimple_build_assign_with_ops(op, local_entropy, local_entropy, rhs); + gsi = gsi_after_labels(bb); + gsi_insert_before(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); +//debug_bb(bb); +} + -+static void perturb_latent_entropy(basic_block bb, tree rhs) ++static void __perturb_latent_entropy(gimple_stmt_iterator *gsi, tree local_entropy) +{ -+ gimple_stmt_iterator gsi; + gimple assign; -+ tree addxorrol, temp; ++ tree temp; ++ enum tree_code op; + + /* 1. create temporary copy of latent_entropy */ -+ temp = create_tmp_var(unsigned_intDI_type_node, "temp_latent_entropy"); -+ add_referenced_var(temp); ++ temp = create_a_tmp_var(unsigned_intDI_type_node, "temp_latent_entropy"); + + /* 2. read... */ -+ temp = make_ssa_name(temp, NULL); -+ assign = gimple_build_assign(temp, latent_entropy_decl); -+ SSA_NAME_DEF_STMT(temp) = assign; + add_referenced_var(latent_entropy_decl); -+ gsi = gsi_after_labels(bb); -+ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ mark_sym_for_renaming(latent_entropy_decl); ++ assign = gimple_build_assign(temp, latent_entropy_decl); ++ gsi_insert_before(gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 3. ...modify... */ -+ addxorrol = fold_build2_loc(UNKNOWN_LOCATION, get_op(NULL), unsigned_intDI_type_node, temp, rhs); -+ temp = make_ssa_name(SSA_NAME_VAR(temp), NULL); -+ assign = gimple_build_assign(temp, addxorrol); -+ SSA_NAME_DEF_STMT(temp) = assign; -+ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ op = get_op(NULL); ++ assign = gimple_build_assign_with_ops(op, temp, temp, local_entropy); ++ gsi_insert_after(gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 4. ...write latent_entropy */ + assign = gimple_build_assign(latent_entropy_decl, temp); ++ gsi_insert_after(gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++} ++ ++static bool handle_tail_calls(basic_block bb, tree local_entropy) ++{ ++ gimple_stmt_iterator gsi; ++ ++ for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { ++ gcall *call; ++ gimple stmt = gsi_stmt(gsi); ++ ++ if (!is_gimple_call(stmt)) ++ continue; ++ ++ call = as_a_gcall(stmt); ++ if (!gimple_call_tail_p(call)) ++ continue; ++ ++ __perturb_latent_entropy(&gsi, local_entropy); ++ return true; ++ } ++ ++ return false; ++} ++ ++static void perturb_latent_entropy(tree local_entropy) ++{ ++ edge_iterator ei; ++ edge e, last_bb_e; ++ basic_block last_bb; ++ ++ gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun))); ++ last_bb_e = single_pred_edge(EXIT_BLOCK_PTR_FOR_FN(cfun)); ++ ++ FOR_EACH_EDGE(e, ei, last_bb_e->src->preds) { ++ if (ENTRY_BLOCK_PTR_FOR_FN(cfun) == e->src) ++ continue; ++ if (EXIT_BLOCK_PTR_FOR_FN(cfun) == e->src) ++ continue; ++ ++ handle_tail_calls(e->src, local_entropy); ++ } ++ ++ last_bb = single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)); ++ if (!handle_tail_calls(last_bb, local_entropy)) { ++ gimple_stmt_iterator gsi = gsi_last_bb(last_bb); ++ ++ __perturb_latent_entropy(&gsi, local_entropy); ++ } ++//debug_bb(single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun))); ++} ++ ++static void init_local_entropy(basic_block bb, tree local_entropy) ++{ ++ gimple assign, call; ++ tree frame_addr, rand_const, temp, fndecl, udi_frame_addr; ++ enum tree_code op; ++ gimple_stmt_iterator gsi = gsi_after_labels(bb); ++ ++ /* 1. create local_entropy_frame_addr */ ++ frame_addr = create_a_tmp_var(ptr_type_node, "local_entropy_frame_addr"); ++ ++ /* 2. local_entropy_frame_addr = __builtin_frame_address() */ ++ fndecl = builtin_decl_implicit(BUILT_IN_FRAME_ADDRESS); ++ call = gimple_build_call(fndecl, 1, integer_zero_node); ++ gimple_call_set_lhs(call, frame_addr); ++ gsi_insert_before(&gsi, call, GSI_NEW_STMT); ++ update_stmt(call); ++ ++ udi_frame_addr = fold_convert(unsigned_intDI_type_node, frame_addr); ++ assign = gimple_build_assign(local_entropy, udi_frame_addr); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ ++ /* 3. create temporary copy of latent_entropy */ ++ temp = create_a_tmp_var(unsigned_intDI_type_node, "temp_latent_entropy"); ++ ++ /* 4. read the global entropy variable into local entropy */ ++ add_referenced_var(latent_entropy_decl); ++ mark_sym_for_renaming(latent_entropy_decl); ++ assign = gimple_build_assign(temp, latent_entropy_decl); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ ++ /* 5. mix local_entropy_frame_addr into local entropy */ ++ assign = gimple_build_assign_with_ops(BIT_XOR_EXPR, local_entropy, local_entropy, temp); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ ++ rand_const = build_int_cstu(unsigned_intDI_type_node, get_random_const()); ++ op = get_op(NULL); ++ assign = gimple_build_assign_with_ops(op, local_entropy, local_entropy, rand_const); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); ++//debug_bb(bb); ++} ++ ++static bool create_latent_entropy_decl(void) ++{ ++ varpool_node_ptr node; ++ ++ if (latent_entropy_decl != NULL_TREE) ++ return true; ++ ++ FOR_EACH_VARIABLE(node) { ++ tree var = NODE_DECL(node); ++ ++ if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1) ++ continue; ++ if (strcmp(IDENTIFIER_POINTER(DECL_NAME(var)), "latent_entropy")) ++ continue; ++ ++ latent_entropy_decl = var; ++// debug_tree(var); ++ break; ++ } ++ ++ return latent_entropy_decl != NULL_TREE; +} + +static unsigned int latent_entropy_execute(void) +{ + basic_block bb; -+ gimple assign; -+ gimple_stmt_iterator gsi; + tree local_entropy; + -+ if (!latent_entropy_decl) { -+ varpool_node_ptr node; -+ -+ FOR_EACH_VARIABLE(node) { -+ tree var = NODE_DECL(node); -+ -+ if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1) -+ continue; -+ if (strcmp(IDENTIFIER_POINTER(DECL_NAME(var)), "latent_entropy")) -+ continue; -+ latent_entropy_decl = var; -+// debug_tree(var); -+ break; -+ } -+ if (!latent_entropy_decl) { -+// debug_tree(current_function_decl); -+ return 0; -+ } ++ if (!create_latent_entropy_decl()) { ++// debug_tree(current_function_decl); ++ return 0; + } + +//fprintf(stderr, "latent_entropy: %s\n", IDENTIFIER_POINTER(DECL_NAME(current_function_decl))); + -+ /* 1. create local entropy variable */ -+ local_entropy = create_tmp_var(unsigned_intDI_type_node, "local_entropy"); -+ add_referenced_var(local_entropy); -+ mark_sym_for_renaming(local_entropy); -+ + /* 2. initialize local entropy variable */ + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); @@ -165807,13 +166589,13 @@ index 0000000..f08a221 + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); + } -+ gsi = gsi_after_labels(bb); + -+ assign = gimple_build_assign(local_entropy, build_int_cstu(unsigned_intDI_type_node, get_random_const())); -+// gimple_set_location(assign, loc); -+ gsi_insert_before(&gsi, assign, GSI_NEW_STMT); -+ update_stmt(assign); -+//debug_bb(bb); ++ /* 1. create the local entropy variable */ ++ local_entropy = create_a_tmp_var(unsigned_intDI_type_node, "local_entropy"); ++ ++ /* 2. initialize the local entropy variable */ ++ init_local_entropy(bb, local_entropy); ++ + bb = bb->next_bb; + + /* 3. instrument each BB with an operation on the local entropy variable */ @@ -165824,13 +166606,11 @@ index 0000000..f08a221 + }; + + /* 4. mix local entropy into the global entropy variable */ -+ gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun))); -+ perturb_latent_entropy(single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)), local_entropy); -+//debug_bb(single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun))); ++ perturb_latent_entropy(local_entropy); + return 0; +} + -+static void latent_entropy_start_unit(void *gcc_data, void *user_data) ++static void latent_entropy_start_unit(void *gcc_data __unused, void *user_data __unused) +{ + tree latent_entropy_type; + @@ -165865,6 +166645,7 @@ index 0000000..f08a221 + +int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) +{ ++ bool enabled = true; + const char * const plugin_name = plugin_info->base_name; + const int argc = plugin_info->argc; + const struct plugin_argument * const argv = plugin_info->argv; @@ -168186,10 +168967,10 @@ index 0000000..f74d85a +targets += size_overflow_hash.h size_overflow_hash_aux.h disable_size_overflow_hash.h diff --git a/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data b/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data new file mode 100644 -index 0000000..2a420f3 +index 0000000..e0a04a1 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data -@@ -0,0 +1,12444 @@ +@@ -0,0 +1,12445 @@ +disable_so_interrupt_pnode_gru_message_queue_desc_4 interrupt_pnode gru_message_queue_desc 0 4 NULL +disable_so_bch_btree_insert_fndecl_12 bch_btree_insert fndecl 0 12 NULL +disable_so_macvlan_sync_address_fndecl_22 macvlan_sync_address fndecl 0 22 NULL nohasharray @@ -180634,6 +181415,7 @@ index 0000000..2a420f3 +enable_so_inofree_iagctl_5194 inofree iagctl 0 5194 NULL +enable_so_inofreefwd_iag_4921 inofreefwd iag 0 4921 NULL +enable_so_iagnum_iag_23227 iagnum iag 0 23227 NULL ++enable_so_offset_lv_35617 offset lv 0 35617 NULL diff --git a/scripts/gcc-plugins/size_overflow_plugin/generate_size_overflow_hash.sh b/scripts/gcc-plugins/size_overflow_plugin/generate_size_overflow_hash.sh new file mode 100644 index 0000000..be9724d @@ -180745,13 +181527,13 @@ index 0000000..be9724d +exit 0 diff --git a/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c b/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c new file mode 100644 -index 0000000..ee987da +index 0000000..cef2817 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c @@ -0,0 +1,369 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -181120,13 +181902,13 @@ index 0000000..ee987da +#include "gcc-generate-gimple-pass.h" diff --git a/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c b/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c new file mode 100644 -index 0000000..f29aac6 +index 0000000..c40bc7c --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c @@ -0,0 +1,1166 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -182292,13 +183074,13 @@ index 0000000..f29aac6 +} diff --git a/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c b/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c new file mode 100644 -index 0000000..c910983 +index 0000000..5ea5f35 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c @@ -0,0 +1,137 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -182772,13 +183554,13 @@ index 0000000..4bd2e7f +#endif diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c new file mode 100644 -index 0000000..4098952 +index 0000000..00c7430 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c @@ -0,0 +1,194 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -182972,10 +183754,10 @@ index 0000000..4098952 +} diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data new file mode 100644 -index 0000000..cbb8a80 +index 0000000..4ed1988 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data -@@ -0,0 +1,21645 @@ +@@ -0,0 +1,21644 @@ +enable_so_recv_ctrl_pipe_us_data_0 recv_ctrl_pipe us_data 0 0 NULL +enable_so___earlyonly_bootmem_alloc_fndecl_3 __earlyonly_bootmem_alloc fndecl 2-3-4 3 NULL +enable_so_v9fs_xattr_get_acl_fndecl_4 v9fs_xattr_get_acl fndecl 5 4 NULL @@ -194807,7 +195589,6 @@ index 0000000..cbb8a80 +enable_so_blocksize_brcmf_sdio_35612 blocksize brcmf_sdio 0 35612 NULL +enable_so_sqp_demux_mlx4_caps_35613 sqp_demux mlx4_caps 0 35613 NULL nohasharray +enable_so_maxcontacts_mt_device_35613 maxcontacts mt_device 0 35613 &enable_so_sqp_demux_mlx4_caps_35613 -+enable_so_offset_lv_35617 offset lv 0 35617 NULL +enable_so_generic_perform_write_fndecl_35619 generic_perform_write fndecl 0-3 35619 NULL nohasharray +enable_so_ext4_update_final_de_fndecl_35619 ext4_update_final_de fndecl 2-3 35619 &enable_so_generic_perform_write_fndecl_35619 nohasharray +enable_so_count_fm10k_ring_35619 count fm10k_ring 0 35619 &enable_so_ext4_update_final_de_fndecl_35619 @@ -204623,13 +205404,14 @@ index 0000000..cbb8a80 +enable_so_connector_write_fndecl_65534 connector_write fndecl 3 65534 NULL diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data new file mode 100644 -index 0000000..17bc0d8 +index 0000000..74e91b2 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data -@@ -0,0 +1,92 @@ +@@ -0,0 +1,97 @@ +enable_so_spa_set_aux_vdevs_fndecl_746 spa_set_aux_vdevs fndecl 3 746 NULL +enable_so_zfs_lookup_fndecl_2144 zfs_lookup fndecl 0 2144 NULL +enable_so_mappedread_fndecl_2627 mappedread fndecl 2 2627 NULL ++enable_so_SMACL_Alloc_fndecl_2775 SMACL_Alloc fndecl 1 2775 NULL +enable_so_vdev_disk_dio_alloc_fndecl_2957 vdev_disk_dio_alloc fndecl 1 2957 NULL +enable_so_nv_alloc_pushpage_spl_fndecl_4286 nv_alloc_pushpage_spl fndecl 2 4286 NULL +enable_so_zpl_xattr_get_fndecl_4574 zpl_xattr_get fndecl 0 4574 NULL @@ -204648,6 +205430,7 @@ index 0000000..17bc0d8 +enable_so_dmu_snapshot_realname_fndecl_14632 dmu_snapshot_realname fndecl 4 14632 NULL +enable_so_kmem_alloc_debug_fndecl_14852 kmem_alloc_debug fndecl 1 14852 NULL +enable_so_kmalloc_node_nofail_fndecl_15151 kmalloc_node_nofail fndecl 1 15151 NULL ++enable_so_size_VNet_EventHeader_15382 size VNet_EventHeader 0 15382 NULL +enable_so_dmu_write_uio_fndecl_16351 dmu_write_uio fndecl 4 16351 NULL +enable_so_zfs_log_write_fndecl_16524 zfs_log_write fndecl 6-5 16524 NULL +enable_so_sa_build_layouts_fndecl_16910 sa_build_layouts fndecl 3 16910 NULL @@ -204676,6 +205459,7 @@ index 0000000..17bc0d8 +enable_so_zfs_replay_fuids_fndecl_31479 zfs_replay_fuids fndecl 4 31479 NULL +enable_so_spa_history_log_to_phys_fndecl_31632 spa_history_log_to_phys fndecl 0-1 31632 NULL +enable_so___zpl_xattr_get_fndecl_32601 __zpl_xattr_get fndecl 0 32601 NULL ++enable_so_VNetUserListenerRead_fndecl_34039 VNetUserListenerRead fndecl 4 34039 NULL +enable_so_proc_copyout_string_fndecl_34049 proc_copyout_string fndecl 2 34049 NULL +enable_so_nv_alloc_sleep_spl_fndecl_34544 nv_alloc_sleep_spl fndecl 2 34544 NULL +enable_so_nv_alloc_nosleep_spl_fndecl_34761 nv_alloc_nosleep_spl fndecl 2 34761 NULL @@ -204709,6 +205493,8 @@ index 0000000..17bc0d8 +enable_so_zfs_log_write_fndecl_50162 zfs_log_write fndecl 6-5 50162 NULL +enable_so_i_fm_alloc_fndecl_51038 i_fm_alloc fndecl 2 51038 NULL +enable_so_copyout_fndecl_51409 copyout fndecl 3 51409 NULL ++enable_so_VNetKernel_MemoryAllocate_fndecl_53131 VNetKernel_MemoryAllocate fndecl 1 53131 NULL ++enable_so_VNetUserIfWrite_fndecl_54044 VNetUserIfWrite fndecl 4 54044 NULL +enable_so_zvol_log_write_fndecl_54898 zvol_log_write fndecl 4-3 54898 NULL +enable_so_zfs_acl_node_alloc_fndecl_55641 zfs_acl_node_alloc fndecl 1 55641 NULL +enable_so_get_nvlist_fndecl_56685 get_nvlist fndecl 2 56685 NULL @@ -204721,13 +205507,13 @@ index 0000000..17bc0d8 +enable_so_zpios_read_fndecl_64734 zpios_read fndecl 3 64734 NULL diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c new file mode 100644 -index 0000000..0a679f8 +index 0000000..457ea92 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c @@ -0,0 +1,1163 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -205890,13 +206676,13 @@ index 0000000..0a679f8 +#include "gcc-generate-ipa-pass.h" diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c new file mode 100644 -index 0000000..7f459ed +index 0000000..b5291e1 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c @@ -0,0 +1,505 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -206401,13 +207187,13 @@ index 0000000..7f459ed + diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c new file mode 100644 -index 0000000..3f8f032 +index 0000000..be40980 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c @@ -0,0 +1,290 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -206697,13 +207483,13 @@ index 0000000..3f8f032 +} diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c new file mode 100644 -index 0000000..87af656 +index 0000000..f24bbc0 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c @@ -0,0 +1,352 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -207055,13 +207841,13 @@ index 0000000..87af656 + diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c new file mode 100644 -index 0000000..eebcf4c +index 0000000..1f5768d --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c @@ -0,0 +1,743 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow @@ -207804,13 +208590,13 @@ index 0000000..eebcf4c +} diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c new file mode 100644 -index 0000000..062204a +index 0000000..69e3a85 --- /dev/null +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c @@ -0,0 +1,1025 @@ +/* + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> -+ * Licensed under the GPL v2, or (at your option) v3 ++ * Licensed under the GPL v2 + * + * Homepage: + * https://github.com/ephox-gcc-plugins/size_overflow |