Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Contribution of Adversarial Packet Testing Functionality to PacketDrill #78

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
820fdaa
When a test fails, before exiting, call function to free the shared o…
AmPaschal Sep 24, 2022
e236e6e
Modified packets and removed linux calls
AmPaschal Sep 24, 2022
0369ca4
Started extending PacketDrill's grammar.
AmPaschal Sep 26, 2022
03a108c
Grammar has been extended with fuzz instructions
AmPaschal Sep 30, 2022
a0af9f3
Integrated support for external fuzz mutation file
AmPaschal Oct 2, 2022
69fdc58
Invokes mutation file for packets to fuzz
AmPaschal Oct 5, 2022
68e059c
Let so_instance manage closing of socket it creates
AmPaschal Oct 13, 2022
c8c894c
Extended Packetdrill's grammar to support fuzz instructions
AmPaschal Dec 21, 2022
18cd129
Merge pull request #1 from AmPaschal/grammar_ext
AmPaschal Dec 21, 2022
75f6bcc
Enabled UDP fuzzing
AmPaschal Feb 13, 2023
02e1630
Added fuzz terminating signal + other minor changes
AmPaschal Mar 10, 2023
1d9afc2
Merge pull request #2 from AmPaschal/grammar_ext
AmPaschal Mar 10, 2023
2f76b2c
Changed implementation of fuzz terminating signal
AmPaschal Mar 11, 2023
d9cd0f9
IPv6, IPv4 and TCP working
Mar 31, 2023
c17e390
Merge branch 'master' into ricardo
Mar 31, 2023
09c7fa7
Updated fuzz terminating signal and added mutation field
AmPaschal Apr 3, 2023
817dcea
Merge branch 'master' of https://github.com/AmPaschal/packetdrill int…
AmPaschal Apr 3, 2023
e1fba1c
Merge branch 'grammar_ext' into ricardo
Apr 5, 2023
7955048
Remove incorrect Rule in Parser
Apr 5, 2023
3195b91
addes packet statement to fuzz option
Apr 6, 2023
437dbf7
Ajustes
May 3, 2023
79f4067
Merge pull request #3 from AmPaschal/ricardo
rcalvom May 25, 2023
f10e770
Added sample mutated scripts
AmPaschal Jul 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/.idea/
/.vscode/
9 changes: 9 additions & 0 deletions gtests/net/mutation-scripts/blocking-accept-fuzz-template.pkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0...0.200 accept(3, ..., ...) = 4
+.1 < S 0:0(0) win 32792 <wscale 8,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 257
+.1 < P. 1:21(20) ack 1 win 257
25 changes: 25 additions & 0 deletions gtests/net/mutation-scripts/blocking-accept-fuzz.pkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Test for blocking accept.

//`../common/defaults.sh`

// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0...0.200 accept(3, ..., ...) = 4

+.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7> { mut tcp data_offset 0xFF ; ins tcp 20 0x02040000 }
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 257

+.1 write(4, ..., 200) = 200
+0 > P. 1:201(200) ack 1
+.1 < . 201:201(0) ack 1 win 257

+.1 < P. 1:11(10) ack 1 win 257
+0 read(4, ..., 10) = 10

+0 close(3) = 0
+0 > F. 201:201(0) ack 1
+0 < . 1:1(0) ack 1002 win 257
10 changes: 10 additions & 0 deletions gtests/net/mutation-scripts/blocking-connect-fuzz.pkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Test for blocking connect.

// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3

+.1...0.200 connect(3, ..., ...) = 0

+0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.1 < S. 0:0(0) ack 1 win 5792 <mss 1460,nop,wscale 2,nop,nop,sackOK> { mut tcp data_offset 0xFF ; ins tcp 20 0x02040000 }
+0 > . 1:1(0) ack 1
4 changes: 2 additions & 2 deletions gtests/net/packetdrill/Makefile.common
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
all: binaries

CFLAGS = -g -Wall -Werror
CFLAGS = -g -Wall -Werror -Wno-unused-result -Wno-stringop-truncation -Wno-int-to-pointer-cast

parser.o: parser.y
bison --output=parser.c --defines=parser.h --report=state parser.y
Expand Down Expand Up @@ -29,7 +29,7 @@ packetdrill-lib := \
link_layer.o wire_conn.o wire_protocol.o \
wire_client.o wire_client_netdev.o \
wire_server.o wire_server_netdev.o \
epoll.o pipe.o file.o so_testing.o wrap.o
epoll.o pipe.o file.o so_testing.o wrap.o fuzz_options.o fm_testing.o

packetdrill-objs := packetdrill.o $(packetdrill-lib)

Expand Down
2 changes: 1 addition & 1 deletion gtests/net/packetdrill/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ void run_code_event(struct state *state, struct event *event,
return;

error_out:
die("%s:%d: runtime error in code: %s\n",
die_free_so(state, "%s:%d: runtime error in code: %s\n",
state->config->script_path, event->line_number, error);
free(error);
}
7 changes: 7 additions & 0 deletions gtests/net/packetdrill/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ enum option_codes {
OPT_DRY_RUN,
OPT_IS_ANYIP,
OPT_SEND_OMIT_FREE,
OPT_FM_FILENAME,
OPT_DEFINE = 'D', /* a '-D' single-letter option */
OPT_VERBOSE = 'v', /* a '-v' single-letter option */
};
Expand Down Expand Up @@ -103,6 +104,7 @@ struct option options[] = {
{ "send_omit_free", .has_arg = false, NULL, OPT_SEND_OMIT_FREE },
{ "define", .has_arg = true, NULL, OPT_DEFINE },
{ "verbose", .has_arg = false, NULL, OPT_VERBOSE },
{ "fm_filename", .has_arg = true, NULL, OPT_FM_FILENAME},
{ NULL },
};

Expand Down Expand Up @@ -513,6 +515,11 @@ static void process_option(int opt, char *optarg, struct config *config,
case OPT_VERBOSE:
config->verbose = true;
break;

case OPT_FM_FILENAME:
config->fm_filename = strdup(optarg);
break;

default:
show_usage();
exit(EXIT_FAILURE);
Expand Down
3 changes: 3 additions & 0 deletions gtests/net/packetdrill/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ struct config {
char *so_filename;
char *so_flags;

/* Fuzz mutation file for fuzzing, using an external mutation file */
char *fm_filename;

/* For anyip testing */
bool is_anyip;

Expand Down
1 change: 1 addition & 0 deletions gtests/net/packetdrill/fd_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct fd_state {
int script_fd; /* file descriptor in the script source */
int live_fd; /* file descriptor in packetdrill runtime */
bool is_closed; /* has app called close(2) ? */
bool so_managed; /* so_instance was used to create this syscall. Should be in charge of closing it */
struct fd_state *next; /* next fd in linked list */
};

Expand Down
94 changes: 94 additions & 0 deletions gtests/net/packetdrill/fm_testing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Author: [email protected] (Paschal Amusuo)
*
* Testing using mutated packets
*/

#include "fm_testing.h"
#include <dlfcn.h>

struct config;

struct fm_packet {
u8 *buffer; /* data buffer: full contents of packet */
u32 buffer_bytes; /* bytes of space in data buffer */

/* Layer 3 */
u8 *ipv4; /* start of IPv4 header, if present */
u8 *ipv6; /* start of IPv6 header, if present */

/* Layer 4 */
u8 *tcp; /* start of TCP header, if present */
u8 *udp; /* start of UDP header, if present */
u8 *icmpv4; /* start of ICMPv4 header, if present */
u8 *icmpv6; /* start of ICMPv6 header, if present */
};

struct packet *handle_packet_mutation(struct packet *packet, struct fm_instance *fm_instance) {

printf("ip_bytes: %d\n", packet->ip_bytes);
printf("buffer_bytes: %d\n", packet->buffer_bytes);

struct fm_packet fm_packet = {
.buffer = (u8 *) packet->buffer,
.buffer_bytes = packet->ip_bytes,
.icmpv4 = (u8 *) packet->icmpv4,
.icmpv6 = (u8 *) packet->icmpv6,
.ipv4 = (u8 *) packet->ipv4,
.ipv6 = (u8 *) packet->ipv6,
.tcp = (u8 *) packet->tcp,
.udp = (u8 *) packet->udp
};

struct fm_packet *mutated_fm_packet = fm_instance->fm_interface.mutate(&fm_packet, packet->fuzz_options);

packet->buffer = mutated_fm_packet->buffer;
packet->ip_bytes = mutated_fm_packet->buffer_bytes;
packet->icmpv4 = (struct icmpv4 *) mutated_fm_packet->icmpv4;
packet->icmpv6 = (struct icmpv6 *) mutated_fm_packet->icmpv6;
packet->ipv4 = (struct ipv4 *) mutated_fm_packet->ipv4;
packet->ipv6 = (struct ipv6 *) mutated_fm_packet->ipv6;
packet->tcp = (struct tcp *) mutated_fm_packet->tcp;
packet->udp = (struct udp *) mutated_fm_packet->udp;

return packet;

}

struct fm_instance *fm_instance_new(void) {
return calloc(1, sizeof(struct fm_instance));
}

int fm_instance_init(struct fm_instance *instance,
const struct config *config) {
fm_interface_init_t init;
char *error;

instance->handle = dlopen(config->fm_filename,
RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE |
RTLD_DEEPBIND);
if (!instance->handle)
die("%s\n", dlerror());
dlerror(); /* clear any existing error */

init = dlsym(instance->handle, "fm_interface_init");
error = dlerror();
if (error)
die("%s\n", error);

init(&instance->fm_interface);
return STATUS_OK;
}

void fm_instance_free(struct fm_instance *instance) {
if (!instance)
return;

instance->fm_interface.free();

if (instance->handle)
dlclose(instance->handle);

memset(instance, 0, sizeof(*instance));
free(instance);
}
45 changes: 45 additions & 0 deletions gtests/net/packetdrill/fm_testing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

/*
* Author: [email protected] (Paschal Amusuo)
*
* Testing using mutated packets
*/

#ifndef __FM_TESTING_H__
#define __FM_TESTING_H__

#include "fm_testing.h"
#include "packet.h"
#include "config.h"

struct config;
struct fm_packet;

struct fm_interface {
struct fm_packet *(*mutate)(struct fm_packet *original, struct fuzz_options *fuzz_options);
void (*free)();
};

typedef void (*fm_interface_init_t)(struct fm_interface *);

struct fm_instance {
struct fm_interface fm_interface;
void *handle;
};


/* Invoke mutate method of fm_interface */
struct packet *handle_packet_mutation(struct packet *packet, struct fm_instance *fm_instance);


/* Allocate a new fm_instance. */
struct fm_instance *fm_instance_new(void);

/* Load the fuzz mutation shared object and setup callback functions. */
int fm_instance_init(struct fm_instance *instance,
const struct config *config);

/* Delete a so_instance and its associated objects. */
void fm_instance_free(struct fm_instance *instance);

#endif /* __FM_TESTING_H__ */
49 changes: 49 additions & 0 deletions gtests/net/packetdrill/fuzz_options.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "fuzz_options.h"

#include <stdlib.h>
#include <string.h>

struct fuzz_options* fuzz_options_new(void) {
struct fuzz_options *options = (struct fuzz_options *) malloc(sizeof(struct fuzz_options));

options->options = malloc(sizeof(struct fuzz_option));
options->capacity = sizeof(struct fuzz_option);
options->count = 0;
options->size = 0;

return options;
}

void fuzz_options_grow(struct fuzz_options *fuzz_options, size_t capacity) {
if (capacity > fuzz_options->capacity) {
fuzz_options->options = realloc(fuzz_options->options, capacity);
fuzz_options->capacity = capacity;
}
}

int fuzz_options_append(struct fuzz_options *fuzz_options, struct fuzz_option *option) {
size_t fuzz_option_size = sizeof(struct fuzz_option);
if (fuzz_option_size + fuzz_options->size > fuzz_options->capacity) {
fuzz_options_grow(fuzz_options, fuzz_options->capacity * 2);
}

memcpy(fuzz_options->options + fuzz_options->count, option, fuzz_option_size);
fuzz_options->size += fuzz_option_size;
fuzz_options->count += 1;

free(option);

return STATUS_OK;
}

struct fuzz_option* fuzz_option_new(enum fuzz_type_t fuzz_type, enum header_type_t header_type, u8 fuzz_field, struct fuzz_value_t fuzz_value) {
struct fuzz_option *option = calloc(1, sizeof(struct fuzz_option));

option->fuzz_type = fuzz_type;
option->header_type = header_type;
option->fuzz_field = fuzz_field;
option->fuzz_value = fuzz_value.value;
option->fuzz_value_byte_count = fuzz_value.byte_count;

return option;
}
Loading