From 8aaf5d60aa0b3ddb05e117f52c0e30ec246b7aad Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 17 Jan 2025 10:39:49 +0100 Subject: tools/syz-declextract: support function scopes Extract info about function scopes formed by switch'es on function arguments. For example if we have: void foo(..., int cmd, ...) { ... switch (cmd) { case FOO: ... block 1 ... case BAR: ... block 2 ... } ... } We record that any data flow within block 1 is only relevant when foo's arg cmd has value FOO, similarly for block 2 and BAR. This allows to do 3 things: 1. Locate ioctl commands that are switched on within transitively called functions. 2. Infer return value for each ioctl command. 3. Infer argument type when it's not specified in _IO macro. This will also allow to infer other multiplexed syscalls. Descriptions generated on Linux commit c4b9570cfb63501. --- .../testdata/file_operations.c.json | 313 +++++++++++++++------ 1 file changed, 230 insertions(+), 83 deletions(-) (limited to 'tools/syz-declextract/testdata/file_operations.c.json') diff --git a/tools/syz-declextract/testdata/file_operations.c.json b/tools/syz-declextract/testdata/file_operations.c.json index c8fd5a9dc..e7dfd31f6 100644 --- a/tools/syz-declextract/testdata/file_operations.c.json +++ b/tools/syz-declextract/testdata/file_operations.c.json @@ -4,53 +4,174 @@ "name": "foo_ioctl", "file": "file_operations.c", "is_static": true, - "loc": 7 + "scopes": [ + { + "arg": -1, + "loc": 2, + "calls": [ + "foo_ioctl2" + ], + "facts": [ + { + "src": { + "argument": { + "func": "foo_ioctl", + "arg": 1 + } + }, + "dst": { + "argument": { + "func": "foo_ioctl2", + "arg": 0 + } + } + }, + { + "src": { + "argument": { + "func": "foo_ioctl", + "arg": 2 + } + }, + "dst": { + "argument": { + "func": "foo_ioctl2", + "arg": 1 + } + } + } + ] + }, + { + "arg": 1, + "values": [ + "FOO_IOCTL1", + "FOO_IOCTL2", + "FOO_IOCTL3", + "FOO_IOCTL4", + "FOO_IOCTL5" + ], + "loc": 5 + } + ] + }, + { + "name": "foo_ioctl2", + "file": "file_operations.c", + "is_static": true, + "scopes": [ + { + "arg": -1, + "loc": 1 + }, + { + "arg": 0, + "values": [ + "FOO_IOCTL6", + "FOO_IOCTL7" + ], + "loc": 3 + } + ] }, { "name": "foo_mmap", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "foo_open", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "foo_read", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "foo_write", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "proc_ioctl", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "proc_open", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "proc_read", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "proc_write", "file": "file_operations.c", - "is_static": true + "is_static": true, + "scopes": [ + { + "arg": -1 + } + ] }, { "name": "unused_ioctl", "file": "file_operations.c", "is_static": true, - "loc": 4 + "scopes": [ + { + "arg": -1, + "loc": 1 + }, + { + "arg": 1, + "values": [ + "UNUSED_IOCTL1", + "UNUSED_IOCTL2" + ], + "loc": 2 + } + ] } ], "consts": [ @@ -79,6 +200,16 @@ "filename": "include/uapi/file_operations.h", "value": 3221775109 }, + { + "name": "FOO_IOCTL6", + "filename": "include/uapi/file_operations.h", + "value": 25350 + }, + { + "name": "FOO_IOCTL7", + "filename": "include/uapi/file_operations.h", + "value": 25351 + }, { "name": "UNUSED_IOCTL1", "filename": "include/uapi/unused_ioctl.h", @@ -129,63 +260,6 @@ "write": "foo_write", "mmap": "foo_mmap", "ioctl": "foo_ioctl", - "ioctl_cmds": [ - { - "name": "FOO_IOCTL5", - "type": { - "ptr": { - "elem": { - "struct": "foo_ioctl_arg" - } - } - } - }, - { - "name": "FOO_IOCTL4", - "type": { - "ptr": { - "elem": { - "struct": "foo_ioctl_arg" - } - } - } - }, - { - "name": "FOO_IOCTL3", - "type": { - "ptr": { - "elem": { - "struct": "foo_ioctl_arg" - }, - "is_const": true - } - } - }, - { - "name": "FOO_IOCTL2", - "type": { - "ptr": { - "elem": { - "int": { - "byte_size": 4, - "name": "int", - "base": "int" - } - }, - "is_const": true - } - } - }, - { - "name": "FOO_IOCTL1", - "type": { - "int": { - "byte_size": 1, - "is_const": true - } - } - } - ], "source_file": "file_operations.c" }, { @@ -206,27 +280,100 @@ { "name": "unused_file_operations", "ioctl": "unused_ioctl", - "ioctl_cmds": [ - { - "name": "UNUSED_IOCTL2", - "type": { + "source_file": "file_operations.c" + } + ], + "ioctls": [ + { + "name": "FOO_IOCTL1", + "type": { + "int": { + "byte_size": 1, + "is_const": true + } + } + }, + { + "name": "FOO_IOCTL2", + "type": { + "ptr": { + "elem": { "int": { - "byte_size": 1, - "is_const": true + "byte_size": 4, + "name": "int", + "base": "int" } + }, + "is_const": true + } + } + }, + { + "name": "FOO_IOCTL3", + "type": { + "ptr": { + "elem": { + "struct": "foo_ioctl_arg" + }, + "is_const": true + } + } + }, + { + "name": "FOO_IOCTL4", + "type": { + "ptr": { + "elem": { + "struct": "foo_ioctl_arg" } - }, - { - "name": "UNUSED_IOCTL1", - "type": { - "int": { - "byte_size": 1, - "is_const": true - } + } + } + }, + { + "name": "FOO_IOCTL5", + "type": { + "ptr": { + "elem": { + "struct": "foo_ioctl_arg" } } - ], - "source_file": "file_operations.c" + } + }, + { + "name": "FOO_IOCTL6", + "type": { + "int": { + "byte_size": 1, + "is_const": true + } + } + }, + { + "name": "FOO_IOCTL7", + "type": { + "int": { + "byte_size": 1, + "is_const": true + } + } + }, + { + "name": "UNUSED_IOCTL1", + "type": { + "int": { + "byte_size": 1, + "is_const": true + } + } + }, + { + "name": "UNUSED_IOCTL2", + "type": { + "int": { + "byte_size": 1, + "is_const": true + } + } } ] } \ No newline at end of file -- cgit mrf-deployment