Calling a function in C without naming it

62 points by mrnossiom a day ago on lobsters | 17 comments

nathell | 23 hours ago

This reminds me how, way back when, at one of the classes in my school we were expected to adhere to coding standards provided. Said coding standards prohibited the use of tabs throughout all files (the language expected was C). They further mandated all submissions to include a Makefile.

Taken literally, this would mean that tabs were forbidden in Makefiles, which as everyone knows makes it pretty impossible to do anything. But I found a way to circumvent this and have tab-less Makefiles that did what they were expected to do! Indeed, I wrote a converter from tabful to tabless Makefiles.

Here’s how it worked – it transformed this:

all:
	gcc a.c -o a

to this:

FOO := $(shell echo 'all:\n\tgcc a.c -o a' > GNUmakefile; $(MAKE) >&2)

all:

i.e. a Makefile containing one rule that does nothing, and defining a dummy eagerly-evaluated variable whose evaluation would write the actual makefile content to a file that takes precedence over the original one, and invoke make recursively on that. This took advantage of the fact that GNU make (nobody used anything else) looks at GNUmakefile first, then makefile, then Makefile.

I never got bonus points for this, but hey, now I have an amusing story!

geocar | 14 hours ago

you can also use semicolon:

all:;gcc -o a a.c

nathell | 14 hours ago

Well what do you know, this would have been much simpler! TIL, thank you!

I'm trying to register in my mind why tabs would be prohibited, did you ever bother to ask?

nathell | 13 hours ago

I didn’t. I assumed this was an exercise in adhering to standards mandated by existing projects we’d encounter in real life.

jaculabilis | 16 hours ago

Preventing arbitrary code from containing a syscall invocation seems like an uphill battle, but if the school controls the execution environment, it would much easier to just run the program through strace with the offending syscalls blocked.

classichasclass | 20 hours ago

So, c'mon, what did your school say when they saw you try this? The story is unfinished! ;)

treykeown | 15 hours ago

Love the cat-and-mouse game of casual sandboxing like this. My guess would be that dlsym(RTLD_NEXT, "execve") should work as well.

invlpg | 15 hours ago

Only if dlsym is an allowed symbol.

[OP] mrnossiom | 3 hours ago

Though I didn't mention it in the article, I did think of dlsym before looking into mmap but the issue is the same as execve, that is there is no symbol that is usable most of the time that lives in the same object as dlsym.

If we wanted to go further, an option would be to reimplement dlsym in user code, leak the base address of libc by reading /proc/<pid>/maps and load symbols. We still need what's done in the article to get open/read access.

accelbread | 20 hours ago

Seems like the system could handle this by compiling the code to wasm, with only the allowed stdlib functions allowed for import.

[OP] mrnossiom | 6 hours ago

This would work for pure C algorithmic exercises, but many of the exercises we have involve interacting with POSIX APIs. This would also make the compilation behaviour different between the students computers and the grader system.

kriive | 14 hours ago

Awesome article! Did you try to run something like this?

char *argv[] = {"/bin/sh", NULL};
char *envp[] = {NULL};
long ret;

__asm__ volatile (
    "syscall"
    : "=a"(ret)
    : "0"(59L),   // SYS_execve
      "D"(argv[0]),
      "S"(argv),
      "d"(envp)
    : "rcx", "r11", "memory"
);

As for how to mitigate this, the sandbox could try to use seccomp. Ideally it should allow only a subset of the syscalls (i.e. not execve)

[OP] mrnossiom | 6 hours ago

I didn't mention it in the article, but usage of inline assembly is checked and banned before execution. A lot of replies talk about filtering syscalls, it works but some exercises may need usage of those syscalls. It may become tedious to annotate every exercises with a whitelist of syscalls. I don't think my school will bother patching it.

sammko | 11 hours ago

This reminded me of ioi/isolate which tries to solve a very similar use case for IOI competitions.

https://github.com/ioi/isolate

Shorden | 7 hours ago

My school had the prescient idea to solicit feedback from CTF players to help strengthen their sandboxing implementations.

icefox | 2 hours ago

something something system call capabilities something something