Skip to content

Commit cc77ace

Browse files
author
Brad Larsen
authored
Overhaul Linux file emulation (#1673)
Overhaul Linux file emulation. Previously, open file descriptors could be mapped to any of the `File`, `Directory`, `SocketDesc`, `Socket`, and `ProcSelfMaps` classes, which didn't share a common supertype, and which didn't have consistent interfaces. Now, each of these classes implements the `FdLike` abstract base class, which specifies a number of methods. This overhaul additionally fixes several issues with the Linux support code: - A program that tried to ioctl on a socket would crash Manticore - In several places, the error code returned by a failing syscall was incorrect - Many file descriptor operations could crash Manticore when used on an already-closed descriptor - Manticore state serialization / deserialization was incorrect for file descriptor types other than File or Socket - In certain cases, `sys_open` / `sys_openat` could crash Manticore when trying to log a debug message - In certain cases, `sys_readv` could crash Manticore, instead of correctly returning a negative int value - `sys_sendfile` was broken due to a variable name typo - In several places in Manticore’s Linux support code, incorrect type hints were present - In some places, an exception would attempt to be raised, but that itself would crash due to a missing import. This commit adds two more example / integration test programs. Additionally, this adds a helper for working with Python abstract base classes. This helper lets you declare on a class, via a decorator, that the class is expected to have no unimplemented abstract methods. If this is not true at runtime, a `TypeError` is thrown. Without this decorator, you will only discover that a class has unimplemented abstract methods when you try to _instantiate_ that class. This may be much, much later than at class creation time, or perhaps not at all, depending on your code coverage. Thanks to Eric Kilmer <eric.d.kilmer@gmail.com> for review!
1 parent f3dcd63 commit cc77ace

12 files changed

Lines changed: 467 additions & 249 deletions

File tree

examples/linux/Makefile

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@ CFLAGS=-O3 -static
33
NOSTDLIBFLAGS=-fno-builtin -static -nostdlib -fomit-frame-pointer -fno-stack-protector
44
PYTHON=python3
55

6-
EXAMPLES= \
7-
arguments \
8-
basic \
9-
crackme \
10-
fclose \
11-
fileio \
12-
helloworld \
13-
ibranch \
14-
indexhell \
15-
sendmail \
16-
simpleassert \
17-
simple_copy \
18-
sindex \
19-
strncmp \
6+
EXAMPLES= \
7+
arguments \
8+
basic \
9+
crackme \
10+
fclose \
11+
fileio \
12+
helloworld \
13+
ibranch \
14+
indexhell \
15+
ioctl_bogus \
16+
ioctl_socket \
17+
sendmail \
18+
simpleassert \
19+
simple_copy \
20+
sindex \
21+
strncmp \
2022

2123
OTHER_EXAMPLES=nostdlib
2224

examples/linux/fileio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ int main(int argc, const char **argv) {
2525
return 3;
2626
}
2727

28-
if (strcmp("my voice is my passport verify me", line) == 0) {
28+
if (strcmp("open sesame", line) == 0) {
2929
fprintf(stdout, "Welcome!\n");
3030
return 0;
3131
} else {

examples/linux/ioctl_bogus.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This example demonstrates a particular syscall that fails at runtime.
2+
// Used primarily as a test of Manticore's file-related syscall implementation.
3+
4+
#include <errno.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
#include <stropts.h>
8+
#include <sys/socket.h>
9+
10+
int main() {
11+
// try bogus ioctl on a non-open file descriptor
12+
int rc = ioctl(42, I_FLUSH, FLUSHRW);
13+
if (rc == -1) {
14+
fprintf(stderr, "got expected error: %s\n", strerror(errno));
15+
return 0;
16+
} else {
17+
fprintf(stdout, "unexpectedly succeeded!\n");
18+
return 1;
19+
}
20+
}

examples/linux/ioctl_socket.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// This example demonstrates a particular syscall that fails at runtime.
2+
// Used primarily as a test of Manticore's file-related syscall implementation.
3+
4+
#include <errno.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
#include <stropts.h>
8+
#include <sys/socket.h>
9+
10+
int main() {
11+
// try bogus ioctl on a socket
12+
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
13+
if (sockfd < 0) {
14+
fprintf(stderr, "error opening socket: %s\n", strerror(errno));
15+
return 1;
16+
}
17+
18+
int rc = ioctl(sockfd, I_FLUSH, FLUSHRW);
19+
if (rc == -1) {
20+
fprintf(stderr, "got expected error calling ioctl: %s\n", strerror(errno));
21+
return 0;
22+
} else {
23+
fprintf(stdout, "unexpectedly succeeded!\n");
24+
return 2;
25+
}
26+
}

manticore/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from manticore.native.cli import native_main
2626

2727

28-
def main():
28+
def main() -> None:
2929
"""
3030
Dispatches execution into one of Manticore's engines: evm or native.
3131
"""
@@ -50,7 +50,7 @@ def main():
5050
native_main(args, logger)
5151

5252

53-
def parse_arguments():
53+
def parse_arguments() -> argparse.Namespace:
5454
def positive(value):
5555
ivalue = int(value)
5656
if ivalue <= 0:

manticore/native/manticore.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from ..core.manticore import ManticoreBase
1414
from ..core.smtlib import ConstraintSet
1515
from ..core.smtlib.solver import Z3Solver, issymbolic
16+
from ..exceptions import ManticoreError
1617
from ..utils import log, config
1718

1819
logger = logging.getLogger(__name__)
@@ -383,7 +384,7 @@ def _make_linux(
383384
concrete_start="",
384385
pure_symbolic=False,
385386
stdin_size=None,
386-
):
387+
) -> State:
387388
from ..platforms import linux
388389

389390
env = {} if env is None else env

0 commit comments

Comments
 (0)