#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/gracl.h>
#include <linux/slab.h>

int grsec_enable_link;
int grsec_enable_dmesg;
int grsec_enable_fifo;
int grsec_enable_execve;
int grsec_enable_execlog;
int grsec_enable_signal;
int grsec_enable_forkfail;
int grsec_enable_time;
int grsec_enable_group;
int grsec_audit_gid;
int grsec_enable_chdir;
int grsec_enable_audit_ipc;
int grsec_enable_mount;
int grsec_enable_chroot_findtask;
int grsec_enable_chroot_mount;
int grsec_enable_chroot_shmat;
int grsec_enable_chroot_fchdir;
int grsec_enable_chroot_double;
int grsec_enable_chroot_pivot;
int grsec_enable_chroot_chdir;
int grsec_enable_chroot_chmod;
int grsec_enable_chroot_mknod;
int grsec_enable_chroot_nice;
int grsec_enable_chroot_execlog;
int grsec_enable_chroot_caps;
int grsec_enable_chroot_sysctl;
int grsec_enable_chroot_unix;
int grsec_enable_tpe;
int grsec_tpe_gid;
int grsec_enable_tpe_all;
int grsec_enable_randpid;
int grsec_enable_randid;
int grsec_enable_randisn;
int grsec_enable_randsrc;
int grsec_enable_randrpc;
int grsec_enable_socket_all;
int grsec_socket_all_gid;
int grsec_enable_socket_client;
int grsec_socket_client_gid;
int grsec_enable_socket_server;
int grsec_socket_server_gid;
int grsec_enable_secure_io;
int grsec_lock;

spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
unsigned long grsec_alert_wtime = 0;
unsigned long grsec_alert_fyet = 0;

spinlock_t grsec_alertgood_lock = SPIN_LOCK_UNLOCKED;
unsigned long grsec_alertgood_wtime = 0;
unsigned long grsec_alertgood_fyet = 0;

spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
spinlock_t grsec_learn_lock = SPIN_LOCK_UNLOCKED;

char *gr_shared_page[NR_CPUS];
extern struct admin_pw *gr_pwent;

void
grsecurity_init(void)
{
	int i;
	/* create the per-cpu shared pages */

	for (i = 0; i < NR_CPUS; i++) {
		gr_shared_page[i] = (char *) get_zeroed_page(GFP_KERNEL);
		if (!gr_shared_page[i]) {
			panic("Unable to allocate grsecurity shared page");
			return;
		}
	}

	/* allocate memory for authentication structure */
	gr_pwent = kmalloc(sizeof(struct admin_pw), GFP_KERNEL);
	if (gr_pwent == NULL) {
		panic("Unable to allocate grsecurity authentication structure");
		return;
	}	

#ifndef CONFIG_GRKERNSEC_SYSCTL
	grsec_lock = 1;
#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
	grsec_enable_group = 1;
	grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
#endif
#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
	grsec_enable_chdir = 1;
#endif
#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
	grsec_enable_audit_ipc = 1;
#endif
#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
	grsec_enable_mount = 1;
#endif
#ifdef CONFIG_GRKERNSEC_LINK
	grsec_enable_link = 1;
#endif
#ifdef CONFIG_GRKERNSEC_DMESG
	grsec_enable_dmesg = 1;
#endif
#ifdef CONFIG_GRKERNSEC_FIFO
	grsec_enable_fifo = 1;
#endif
#ifdef CONFIG_GRKERNSEC_EXECVE
	grsec_enable_execve = 1;
#endif
#ifdef CONFIG_GRKERNSEC_EXECLOG
	grsec_enable_execlog = 1;
#endif
#ifdef CONFIG_GRKERNSEC_SIGNAL
	grsec_enable_signal = 1;
#endif
#ifdef CONFIG_GRKERNSEC_FORKFAIL
	grsec_enable_forkfail = 1;
#endif
#ifdef CONFIG_GRKERNSEC_TIME
	grsec_enable_time = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
	grsec_enable_chroot_findtask = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
	grsec_enable_chroot_unix = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
	grsec_enable_chroot_mount = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
	grsec_enable_chroot_fchdir = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
	grsec_enable_chroot_shmat = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
	grsec_enable_chroot_double = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
	grsec_enable_chroot_pivot = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
	grsec_enable_chroot_chdir = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
	grsec_enable_chroot_chmod = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
	grsec_enable_chroot_mknod = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
	grsec_enable_chroot_nice = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
	grsec_enable_chroot_execlog = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
	grsec_enable_chroot_caps = 1;
#endif
#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
	grsec_enable_chroot_sysctl = 1;
#endif
#ifdef CONFIG_GRKERNSEC_TPE
	grsec_enable_tpe = 1;
	grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
#ifdef CONFIG_GRKERNSEC_TPE_ALL
	grsec_enable_tpe_all = 1;
#endif
#endif
#ifdef CONFIG_GRKERNSEC_RANDPID
	grsec_enable_randpid = 1;
#endif
#ifdef CONFIG_GRKERNSEC_RANDID
	grsec_enable_randid = 1;
#endif
#ifdef CONFIG_GRKERNSEC_RANDISN
	grsec_enable_randisn = 1;
#endif
#ifdef CONFIG_GRKERNSEC_RANDSRC
	grsec_enable_randsrc = 1;
#endif
#ifdef CONFIG_GRKERNSEC_RANDRPC
	grsec_enable_randrpc = 1;
#endif
#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
	grsec_enable_socket_all = 1;
	grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
#endif
#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
	grsec_enable_socket_client = 1;
	grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
#endif
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
	grsec_enable_socket_server = 1;
	grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
#endif
#ifdef CONFIG_GRKERNSEC_IO
	grsec_enable_secure_io = 1;
#endif
#endif

	return;
}
