diff --git a/Dockerfile b/Dockerfile
index dd56d201d37704b134996beea1b08f21a8500352..1066c2c8841a23dc7cb0ecdedd4863a0433f72e7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,13 @@
 FROM gitlab.cs.pub.ro:5050/so2/so2-assignments
 
 RUN echo "Hello from Docker"
+RUN mkdir -p /linux/tools/labs/skels/assignments/0-list
+RUN mkdir -p /linux/tools/labs/skels/assignments/0-list-checker
+
+COPY ./checker/0-list-checker /linux/tools/labs/skels/assignments/0-list-checker
+
+COPY ./checker/checker_daemons/so2_vm_checker_daemon.sh /linux/tools/labs/rootfs/etc/init.d
+RUN chmod +x /linux/tools/labs/rootfs/etc/init.d/so2_vm_checker_daemon.sh
+RUN chroot /linux/tools/labs/rootfs update-rc.d so2_vm_checker_daemon.sh defaults
 
 COPY ./checker ${CHECKER_DATA_DIRECTORY}
diff --git a/checker/0-list-checker/_checker b/checker/0-list-checker/_checker
new file mode 100644
index 0000000000000000000000000000000000000000..4f15f8846818ad6c85ae1f1b237de403fdf41b7b
--- /dev/null
+++ b/checker/0-list-checker/_checker
@@ -0,0 +1,775 @@
+#!/bin/sh
+
+#
+# List kernel API checker
+#
+#
+
+# Enable/disable debug (1/0).
+DEBUG_=1
+
+DEBUG()
+{
+    if test "x$DEBUG_" = "x1"; then
+        $@ 1>&2
+    fi
+}
+
+max_points=90
+
+# Enable/disable exiting when program fails.
+EXIT_IF_FAIL=0
+
+test_do_fail()
+{
+    points=$1
+    printf "failed  [00/%02d]\n" "$max_points"
+    if test "x$EXIT_IF_FAIL" = "x1"; then
+        exit 1
+    fi
+}
+
+test_do_pass()
+{
+    points=$1
+    printf "passed  [%02d/%02d]\n" "$points" "$max_points"
+}
+
+basic_test()
+{
+    message=$1
+    points=$2
+    shift 2
+    test_command=$@
+
+    printf "%s" "$message"
+
+    i=0
+    limit=$((60 - ${#message}))
+    while test "$i" -lt "$limit"; do
+        printf "."
+        i=$(($i+1))
+    done
+
+    $test_command > /dev/null 2>&1
+    if test $? -eq 0; then
+        test_do_pass "$points"
+    else
+        test_do_fail "$points"
+    fi
+}
+
+module="list"
+module_file="$module".ko
+proc_folder="/proc/list"
+preview="$proc_folder/preview"
+management="$proc_folder/management"
+
+init_test()
+{
+    dmesg -c > /dev/null 2>&1
+    insmod "$module_file"
+    if test $? -ne 0; then
+        echo "Error inserting module." 1>&2
+        exit 1
+    fi
+    sleep 1
+}
+
+cleanup_test()
+{
+    rmmod "$module"
+}
+
+test_module_exists()
+{
+    init_test
+
+    lsmod 2> /dev/null | grep -w list > /dev/null 2>&1
+    basic_test "module_exists" 1 test "$?" -eq 0
+
+    cleanup_test
+}
+
+test_proc_folder_exits()
+{
+    init_test
+
+    basic_test "folder_exists" 1 test -d "$proc_folder"
+
+    cleanup_test
+}
+
+test_preview_exits()
+{
+    init_test
+
+    basic_test "preview_exists" 1 test -f "$preview"
+
+    cleanup_test
+}
+
+test_management_exits()
+{
+    init_test
+
+    basic_test "management_exists" 1 test -f "$management"
+
+    cleanup_test
+}
+
+test_preview_is_readable()
+{
+    init_test
+
+    cat "$preview" > /dev/null 2>&1
+    basic_test "preview_is_readable" 1 test $? -eq 0
+
+    cleanup_test
+}
+
+test_preview_is_not_writable()
+{
+    init_test
+
+    echo "hello" 2>&1 > "$preview" | grep "Input/output error" > /dev/null
+    basic_test "preview_is_not_writable" 1 test $? -eq 0
+
+    cleanup_test
+}
+
+test_management_is_writable()
+{
+    init_test
+
+    echo "hello" 2>&1 > "$management" | grep "Input/output error" > /dev/null
+    basic_test "management_is_writable" 1 test $? -ne 0
+
+    cleanup_test
+}
+
+test_management_is_not_readable()
+{
+    init_test
+
+    cat "$management" > /dev/null 2>&1
+    basic_test "management_is_not_readable" 1 test $? -ne 0
+
+    cleanup_test
+}
+
+test_addf_no_error()
+{
+    init_test
+
+    echo "addf lorem" > "$management" 2> /dev/null
+    basic_test "addf_no_error" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_print()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "addf_print" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_print_once()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    no=$(cat "$preview" | grep "lorem" | wc -l)
+    basic_test "addf_print_once" 2 test "$no" -eq 1
+
+    cleanup_test
+}
+
+test_adde_no_error()
+{
+    init_test
+
+    echo "adde lorem" > "$management" 2> /dev/null
+    basic_test "adde_no_error" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_print()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "adde_print" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_print_once()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    no=$(cat "$preview" | grep "lorem" | wc -l)
+    basic_test "adde_print_once" 2 test "$no" -eq 1
+
+    cleanup_test
+}
+
+test_addf_two_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "addf_two_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_addf_two_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    ret1=$?
+    cat "$preview" | grep "ipsum" > /dev/null
+    ret2=$?
+    basic_test "addf_two_content" 2 test "$ret1" -eq 0 -a "$ret2" -eq 0
+
+    cleanup_test
+}
+
+test_addf_same_twice_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "addf_same_twice_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_addf_same_twice_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "addf_same_twice_content" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_same_twice_content_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf lorem" > "$management"
+    no=$(cat "$preview" | grep "lorem" | wc -l)
+    basic_test "addf_same_twice_content_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_adde_two_number()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "adde_two_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_adde_two_content()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    ret1=$?
+    cat "$preview" | grep "ipsum" > /dev/null
+    ret2=$?
+    basic_test "adde_two_content" 2 test "$ret1" -eq 0 -a "$ret2" -eq 0
+
+    cleanup_test
+}
+
+test_adde_same_twice_number()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "adde_same_twice_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_adde_same_twice_content()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "adde_same_twice_content" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_same_twice_content_number()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde lorem" > "$management"
+    no=$(cat "$preview" | grep "lorem" | wc -l)
+    basic_test "adde_same_twice_content_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_addf_front_after_addf()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+
+    # "ipsum" must be first.
+    cat "$preview" | head -n 1 | grep "ipsum" > /dev/null
+    basic_test "addf_front_after_addf" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_front_after_adde()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "addf ipsum" > "$management"
+
+    # "ipsum" must be first.
+    cat "$preview" | head -n 1 | grep "ipsum" > /dev/null
+    basic_test "addf_front_after_adde" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_front_after_adde_addf()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+
+    # "dolor" must be first.
+    cat "$preview" | head -n 1 | grep "dolor" > /dev/null
+    basic_test "addf_front_after_adde_addf" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_addf_front_after_addf_adde()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "addf dolor" > "$management"
+
+    # "dolor" must be first.
+    cat "$preview" | head -n 1 | grep "dolor" > /dev/null
+    basic_test "addf_front_after_addf_adde" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_end_after_addf()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+
+    # "ipsum" must be last.
+    cat "$preview" | tail -n -1 | grep "ipsum" > /dev/null
+    basic_test "adde_end_after_addf" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_end_after_adde()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "adde ipsum" > "$management"
+
+    # "ipsum" must be last.
+    cat "$preview" | tail -n -1 | grep "ipsum" > /dev/null
+    basic_test "addf_end_after_adde" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_end_after_adde_addf()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "adde dolor" > "$management"
+
+    # "dolor" must be last.
+    cat "$preview" | tail -n -1 | grep "dolor" > /dev/null
+    basic_test "adde_end_after_adde_addf" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_adde_end_after_addf_adde()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "adde dolor" > "$management"
+
+    # "dolor" must be last.
+    cat "$preview" | tail -n -1 | grep "dolor" > /dev/null
+    basic_test "adde_end_after_addf_adde" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_delf_no_error()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "delf lorem" > "$management"
+    basic_test "delf_no_error" 2 test $? -eq 0
+
+    cleanup_test
+}
+
+test_delf_removes_front()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "delf lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "delf_removes_front" 2 test "$no" -eq 0
+
+    cleanup_test
+}
+
+test_delf_removes_end()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "delf lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "delf_removes_end" 2 test "$no" -eq 0
+
+    cleanup_test
+}
+
+test_delf_front_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "delf lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "delf_front_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_delf_front_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "delf lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "delf_front_content" 2 test $? -ne 0
+
+    cleanup_test
+}
+
+test_delf_first()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "delf ipsum" > "$management"
+    cat "$preview" | grep "ipsum" > /dev/null
+    basic_test "delf_first" 2 test $? -ne 0
+
+    cleanup_test
+}
+
+test_delf_none()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "delf dolor" > "$management" 2> /dev/null
+    no=$(cat "$preview" | wc -l)
+    basic_test "delf_none" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_dela_one_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "dela ipsum" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "dela_one_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_dela_one_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "dela ipsum" > "$management"
+    cat "$preview" | grep "ipsum" > /dev/null
+    basic_test "dela_one_content" 2 test $? -ne 0
+
+    cleanup_test
+}
+
+test_dela_two_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "dela ipsum" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "dela_one_number" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_dela_two_content()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "addf dolor" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "dela ipsum" > "$management"
+    cat "$preview" | grep "ipsum" > /dev/null
+    basic_test "dela_one_content" 2 test $? -ne 0
+
+    cleanup_test
+}
+
+test_dela_all_five_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde lorem" > "$management"
+    echo "addf lorem" > "$management"
+    echo "adde lorem" > "$management"
+    echo "addf lorem" > "$management"
+    echo "dela lorem" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "dela_all_five_number" 2 test "$no" -eq 0
+
+    cleanup_test
+}
+
+test_dela_all_five_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde lorem" > "$management"
+    echo "addf lorem" > "$management"
+    echo "adde lorem" > "$management"
+    echo "addf lorem" > "$management"
+    echo "dela lorem" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "dela_all_five_content" 2 test $? -ne 0
+
+    cleanup_test
+}
+
+test_dela_none()
+{
+    init_test
+
+    echo "adde lorem" > "$management"
+    echo "addf ipsum" > "$management"
+    echo "dela dolor" > "$management" 2> /dev/null
+    no=$(cat "$preview" | wc -l)
+    basic_test "dela_none" 2 test "$no" -eq 2
+
+    cleanup_test
+}
+
+test_mix_number()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "adde dolor" > "$management"
+    echo "addf sit" > "$management"
+    echo "adde sit" > "$management"
+    echo "addf sit" > "$management"
+    echo "addf lorem" > "$management"
+    echo "delf lorem" > "$management"
+    echo "delf dolor" > "$management"
+    echo "adde dolor" > "$management"
+    echo "dela sit" > "$management"
+    echo "delf ipsum" > "$management"
+    echo "delf ipsum" > "$management"
+    echo "dela dolor" > "$management"
+    no=$(cat "$preview" | wc -l)
+    basic_test "mix_number" 3 test "$no" -eq 1
+
+    cleanup_test
+}
+
+test_mix_content()
+{
+    init_test
+
+    echo "addf lorem" > "$management"
+    echo "adde ipsum" > "$management"
+    echo "adde dolor" > "$management"
+    echo "addf sit" > "$management"
+    echo "adde sit" > "$management"
+    echo "addf sit" > "$management"
+    echo "addf lorem" > "$management"
+    echo "delf lorem" > "$management"
+    echo "delf dolor" > "$management"
+    echo "adde dolor" > "$management"
+    echo "dela sit" > "$management"
+    echo "delf ipsum" > "$management"
+    echo "delf ipsum" > "$management"
+    echo "dela dolor" > "$management"
+    cat "$preview" | grep "lorem" > /dev/null
+    basic_test "mix_content" 3 test "$no" -eq 1
+
+    cleanup_test
+}
+
+run_tests()
+{
+    test_module_exists
+    test_proc_folder_exits
+    test_preview_exits
+    test_management_exits
+    test_preview_is_readable
+    test_preview_is_not_writable
+    test_management_is_writable
+    test_management_is_not_readable
+    test_addf_no_error
+    test_addf_print
+    test_addf_print_once
+    test_adde_no_error
+    test_adde_print
+    test_adde_print_once
+    test_addf_two_number
+    test_addf_two_content
+    test_addf_same_twice_number
+    test_addf_same_twice_content
+    test_addf_same_twice_content_number
+    test_adde_two_number
+    test_adde_two_content
+    test_adde_same_twice_number
+    test_adde_same_twice_content
+    test_adde_same_twice_content_number
+    test_addf_front_after_addf
+    test_addf_front_after_adde
+    test_addf_front_after_adde_addf
+    test_addf_front_after_addf_adde
+    test_adde_end_after_addf
+    test_adde_end_after_adde
+    test_adde_end_after_adde_addf
+    test_adde_end_after_addf_adde
+    test_delf_no_error
+    test_delf_removes_front
+    test_delf_removes_end
+    test_delf_front_number
+    test_delf_front_content
+    test_delf_first
+    test_delf_none
+    test_dela_one_number
+    test_dela_one_content
+    test_dela_two_number
+    test_dela_two_content
+    test_dela_all_five_number
+    test_dela_all_five_content
+    test_dela_none
+    test_mix_number
+    test_mix_content
+}
+
+run_tests | tee results.txt
+
+cat results.txt | grep '\[.*\]$' | awk -F '[] /[]+' '
+BEGIN {
+    sum=0
+}
+
+{
+    sum += $(NF-2);
+}
+
+END {
+    printf "\n%66s  [%02d/90]\n", "Total:", sum;
+}'
+
+rm results.txt
diff --git a/checker/checker.sh b/checker/checker.sh
index 12d97bb9a00a2b634dbbf4f08a32ec20167cab4b..a3a809760c4464fa390eb2365560ff4e7436cad1 100755
--- a/checker/checker.sh
+++ b/checker/checker.sh
@@ -1,108 +1,86 @@
 #!/bin/bash
 
-EXECUTABLE="../src/perfect"
-TIMEOUT_DURATION=10
-SCORE=0
-TOTAL_SCORE=0
-
-test_err()
+TIMEOUT=300 # 5 min
+SO2_WORKSPACE=/linux/tools/labs
+ASSIGNMENT0_MOD=list.ko
+ASSIGNMENT0_DIR=${SO2_WORKSPACE}/skels/assignments/0-list
+ASSIGNMENT0_CHECKER_DIR=${SO2_WORKSPACE}/skels/assignments/0-list-checker
+ASSIGNMENT0_OUTPUT=${SO2_WORKSPACE}/skels/0-list-output
+ASSIGNMENT0_FINISHED=${SO2_WORKSPACE}/skels/0-list-finished
+
+usage()
 {
-    local temp_output=''
-    temp_output="$(mktemp)"
-
-    timeout "$TIMEOUT_DURATION" bash -c "$EXECUTABLE {} > $temp_output 2>&1"
-
-    diff -Zq "$temp_output" "./references/ref1" > /dev/null 2>&1
-    return $?
-}
-
-test_single()
-{
-    local temp_output=''
-    temp_output="$(mktemp)"
-
-    timeout "$TIMEOUT_DURATION" xargs -a ./input/input2 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
-
-    diff -Zq "$temp_output" "./references/ref2" > /dev/null 2>&1
-    return $?
+	echo "Usage: $0 <assignment>"
+	exit 1
 }
 
-test_multiple()
+timeout_exceeded()
 {
-    local temp_output=''
-    temp_output="$(mktemp)"
-
-    timeout "$TIMEOUT_DURATION" xargs -a ./input/input3 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
-
-    diff -Zq "$temp_output" "./references/ref3" > /dev/null 2>&1
-    return $?
+	echo TIMEOUT EXCEEDED !!! killing the process
+	pkill -SIGKILL qemu
+	exit 1
 }
 
-test_edge()
+run_checker()
 {
-    local temp_output=''
-    temp_output="$(mktemp)"
-
-    timeout "$TIMEOUT_DURATION" xargs -a ./input/input4 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
-
-    diff -Zq "$temp_output" "./references/ref4" > /dev/null 2>&1
-    return $?
-}
-
-setup()
-{
-    pushd ../src > /dev/null || exit 1
-    make -s build
-    popd > /dev/null || exit 1
-}
-
-cleanup()
-{
-    pushd ../src > /dev/null || exit 1
-    make -s clean
-    popd > /dev/null || exit 1
-}
-
-test_fun_array=(                        \
-	test_err            "Name 1"    25  \
-	test_single         "Name 2"    25  \
-	test_multiple       "Name 3"    25  \
-	test_edge           "Name 4"    25  \
-)
-
-run_test()
-{
-    test_index="$1"
-    test_func_index=$((test_index * 3))
-    description=${test_fun_array[$((test_func_index + 1))]}
-    points=${test_fun_array[$((test_func_index + 2))]}
-    TOTAL_SCORE=$((TOTAL_SCORE + points))
-
-    echo -ne "Testing\t\t$description\t"
-    if ${test_fun_array["$test_func_index"]} ; then
-        SCORE=$((SCORE + points))
-        echo "$points/$points"
-        return 0
-    else
-        echo "0/$points"
-        return 1
-    fi
-}
-
-test_all()
-{
-    for i in $(seq 0 "$((${#test_fun_array[@]} / 3 - 1))") ; do
-        run_test "$i"
-    done
-
-    echo -e "\nTotal: $SCORE/$TOTAL_SCORE"
+	local assignment_mod=$1
+	local assignment_dir=$2
+	local checker_dir=$3
+	local output=$4
+	local finished=$5
+	local assignment=$6
+	
+	local module_path="${assignment_dir}/${assignment_mod}"
+
+	pushd /linux/tools/labs
+		if [ -f $module_path ]; then
+			echo "Removing ${module_path}"
+		fi
+		if [ -f $output ]; then
+			echo "Removing $output"
+			rm $output &> /dev/null
+		fi
+		if [ -f $finished ]; then
+			echo "Removing $finished"
+			rm $finished &> /dev/null
+		fi
+
+		echo "Building..."
+		make build
+
+		if [ ! -f $module_path ]; then
+			echo "Cannot find $assignment_mod"
+			exit 1
+		fi
+	
+		# copy *.ko in checker
+		echo "Copying $module_path into $checker_dir"
+		cp $module_path $checker_dir
+
+		LINUX_ADD_CMDLINE="so2=$assignment" ./qemu/run-qemu.sh &> /dev/null &
+		
+		echo -n "CHECKER IS RUNNING"
+		while [ ! -f $finished ]
+		do
+			if ((timeout >= TIMEOUT)); then
+				if [ -f $output ]; then
+					cat $output
+				fi
+				timeout_exceeded
+			fi
+			sleep 2
+			(( timeout += 2 ))
+			echo -n .
+		done
+		cat $output
+	popd
 }
 
-setup
-if [ -z "$1" ] ; then
-    test_all
-else
-    run_test "$1"
-    exit $?
-fi
-cleanup
+case $1 in
+	0-list)
+		run_checker $ASSIGNMENT0_MOD $ASSIGNMENT0_DIR $ASSIGNMENT0_CHECKER_DIR $ASSIGNMENT0_OUTPUT $ASSIGNMENT0_FINISHED $1
+		;;
+	*)
+		usage
+		;;
+esac
diff --git a/checker/checker_daemons/so2_vm_checker_daemon.sh b/checker/checker_daemons/so2_vm_checker_daemon.sh
new file mode 100644
index 0000000000000000000000000000000000000000..162bba828b1df65015196bfd5a3acf2b96d8015e
--- /dev/null
+++ b/checker/checker_daemons/so2_vm_checker_daemon.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# THIS SCRIPT RUNS INSIDE THE SO2 VM
+
+ASSIGNMENT0_CHECKER=/home/root/skels/assignments/0-list-checker
+ASSIGNMENT0_OUTPUT=/home/root/skels/0-list-output
+ASSIGNMENT0_FINISHED=/home/root/skels/0-list-finished
+
+assign0_list()
+{
+        cd $ASSIGNMENT0_CHECKER
+     	   sh _checker &> $ASSIGNMENT0_OUTPUT
+       	   echo FINISHED &> $ASSIGNMENT0_FINISHED
+        cd -
+}
+
+start()
+{
+        local arg=$(cat /proc/cmdline | grep -o 'so2=[^ ]*' | cut -d= -f2)
+        case "$arg" in
+                0-list)
+                        assign0_list
+                        ;;
+                *)
+                        echo "Unknown option"
+                        exit 0
+                        ;;
+        esac
+}
+
+# Carry out specific functions when asked to by the system
+case "$1" in
+        start)
+                echo "Starting so2_vm_checker_daemon.sh..."
+                start
+                ;;
+        stop)
+                echo "Stopping so2_vm_checker_daemon.sh..."
+                sleep 2
+                ;;
+        *)
+                echo "Usage: /etc/init.d/foo {start|stop}"
+                exit 1
+                ;;
+        esac
+
+exit 0
+
diff --git a/checker/input/input1 b/checker/input/input1
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/checker/input/input2 b/checker/input/input2
deleted file mode 100644
index 56a6051ca2b02b04ef92d5150c9ef600403cb1de..0000000000000000000000000000000000000000
--- a/checker/input/input2
+++ /dev/null
@@ -1 +0,0 @@
-1
\ No newline at end of file
diff --git a/checker/input/input3 b/checker/input/input3
deleted file mode 100644
index e440e5c842586965a7fb77deda2eca68612b1f53..0000000000000000000000000000000000000000
--- a/checker/input/input3
+++ /dev/null
@@ -1 +0,0 @@
-3
\ No newline at end of file
diff --git a/checker/input/input4 b/checker/input/input4
deleted file mode 100644
index c227083464fb9af8955c90d2924774ee50abb547..0000000000000000000000000000000000000000
--- a/checker/input/input4
+++ /dev/null
@@ -1 +0,0 @@
-0
\ No newline at end of file
diff --git a/checker/references/ref1 b/checker/references/ref1
deleted file mode 100644
index 8fac0de40be37c53e8a1d0ee97e6aa632c41b0b9..0000000000000000000000000000000000000000
--- a/checker/references/ref1
+++ /dev/null
@@ -1 +0,0 @@
-Not enough arguments!
diff --git a/checker/references/ref2 b/checker/references/ref2
deleted file mode 100644
index d00491fd7e5bb6fa28c517a0bb32b8b506539d4d..0000000000000000000000000000000000000000
--- a/checker/references/ref2
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/checker/references/ref3 b/checker/references/ref3
deleted file mode 100644
index cc3759002bf5280e344eeadc5dbf9ea31b3e0b78..0000000000000000000000000000000000000000
--- a/checker/references/ref3
+++ /dev/null
@@ -1 +0,0 @@
-1 1 1
diff --git a/checker/references/ref4 b/checker/references/ref4
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/checker/references/ref4
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/local.sh b/local.sh
index da63f8fc12b8e5885f04c5348e700b7e79fe549e..c68b2822be04c0a22f46272f713a8467be47219d 100755
--- a/local.sh
+++ b/local.sh
@@ -13,6 +13,12 @@ DEFAULT_IMAGE_NAME="so2/0-list"
 DEFAULT_TAG='latest'
 DEFAULT_REGISTRY='gitlab.cs.pub.ro:5050'
 
+SRC_DIR="$(realpath ./src)"
+CHECKER_BASE_DIR="$(realpath ./checker)"
+ASSIGNMENT_CHECKER_DIR="$(realpath ./checker/0-list-checker)"
+SO2_WORKSPACE=/linux/tools/labs
+ASSIGNMENT_MOUNT_DIR="${SO2_WORKSPACE}/skels/assignments/0-list"
+ASSIGNMENT_CHECKER_MOUNT_DIR="${SO2_WORKSPACE}/skels/assignments/0-list-checker"
 MOUNT_PROJECT_DIRECTORY="/build/$USER/$(basename "$(pwd)")"
 
 #=============================================================================
@@ -61,10 +67,11 @@ print_help() {
     echo "      --full_image_name <full_image_name> - the full name of the image (default: gitlab.cs.pub.ro:5050/<current_directory_name>:latest)"
     echo "      argumets_for_checker - list of space separated arguments to be passed to the checker"
     echo ""
-    echo "local.sh docker interactive [--full_image_name <full_image_name>] [--use_executable <executbale>]"
+    echo "local.sh docker interactive [--full_image_name <full_image_name>] [--use_executable <executbale>] [--privileged]"
     echo ""
     echo "      --full_image_name <full_image_name> - the full name of the image (default: gitlab.cs.pub.ro:5050/<current_directory_name>:latest)"
     echo "      --use_executable <executable> - command to run inside the container (default: /bin/bash)"
+    echo "      --privileged - run a privileged container. This allows the use of KVM"
     echo ""
     echo "local.sh checker [--remove_image] [--use_existing_image <image_name>] [--force_build] [argumets_for_checker]"
     echo ""
@@ -179,16 +186,20 @@ docker_interactive() {
                 shift
                 executable="$1"
             ;;
+	    --privileged)
+		privileged=--privileged
         esac
         shift
     done
 
     tmpdir="$(mktemp -d)"
-    cp -R ./* "$tmpdir"
-
-    docker run --rm -it \
-            --mount type=bind,source="$tmpdir",target="$MOUNT_PROJECT_DIRECTORY" \
-            --workdir "$MOUNT_PROJECT_DIRECTORY" \
+    set -x
+    cp -R ${ASSIGNMENT_CHECKER_DIR}/* "$tmpdir"
+    
+    docker run $privileged --rm -it \
+            --mount type=bind,source="$SRC_DIR",target="$ASSIGNMENT_MOUNT_DIR" \
+            --mount type=bind,source="$tmpdir",target="$ASSIGNMENT_CHECKER_MOUNT_DIR" \
+            --workdir "$SO2_WORKSPACE" \
             "$full_image_name" "$executable"
 }
 
@@ -240,6 +251,12 @@ checker_main() {
         docker build "${extra_docker_args[@]}" -q -t "$image_name" .
     fi
 
+    assign_tmpdir="$(mktemp -d)"
+    cp -R ${SRC_DIR}/* "$assign_tmpdir"
+
+    assign_check_tmpdir="$(mktemp -d)"
+    cp -R ${ASSIGNMENT_CHECKER_DIR}/* "$assign_check_tmpdir"
+    
     tmpdir="$(mktemp -d)"
     cp -R ./* "$tmpdir"
 
@@ -249,6 +266,8 @@ checker_main() {
     # otherwise stick to relative paths.
     # It is guaranteed that the current working directory in which checker.sh will run is  $CI_PROJECT_DIR/checker.
     docker run --rm \
+            --mount type=bind,source="$assign_tmpdir",target="$ASSIGNMENT_MOUNT_DIR" \
+            --mount type=bind,source="$assign_check_tmpdir",target="$ASSIGNMENT_CHECKER_MOUNT_DIR" \
             --mount type=bind,source="$tmpdir",target="$MOUNT_PROJECT_DIRECTORY" \
             "$image_name" /bin/bash -c "rm -rf /usr/local/bin/bash; cd \"$MOUNT_PROJECT_DIRECTORY/checker\"; \"$MOUNT_PROJECT_DIRECTORY/checker/checker.sh\" \"${script_args[@]}\"" # remove bash middleware script
 
diff --git a/src/Kbuild b/src/Kbuild
new file mode 100644
index 0000000000000000000000000000000000000000..5e45a816841549a017843600ee193089cabdb5c1
--- /dev/null
+++ b/src/Kbuild
@@ -0,0 +1 @@
+obj-m = list.o
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index 6e912480cca5dbb79e0aa01c5d509f22e1902f29..0000000000000000000000000000000000000000
--- a/src/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-build: main.c
-	gcc main.c -o perfect
-
-.PHONY: clean
-
-clean:
-	rm perfect
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000000000000000000000000000000000000..9584f21d3229ce9031bf6788a3f29a7b1898dc9d
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * list.c - Linux kernel list API
+ *
+ * TODO 1/0: Fill in name / email
+ * Author: FirstName LastName <user@email.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+
+#define PROCFS_MAX_SIZE		512
+
+#define procfs_dir_name		"list"
+#define procfs_file_read	"preview"
+#define procfs_file_write	"management"
+
+struct proc_dir_entry *proc_list;
+struct proc_dir_entry *proc_list_read;
+struct proc_dir_entry *proc_list_write;
+
+/* TODO 2: define your list! */
+
+static int list_proc_show(struct seq_file *m, void *v)
+{
+	/* TODO 3: print your list. One element / line. */
+	seq_puts(m, "Remove this line\n");
+
+	return 0;
+}
+
+static int list_read_open(struct inode *inode, struct  file *file)
+{
+	return single_open(file, list_proc_show, NULL);
+}
+
+static int list_write_open(struct inode *inode, struct  file *file)
+{
+	return single_open(file, list_proc_show, NULL);
+}
+
+static ssize_t list_write(struct file *file, const char __user *buffer,
+			  size_t count, loff_t *offs)
+{
+	char local_buffer[PROCFS_MAX_SIZE];
+	unsigned long local_buffer_size = 0;
+
+	local_buffer_size = count;
+	if (local_buffer_size > PROCFS_MAX_SIZE)
+		local_buffer_size = PROCFS_MAX_SIZE;
+
+	memset(local_buffer, 0, PROCFS_MAX_SIZE);
+	if (copy_from_user(local_buffer, buffer, local_buffer_size))
+		return -EFAULT;
+
+	/* local_buffer contains your command written in /proc/list/management
+	 * TODO 4/0: parse the command and add/delete elements.
+	 */
+
+	return local_buffer_size;
+}
+
+static const struct proc_ops r_pops = {
+	.proc_open		= list_read_open,
+	.proc_read		= seq_read,
+	.proc_release	= single_release,
+};
+
+static const struct proc_ops w_pops = {
+	.proc_open		= list_write_open,
+	.proc_write		= list_write,
+	.proc_release	= single_release,
+};
+
+static int list_init(void)
+{
+	proc_list = proc_mkdir(procfs_dir_name, NULL);
+	if (!proc_list)
+		return -ENOMEM;
+
+	proc_list_read = proc_create(procfs_file_read, 0000, proc_list,
+				     &r_pops);
+	if (!proc_list_read)
+		goto proc_list_cleanup;
+
+	proc_list_write = proc_create(procfs_file_write, 0000, proc_list,
+				      &w_pops);
+	if (!proc_list_write)
+		goto proc_list_read_cleanup;
+
+	return 0;
+
+proc_list_read_cleanup:
+	proc_remove(proc_list_read);
+proc_list_cleanup:
+	proc_remove(proc_list);
+	return -ENOMEM;
+}
+
+static void list_exit(void)
+{
+	proc_remove(proc_list);
+}
+
+module_init(list_init);
+module_exit(list_exit);
+
+MODULE_DESCRIPTION("Linux kernel list API");
+/* TODO 5: Fill in your name / email address */
+MODULE_AUTHOR("FirstName LastName <your@email.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 4556184bc231930d22e9ff3c17b81cfdc93525e5..0000000000000000000000000000000000000000
--- a/src/main.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv)
-{
-    return 0;
-}
diff --git a/src/solution.c b/src/solution.c
deleted file mode 100644
index ac5e990d44ffd6f848e80cd7a06dbf24c2a1d6a3..0000000000000000000000000000000000000000
--- a/src/solution.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv)
-{
-    if (argc != 2) {
-        fprintf(stderr, "Not enough arguments!\n");
-        return 1;
-    }
-
-    int number = atoi(argv[1]);
-
-    for (int i = 0; i < number; i++)
-        printf("1 ");
-
-    printf("\n");
-    return 0;
-}