Skip to content

Commit

Permalink
TEST COMMIT FOR MEGA MERGE WORKFLOW
Browse files Browse the repository at this point in the history
  • Loading branch information
edwintorok committed Feb 26, 2025
Show file tree
Hide file tree
Showing 52 changed files with 3,210 additions and 1,065 deletions.
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ doc:
sdk:
dune build --profile=$(PROFILE) @sdkgen xapi-sdk.install @ocaml/sdk-gen/install

# workaround for no .resx generation, just for compilation testing
sdksanity: sdk
cd _build/install/default/share/csharp/src && dotnet add package Newtonsoft.Json && dotnet build -f netstandard2.0
cd _build/install/default/share/csharp && dotnet test XenServerTest -p:DefineConstants=BUILD_FOR_TEST

.PHONY: sdk-build-c

sdk-build-c: sdk
Expand Down Expand Up @@ -153,7 +158,7 @@ DUNE_IU_PACKAGES1+=xapi-client xapi-schema xapi-consts xapi-cli-protocol xapi-da
DUNE_IU_PACKAGES1+=xen-api-client xen-api-client-lwt rrdd-plugin rrd-transport
DUNE_IU_PACKAGES1+=gzip http-lib pciutil sexpr stunnel uuid xml-light2 zstd xapi-compression safe-resources
DUNE_IU_PACKAGES1+=message-switch message-switch-cli message-switch-core message-switch-lwt
DUNE_IU_PACKAGES1+=message-switch-unix xapi-idl forkexec xapi-forkexecd xapi-storage xapi-storage-script xapi-storage-cli
DUNE_IU_PACKAGES1+=message-switch-unix xapi-idl xapi-forkexecd xapi-storage xapi-storage-script xapi-storage-cli
DUNE_IU_PACKAGES1+=xapi-nbd varstored-guard xapi-log xapi-open-uri xapi-tracing xapi-tracing-export xapi-expiry-alerts cohttp-posix
DUNE_IU_PACKAGES1+=xapi-rrd xapi-inventory clock xapi-sdk
DUNE_IU_PACKAGES1+=xapi-stdext-date xapi-stdext-encodings xapi-stdext-pervasives xapi-stdext-std xapi-stdext-threads xapi-stdext-unix xapi-stdext-zerocheck xapi-tools
Expand All @@ -173,7 +178,7 @@ DUNE_IU_PACKAGES3=-j $(JOBS) --destdir=$(DESTDIR) --prefix=$(OPTDIR) --libdir=$(
install-dune3:
dune install $(DUNE_IU_PACKAGES3)

DUNE_IU_PACKAGES4=-j $(JOBS) --destdir=$(DESTDIR) --prefix=$(PREFIX) --libdir=$(LIBDIR) --libexecdir=/usr/libexec --mandir=$(MANDIR) vhd-tool
DUNE_IU_PACKAGES4=-j $(JOBS) --destdir=$(DESTDIR) --prefix=$(PREFIX) --libdir=$(LIBDIR) --libexecdir=/usr/libexec --mandir=$(MANDIR) vhd-tool forkexec

install-dune4:
dune install $(DUNE_IU_PACKAGES4)
Expand Down
21 changes: 21 additions & 0 deletions ocaml/forkexecd/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(data_only_dirs helper)

(rule
(deps (source_tree helper))
(targets vfork_helper)
(package forkexec)
(action
(no-infer
(progn
(chdir helper (run make))
(copy helper/vfork_helper vfork_helper)
)
)
)
)

(install
(package forkexec)
(section libexec_root)
(files (vfork_helper as xapi/vfork_helper))
)
33 changes: 33 additions & 0 deletions ocaml/forkexecd/helper/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## Set some macro but not override environment ones
CFLAGS ?= -O2 -g -Wall -Werror
LDFLAGS ?=

all:: vfork_helper

clean::
rm -f vfork_helper *.o

%.o: %.c
$(CC) $(CFLAGS) -MMD -MP -MF $@.d -c -o $@ $<

vfork_helper: vfork_helper.o close_from.o syslog.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -pthread

-include $(wildcard *.o.d)

## Fuzzer uses AFL (American Fuzzy Lop).
##
## Use "make fuzz" to build and launch the fuzzer
##
## Use "make show" to look at the first failures (if found).

fuzz::
afl-gcc $(CFLAGS) -Wall -Werror -o algo_fuzzer algo_fuzzer.c
rm -rf testcase_dir
mkdir testcase_dir
echo maomaoamaoaoao > testcase_dir/test1
rm -rf findings_dir/
afl-fuzz -i testcase_dir -o findings_dir -D -- ./algo_fuzzer

show::
cat "$$(ls -1 findings_dir/default/crashes/id* | head -1)" | ./algo_fuzzer
246 changes: 246 additions & 0 deletions ocaml/forkexecd/helper/algo_fuzzer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@

/*
* Copyright (C) Cloud Software Group, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

#undef NDEBUG
#define DEBUG 1

#if DEBUG
#define log(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
#else
#define log(fmt, ...) do {} while(0)
#endif

// include as first file to make sure header is self contained
#include "redirect_algo.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>

static int fake_close(int fd);

typedef struct {
bool open;
bool cloexec;
char *name;
} fd;

#define NUM_FDS 4096
static fd fds[NUM_FDS];

static bool
fake_close_fds_from(int fd_from)
{
for (int fd = fd_from; fd < NUM_FDS; ++fd)
fake_close(fd);

return true;
}

#define O_WRONLY 1
static int
fake_open(const char *fn, int dummy)
{
for (int i = 0; i < NUM_FDS; ++i)
if (!fds[i].open) {
assert(fds[i].name == NULL);
fds[i].name = strdup(fn);
fds[i].open = true;
fds[i].cloexec = false;
return i;
}
assert(0);
return -1;
}

static int
fake_close(int fd)
{
assert(fd >= 0);
assert(fd < NUM_FDS);
if (!fds[fd].open) {
errno = EBADF;
return -1;
}
fds[fd].open = false;
free(fds[fd].name);
fds[fd].name = NULL;
return 0;
}

static int
fake_dup2(int from, int to)
{
assert(from >= 0 && from < NUM_FDS);
assert(to >= 0 && to < NUM_FDS);
assert(fds[from].open);
assert(from != to);
free(fds[to].name);
fds[to].open = true;
fds[to].name = strdup(fds[from].name);
fds[to].cloexec = false;
return 0;
}

static int
fake_fcntl(int fd)
{
assert(fd >= 0 && fd < NUM_FDS);
assert(fds[fd].open);
fds[fd].cloexec = false;
return 0;
}

int main(int argc, char **argv)
{
// Input where a given FD goes??
// No, not enough, can be duplicated.
// Numbers >4096 in 2 bytes not file descriptor,
// (-1 for standard, skip for normal).
// We should add some random fds.
enum { MAX_FILE_BUF = 2048 };
uint16_t file_buf[MAX_FILE_BUF];
size_t read = fread(file_buf, 2, MAX_FILE_BUF, stdin);
if (read < 3)
return 0;

static const char standard_names[][8] = {
"stdin", "stdout", "stderr"
};
int num_mappings = 0;
uint16_t *num = file_buf;
mapping mappings[MAX_FILE_BUF];
int i = 0;
for (i = 0; i < 3; ++i) {
mapping *m = &mappings[num_mappings++];
m->uuid = standard_names[i];
uint16_t n = *num++;
m->current_fd = n < NUM_FDS ? n : -1;
m->wanted_fd = i;
}
for (; i < read; ++i) {
uint16_t n = *num++;
if (n >= NUM_FDS)
continue;

mapping *m = &mappings[num_mappings++];
m->current_fd = n;
m->wanted_fd = -1;
char buf[64];
sprintf(buf, "file%d", i);
m->uuid = strdup(buf);
}
if (num_mappings > MAX_TOTAL_MAPPINGS)
return 0;

for (unsigned n = 0; n < num_mappings; ++n) {
mapping *m = &mappings[n];
int fd = m->current_fd;
if (fd < 0)
continue;
fake_close(fd);
fds[fd].open = true;
fds[fd].name = strdup(m->uuid);
fds[fd].cloexec = true;
}

// Check in the final file mapping all valid mappings
// have an open file descriptor.
// There should be no duplicate numbers in current_fd.
// current_fd must be in a range.
// Only if wanted_fd >= 0 current_fd can be -1.
// There should be a correspondance between input and output names.
// If current_fd was -1 it will still be -1.
// If wanted_fd >= 0 current_fd should be the same.

fd_operation operations[MAX_OPERATIONS];
int num_operations =
redirect_mappings(mappings, num_mappings, operations);
assert(num_operations > 0);
assert(num_operations <= MAX_OPERATIONS);

for (int i = 0; i < num_operations; ++i) {
const fd_operation* op = &operations[i];
log("op %d %d %d", op->fd_from, op->fd_to, op->operation);
switch (op->operation) {
case FD_OP_DUP:
if (op->fd_from == op->fd_to)
fake_fcntl(op->fd_from);
else
fake_dup2(op->fd_from, op->fd_to);
break;
case FD_OP_MOVE:
assert(op->fd_from != op->fd_to);
fake_dup2(op->fd_from, op->fd_to);
fake_close(op->fd_from);
break;
case FD_OP_DEVNULL:
// first close old, then create new one
fake_close(op->fd_to);
// TODO ideally we want read only for input for Ocaml did the same...
assert(fake_open("/dev/null", O_WRONLY) == op->fd_to);
break;
case FD_OP_CLOSE_FROM:
fake_close_fds_from(op->fd_from);
break;
default:
assert(0);
}
}

// check files opened
for (int fd = 0; fd < NUM_FDS; ++fd)
assert(fds[fd].open == (fd < num_mappings));

for (int fd = 0; fd < num_mappings; ++fd) {
assert(fds[fd].cloexec == false);
log("file %d %s", fd, fds[fd].name);
}

// Check in the final file mapping all valid mappings
// has an open file descriptor.
bool already_found[NUM_FDS] = { false, };
for (unsigned n = 0; n < num_mappings; ++n) {
const int fd = mappings[n].current_fd;
const int wanted = mappings[n].wanted_fd;
if (fd >= 0) {
assert(fd < NUM_FDS);
assert(fds[fd].open);

// There should be no duplicate numbers in current_fd.
assert(!already_found[fd]);
already_found[fd] = true;
} else {
// Only if wanted_fd >= 0 current_fd can be -1.
assert(mappings[n].wanted_fd >= 0);
assert(fd == -1);
}

// If wanted_fd >= 0 current_fd should be the same.
if (wanted >= 0)
assert(wanted == fd || fd == -1);

// current_fd must be in a range.
assert(fd >= -1);
assert(fd < num_mappings);
}

// There should be a correspondance between input and output names.
// If current_fd was -1 it will still be -1.
}
Loading

0 comments on commit a26a387

Please sign in to comment.