clang not stuck at #include "/dev/whatever"

108 views Asked by At

I'm working on a project of code safety of online judger. One possible vulnerability is when someone uploads a piece of code like this:

#include "/dev/stdin"
#include "/proc/self/fd/0"
#include <stdio.h>
// Other legitimate code

I'm trying to reproduce it. When compiling it with gcc foo.c, gcc gets stuck and reads from terminal until EOF (Ctrl-D) as expected. When I clang foo.c, well, nothing happened. Clang just behaves as if the lines have never existed. Then I tried these codes:

#include "/dev/zero"
#include "/dev/random"
#include "/dev/ram"

Still no luck. Why does Clang ignore all these? How can I make Clang stuck by #include-ing something?

2

There are 2 answers

1
mevets On BEST ANSWER

Make a fifo, and #include it. Note this only appears to stop clang; it doesn’t read from it. This might only work until the clang team see this....

0
John Bollinger On

The C standard specifies that

A preprocessing directive of the form

# include <h-char-sequence> new-line

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence [...]. How the places are specified or the header identified is implementation-defined.

A preprocessing directive of the form

# include "q-char-sequence" new-line

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

# include <h-char-sequence> new-line

with the identical contained sequence (including > characters, if any) from the original directive.

(C2011 6.10.2/2-3; emphasis added)

In particular, a C implementation is by no means required to interpret a header name that has the form of an absolute path as an absolute path. Such header names are not even among those for which a conforming compiler must provide unique mappings.

Conforming C compilers must document all implementation-defined behaviors. GCC does provide documentation covering this area, but those docs do not seem to address absolute paths explicitly. It seems reasonable to me, however, that GCC just uses given path. Clang evidently behaves differently, but it does not document its implementation-defined behaviors (and therefore is non-conforming in that regard). Its output may give clues about what it's doing.

Update:

Why does Clang ignore all these?

You could examine its source to determine the details of what Clang is doing, but only the Clang development team could tell you for sure why Clang is implemented that way. Perhaps its developers anticipated your hosted-service use case and intentionally hardened Clang against the kind of attack you describe.

How can I make Clang stuck by #include-ing something?

The approaches you've already tried seem the most likely ones. If they didn't work then there might not be a way to break Clang that way.