diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 17b2e72..333602b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,5 +15,33 @@ jobs: with: distribution: 'temurin' java-version: '21' - - name: Install - run: cd learner; ./install.sh + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install TCP-Fuzzer + run: ./install.sh + + Linux_basic: + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: true + steps: + - name: Checkout code + uses: actions/checkout@v6 + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '21' + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install TCP-Fuzzer + run: ./install.sh + - name: Test Ubuntu 24.04 + run: | + ./run.sh -alphabet config/basic.xml -output output/ubuntu -eqvQueries 100 + ./diff_hyps.sh experiments/models/linux-6.17.0_basic output/ubuntu 3 diff --git a/config/basic.xml b/config/basic.xml new file mode 100644 index 0000000..fff7855 --- /dev/null +++ b/config/basic.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/config/alphabet.xml b/config/full_data.xml similarity index 100% rename from config/alphabet.xml rename to config/full_data.xml diff --git a/config/learner_args b/config/learner_args index 7044e21..b57dfed 100644 --- a/config/learner_args +++ b/config/learner_args @@ -4,6 +4,10 @@ localhost:18200 -tcpMapperAddress localhost:18200 -alphabet -${fuzzer.dir}/config/alphabet.xml --memQueryRuns -3 +${fuzzer.dir}/config/full_data.xml +#-memQueryRuns +#3 +-command +python3 ${fuzzer.dir}/sutadapter/serverAdapter.py --port 9000 +-startWait +50 diff --git a/diff_hyps.sh b/diff_hyps.sh new file mode 100755 index 0000000..7b4b630 --- /dev/null +++ b/diff_hyps.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +dir1=$1 +dir2=$2 +num_rounds=$3 + +if [[ $# != 3 ]]; then + echo "Usage: ${0##*/} dir1 dir2 num_rounds" + echo "Diffs the first num_rounds hypotheses stored in two dirs" + exit 1 +fi + +if [[ ! -d ${dir1} ]]; then + echo "${dir1}"": No such directory" + exit 1 +fi +if [[ ! -d ${dir2} ]]; then + echo "${dir2}"": No such directory" + exit 1 +fi + +for ((i = 1 ; i <= num_rounds ; i++)); do + if ! diff --unified=0 "${dir1}"/hyp"${i}".dot "${dir2}"/hyp"${i}".dot; then + exit 1 + fi +done diff --git a/experiments/models/linux-6.17.0_basic/alphabet.xml b/experiments/models/linux-6.17.0_basic/alphabet.xml new file mode 100644 index 0000000..fff7855 --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/alphabet.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/experiments/models/linux-6.17.0_basic/command.args b/experiments/models/linux-6.17.0_basic/command.args new file mode 100644 index 0000000..7649d81 --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/command.args @@ -0,0 +1,17 @@ +state-fuzzer-server +-connect +localhost:18200 +-tcpMapperAddress +localhost:18200 +-alphabet +${fuzzer.dir}/config/alphabet.xml +#-memQueryRuns +#3 +-command +python3 ${fuzzer.dir}/sutadapter/serverAdapter.py --port 9000 +-startWait +50 +-alphabet +/home/pfg666/GitHub/tools/TCP-Fuzzer/config/basic.xml +-eqvQueries +100 diff --git a/experiments/models/linux-6.17.0_basic/hyp1.dot b/experiments/models/linux-6.17.0_basic/hyp1.dot new file mode 100644 index 0000000..9bc7844 --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/hyp1.dot @@ -0,0 +1,11 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s0 -> s0 [label="S / SA"]; + s0 -> s0 [label="A / timeout"]; + s0 -> s0 [label="FA / timeout"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/models/linux-6.17.0_basic/hyp2.dot b/experiments/models/linux-6.17.0_basic/hyp2.dot new file mode 100644 index 0000000..777684b --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/hyp2.dot @@ -0,0 +1,23 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s0 -> s1 [label="S / SA"]; + s0 -> s0 [label="A / timeout"]; + s0 -> s0 [label="FA / timeout"]; + s1 -> s0 [label="S / timeout"]; + s1 -> s3 [label="A / timeout"]; + s1 -> s2 [label="FA / FA"]; + s2 -> s2 [label="S / SOCKET_CLOSED"]; + s2 -> s2 [label="A / SOCKET_CLOSED"]; + s2 -> s2 [label="FA / SOCKET_CLOSED"]; + s3 -> s1 [label="S / A"]; + s3 -> s3 [label="A / timeout"]; + s3 -> s2 [label="FA / FA"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/models/linux-6.17.0_basic/hyp3.dot b/experiments/models/linux-6.17.0_basic/hyp3.dot new file mode 100644 index 0000000..7a97c32 --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/hyp3.dot @@ -0,0 +1,27 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s0 -> s1 [label="S / SA"]; + s0 -> s0 [label="A / timeout"]; + s0 -> s0 [label="FA / timeout"]; + s1 -> s0 [label="S / timeout"]; + s1 -> s3 [label="A / timeout"]; + s1 -> s2 [label="FA / FA"]; + s2 -> s2 [label="S / SOCKET_CLOSED"]; + s2 -> s2 [label="A / SOCKET_CLOSED"]; + s2 -> s2 [label="FA / SOCKET_CLOSED"]; + s3 -> s4 [label="S / A"]; + s3 -> s3 [label="A / timeout"]; + s3 -> s2 [label="FA / FA"]; + s4 -> s3 [label="S / timeout"]; + s4 -> s3 [label="A / timeout"]; + s4 -> s2 [label="FA / FA"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/models/linux-6.17.0_basic/learnedModel.dot b/experiments/models/linux-6.17.0_basic/learnedModel.dot new file mode 100644 index 0000000..7a97c32 --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/learnedModel.dot @@ -0,0 +1,27 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s0 -> s1 [label="S / SA"]; + s0 -> s0 [label="A / timeout"]; + s0 -> s0 [label="FA / timeout"]; + s1 -> s0 [label="S / timeout"]; + s1 -> s3 [label="A / timeout"]; + s1 -> s2 [label="FA / FA"]; + s2 -> s2 [label="S / SOCKET_CLOSED"]; + s2 -> s2 [label="A / SOCKET_CLOSED"]; + s2 -> s2 [label="FA / SOCKET_CLOSED"]; + s3 -> s4 [label="S / A"]; + s3 -> s3 [label="A / timeout"]; + s3 -> s2 [label="FA / FA"]; + s4 -> s3 [label="S / timeout"]; + s4 -> s3 [label="A / timeout"]; + s4 -> s2 [label="FA / FA"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/models/linux-6.17.0_basic/learnedModel.pdf b/experiments/models/linux-6.17.0_basic/learnedModel.pdf new file mode 100644 index 0000000..3d080e5 Binary files /dev/null and b/experiments/models/linux-6.17.0_basic/learnedModel.pdf differ diff --git a/experiments/models/linux-6.17.0_basic/statistics.txt b/experiments/models/linux-6.17.0_basic/statistics.txt new file mode 100644 index 0000000..93dc94a --- /dev/null +++ b/experiments/models/linux-6.17.0_basic/statistics.txt @@ -0,0 +1,100 @@ +=== RUN DESCRIPTION === +Alphabet: [S, A, FA] + +### StateFuzzerConfigStandard Parameters +# -help +# -debug +# -quiet +-output +output/o_2026-04-30_12-16-06 + +### LearnerConfigStandard Parameters +-alphabet +/home/pfg666/GitHub/tools/TCP-Fuzzer/config/basic.xml +-learningAlgorithm +TTT +-equivalenceAlgorithms +RANDOM_WP_METHOD +-depth +1 +-minLength +5 +-maxLength +15 +-randLength +5 +-eqvQueries +100 +-memQueryRuns +1 +-memQueryRetries +3 +# -logQueries +-probReset +0.0 +# -testFile +-seed +0 +# -cacheTests +# -ceSanitizationDisable +# -skipNonDetTests +-ceReruns +3 +# -probabilisticSanitizationDisable +# -timeLimit +# -testLimit +# -roundLimit +-eqvThreads +1 + +### SULConfigStandard Parameters +-responseWait +100 +# -inputResponseTimeout +-command +python3 /home/pfg666/GitHub/tools/TCP-Fuzzer/sutadapter/serverAdapter.py --port 9000 +# -terminateCommand +# -processDir +# -redirectOutputStreams +-processTrigger +NEW_TEST +-startWait +50 + +### SULServerConfigStandard Parameters +-connect +localhost:18200 + +### MapperConfigStandard Parameters +# -mapperConnectionConfig +# -repeatingOutputs +# -socketClosedAsTimeout +# -disabledAsTimeout +# -dontMergeRepeating + +### SULAdapterConfigStandard Parameters +# -adapterPort +-adapterAddress +localhost + +=== STATISTICS === +Learning finished: true +Size of the input alphabet: 3 +Number of states: 5 +Number of hypotheses: 3 +Number of inputs: 1120 +Number of tests: 109 +Number of learning inputs: 89 +Number of learning tests: 27 +Number of inputs up to last hypothesis: 239 +Number of tests up to last hypothesis: 41 +Time (ms) to learn model: 302925 +Counterexamples: +CE 1:Query[ε|A A FA FA FA S FA FA S A FA / timeout timeout timeout timeout timeout SA FA SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED] +CE 2:Query[ε|S A A S S A A FA S FA S S / SA timeout timeout A timeout timeout timeout FA SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED] +Number of inputs when hypothesis was generated: [3, 95, 239] +Number of tests when hypothesis was generated: [3, 23, 41] +Time (ms) when hypothesis was generated: [2799, 43975, 95216] +Number of inputs when counterexample was found: [47, 201] +Number of tests when counterexample was found: [7, 33] +Time (ms) when counterexample was found: [16834, 74894] diff --git a/install.sh b/install.sh index 103a4da..6dcdc56 100755 --- a/install.sh +++ b/install.sh @@ -16,27 +16,27 @@ function install_learner() { if [[ $? -ne 0 ]]; then echo "Failed to install Learner" - exit + exit 1 else echo "Learner installed successfully" fi } -function install_mapper_env() { - echo "Installing Mapper environment" +function install_mapper() { + echo "Installing Mapper" ( cd ${MAPPER_DIR}; - ./install_env.sh + ./install.sh ) if [[ $? -ne 0 ]]; then - echo "Failed to install Mapper environment" - exit + echo "Failed to install Mapper" + exit 1 else - echo "Mapper environment installed successfully" + echo "Mapper installed successfully" fi } # Installing learner and mapper components install_learner -install_mapper_env +install_mapper diff --git a/mapper/install_env.sh b/mapper/install.sh similarity index 70% rename from mapper/install_env.sh rename to mapper/install.sh index 6e3aa15..ac2dee1 100755 --- a/mapper/install_env.sh +++ b/mapper/install.sh @@ -2,6 +2,11 @@ MAPPER_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && p readonly MAPPER_SCRIPT_DIR readonly ENV_DIR=${MAPPER_SCRIPT_DIR}/.venv +# Installing dependencies +echo "Installing dependencies where necessary." +sudo apt-get update +sudo apt-get install -y libpcap-dev tcpdump || (echo "Failed to install libraries"; exit 1) + if [[ -d ${ENV_DIR} ]] then echo "Detected Python virtual environment. Skipping Python environment creation." @@ -10,7 +15,8 @@ else python3 -m venv $ENV_DIR source $ENV_DIR/bin/activate echo "Installing required libraries" - pip install -r requirements.txt + pip install --upgrade pip + pip install -r ${MAPPER_SCRIPT_DIR}/requirements.txt || (echo "Fail to install required Python packages"; exit 1) fi # If the script is being sourced, activate the environment diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..760517e --- /dev/null +++ b/run.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +set -euo pipefail + +learner_config=$SCRIPT_DIR/config/learner_args +mapper_config=$SCRIPT_DIR/config/mapperconfig.toml + +# These values have to be consistent with the arguments in config +#SERVER_PORT=9000 +HOST=127.0.0.1 +MAPPER_PORT=18200 + + +# Clean up background processes on exit +cleanup() { + echo "Cleaning up..." + kill "$MAPPER_PID" 2>/dev/null || true + sudo iptables --flush OUTPUT +} +trap cleanup EXIT + +start_mapper() { + # Start TCP Mapper + echo "Starting Mapper..." + ( + sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP + source $SCRIPT_DIR/mapper/.venv/bin/activate + echo sudo $SCRIPT_DIR/mapper/.venv/bin/python $SCRIPT_DIR/mapper/main.py $mapper_config + sudo $SCRIPT_DIR/mapper/.venv/bin/python $SCRIPT_DIR/mapper/main.py $mapper_config + ) & + + MAPPER_PID=$! + # Wait for mapper to be ready + echo "Wait for mapper to be ready" + until ss -ltn sport = :$MAPPER_PORT | grep -q LISTEN; do + sleep 0.1 + done + echo "Mapper started (PID $MAPPER_PID)" + sleep 1 +} + +start_learner() { + # Start learner + echo "Starting Learner..." + echo java -jar $SCRIPT_DIR/learner/target/TCP-Learner.jar $learner_config $@ + java -jar $SCRIPT_DIR/learner/target/TCP-Learner.jar $learner_config $@ +} + +while [[ "$1" =~ ^- ]]; do case $1 in + -lc | --learner-config ) + shift; + learner_config=$1 + ;; + -mc | --mapper-config ) + shift; + mapper_config=$1 + ;; + * ) + break + ;; + esac; shift; done + +start_mapper +start_learner $@ \ No newline at end of file