Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <D6DDBEC5E2802849A9493717C9A419C3E5343C1C@GSjpTK1DCembx17.service.hitachi.net>
Date: Fri, 22 Sep 2017 02:49:59 +0000
From: 中村雄一 / NAKAMURA,YUUICHI
	<yuichi.nakamura.fe@...achi.com>
To: "kernel-hardening@...ts.openwall.com"
	<kernel-hardening@...ts.openwall.com>
CC: "yamauchi@...okayama-u.ac.jp" <yamauchi@...okayama-u.ac.jp>
Subject: [RFC] A method to prevent priviledge escalation 

Hi.

As we said in Linux Security Summit 2017, 
we would like to post a patch to prevent privilege escalation attack.

The concept is here:
http://events.linuxfoundation.org/sites/events/files/slides/nakamura_20170831_1.pdf

This work is still work in progress and feedback is welcomed.
Below patch works for linux-4.4.0, 
To see that it works (try it in a safe place!), 
 * build vulnerable kernel on Ubuntu 16.04.1 
   source: https://launchpad.net/ubuntu/+source/linux/4.4.0-62.83
   please enable "CONFIG_AKO" in kernel config.
 * try a poc code for kernel vulnerability
   https://github.com/xairy/kernel-exploits/blob/master/CVE-2017-6074/poc.c
 * look at kernel log, you can see a log that it detected attack like below:
 AKO: detected unauthorized change of UID. syscall=45 original: uid=1000, euid=1000, fsuid=1000, suid=1000 attempt: uid=0, euid=0, fsuid=0, suid=0
 AKO: detected unauthorized change of gid. syscall=45 original: gid=1000, egid=1000, fsgid=1000, sgid=1000 attempt: gid=0, egid=0, fsgid=0, sgid=0

Regards,
Yuichi Nakamura, Hitachi,Ltd.
Toshihiro Yamauchi, Okayama University

--- linux-4.4.0-62-83.orig/arch/x86/kernel/ako.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-4.4.0/arch/x86/kernel/ako.c	2017-07-02 17:43:15.780000000 +0900
@@ -0,0 +1,55 @@
+/*
+ * Additional Kernel Observer (AKO)
+ *   CPU specific part
+ * Copyright 2017 Okayama-University
+ *     Yohei Akao, Yamauchi Laboratory
+ * Copyright 2017 Hitachi,Ltd.
+ *     Yuichi Nakamura
+ */
+
+#include <linux/cred.h>
+#include <linux/printk.h>
+#include <linux/ako.h>
+
+asmlinkage void AKO_before(struct ako_struct * ako_cred, unsigned long long ako_sysnum)
+{
+        /* Called at the entry of system calls,
+           credential data are saved to detect priviledge escalation attacks
+           that exploit vulnerabilites of system calls.
+        */
+
+       /*save system call number*/
+        ako_cred->ako_sysnum = ako_sysnum;
+
+	/*System calls that change credential are skipped*/	
+	if(!AKO_syscall_checked(ako_sysnum))
+		return;
+
+	/*credential data are saved*/
+        AKO_save_creds(ako_cred,ako_sysnum);
+	/*addr_limit is saved*/
+	ako_cred->ako_addr_limit = current_thread_info()->addr_limit.seg;
+
+}
+
+
+asmlinkage void AKO_after(struct ako_struct * ako_cred)
+{
+	/*System calls that change credential are skipped*/	
+	if(!AKO_syscall_checked(ako_cred->ako_sysnum))
+		return;
+
+	/*check addr_limit, restore if changed*/
+/*        if(current_thread_info()->addr_limit.seg != ako_cred->ako_addr_limit){
+		audit_AKO_rlimit(ako_cred, current_thread_info()->addr_limit.seg); 
+                current_thread_info()->addr_limit.seg = ako_cred->ako_addr_limit;
+		audit_AKO_restore(ako_cred, "addr_limit");
+                return ;
+        } */
+
+	/*check credentials, and restore if changed*/
+        AKO_check_creds(ako_cred);
+
+        return;
+}
+
--- linux-4.4.0-62-83.orig/kernel/ako.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-4.4.0/kernel/ako.c	2017-07-03 23:06:54.068000000 +0900
@@ -0,0 +1,389 @@
+/*
+ * Additional Kernel Observer (AKO)
+ *  Common features
+ * Copyright 2017 Okayama-University
+ *     Yohei Akao, Yamauchi Laboratory
+ * Copyright 2017 Hitachi,Ltd.
+ *     Yuichi Nakamura
+ */
+
+#include <linux/printk.h>
+#include <linux/cred.h>
+#include <linux/syscalls.h>
+#include <linux/ako.h>
+
+#include <linux/audit.h>
+#include <uapi/linux/audit.h>
+#include "audit.h"
+
+void audit_AKO_rlimit(struct ako_struct * ako_cred, unsigned long current_addr_limit) {
+	/*This is called from arch/xx/ako.c*/
+	struct audit_buffer *ab;
+
+	printk(KERN_INFO "AKO: detected unauthorized change of addr_limit: syscall=%u original: 0x%lx, attempt: 0x%lx", ako_cred->ako_sysnum, ako_cred->ako_addr_limit,current_addr_limit);
+        if(!audit_enabled) {
+                return;
+        }
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SYSCALL);
+	if (unlikely(!ab))
+		return;
+
+	audit_log_format(ab, "AKO: detected unauthorized change of addr_limit: syscall=%u original: 0x%lx, attempt: 0x%lx", ako_cred->ako_sysnum, ako_cred->ako_addr_limit,current_addr_limit);
+        audit_log_d_path_exe(ab, current->mm);
+        audit_log_end(ab);
+	return; 
+}
+
+void audit_AKO_restore(struct ako_struct * ako_cred, const char * cred_type)
+{
+	struct audit_buffer *ab;
+	
+	printk(KERN_INFO "AKO: restored credential:%s syscall=%u", cred_type, ako_cred->ako_sysnum);
+	if(!audit_enabled) {
+		return;
+	}
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SYSCALL);
+        if (unlikely(!ab))
+                return;
+
+	audit_log_format(ab, "AKO: restored credential:%s syscall=%u", cred_type,
+	ako_cred->ako_sysnum);
+	
+	audit_log_d_path_exe(ab, current->mm);
+ 	audit_log_end(ab);
+}
+
+static void audit_AKO_uid(struct ako_struct * ako_cred)
+{
+        struct audit_buffer *ab;
+        const struct cred *ccred;
+        ccred = current->cred;
+
+	printk(KERN_INFO "AKO: detected unauthorized change of UID. syscall=%u original: uid=%u, euid=%u, fsuid=%u, suid=%u attempt: uid=%u, euid=%u, fsuid=%u, suid=%u", ako_cred->ako_sysnum, 
+	ako_cred->ako_uid, ako_cred->ako_euid, ako_cred->ako_fsuid, ako_cred->ako_suid, 
+	ccred->uid.val, ccred->euid.val, current_fsuid().val, ccred->suid.val);
+
+	if(!audit_enabled) {
+ 		return;
+	}
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SYSCALL);
+	if (unlikely(!ab))
+		return;
+	audit_log_format(ab, "AKO: detected unauthorized change of UID. syscall=%u original: uid=%u, euid=%u, fsuid=%u, suid=%u attempt: uid=%u, euid=%u, fsuid=%u, suid=%u", ako_cred->ako_sysnum,
+	ako_cred->ako_uid, ako_cred->ako_euid, ako_cred->ako_fsuid, ako_cred->ako_suid,
+	ccred->uid.val, ccred->euid.val, ccred->fsuid.val, ccred->suid.val);
+
+        audit_log_d_path_exe(ab, current->mm);
+        audit_log_end(ab);
+
+        return;
+}
+
+static void audit_AKO_gid(struct ako_struct * ako_cred)
+{
+        struct audit_buffer *ab;
+        const struct cred *ccred;
+        ccred = current->cred;
+
+        printk(KERN_INFO "AKO: detected unauthorized change of gid. syscall=%u original: gid=%u, egid=%u, fsgid=%u, sgid=%u attempt: gid=%u, egid=%u, fsgid=%u, sgid=%u", ako_cred->ako_sysnum,
+        ako_cred->ako_gid, ako_cred->ako_egid, ako_cred->ako_fsgid, ako_cred->ako_sgid,
+        ccred->gid.val, ccred->egid.val, ccred->fsgid.val, ccred->sgid.val);
+
+        if(!audit_enabled) {
+                return;
+        }
+
+        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SYSCALL);
+        if (unlikely(!ab))
+                return;
+        audit_log_format(ab, "AKO: detected unauthorized change of gid. syscall=%u original: gid=%u, egid=%u, fsgid=%u, sgid=%u attempt: gid=%u, egid=%u, fsgid=%u, sgid=%u", ako_cred->ako_sysnum,
+        ako_cred->ako_gid, ako_cred->ako_egid, ako_cred->ako_fsgid, ako_cred->ako_sgid,
+        ccred->gid.val, ccred->egid.val, ccred->fsgid.val, ccred->sgid.val);
+
+        audit_log_d_path_exe(ab, current->mm);
+        audit_log_end(ab);
+
+        return;
+}
+
+static void audit_AKO_cap(struct ako_struct * ako_cred)
+{
+	struct audit_buffer *ab;
+	const struct cred *ccred;
+	ccred = current->cred;
+
+	 printk(KERN_INFO "AKO: detected unauthorized change of capability. syscall=%u original: inh[0]=%u inh[1]=%u per[0]=%u per[1]=%u eff[0]=%u eff[1]%u bset[0]=%u bset[1]=%u attempt: inh[0]=%u inh[1]=%u per[0]=%u per[1]=%u eff[0]=%u eff[1]%u bset[0]=%u bset[1]=%u",
+	ako_cred->ako_sysnum,
+	ako_cred->ako_inheritable[0], ako_cred->ako_inheritable[1],
+	ako_cred->ako_permitted[0], ako_cred->ako_permitted[1],
+	ako_cred->ako_effective[0], ako_cred->ako_effective[1],
+       	ako_cred->ako_bset[0], ako_cred->ako_bset[1],
+	ccred->cap_inheritable.cap[0], ccred->cap_inheritable.cap[1],
+	ccred->cap_permitted.cap[0], ccred->cap_permitted.cap[1],
+	ccred->cap_effective.cap[0], ccred->cap_effective.cap[1],
+	ccred->cap_bset.cap[0], ccred->cap_bset.cap[1]);
+
+	if (!audit_enabled)
+		return;
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SYSCALL);
+	if (unlikely(!ab))
+		return;
+
+	audit_log_format(ab, "AKO: detected unauthorized change of capability. syscall=%u original: inh[0]=%u inh[1]=%u per[0]=%u per[1]=%u eff[0]=%u eff[1]%u bset[0]=%u bset[1]=%u attempt: inh[0]=%u inh[1]=%u per[0]=%u per[1]=%u eff[0]=%u eff[1]%u bset[0]=%u bset[1]=%u", 
+	ako_cred->ako_sysnum, 
+	ako_cred->ako_inheritable[0], ako_cred->ako_inheritable[1],
+	ako_cred->ako_permitted[0], ako_cred->ako_permitted[1], 
+ 	ako_cred->ako_effective[0], ako_cred->ako_effective[1],
+ 	ako_cred->ako_bset[0], ako_cred->ako_bset[1],
+	ccred->cap_inheritable.cap[0], ccred->cap_inheritable.cap[1],
+	ccred->cap_permitted.cap[0], ccred->cap_permitted.cap[1],
+	ccred->cap_effective.cap[0], ccred->cap_effective.cap[1],
+	ccred->cap_bset.cap[0], ccred->cap_bset.cap[1]);
+
+	audit_log_d_path_exe(ab, current->mm);
+	audit_log_end(ab);
+
+	return;
+}
+
+
+
+void AKO_save_creds(struct ako_struct * ako_cred, int ako_sysnum)
+{
+
+        /*Save credential information to be observed */
+        /*UID and GID*/
+        ako_cred->ako_uid = current->cred->uid.val;
+        ako_cred->ako_euid = current->cred->euid.val;
+        ako_cred->ako_fsuid = current->cred->fsuid.val;
+        ako_cred->ako_suid = current->cred->suid.val;
+        ako_cred->ako_gid = current->cred->gid.val;
+        ako_cred->ako_egid = current->cred->egid.val;
+        ako_cred->ako_fsgid = current->cred->fsgid.val;
+        ako_cred->ako_sgid = current->cred->sgid.val;
+        /*Capability*/
+        ako_cred->ako_inheritable[0] = current->cred->cap_inheritable.cap[0];
+        ako_cred->ako_inheritable[1] = current->cred->cap_inheritable.cap[1];
+        ako_cred->ako_permitted[0] = current->cred->cap_permitted.cap[0];
+        ako_cred->ako_permitted[1] = current->cred->cap_permitted.cap[1];
+        ako_cred->ako_effective[0] = current->cred->cap_effective.cap[0];
+        ako_cred->ako_effective[1] = current->cred->cap_effective.cap[1];
+        ako_cred->ako_bset[0] = current->cred->cap_bset.cap[0];
+        ako_cred->ako_bset[1] = current->cred->cap_bset.cap[1];
+
+        return;
+}
+
+/*copy from sys.c*/
+static int set_user(struct cred *new)
+{
+	struct user_struct *new_user;
+
+	new_user = alloc_uid(new->uid);
+	if (!new_user)
+		return -EAGAIN;
+
+	/*
+	 * We don't fail in case of NPROC limit excess here because too many
+	 * poorly written programs don't check set*uid() return code, assuming
+	 * it never fails if called by root.  We may still enforce NPROC limit
+	 * for programs doing set*uid()+execve() by harmlessly deferring the
+	 * failure to the execve() stage.
+	 */
+	if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
+			new_user != INIT_USER)
+		current->flags |= PF_NPROC_EXCEEDED;
+	else
+		current->flags &= ~PF_NPROC_EXCEEDED;
+
+	free_uid(new->user);
+	new->user = new_user;
+	return 0;
+}
+
+
+static int AKO_restore_uids(struct ako_struct * ako_cred)
+{
+        struct cred *new;
+        struct user_namespace *ns = current_user_ns();
+        kuid_t uid;
+        kuid_t suid;
+        kuid_t euid;
+        kuid_t fsuid;
+	kernel_cap_t effective, permitted;
+        
+	new = prepare_creds();
+        if (!new)
+                return -ENOMEM;
+
+        uid = make_kuid(ns, ako_cred->ako_uid);
+        if (!uid_valid(uid))
+                return -EINVAL;
+        suid = make_kuid(ns, ako_cred->ako_suid);
+        if (!uid_valid(suid))
+                return -EINVAL;
+        euid = make_kuid(ns, ako_cred->ako_euid);
+        if (!uid_valid(euid))
+                return -EINVAL;
+        fsuid = make_kuid(ns, ako_cred->ako_fsuid);
+        if (!uid_valid(fsuid))
+                return -EINVAL;
+        new->uid = uid;
+        new->suid = suid;
+        new->euid = euid;
+        new->fsuid = fsuid;
+
+	/*clear capabilities*/
+	effective.cap[0] = 0;
+	effective.cap[1] = 0;
+	permitted.cap[0] = 0;
+	permitted.cap[1] = 0;
+	new->cap_effective  = effective;
+	new->cap_permitted  = permitted;
+
+	set_user(new);
+        commit_creds(new);
+        return 0;
+}
+
+static int AKO_restore_gids(struct ako_struct * ako_cred)
+{
+        struct cred *new;
+        struct user_namespace *ns = current_user_ns();
+        kgid_t gid;
+        kgid_t sgid;
+        kgid_t egid;
+        kgid_t fsgid;
+	kernel_cap_t effective, permitted;
+
+        new = prepare_creds();
+        if (!new)
+                return -ENOMEM;
+
+        gid = make_kgid(ns, ako_cred->ako_gid);
+        if (!gid_valid(gid))
+                return -EINVAL;
+        sgid = make_kgid(ns, ako_cred->ako_sgid);
+        if (!gid_valid(sgid))
+                return -EINVAL;
+        egid = make_kgid(ns, ako_cred->ako_egid);
+        if (!gid_valid(egid))
+                return -EINVAL;
+        fsgid = make_kgid(ns, ako_cred->ako_fsgid);
+        if (!gid_valid(fsgid))
+                return -EINVAL;
+        new->gid = gid;
+        new->sgid = sgid;
+        new->egid = egid;
+        new->fsgid = fsgid;
+
+        /*clear capabilities*/
+	effective.cap[0] = 0;
+	effective.cap[1] = 0;
+	permitted.cap[0] = 0;
+	permitted.cap[1] = 0;
+	new->cap_effective  = effective;
+	new->cap_permitted  = permitted;
+
+        commit_creds(new);
+
+        return 0;
+}
+static int AKO_restore_caps(struct ako_struct * ako_cred)
+{
+        struct cred *new;
+        kernel_cap_t inheritable, permitted, effective, bset;
+        unsigned i;
+        new = prepare_creds();
+        if (!new)
+                return -ENOMEM;
+
+        for (i = 0; i<2; i++) {
+                inheritable.cap[i] = ako_cred->ako_inheritable[i];
+                permitted.cap[i] = ako_cred->ako_permitted[i];
+                effective.cap[i] = ako_cred->ako_effective[i];
+                bset.cap[i] = ako_cred->ako_bset[i];
+        }
+
+        new->cap_effective   = effective;
+        new->cap_inheritable = inheritable;
+        new->cap_permitted   = permitted;
+        new->cap_bset   = bset;
+
+        commit_creds(new);
+
+        return 0;
+}
+
+inline int AKO_syscall_checked(int sysnum)
+{
+	 /*Since following system calls change credential information,
+          AKO does not detect attacks for them*/
+
+        if((sysnum == __NR_execve)   || (sysnum == __NR_setuid)    || (sysnum == __NR_setgid)    || (sysnum == __NR_setreuid) ||
+           (sysnum == __NR_setregid) || (sysnum == __NR_setresuid) || (sysnum == __NR_setresgid) || (sysnum == __NR_setfsuid) ||
+           (sysnum == __NR_setfsgid) || (sysnum == __NR_capset)    || (sysnum == __NR_prctl) || (sysnum == __NR_unshare)  ){
+                return 0;
+        }
+	return 1;
+
+}
+
+void AKO_check_creds(struct ako_struct * ako_cred)
+{
+        /*Called at the exit of system call */
+        /*Compare credntial information before the systemcall
+          if changed, the information is restored and logged*/
+	int uid_modified = 0;
+	int gid_modified = 0;
+ 	int cap_modified = 0;	
+
+        /*check uids*/
+        if(ako_cred->ako_uid != current->cred->uid.val || ako_cred->ako_euid != current->cred->euid.val || ako_cred->ako_fsuid != current->cred->fsuid.val ||
+           ako_cred->ako_suid != current->cred->suid.val){
+		audit_AKO_uid(ako_cred);
+		uid_modified = 1;
+        }
+
+	/*Check gids*/
+        if(ako_cred->ako_gid != current->cred->gid.val || ako_cred->ako_egid != current->cred->egid.val || ako_cred->ako_fsgid != current->cred->fsgid.val ||
+           ako_cred->ako_sgid != current->cred->sgid.val){
+		audit_AKO_gid(ako_cred);
+		gid_modified = 1;		
+        }
+	/*Check capabilities*/
+        if(ako_cred->ako_inheritable[0] != current->cred->cap_inheritable.cap[0] || ako_cred->ako_inheritable[1] != current->cred->cap_inheritable.cap[1] ||
+           ako_cred->ako_permitted[0]   != current->cred->cap_permitted.cap[0]   || ako_cred->ako_permitted[1]   != current->cred->cap_permitted.cap[1]   ||
+           ako_cred->ako_effective[0]   != current->cred->cap_effective.cap[0]   || ako_cred->ako_effective[1]   != current->cred->cap_effective.cap[1]   ||
+           ako_cred->ako_bset[0]        != current->cred->cap_bset.cap[0]        || ako_cred->ako_bset[1]        != current->cred->cap_bset.cap[1] ){
+		audit_AKO_cap(ako_cred);
+		cap_modified = 1;
+        }
+
+	/*restore creds if modified*/
+	if (uid_modified) {
+		/*Restore uids*/
+               if(!AKO_restore_uids(ako_cred))
+                        audit_AKO_restore(ako_cred,"uids");
+                else
+                        do_exit(SIGKILL);
+
+	}
+	if (gid_modified) {
+                /*Restore gids*/
+                if(!AKO_restore_gids(ako_cred))
+                        audit_AKO_restore(ako_cred,"gids");
+                else
+                        do_exit(SIGKILL);
+	}
+	if (cap_modified) {
+		/*restore capabilities*/
+		if(!AKO_restore_caps(ako_cred))
+			audit_AKO_restore(ako_cred,"capabilities");
+		else
+			do_exit(SIGKILL);
+	}
+
+        return;
+}
--- linux-4.4.0-62-83.orig/include/linux/ako.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-4.4.0/include/linux/ako.h	2017-07-04 22:33:45.188000000 +0900
@@ -0,0 +1,35 @@
+#ifndef __LINUX__AKO_H
+#define __LINUX__AKO_H
+/*
+ * Additional Kernel Observer (AKO)
+ * Copyright (c) 2017 Okayama-University
+ *     Yohei Akao, Yamauchi Laboratory, Okayama University
+ * Copyright (c) 2017 Hitachi,Ltd.
+ *	Yuichi Nakamura
+ */
+
+struct ako_struct{
+int ako_sysnum;
+/*Credential information to be observed*/
+unsigned long ako_addr_limit;
+uid_t  ako_uid;
+uid_t  ako_euid;
+uid_t  ako_fsuid;
+uid_t  ako_suid;
+gid_t  ako_gid;
+gid_t  ako_egid;
+gid_t  ako_fsgid;
+gid_t  ako_sgid;
+__u32  ako_inheritable[2];
+__u32  ako_permitted[2];
+__u32  ako_effective[2];
+__u32  ako_bset[2];
+};
+extern void AKO_save_creds(struct ako_struct * ako_cred, int ako_sysnum);
+extern void AKO_check_creds(struct ako_struct * ako_cred);
+extern void AKO_save_addr_limit(struct ako_struct * ako_cred);
+extern int AKO_syscall_checked(int sysnum);
+extern void audit_AKO_rlimit(struct ako_struct * ako_cred, unsigned long current_addr_limit);
+extern void audit_AKO_restore(struct ako_struct * ako_cred, const char * cred_type);
+
+#endif
--- linux-4.4.0-62-83.orig/kernel/Makefile	2017-06-18 14:33:57.240000000 +0900
+++ linux-4.4.0/kernel/Makefile	2017-07-04 22:29:00.004000000 +0900
@@ -13,6 +13,8 @@
 
 obj-$(CONFIG_MULTIUSER) += groups.o
 
+obj-$(CONFIG_AKO) += ako.o
+
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace debug files and internal ftrace files
 CFLAGS_REMOVE_cgroup-debug.o = $(CC_FLAGS_FTRACE)
--- linux-4.4.0-62-83.orig/arch/x86/kernel/Makefile	2017-06-18 14:34:04.180000000 +0900
+++ linux-4.4.0/arch/x86/kernel/Makefile	2017-07-04 22:16:11.372000000 +0900
@@ -23,6 +23,7 @@
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y			:= process_$(BITS).o signal.o
+obj-$(CONFIG_AKO)	+= ako.o
 obj-$(CONFIG_COMPAT)	+= signal_compat.o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time.o ioport.o dumpstack.o nmi.o
--- linux-4.4.0-62-83.orig/init/Kconfig	2017-06-18 14:33:57.236000000 +0900
+++ linux-4.4.0/init/Kconfig	2017-07-04 22:14:43.080000000 +0900
@@ -333,6 +333,17 @@
 	depends on AUDITSYSCALL
 	select FSNOTIFY
 
+config HAVE_ARCH_AKO
+        bool
+
+config AKO
+        bool "Enable Additional Kernel Observer (AKO)" 
+        depends on AUDIT && HAVE_ARCH_AKO
+        help
+          AKO detects and prevents priviledge escalation attacks 
+          that exploit vulnerabilities of kernel
+
+
 source "kernel/irq/Kconfig"
 source "kernel/time/Kconfig"
 
--- linux-4.4.0-62-83.orig/arch/x86/Kconfig	2017-06-18 14:34:03.924000000 +0900
+++ linux-4.4.0/arch/x86/Kconfig	2017-07-06 12:27:26.692000000 +0900
@@ -76,6 +76,7 @@
 	select HAVE_ACPI_APEI_NMI		if ACPI
 	select HAVE_ALIGNED_STRUCT_PAGE		if SLUB
 	select HAVE_AOUT			if X86_32
+	select HAVE_ARCH_AKO			if X86_64
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_HUGE_VMAP		if X86_64 || X86_PAE
 	select HAVE_ARCH_JUMP_LABEL
--- linux-4.4.0-62-83.orig/arch/x86/entry/entry_64.S	2017-06-18 14:34:04.008000000 +0900
+++ linux-4.4.0/arch/x86/entry/entry_64.S	2017-07-01 23:07:43.824000000 +0900
@@ -182,9 +182,43 @@
 #endif
 	ja	1f				/* return -ENOSYS (already in pt_regs->ax) */
 	movq	%r10, %rcx
+/*
+ * Additional Kernel Observer (AKO)
+ * Copyright (c) 2017 Okayama-University
+ *     Yohei Akao, Yamauchi Laboratory, Okayama University
+ */
+	subq	$6144,%rsp /*Allocate area in stack to save credential information*/
+	ALLOC_PT_GPREGS_ON_STACK
+	SAVE_C_REGS
+	SAVE_EXTRA_REGS
+	leaq	15*8(%rsp), %rdi /* size of SAVE_C_REGS and size of SAVE_EXTRA_REGS is added to rsp, and start address of allocated area is saved in %rdi*/
+	movq	%rax, %rsi /* Syscall number(%rax) is saved in %rsi */
+	call AKO_before /*credential information is saved*/
+	RESTORE_EXTRA_REGS
+	RESTORE_C_REGS
+	REMOVE_PT_GPREGS_FROM_STACK
+	addq	$6144,%rsp /*Allocate area in stack to save credential information*/
+	/*end of AKO*/
 	call	*sys_call_table(, %rax, 8)
+/*
+ * Additional Kernel Observer (AKO)
+ * Copyright (c) 2017 Okayama-University
+ *     Yohei Akao, Yamauchi Laboratory, Okayama University
+ */
+	/*Start of AKO*/
+	subq	$6144,%rsp
+	ALLOC_PT_GPREGS_ON_STACK
+	SAVE_C_REGS
+	SAVE_EXTRA_REGS
+	leaq	15*8(%rsp), %rdi
+	call AKO_after
+	RESTORE_EXTRA_REGS
+	RESTORE_C_REGS
+	REMOVE_PT_GPREGS_FROM_STACK
+	/*Free area to store credential infomation*/
+	addq	$6144,%rsp
+	/*End of AKO*/
 	movq	%rax, RAX(%rsp)
-1:
 /*
  * Syscall return path ending with SYSRET (fast path).
  * Has incompletely filled pt_regs.

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.