Created
January 9, 2011 08:37
-
-
Save hiromu/771537 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 8878b67615739dc52a96031d75185fda16f9d294 Mon Sep 17 00:00:00 2001 | |
From: Hiromu Yakura <hiromu1996@gmail.com> | |
Date: Sun, 9 Jan 2011 17:26:55 +0900 | |
Subject: [PATCH] Add: sys_brainfuck(): This is interpreter of brainfuck. | |
--- | |
arch/arm/include/asm/unistd.h | 1 + | |
arch/arm/kernel/calls.S | 2 +- | |
include/linux/syscalls.h | 4 +- | |
kernel/Makefile | 2 +- | |
kernel/brainfuck.c | 135 +++++++++++++++++++++++++++++++++++++++++ | |
5 files changed, 141 insertions(+), 3 deletions(-) | |
create mode 100644 kernel/brainfuck.c | |
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h | |
index 0106184..f03110d 100644 | |
--- a/arch/arm/include/asm/unistd.h | |
+++ b/arch/arm/include/asm/unistd.h | |
@@ -249,6 +249,7 @@ | |
#define __NR_fcntl64 (__NR_SYSCALL_BASE+221) | |
/* 222 for tux */ | |
/* 223 is unused */ | |
+#define __NR_brainfuck (__NR_SYSCALL_BASE+223) | |
#define __NR_gettid (__NR_SYSCALL_BASE+224) | |
#define __NR_readahead (__NR_SYSCALL_BASE+225) | |
#define __NR_setxattr (__NR_SYSCALL_BASE+226) | |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S | |
index 9ca8d13..c391ada 100644 | |
--- a/arch/arm/kernel/calls.S | |
+++ b/arch/arm/kernel/calls.S | |
@@ -232,7 +232,7 @@ | |
/* 220 */ CALL(sys_madvise) | |
CALL(ABI(sys_fcntl64, sys_oabi_fcntl64)) | |
CALL(sys_ni_syscall) /* TUX */ | |
- CALL(sys_ni_syscall) | |
+ CALL(sys_brainfuck) | |
CALL(sys_gettid) | |
/* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead)) | |
CALL(sys_setxattr) | |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h | |
index f9f900c..8ea1a4f 100644 | |
--- a/include/linux/syscalls.h | |
+++ b/include/linux/syscalls.h | |
@@ -691,7 +691,9 @@ asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, | |
size_t); | |
asmlinkage long sys_pipe2(int __user *, int); | |
asmlinkage long sys_pipe(int __user *); | |
- | |
+asmlinkage long sys_brainfuck(char *source_user, char *input_user, | |
+ char *output_user, unsigned int source_len, | |
+ unsigned int input_len, unsigned int output_len); | |
int kernel_execve(const char *filename, char *const argv[], char *const envp[]); | |
#endif | |
diff --git a/kernel/Makefile b/kernel/Makefile | |
index e4791b3..79de1a1 100644 | |
--- a/kernel/Makefile | |
+++ b/kernel/Makefile | |
@@ -10,7 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ | |
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | |
hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | |
notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ | |
- async.o | |
+ async.o brainfuck.o | |
ifdef CONFIG_FUNCTION_TRACER | |
# Do not trace debug files and internal ftrace files | |
diff --git a/kernel/brainfuck.c b/kernel/brainfuck.c | |
new file mode 100644 | |
index 0000000..ac4ac24 | |
--- /dev/null | |
+++ b/kernel/brainfuck.c | |
@@ -0,0 +1,135 @@ | |
+#include <linux/errno.h> | |
+#include <linux/kernel.h> | |
+#include <linux/unistd.h> | |
+#include <linux/slab.h> | |
+#include <linux/syscalls.h> | |
+#include <asm/uaccess.h> | |
+ | |
+#define MEMORY_UNIT unsigned char | |
+#define BF_MEMORY_SIZE 30000 | |
+ | |
+SYSCALL_DEFINE6(brainfuck, char *, source_user, char *, input_user, | |
+ char *, output_user, unsigned int, source_len, | |
+ unsigned int, input_len, unsigned int, output_len) | |
+{ | |
+ int ptr = 0, len = 0, len2 = 0, i, count; | |
+ MEMORY_UNIT *mem; | |
+ char *source, *input, *output; | |
+ printk(KERN_DEBUG "sys_brainfuck: Hello. This is brainfuck interpriter.\n"); | |
+ | |
+ mem = (char *)kmalloc(sizeof(MEMORY_UNIT) * BF_MEMORY_SIZE, GFP_KERNEL); | |
+ if(mem == NULL) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't allocate memory.\n"); | |
+ return -ENOMEM; | |
+ } | |
+ memset(mem, 0, sizeof(mem)); | |
+ | |
+ source = (char *)kmalloc(sizeof(char) * source_len, GFP_KERNEL); | |
+ if(source == NULL) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't allocate memory.\n"); | |
+ return -ENOMEM; | |
+ } | |
+ if(copy_from_user(source, source_user, sizeof(char) * source_len)) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't copy source code.\n"); | |
+ return -EFAULT; | |
+ } | |
+ | |
+ input = (char *)kmalloc(sizeof(char) * input_len, GFP_KERNEL); | |
+ if(input == NULL) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't allocate memory.\n"); | |
+ return -ENOMEM; | |
+ } | |
+ if(copy_from_user(input, input_user, sizeof(char) * input_len)) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't copy input string.\n"); | |
+ return -EFAULT; | |
+ } | |
+ | |
+ output = (char *)kmalloc(sizeof(char) * output_len, GFP_KERNEL); | |
+ if(input == NULL) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't allocate memory.\n"); | |
+ return -ENOMEM; | |
+ } | |
+ | |
+ for(i = 0; i < source_len; i++) { | |
+ if(source[i] == '>') { | |
+ if(ptr >= BF_MEMORY_SIZE) { | |
+ printk(KERN_ERR "sys_brainfuck: Memory pointer is too large.\n"); | |
+ return -EFAULT; | |
+ } | |
+ ptr++; | |
+ } else if(source[i] == '<') { | |
+ if(ptr <= 0) { | |
+ printk(KERN_ERR "sys_brainfuck: Memory pointer is negative.\n"); | |
+ return -EFAULT; | |
+ } | |
+ ptr--; | |
+ } else if(source[i] == '+') { | |
+ if(mem[ptr] >= 255) { | |
+ printk(KERN_ERR "sys_brainfuck: Value is too large.\n"); | |
+ return -ERANGE; | |
+ } | |
+ mem[ptr]++; | |
+ } else if(source[i] == '-') { | |
+ if(mem[ptr] <= 0) { | |
+ printk(KERN_ERR "sys_brainfuck: Value is too small.\n"); | |
+ return -ERANGE; | |
+ } | |
+ mem[ptr]--; | |
+ } else if(source[i] == '.') { | |
+ if(len >= output_len - 1) { | |
+ printk(KERN_ERR "sys_brainfuck: Output is too large.\n"); | |
+ return -ERANGE; | |
+ } | |
+ output[len] = mem[ptr]; | |
+ len++; | |
+ } else if(source[i] == ',') { | |
+ if(len2 >= input_len - 1) { | |
+ printk(KERN_ERR "sys_brainfuck: Input is too short.\n"); | |
+ return -ERANGE; | |
+ } | |
+ mem[ptr] = input[len2]; | |
+ len2++; | |
+ } else if(source[i] == '[') { | |
+ if(!mem[ptr]) { | |
+ count = 1; | |
+ while(1) { | |
+ i++; | |
+ if(source[i] == '[') { | |
+ count++; | |
+ } else if(source[i] == ']') { | |
+ count--; | |
+ if(!count) | |
+ break; | |
+ } else if(i >= source_len - 2) { | |
+ printk(KERN_ERR "sys_brainfuck: Source code is wrong.\n"); | |
+ return -ERANGE; | |
+ } | |
+ } | |
+ } | |
+ } else if(source[i] == ']') { | |
+ count = 1; | |
+ while(1) { | |
+ i--; | |
+ if(source[i] == ']') { | |
+ count++; | |
+ } else if(source[i] == '[') { | |
+ count--; | |
+ if(!count) | |
+ break; | |
+ } else if(i <= 0) { | |
+ printk(KERN_ERR "sys_brainfuck: Source code is wrong.\n"); | |
+ return -ERANGE; | |
+ } | |
+ } | |
+ i--; | |
+ } | |
+ } | |
+ | |
+ output[len] = '\0'; | |
+ printk(KERN_DEBUG "sys_brainfuck: %s\n", output); | |
+ if(copy_to_user(output_user, output, sizeof(char) * (len + 1))) { | |
+ printk(KERN_ERR "sys_brainfuck: Can't copy output.\n"); | |
+ return -EFAULT; | |
+ } | |
+ return 0; | |
+} | |
-- | |
1.7.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment