Skip to content

Instantly share code, notes, and snippets.

@hiromu
Created January 9, 2011 08:37
Show Gist options
  • Save hiromu/771537 to your computer and use it in GitHub Desktop.
Save hiromu/771537 to your computer and use it in GitHub Desktop.
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