diff options
author | Anthony G. Basile <blueness@gentoo.org> | 2012-11-24 07:49:18 -0500 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2012-11-24 07:49:18 -0500 |
commit | d88a7209c49fbf714f2805ed8851059410365ebb (patch) | |
tree | 78fa916a9275a41d5e1182e60817fe3b1dc8ef9c | |
parent | Grsec/PaX: 2.9.1-{2.6.32.60,3.2.34,3.6.7}-201211181105 (diff) | |
download | hardened-patchset-d88a7209c49fbf714f2805ed8851059410365ebb.tar.gz hardened-patchset-d88a7209c49fbf714f2805ed8851059410365ebb.tar.bz2 hardened-patchset-d88a7209c49fbf714f2805ed8851059410365ebb.zip |
Grsec/PaX: 2.9.1-{2.6.32.60,3.2.34,3.6.7}-20121122100020121122
-rw-r--r-- | 2.6.32/0000_README | 2 | ||||
-rw-r--r-- | 2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211220959.patch (renamed from 2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211181103.patch) | 99 | ||||
-rw-r--r-- | 3.2.34/0000_README | 2 | ||||
-rw-r--r-- | 3.2.34/4420_grsecurity-2.9.1-3.2.34-201211220959.patch (renamed from 3.2.34/4420_grsecurity-2.9.1-3.2.34-201211181104.patch) | 324 | ||||
-rw-r--r-- | 3.6.7/0000_README | 2 | ||||
-rw-r--r-- | 3.6.7/4420_grsecurity-2.9.1-3.6.7-201211221000.patch (renamed from 3.6.7/4420_grsecurity-2.9.1-3.6.7-201211181105.patch) | 340 |
6 files changed, 618 insertions, 151 deletions
diff --git a/2.6.32/0000_README b/2.6.32/0000_README index 00e77a9..424bb70 100644 --- a/2.6.32/0000_README +++ b/2.6.32/0000_README @@ -34,7 +34,7 @@ Patch: 1059_linux-2.6.32.60.patch From: http://www.kernel.org Desc: Linux 2.6.32.59 -Patch: 4420_grsecurity-2.9.1-2.6.32.60-201211181103.patch +Patch: 4420_grsecurity-2.9.1-2.6.32.60-201211220959.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211181103.patch b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211220959.patch index 4688218..8492134 100644 --- a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211181103.patch +++ b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201211220959.patch @@ -77942,7 +77942,7 @@ index a24c58e..53f91ee 100644 if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { diff --git a/fs/fs_struct.c b/fs/fs_struct.c -index eee0590..0a5b2ee 100644 +index eee0590..34791ce 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -4,6 +4,7 @@ @@ -77975,7 +77975,14 @@ index eee0590..0a5b2ee 100644 count++; } if (fs->pwd.dentry == old_root->dentry -@@ -89,7 +98,8 @@ void exit_fs(struct task_struct *tsk) +@@ -84,12 +93,15 @@ void exit_fs(struct task_struct *tsk) + { + struct fs_struct *fs = tsk->fs; + ++ gr_put_exec_file(tsk); ++ + if (fs) { + int kill; task_lock(tsk); write_lock(&fs->lock); tsk->fs = NULL; @@ -77985,7 +77992,7 @@ index eee0590..0a5b2ee 100644 write_unlock(&fs->lock); task_unlock(tsk); if (kill) -@@ -102,7 +112,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) +@@ -102,7 +114,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); /* We don't need to lock fs - think why ;-) */ if (fs) { @@ -77994,7 +78001,7 @@ index eee0590..0a5b2ee 100644 fs->in_exec = 0; rwlock_init(&fs->lock); fs->umask = old->umask; -@@ -127,8 +137,9 @@ int unshare_fs_struct(void) +@@ -127,8 +139,9 @@ int unshare_fs_struct(void) task_lock(current); write_lock(&fs->lock); @@ -78005,7 +78012,7 @@ index eee0590..0a5b2ee 100644 write_unlock(&fs->lock); task_unlock(current); -@@ -141,13 +152,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); +@@ -141,13 +154,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); int current_umask(void) { @@ -78021,7 +78028,15 @@ index eee0590..0a5b2ee 100644 .lock = __RW_LOCK_UNLOCKED(init_fs.lock), .umask = 0022, }; -@@ -162,12 +173,13 @@ void daemonize_fs_struct(void) +@@ -156,18 +169,21 @@ void daemonize_fs_struct(void) + { + struct fs_struct *fs = current->fs; + ++ gr_put_exec_file(current); ++ + if (fs) { + int kill; + task_lock(current); write_lock(&init_fs.lock); @@ -84700,10 +84715,10 @@ index 0000000..1b9afa9 +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..42c1316 +index 0000000..a4c751d --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4198 @@ +@@ -0,0 +1,4214 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -88892,6 +88907,22 @@ index 0000000..42c1316 + return (obj->mode & GR_FIND) ? 1 : 0; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ struct file *filp; ++ ++ write_lock(&grsec_exec_file_lock); ++ filp = task->exec_file; ++ task->exec_file = NULL; ++ write_unlock(&grsec_exec_file_lock); ++ ++ if (filp) ++ fput(filp); ++ ++ return; ++} ++ ++ +#ifdef CONFIG_NETFILTER_XT_MATCH_GRADM_MODULE +EXPORT_SYMBOL(gr_acl_is_enabled); +#endif @@ -90996,10 +91027,10 @@ index 0000000..197bdd5 +} diff --git a/grsecurity/grsec_disabled.c b/grsecurity/grsec_disabled.c new file mode 100644 -index 0000000..40545bf +index 0000000..7a358f8 --- /dev/null +++ b/grsecurity/grsec_disabled.c -@@ -0,0 +1,437 @@ +@@ -0,0 +1,442 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -91431,6 +91462,11 @@ index 0000000..40545bf + return dentry->d_inode->i_sb->s_dev; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ return; ++} ++ +EXPORT_SYMBOL(gr_learn_resource); +EXPORT_SYMBOL(gr_set_kernel_label); +#ifdef CONFIG_SECURITY @@ -96665,10 +96701,10 @@ index 0000000..ac88734 +#define GR_SYMLINKOWNER_MSG "denied following symlink %.950s since symlink owner %u does not match target owner %u, by " diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h new file mode 100644 -index 0000000..d44d8a6 +index 0000000..0e2a522 --- /dev/null +++ b/include/linux/grsecurity.h -@@ -0,0 +1,225 @@ +@@ -0,0 +1,226 @@ +#ifndef GR_SECURITY_H +#define GR_SECURITY_H +#include <linux/fs.h> @@ -96868,6 +96904,7 @@ index 0000000..d44d8a6 +int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode); +void gr_audit_ptrace(struct task_struct *task); +dev_t gr_get_dev_from_dentry(struct dentry *dentry); ++void gr_put_exec_file(struct task_struct *task); + +int gr_ptrace_readexec(struct file *file, int unsafe_flags); + @@ -101636,21 +101673,10 @@ index 9c06d10..5b211dc 100644 if (ret < 0) return ret; diff --git a/kernel/exit.c b/kernel/exit.c -index a2a1659..66af9b1 100644 +index a2a1659..55ff5d7 100644 --- a/kernel/exit.c +++ b/kernel/exit.c -@@ -55,6 +55,10 @@ - #include <asm/pgtable.h> - #include <asm/mmu_context.h> - -+#ifdef CONFIG_GRKERNSEC -+extern rwlock_t grsec_exec_file_lock; -+#endif -+ - static void exit_mm(struct task_struct * tsk); - - static void __unhash_process(struct task_struct *p) -@@ -174,6 +178,10 @@ void release_task(struct task_struct * p) +@@ -174,6 +174,10 @@ void release_task(struct task_struct * p) struct task_struct *leader; int zap_leader; repeat: @@ -101661,7 +101687,7 @@ index a2a1659..66af9b1 100644 tracehook_prepare_release_task(p); /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials */ -@@ -397,7 +405,7 @@ int allow_signal(int sig) +@@ -397,7 +401,7 @@ int allow_signal(int sig) * know it'll be handled, so that they don't get converted to * SIGKILL or just silently dropped. */ @@ -101670,25 +101696,16 @@ index a2a1659..66af9b1 100644 recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return 0; -@@ -433,6 +441,17 @@ void daemonize(const char *name, ...) +@@ -433,6 +437,8 @@ void daemonize(const char *name, ...) vsnprintf(current->comm, sizeof(current->comm), name, args); va_end(args); -+#ifdef CONFIG_GRKERNSEC -+ write_lock(&grsec_exec_file_lock); -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+ write_unlock(&grsec_exec_file_lock); -+#endif -+ + gr_set_kernel_label(current); + /* * If we were started as result of loading a module, close all of the * user space pages. We don't need them, and if we didn't close them -@@ -897,17 +916,17 @@ NORET_TYPE void do_exit(long code) +@@ -897,17 +903,17 @@ NORET_TYPE void do_exit(long code) struct task_struct *tsk = current; int group_dead; @@ -101713,7 +101730,7 @@ index a2a1659..66af9b1 100644 * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before * continuing. Amongst other possible reasons, this is to prevent * mm_release()->clear_child_tid() from writing to a user-controlled -@@ -915,6 +934,13 @@ NORET_TYPE void do_exit(long code) +@@ -915,6 +921,13 @@ NORET_TYPE void do_exit(long code) */ set_fs(USER_DS); @@ -101727,7 +101744,7 @@ index a2a1659..66af9b1 100644 tracehook_report_exit(&code); validate_creds_for_do_exit(tsk); -@@ -973,6 +999,9 @@ NORET_TYPE void do_exit(long code) +@@ -973,6 +986,9 @@ NORET_TYPE void do_exit(long code) tsk->exit_code = code; taskstats_exit(tsk, group_dead); @@ -101737,7 +101754,7 @@ index a2a1659..66af9b1 100644 exit_mm(tsk); if (group_dead) -@@ -1059,7 +1088,7 @@ SYSCALL_DEFINE1(exit, int, error_code) +@@ -1059,7 +1075,7 @@ SYSCALL_DEFINE1(exit, int, error_code) * Take down every thread in the group. This is called by fatal signals * as well as by sys_exit_group (below). */ @@ -101746,7 +101763,7 @@ index a2a1659..66af9b1 100644 do_group_exit(int exit_code) { struct signal_struct *sig = current->signal; -@@ -1188,7 +1217,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) +@@ -1188,7 +1204,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) if (unlikely(wo->wo_flags & WNOWAIT)) { int exit_code = p->exit_code; diff --git a/3.2.34/0000_README b/3.2.34/0000_README index 0896e71..5f22bbb 100644 --- a/3.2.34/0000_README +++ b/3.2.34/0000_README @@ -54,7 +54,7 @@ Patch: 1033_linux-3.2.34.patch From: http://www.kernel.org Desc: Linux 3.2.34 -Patch: 4420_grsecurity-2.9.1-3.2.34-201211181104.patch +Patch: 4420_grsecurity-2.9.1-3.2.34-201211220959.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/3.2.34/4420_grsecurity-2.9.1-3.2.34-201211181104.patch b/3.2.34/4420_grsecurity-2.9.1-3.2.34-201211220959.patch index 08bfa63..f917c5d 100644 --- a/3.2.34/4420_grsecurity-2.9.1-3.2.34-201211181104.patch +++ b/3.2.34/4420_grsecurity-2.9.1-3.2.34-201211220959.patch @@ -26314,10 +26314,139 @@ index 6687022..ceabcfa 100644 + pax_force_retaddr ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c -index 5a5b6e4..201d42e 100644 +index 5a5b6e4..2265c0f 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c -@@ -117,6 +117,10 @@ static inline void bpf_flush_icache(void *start, void *end) +@@ -11,6 +11,7 @@ + #include <asm/cacheflush.h> + #include <linux/netdevice.h> + #include <linux/filter.h> ++#include <linux/random.h> + + /* + * Conventions : +@@ -45,13 +46,87 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) + return ptr + len; + } + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++#define MAX_INSTR_CODE_SIZE 96 ++#else ++#define MAX_INSTR_CODE_SIZE 64 ++#endif ++ + #define EMIT(bytes, len) do { prog = emit_code(prog, bytes, len); } while (0) + + #define EMIT1(b1) EMIT(b1, 1) + #define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2) + #define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3) + #define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4) ++ ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++/* original constant will appear in ecx */ ++#define DILUTE_CONST_SEQUENCE(_off, _key) \ ++do { \ ++ /* mov ecx, randkey */ \ ++ EMIT1(0xb9); \ ++ EMIT(_key, 4); \ ++ /* xor ecx, randkey ^ off */ \ ++ EMIT2(0x81, 0xf1); \ ++ EMIT((_key) ^ (_off), 4); \ ++} while (0) ++ ++#define EMIT1_off32(b1, _off) \ ++do { \ ++ switch (b1) { \ ++ case 0x05: /* add eax, imm32 */ \ ++ case 0x2d: /* sub eax, imm32 */ \ ++ case 0x25: /* and eax, imm32 */ \ ++ case 0x0d: /* or eax, imm32 */ \ ++ case 0xb8: /* mov eax, imm32 */ \ ++ case 0x3d: /* cmp eax, imm32 */ \ ++ case 0xa9: /* test eax, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ EMIT2((b1) - 4, 0xc8); /* convert imm instruction to eax, ecx */\ ++ break; \ ++ case 0xbb: /* mov ebx, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* mov ebx, ecx */ \ ++ EMIT2(0x89, 0xcb); \ ++ break; \ ++ case 0xbe: /* mov esi, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* mov esi, ecx */ \ ++ EMIT2(0x89, 0xce); \ ++ break; \ ++ case 0xe9: /* jmp rel imm32 */ \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ /* prevent fall-through, we're not called if off = 0 */ \ ++ EMIT(0xcccccccc, 4); \ ++ EMIT(0xcccccccc, 4); \ ++ break; \ ++ default: \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ } \ ++} while (0) ++ ++#define EMIT2_off32(b1, b2, _off) \ ++do { \ ++ if ((b1) == 0x8d && (b2) == 0xb3) { /* lea esi, [rbx+imm32] */ \ ++ EMIT2(0x8d, 0xb3); /* lea esi, [rbx+randkey] */ \ ++ EMIT(randkey, 4); \ ++ EMIT2(0x8d, 0xb6); /* lea esi, [esi+off-randkey] */ \ ++ EMIT((_off) - randkey, 4); \ ++ } else if ((b1) == 0x69 && (b2) == 0xc0) { /* imul eax, imm32 */\ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* imul eax, ecx */ \ ++ EMIT3(0x0f, 0xaf, 0xc1); \ ++ } else { \ ++ EMIT2(b1, b2); \ ++ EMIT(_off, 4); \ ++ } \ ++} while (0) ++#else + #define EMIT1_off32(b1, off) do { EMIT1(b1); EMIT(off, 4);} while (0) ++#define EMIT2_off32(b1, b2, off) do { EMIT2(b1, b2); EMIT(off, 4);} while (0) ++#endif + + #define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ + #define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ +@@ -86,6 +161,24 @@ do { \ + #define X86_JBE 0x76 + #define X86_JA 0x77 + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++#define APPEND_FLOW_VERIFY() \ ++do { \ ++ /* mov ecx, randkey */ \ ++ EMIT1(0xb9); \ ++ EMIT(randkey, 4); \ ++ /* cmp ecx, randkey */ \ ++ EMIT2(0x81, 0xf9); \ ++ EMIT(randkey, 4); \ ++ /* jz after 8 int 3s */ \ ++ EMIT2(0x74, 0x08); \ ++ EMIT(0xcccccccc, 4); \ ++ EMIT(0xcccccccc, 4); \ ++} while (0) ++#else ++#define APPEND_FLOW_VERIFY() do { } while (0) ++#endif ++ + #define EMIT_COND_JMP(op, offset) \ + do { \ + if (is_near(offset)) \ +@@ -93,6 +186,7 @@ do { \ + else { \ + EMIT2(0x0f, op + 0x10); \ + EMIT(offset, 4); /* jxx .+off32 */ \ ++ APPEND_FLOW_VERIFY(); \ + } \ + } while (0) + +@@ -117,10 +211,14 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } @@ -26328,7 +26457,22 @@ index 5a5b6e4..201d42e 100644 void bpf_jit_compile(struct sk_filter *fp) { -@@ -141,6 +145,10 @@ void bpf_jit_compile(struct sk_filter *fp) +- u8 temp[64]; ++ u8 temp[MAX_INSTR_CODE_SIZE]; + u8 *prog; + unsigned int proglen, oldproglen = 0; + int ilen, i; +@@ -133,6 +231,9 @@ void bpf_jit_compile(struct sk_filter *fp) + unsigned int *addrs; + const struct sock_filter *filter = fp->insns; + int flen = fp->len; ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ unsigned int randkey; ++#endif + + if (!bpf_jit_enable) + return; +@@ -141,11 +242,19 @@ void bpf_jit_compile(struct sk_filter *fp) if (addrs == NULL) return; @@ -26336,10 +26480,49 @@ index 5a5b6e4..201d42e 100644 + if (!fp->work) + goto out; + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ randkey = get_random_int(); ++#endif ++ /* Before first pass, make a rough estimation of addrs[] - * each bpf instruction is translated to less than 64 bytes +- * each bpf instruction is translated to less than 64 bytes ++ * each bpf instruction is translated to less than MAX_INSTR_CODE_SIZE bytes */ -@@ -477,7 +485,7 @@ void bpf_jit_compile(struct sk_filter *fp) + for (proglen = 0, i = 0; i < flen; i++) { +- proglen += 64; ++ proglen += MAX_INSTR_CODE_SIZE; + addrs[i] = proglen; + } + cleanup_addr = proglen; /* epilogue address */ +@@ -253,10 +362,8 @@ void bpf_jit_compile(struct sk_filter *fp) + case BPF_S_ALU_MUL_K: /* A *= K */ + if (is_imm8(K)) + EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ +- else { +- EMIT2(0x69, 0xc0); /* imul imm32,%eax */ +- EMIT(K, 4); +- } ++ else ++ EMIT2_off32(0x69, 0xc0, K); /* imul imm32,%eax */ + break; + case BPF_S_ALU_DIV_X: /* A /= X; */ + seen |= SEEN_XREG; +@@ -276,8 +383,14 @@ void bpf_jit_compile(struct sk_filter *fp) + EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */ + break; + case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ DILUTE_CONST_SEQUENCE(K, randkey); ++ // imul rax, rcx ++ EMIT4(0x48, 0x0f, 0xaf, 0xc1); ++#else + EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ + EMIT(K, 4); ++#endif + EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ + break; + case BPF_S_ALU_AND_X: +@@ -477,7 +590,7 @@ void bpf_jit_compile(struct sk_filter *fp) common_load: seen |= SEEN_DATAREF; if ((int)K < 0) { /* Abort the JIT because __load_pointer() is needed. */ @@ -26348,7 +26531,7 @@ index 5a5b6e4..201d42e 100644 } t_offset = func - (image + addrs[i]); EMIT1_off32(0xbe, K); /* mov imm32,%esi */ -@@ -492,7 +500,7 @@ common_load: seen |= SEEN_DATAREF; +@@ -492,7 +605,7 @@ common_load: seen |= SEEN_DATAREF; case BPF_S_LDX_B_MSH: if ((int)K < 0) { /* Abort the JIT because __load_pointer() is needed. */ @@ -26357,7 +26540,7 @@ index 5a5b6e4..201d42e 100644 } seen |= SEEN_DATAREF | SEEN_XREG; t_offset = sk_load_byte_msh - (image + addrs[i]); -@@ -582,17 +590,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -582,17 +695,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; default: /* hmm, too complex filter, give up with jit compiler */ @@ -26380,7 +26563,7 @@ index 5a5b6e4..201d42e 100644 } proglen += ilen; addrs[i] = proglen; -@@ -613,11 +622,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -613,11 +727,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { @@ -26394,7 +26577,7 @@ index 5a5b6e4..201d42e 100644 } oldproglen = proglen; } -@@ -633,7 +640,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -633,7 +745,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; @@ -26406,7 +26589,7 @@ index 5a5b6e4..201d42e 100644 out: kfree(addrs); return; -@@ -641,18 +651,20 @@ out: +@@ -641,18 +756,20 @@ out: static void jit_free_defer(struct work_struct *arg) { @@ -46415,7 +46598,7 @@ index 0845f84..7b4ebef 100644 if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { diff --git a/fs/fs_struct.c b/fs/fs_struct.c -index 78b519c..0386555 100644 +index 78b519c..7c6fd17 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -4,6 +4,7 @@ @@ -46448,7 +46631,15 @@ index 78b519c..0386555 100644 count++; } if (fs->pwd.dentry == old_root->dentry -@@ -109,7 +118,8 @@ void exit_fs(struct task_struct *tsk) +@@ -103,13 +112,16 @@ void exit_fs(struct task_struct *tsk) + { + struct fs_struct *fs = tsk->fs; + ++ gr_put_exec_file(tsk); ++ + if (fs) { + int kill; + task_lock(tsk); spin_lock(&fs->lock); write_seqcount_begin(&fs->seq); tsk->fs = NULL; @@ -46458,7 +46649,7 @@ index 78b519c..0386555 100644 write_seqcount_end(&fs->seq); spin_unlock(&fs->lock); task_unlock(tsk); -@@ -123,7 +133,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) +@@ -123,7 +135,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); /* We don't need to lock fs - think why ;-) */ if (fs) { @@ -46467,7 +46658,7 @@ index 78b519c..0386555 100644 fs->in_exec = 0; spin_lock_init(&fs->lock); seqcount_init(&fs->seq); -@@ -132,6 +142,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) +@@ -132,6 +144,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) spin_lock(&old->lock); fs->root = old->root; path_get_longterm(&fs->root); @@ -46477,7 +46668,7 @@ index 78b519c..0386555 100644 fs->pwd = old->pwd; path_get_longterm(&fs->pwd); spin_unlock(&old->lock); -@@ -150,8 +163,9 @@ int unshare_fs_struct(void) +@@ -150,8 +165,9 @@ int unshare_fs_struct(void) task_lock(current); spin_lock(&fs->lock); @@ -46488,7 +46679,7 @@ index 78b519c..0386555 100644 spin_unlock(&fs->lock); task_unlock(current); -@@ -164,13 +178,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); +@@ -164,13 +180,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); int current_umask(void) { @@ -46504,7 +46695,15 @@ index 78b519c..0386555 100644 .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), .seq = SEQCNT_ZERO, .umask = 0022, -@@ -186,12 +200,13 @@ void daemonize_fs_struct(void) +@@ -180,18 +196,21 @@ void daemonize_fs_struct(void) + { + struct fs_struct *fs = current->fs; + ++ gr_put_exec_file(current); ++ + if (fs) { + int kill; + task_lock(current); spin_lock(&init_fs.lock); @@ -51324,10 +51523,10 @@ index 87323f1..dab9d00 100644 ip = issum ? mp->m_rsumip : mp->m_rbmip; diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig new file mode 100644 -index 0000000..ae8456d +index 0000000..b0d5e22 --- /dev/null +++ b/grsecurity/Kconfig -@@ -0,0 +1,947 @@ +@@ -0,0 +1,964 @@ +# +# grecurity configuration +# @@ -51390,6 +51589,23 @@ index 0000000..ae8456d + IF YOU USE XFree86. If you use XFree86 and you still want to + protect your kernel against modification, use the RBAC system. + ++config GRKERNSEC_JIT_HARDEN ++ bool "Harden BPF JIT against spray attacks" ++ default y if GRKERNSEC_CONFIG_AUTO ++ depends on BPF_JIT ++ help ++ If you say Y here, the native code generated by the kernel's Berkeley ++ Packet Filter (BPF) JIT engine will be hardened against JIT-spraying ++ attacks that attempt to fit attacker-beneficial instructions in ++ 32bit immediate fields of JIT-generated native instructions. The ++ attacker will generally aim to cause an unintended instruction sequence ++ of JIT-generated native code to execute by jumping into the middle of ++ a generated instruction. This feature effectively randomizes the 32bit ++ immediate constants present in the generated code to thwart such attacks. ++ ++ If you're using KERNEXEC, it's recommended that you enable this option ++ to supplement the hardening of the kernel. ++ +config GRKERNSEC_PROC_MEMMAP + bool "Harden ASLR against information leaks and entropy reduction" + default y if (GRKERNSEC_CONFIG_AUTO || PAX_NOEXEC || PAX_ASLR) @@ -52321,10 +52537,10 @@ index 0000000..1b9afa9 +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..7feb2c5 +index 0000000..93f15bf --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4213 @@ +@@ -0,0 +1,4229 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -56528,6 +56744,22 @@ index 0000000..7feb2c5 + return (obj->mode & GR_FIND) ? 1 : 0; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ struct file *filp; ++ ++ write_lock(&grsec_exec_file_lock); ++ filp = task->exec_file; ++ task->exec_file = NULL; ++ write_unlock(&grsec_exec_file_lock); ++ ++ if (filp) ++ fput(filp); ++ ++ return; ++} ++ ++ +#ifdef CONFIG_NETFILTER_XT_MATCH_GRADM_MODULE +EXPORT_SYMBOL(gr_acl_is_enabled); +#endif @@ -58611,10 +58843,10 @@ index 0000000..a2dc675 +} diff --git a/grsecurity/grsec_disabled.c b/grsecurity/grsec_disabled.c new file mode 100644 -index 0000000..213ad8b +index 0000000..b79fe50 --- /dev/null +++ b/grsecurity/grsec_disabled.c -@@ -0,0 +1,437 @@ +@@ -0,0 +1,442 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -59046,6 +59278,11 @@ index 0000000..213ad8b + return dentry->d_inode->i_sb->s_dev; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ return; ++} ++ +EXPORT_SYMBOL(gr_learn_resource); +EXPORT_SYMBOL(gr_set_kernel_label); +#ifdef CONFIG_SECURITY @@ -63472,10 +63709,10 @@ index 0000000..54f4e85 +#define GR_SYMLINKOWNER_MSG "denied following symlink %.950s since symlink owner %u does not match target owner %u, by " diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h new file mode 100644 -index 0000000..c14f3fb +index 0000000..90ccf22 --- /dev/null +++ b/include/linux/grsecurity.h -@@ -0,0 +1,235 @@ +@@ -0,0 +1,236 @@ +#ifndef GR_SECURITY_H +#define GR_SECURITY_H +#include <linux/fs.h> @@ -63685,6 +63922,7 @@ index 0000000..c14f3fb +int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode); +void gr_audit_ptrace(struct task_struct *task); +dev_t gr_get_dev_from_dentry(struct dentry *dentry); ++void gr_put_exec_file(struct task_struct *task); + +int gr_ptrace_readexec(struct file *file, int unsafe_flags); + @@ -68111,21 +68349,10 @@ index 7d1f05e..66d5a8e 100644 /* diff --git a/kernel/exit.c b/kernel/exit.c -index 234e152..3600fae 100644 +index 234e152..2e3e7e1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c -@@ -57,6 +57,10 @@ - #include <asm/pgtable.h> - #include <asm/mmu_context.h> - -+#ifdef CONFIG_GRKERNSEC -+extern rwlock_t grsec_exec_file_lock; -+#endif -+ - static void exit_mm(struct task_struct * tsk); - - static void __unhash_process(struct task_struct *p, bool group_dead) -@@ -168,6 +172,10 @@ void release_task(struct task_struct * p) +@@ -168,6 +168,10 @@ void release_task(struct task_struct * p) struct task_struct *leader; int zap_leader; repeat: @@ -68136,7 +68363,7 @@ index 234e152..3600fae 100644 /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ rcu_read_lock(); -@@ -380,7 +388,7 @@ int allow_signal(int sig) +@@ -380,7 +384,7 @@ int allow_signal(int sig) * know it'll be handled, so that they don't get converted to * SIGKILL or just silently dropped. */ @@ -68145,25 +68372,16 @@ index 234e152..3600fae 100644 recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return 0; -@@ -416,6 +424,17 @@ void daemonize(const char *name, ...) +@@ -416,6 +420,8 @@ void daemonize(const char *name, ...) vsnprintf(current->comm, sizeof(current->comm), name, args); va_end(args); -+#ifdef CONFIG_GRKERNSEC -+ write_lock(&grsec_exec_file_lock); -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+ write_unlock(&grsec_exec_file_lock); -+#endif -+ + gr_set_kernel_label(current); + /* * If we were started as result of loading a module, close all of the * user space pages. We don't need them, and if we didn't close them -@@ -874,6 +893,8 @@ NORET_TYPE void do_exit(long code) +@@ -874,6 +880,8 @@ NORET_TYPE void do_exit(long code) struct task_struct *tsk = current; int group_dead; @@ -68172,7 +68390,7 @@ index 234e152..3600fae 100644 profile_task_exit(tsk); WARN_ON(blk_needs_flush_plug(tsk)); -@@ -890,7 +911,6 @@ NORET_TYPE void do_exit(long code) +@@ -890,7 +898,6 @@ NORET_TYPE void do_exit(long code) * mm_release()->clear_child_tid() from writing to a user-controlled * kernel address. */ @@ -68180,7 +68398,7 @@ index 234e152..3600fae 100644 ptrace_event(PTRACE_EVENT_EXIT, code); -@@ -952,6 +972,9 @@ NORET_TYPE void do_exit(long code) +@@ -952,6 +959,9 @@ NORET_TYPE void do_exit(long code) tsk->exit_code = code; taskstats_exit(tsk, group_dead); @@ -68190,7 +68408,7 @@ index 234e152..3600fae 100644 exit_mm(tsk); if (group_dead) -@@ -1065,7 +1088,7 @@ SYSCALL_DEFINE1(exit, int, error_code) +@@ -1065,7 +1075,7 @@ SYSCALL_DEFINE1(exit, int, error_code) * Take down every thread in the group. This is called by fatal signals * as well as by sys_exit_group (below). */ diff --git a/3.6.7/0000_README b/3.6.7/0000_README index 8b389a1..05b1561 100644 --- a/3.6.7/0000_README +++ b/3.6.7/0000_README @@ -6,7 +6,7 @@ Patch: 1006_linux-3.6.7.patch From: http://www.kernel.org Desc: Linux 3.6.7 -Patch: 4420_grsecurity-2.9.1-3.6.7-201211181105.patch +Patch: 4420_grsecurity-2.9.1-3.6.7-201211221000.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/3.6.7/4420_grsecurity-2.9.1-3.6.7-201211181105.patch b/3.6.7/4420_grsecurity-2.9.1-3.6.7-201211221000.patch index 6f0229a..cdc60ce 100644 --- a/3.6.7/4420_grsecurity-2.9.1-3.6.7-201211181105.patch +++ b/3.6.7/4420_grsecurity-2.9.1-3.6.7-201211221000.patch @@ -26100,10 +26100,139 @@ index 877b9a1..a8ecf42 100644 + pax_force_retaddr ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c -index 33643a8..8e44870 100644 +index 33643a8..f6211a0 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c -@@ -120,6 +120,11 @@ static inline void bpf_flush_icache(void *start, void *end) +@@ -11,6 +11,7 @@ + #include <asm/cacheflush.h> + #include <linux/netdevice.h> + #include <linux/filter.h> ++#include <linux/random.h> + + /* + * Conventions : +@@ -48,13 +49,87 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) + return ptr + len; + } + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++#define MAX_INSTR_CODE_SIZE 96 ++#else ++#define MAX_INSTR_CODE_SIZE 64 ++#endif ++ + #define EMIT(bytes, len) do { prog = emit_code(prog, bytes, len); } while (0) + + #define EMIT1(b1) EMIT(b1, 1) + #define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2) + #define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3) + #define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4) ++ ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++/* original constant will appear in ecx */ ++#define DILUTE_CONST_SEQUENCE(_off, _key) \ ++do { \ ++ /* mov ecx, randkey */ \ ++ EMIT1(0xb9); \ ++ EMIT(_key, 4); \ ++ /* xor ecx, randkey ^ off */ \ ++ EMIT2(0x81, 0xf1); \ ++ EMIT((_key) ^ (_off), 4); \ ++} while (0) ++ ++#define EMIT1_off32(b1, _off) \ ++do { \ ++ switch (b1) { \ ++ case 0x05: /* add eax, imm32 */ \ ++ case 0x2d: /* sub eax, imm32 */ \ ++ case 0x25: /* and eax, imm32 */ \ ++ case 0x0d: /* or eax, imm32 */ \ ++ case 0xb8: /* mov eax, imm32 */ \ ++ case 0x3d: /* cmp eax, imm32 */ \ ++ case 0xa9: /* test eax, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ EMIT2((b1) - 4, 0xc8); /* convert imm instruction to eax, ecx */\ ++ break; \ ++ case 0xbb: /* mov ebx, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* mov ebx, ecx */ \ ++ EMIT2(0x89, 0xcb); \ ++ break; \ ++ case 0xbe: /* mov esi, imm32 */ \ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* mov esi, ecx */ \ ++ EMIT2(0x89, 0xce); \ ++ break; \ ++ case 0xe9: /* jmp rel imm32 */ \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ /* prevent fall-through, we're not called if off = 0 */ \ ++ EMIT(0xcccccccc, 4); \ ++ EMIT(0xcccccccc, 4); \ ++ break; \ ++ default: \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ } \ ++} while (0) ++ ++#define EMIT2_off32(b1, b2, _off) \ ++do { \ ++ if ((b1) == 0x8d && (b2) == 0xb3) { /* lea esi, [rbx+imm32] */ \ ++ EMIT2(0x8d, 0xb3); /* lea esi, [rbx+randkey] */ \ ++ EMIT(randkey, 4); \ ++ EMIT2(0x8d, 0xb6); /* lea esi, [esi+off-randkey] */ \ ++ EMIT((_off) - randkey, 4); \ ++ } else if ((b1) == 0x69 && (b2) == 0xc0) { /* imul eax, imm32 */\ ++ DILUTE_CONST_SEQUENCE(_off, randkey); \ ++ /* imul eax, ecx */ \ ++ EMIT3(0x0f, 0xaf, 0xc1); \ ++ } else { \ ++ EMIT2(b1, b2); \ ++ EMIT(_off, 4); \ ++ } \ ++} while (0) ++#else + #define EMIT1_off32(b1, off) do { EMIT1(b1); EMIT(off, 4);} while (0) ++#define EMIT2_off32(b1, b2, off) do { EMIT2(b1, b2); EMIT(off, 4);} while (0) ++#endif + + #define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ + #define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ +@@ -89,6 +164,24 @@ do { \ + #define X86_JBE 0x76 + #define X86_JA 0x77 + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++#define APPEND_FLOW_VERIFY() \ ++do { \ ++ /* mov ecx, randkey */ \ ++ EMIT1(0xb9); \ ++ EMIT(randkey, 4); \ ++ /* cmp ecx, randkey */ \ ++ EMIT2(0x81, 0xf9); \ ++ EMIT(randkey, 4); \ ++ /* jz after 8 int 3s */ \ ++ EMIT2(0x74, 0x08); \ ++ EMIT(0xcccccccc, 4); \ ++ EMIT(0xcccccccc, 4); \ ++} while (0) ++#else ++#define APPEND_FLOW_VERIFY() do { } while (0) ++#endif ++ + #define EMIT_COND_JMP(op, offset) \ + do { \ + if (is_near(offset)) \ +@@ -96,6 +189,7 @@ do { \ + else { \ + EMIT2(0x0f, op + 0x10); \ + EMIT(offset, 4); /* jxx .+off32 */ \ ++ APPEND_FLOW_VERIFY(); \ + } \ + } while (0) + +@@ -120,12 +214,17 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } @@ -26115,7 +26244,24 @@ index 33643a8..8e44870 100644 #define CHOOSE_LOAD_FUNC(K, func) \ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) -@@ -146,6 +151,10 @@ void bpf_jit_compile(struct sk_filter *fp) + void bpf_jit_compile(struct sk_filter *fp) + { +- u8 temp[64]; ++ u8 temp[MAX_INSTR_CODE_SIZE]; + u8 *prog; + unsigned int proglen, oldproglen = 0; + int ilen, i; +@@ -138,6 +237,9 @@ void bpf_jit_compile(struct sk_filter *fp) + unsigned int *addrs; + const struct sock_filter *filter = fp->insns; + int flen = fp->len; ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ unsigned int randkey; ++#endif + + if (!bpf_jit_enable) + return; +@@ -146,11 +248,19 @@ void bpf_jit_compile(struct sk_filter *fp) if (addrs == NULL) return; @@ -26123,10 +26269,59 @@ index 33643a8..8e44870 100644 + if (!fp->work) + goto out; + ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ randkey = get_random_int(); ++#endif ++ /* Before first pass, make a rough estimation of addrs[] - * each bpf instruction is translated to less than 64 bytes +- * each bpf instruction is translated to less than 64 bytes ++ * each bpf instruction is translated to less than MAX_INSTR_CODE_SIZE bytes */ -@@ -593,17 +602,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; + for (proglen = 0, i = 0; i < flen; i++) { +- proglen += 64; ++ proglen += MAX_INSTR_CODE_SIZE; + addrs[i] = proglen; + } + cleanup_addr = proglen; /* epilogue address */ +@@ -258,10 +368,8 @@ void bpf_jit_compile(struct sk_filter *fp) + case BPF_S_ALU_MUL_K: /* A *= K */ + if (is_imm8(K)) + EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ +- else { +- EMIT2(0x69, 0xc0); /* imul imm32,%eax */ +- EMIT(K, 4); +- } ++ else ++ EMIT2_off32(0x69, 0xc0, K); /* imul imm32,%eax */ + break; + case BPF_S_ALU_DIV_X: /* A /= X; */ + seen |= SEEN_XREG; +@@ -281,8 +389,14 @@ void bpf_jit_compile(struct sk_filter *fp) + EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */ + break; + case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ ++#ifdef CONFIG_GRKERNSEC_JIT_HARDEN ++ DILUTE_CONST_SEQUENCE(K, randkey); ++ // imul rax, rcx ++ EMIT4(0x48, 0x0f, 0xaf, 0xc1); ++#else + EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ + EMIT(K, 4); ++#endif + EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ + break; + case BPF_S_ALU_AND_X: +@@ -509,8 +623,7 @@ common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; + if (is_imm8(K)) { + EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */ + } else { +- EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */ +- EMIT(K, 4); ++ EMIT2_off32(0x8d, 0xb3, K); /* lea imm32(%rbx),%esi */ + } + } else { + EMIT2(0x89,0xde); /* mov %ebx,%esi */ +@@ -593,17 +706,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; default: /* hmm, too complex filter, give up with jit compiler */ @@ -26149,7 +26344,7 @@ index 33643a8..8e44870 100644 } proglen += ilen; addrs[i] = proglen; -@@ -624,11 +634,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -624,11 +738,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { @@ -26163,7 +26358,7 @@ index 33643a8..8e44870 100644 } oldproglen = proglen; } -@@ -644,7 +652,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -644,7 +756,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; @@ -26175,7 +26370,7 @@ index 33643a8..8e44870 100644 out: kfree(addrs); return; -@@ -652,18 +663,20 @@ out: +@@ -652,18 +767,20 @@ out: static void jit_free_defer(struct work_struct *arg) { @@ -46151,7 +46346,7 @@ index 96f2428..f5eeb8e 100644 if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { diff --git a/fs/fs_struct.c b/fs/fs_struct.c -index 5df4775..9d9336f 100644 +index 5df4775..f656176 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -4,6 +4,7 @@ @@ -46201,7 +46396,14 @@ index 5df4775..9d9336f 100644 hits += replace_path(&fs->pwd, old_root, new_root); write_seqcount_end(&fs->seq); while (hits--) { -@@ -99,7 +116,8 @@ void exit_fs(struct task_struct *tsk) +@@ -94,12 +111,15 @@ void exit_fs(struct task_struct *tsk) + { + struct fs_struct *fs = tsk->fs; + ++ gr_put_exec_file(tsk); ++ + if (fs) { + int kill; task_lock(tsk); spin_lock(&fs->lock); tsk->fs = NULL; @@ -46211,7 +46413,7 @@ index 5df4775..9d9336f 100644 spin_unlock(&fs->lock); task_unlock(tsk); if (kill) -@@ -112,7 +130,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) +@@ -112,7 +132,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); /* We don't need to lock fs - think why ;-) */ if (fs) { @@ -46220,7 +46422,7 @@ index 5df4775..9d9336f 100644 fs->in_exec = 0; spin_lock_init(&fs->lock); seqcount_init(&fs->seq); -@@ -121,6 +139,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) +@@ -121,6 +141,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) spin_lock(&old->lock); fs->root = old->root; path_get(&fs->root); @@ -46230,7 +46432,7 @@ index 5df4775..9d9336f 100644 fs->pwd = old->pwd; path_get(&fs->pwd); spin_unlock(&old->lock); -@@ -139,8 +160,9 @@ int unshare_fs_struct(void) +@@ -139,8 +162,9 @@ int unshare_fs_struct(void) task_lock(current); spin_lock(&fs->lock); @@ -46241,7 +46443,7 @@ index 5df4775..9d9336f 100644 spin_unlock(&fs->lock); task_unlock(current); -@@ -153,13 +175,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); +@@ -153,13 +177,13 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct); int current_umask(void) { @@ -46257,7 +46459,15 @@ index 5df4775..9d9336f 100644 .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), .seq = SEQCNT_ZERO, .umask = 0022, -@@ -175,12 +197,13 @@ void daemonize_fs_struct(void) +@@ -169,18 +193,21 @@ void daemonize_fs_struct(void) + { + struct fs_struct *fs = current->fs; + ++ gr_put_exec_file(current); ++ + if (fs) { + int kill; + task_lock(current); spin_lock(&init_fs.lock); @@ -50872,10 +51082,10 @@ index 4e00cf0..3374374 100644 kfree(s); diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig new file mode 100644 -index 0000000..d38b430 +index 0000000..10c36fb --- /dev/null +++ b/grsecurity/Kconfig -@@ -0,0 +1,947 @@ +@@ -0,0 +1,964 @@ +# +# grecurity configuration +# @@ -50938,6 +51148,23 @@ index 0000000..d38b430 + IF YOU USE XFree86. If you use XFree86 and you still want to + protect your kernel against modification, use the RBAC system. + ++config GRKERNSEC_JIT_HARDEN ++ bool "Harden BPF JIT against spray attacks" ++ default y if GRKERNSEC_CONFIG_AUTO ++ depends on BPF_JIT ++ help ++ If you say Y here, the native code generated by the kernel's Berkeley ++ Packet Filter (BPF) JIT engine will be hardened against JIT-spraying ++ attacks that attempt to fit attacker-beneficial instructions in ++ 32bit immediate fields of JIT-generated native instructions. The ++ attacker will generally aim to cause an unintended instruction sequence ++ of JIT-generated native code to execute by jumping into the middle of ++ a generated instruction. This feature effectively randomizes the 32bit ++ immediate constants present in the generated code to thwart such attacks. ++ ++ If you're using KERNEXEC, it's recommended that you enable this option ++ to supplement the hardening of the kernel. ++ +config GRKERNSEC_PROC_MEMMAP + bool "Harden ASLR against information leaks and entropy reduction" + default y if (GRKERNSEC_CONFIG_AUTO || PAX_NOEXEC || PAX_ASLR) @@ -51869,10 +52096,10 @@ index 0000000..1b9afa9 +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..b736032 +index 0000000..4428c82 --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4040 @@ +@@ -0,0 +1,4056 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -55903,6 +56130,22 @@ index 0000000..b736032 + return (obj->mode & GR_FIND) ? 1 : 0; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ struct file *filp; ++ ++ write_lock(&grsec_exec_file_lock); ++ filp = task->exec_file; ++ task->exec_file = NULL; ++ write_unlock(&grsec_exec_file_lock); ++ ++ if (filp) ++ fput(filp); ++ ++ return; ++} ++ ++ +#ifdef CONFIG_NETFILTER_XT_MATCH_GRADM_MODULE +EXPORT_SYMBOL(gr_acl_is_enabled); +#endif @@ -58012,10 +58255,10 @@ index 0000000..9807ee2 +} diff --git a/grsecurity/grsec_disabled.c b/grsecurity/grsec_disabled.c new file mode 100644 -index 0000000..213ad8b +index 0000000..b79fe50 --- /dev/null +++ b/grsecurity/grsec_disabled.c -@@ -0,0 +1,437 @@ +@@ -0,0 +1,442 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -58447,6 +58690,11 @@ index 0000000..213ad8b + return dentry->d_inode->i_sb->s_dev; +} + ++void gr_put_exec_file(struct task_struct *task) ++{ ++ return; ++} ++ +EXPORT_SYMBOL(gr_learn_resource); +EXPORT_SYMBOL(gr_set_kernel_label); +#ifdef CONFIG_SECURITY @@ -62887,10 +63135,10 @@ index 0000000..54f4e85 +#define GR_SYMLINKOWNER_MSG "denied following symlink %.950s since symlink owner %u does not match target owner %u, by " diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h new file mode 100644 -index 0000000..f9b9a21 +index 0000000..187b3ed --- /dev/null +++ b/include/linux/grsecurity.h -@@ -0,0 +1,238 @@ +@@ -0,0 +1,239 @@ +#ifndef GR_SECURITY_H +#define GR_SECURITY_H +#include <linux/fs.h> @@ -63103,6 +63351,7 @@ index 0000000..f9b9a21 +int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode); +void gr_audit_ptrace(struct task_struct *task); +dev_t gr_get_dev_from_dentry(struct dentry *dentry); ++void gr_put_exec_file(struct task_struct *task); + +int gr_ptrace_readexec(struct file *file, int unsafe_flags); + @@ -67384,21 +67633,10 @@ index 7fee567..8affa2c 100644 /* diff --git a/kernel/exit.c b/kernel/exit.c -index f65345f9..9c28dab 100644 +index f65345f9..1423231 100644 --- a/kernel/exit.c +++ b/kernel/exit.c -@@ -59,6 +59,10 @@ - #include <asm/pgtable.h> - #include <asm/mmu_context.h> - -+#ifdef CONFIG_GRKERNSEC -+extern rwlock_t grsec_exec_file_lock; -+#endif -+ - static void exit_mm(struct task_struct * tsk); - - static void __unhash_process(struct task_struct *p, bool group_dead) -@@ -182,6 +186,10 @@ void release_task(struct task_struct * p) +@@ -182,6 +182,10 @@ void release_task(struct task_struct * p) struct task_struct *leader; int zap_leader; repeat: @@ -67409,7 +67647,7 @@ index f65345f9..9c28dab 100644 /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ rcu_read_lock(); -@@ -394,7 +402,7 @@ int allow_signal(int sig) +@@ -394,7 +398,7 @@ int allow_signal(int sig) * know it'll be handled, so that they don't get converted to * SIGKILL or just silently dropped. */ @@ -67418,25 +67656,16 @@ index f65345f9..9c28dab 100644 recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return 0; -@@ -430,6 +438,17 @@ void daemonize(const char *name, ...) +@@ -430,6 +434,8 @@ void daemonize(const char *name, ...) vsnprintf(current->comm, sizeof(current->comm), name, args); va_end(args); -+#ifdef CONFIG_GRKERNSEC -+ write_lock(&grsec_exec_file_lock); -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+ write_unlock(&grsec_exec_file_lock); -+#endif -+ + gr_set_kernel_label(current); + /* * If we were started as result of loading a module, close all of the * user space pages. We don't need them, and if we didn't close them -@@ -907,6 +926,8 @@ void do_exit(long code) +@@ -907,6 +913,8 @@ void do_exit(long code) struct task_struct *tsk = current; int group_dead; @@ -67445,7 +67674,7 @@ index f65345f9..9c28dab 100644 profile_task_exit(tsk); WARN_ON(blk_needs_flush_plug(tsk)); -@@ -923,7 +944,6 @@ void do_exit(long code) +@@ -923,7 +931,6 @@ void do_exit(long code) * mm_release()->clear_child_tid() from writing to a user-controlled * kernel address. */ @@ -67453,7 +67682,7 @@ index f65345f9..9c28dab 100644 ptrace_event(PTRACE_EVENT_EXIT, code); -@@ -982,6 +1002,9 @@ void do_exit(long code) +@@ -982,6 +989,9 @@ void do_exit(long code) tsk->exit_code = code; taskstats_exit(tsk, group_dead); @@ -67463,7 +67692,7 @@ index f65345f9..9c28dab 100644 exit_mm(tsk); if (group_dead) -@@ -1099,7 +1122,7 @@ SYSCALL_DEFINE1(exit, int, error_code) +@@ -1099,7 +1109,7 @@ SYSCALL_DEFINE1(exit, int, error_code) * Take down every thread in the group. This is called by fatal signals * as well as by sys_exit_group (below). */ @@ -83091,7 +83320,7 @@ index 0000000..92ed719 + return 0; +} diff --git a/tools/gcc/generate_size_overflow_hash.sh b/tools/gcc/generate_size_overflow_hash.sh -new file mode 100644 +new file mode 100755 index 0000000..02c6bec --- /dev/null +++ b/tools/gcc/generate_size_overflow_hash.sh @@ -84099,10 +84328,10 @@ index 0000000..b8008f7 +} diff --git a/tools/gcc/size_overflow_hash.data b/tools/gcc/size_overflow_hash.data new file mode 100644 -index 0000000..9332f17 +index 0000000..67468e3 --- /dev/null +++ b/tools/gcc/size_overflow_hash.data -@@ -0,0 +1,3597 @@ +@@ -0,0 +1,3600 @@ +_000001_hash alloc_dr 2 65495 _000001_hash NULL +_000002_hash __copy_from_user 3 10918 _000002_hash NULL +_000003_hash copy_from_user 3 17559 _000003_hash NULL @@ -87700,6 +87929,9 @@ index 0000000..9332f17 +_003894_hash io_mapping_map_wc 2 19284 _003894_hash NULL +_003895_hash nfs_dns_resolve_name 3 25036 _003895_hash NULL +_003896_hash nfs_parse_server_name 2 1899 _003896_hash NULL ++_003897_hash acl_alloc 1 35979 _003897_hash NULL ++_003898_hash acl_alloc_stack_init 1 60630 _003898_hash NULL ++_003899_hash create_table 2 16213 _003899_hash NULL diff --git a/tools/gcc/size_overflow_plugin.c b/tools/gcc/size_overflow_plugin.c new file mode 100644 index 0000000..1aa0dce |