11f5207bJohn Levon#include "smatch.h"
21f5207bJohn Levon#include "linearize.h"
31f5207bJohn Levon
41f5207bJohn Levonstatic int my_id;
51f5207bJohn Levonstatic struct symbol *cur_syscall;
61f5207bJohn Levon
71f5207bJohn Levonstatic const char *expression_type_name(enum expression_type type)
81f5207bJohn Levon{
91f5207bJohn Levon	static const char *expression_type_name[] = {
101f5207bJohn Levon		[EXPR_VALUE] = "EXPR_VALUE",
111f5207bJohn Levon		[EXPR_STRING] = "EXPR_STRING",
121f5207bJohn Levon		[EXPR_SYMBOL] = "EXPR_SYMBOL",
131f5207bJohn Levon		[EXPR_TYPE] = "EXPR_TYPE",
141f5207bJohn Levon		[EXPR_BINOP] = "EXPR_BINOP",
151f5207bJohn Levon		[EXPR_ASSIGNMENT] = "EXPR_ASSIGNMENT",
161f5207bJohn Levon		[EXPR_LOGICAL] = "EXPR_LOGICAL",
171f5207bJohn Levon		[EXPR_DEREF] = "EXPR_DEREF",
181f5207bJohn Levon		[EXPR_PREOP] = "EXPR_PREOP",
191f5207bJohn Levon		[EXPR_POSTOP] = "EXPR_POSTOP",
201f5207bJohn Levon		[EXPR_CAST] = "EXPR_CAST",
211f5207bJohn Levon		[EXPR_FORCE_CAST] = "EXPR_FORCE_CAST",
221f5207bJohn Levon		[EXPR_IMPLIED_CAST] = "EXPR_IMPLIED_CAST",
231f5207bJohn Levon		[EXPR_SIZEOF] = "EXPR_SIZEOF",
241f5207bJohn Levon		[EXPR_ALIGNOF] = "EXPR_ALIGNOF",
251f5207bJohn Levon		[EXPR_PTRSIZEOF] = "EXPR_PTRSIZEOF",
261f5207bJohn Levon		[EXPR_CONDITIONAL] = "EXPR_CONDITIONAL",
271f5207bJohn Levon		[EXPR_SELECT] = "EXPR_SELECT",
281f5207bJohn Levon		[EXPR_STATEMENT] = "EXPR_STATEMENT",
291f5207bJohn Levon		[EXPR_CALL] = "EXPR_CALL",
301f5207bJohn Levon		[EXPR_COMMA] = "EXPR_COMMA",
311f5207bJohn Levon		[EXPR_COMPARE] = "EXPR_COMPARE",
321f5207bJohn Levon		[EXPR_LABEL] = "EXPR_LABEL",
331f5207bJohn Levon		[EXPR_INITIALIZER] = "EXPR_INITIALIZER",
341f5207bJohn Levon		[EXPR_IDENTIFIER] = "EXPR_IDENTIFIER",
351f5207bJohn Levon		[EXPR_INDEX] = "EXPR_INDEX",
361f5207bJohn Levon		[EXPR_POS] = "EXPR_POS",
371f5207bJohn Levon		[EXPR_FVALUE] = "EXPR_FVALUE",
381f5207bJohn Levon		[EXPR_SLICE] = "EXPR_SLICE",
391f5207bJohn Levon		[EXPR_OFFSETOF] = "EXPR_OFFSETOF",
401f5207bJohn Levon	};
411f5207bJohn Levon	return expression_type_name[type] ?: "UNKNOWN_EXPRESSION_TYPE";
421f5207bJohn Levon}
431f5207bJohn Levon
441f5207bJohn Levonstatic inline void prefix() {
451f5207bJohn Levon	printf("%s:%d %s() ", get_filename(), get_lineno(), get_function());
461f5207bJohn Levon}
471f5207bJohn Levon
481f5207bJohn Levonstatic void match_syscall_definition(struct symbol *sym)
491f5207bJohn Levon{
501f5207bJohn Levon	// struct symbol *arg;
511f5207bJohn Levon	char *macro;
521f5207bJohn Levon	char *name;
531f5207bJohn Levon	int is_syscall = 0;
541f5207bJohn Levon
551f5207bJohn Levon	macro = get_macro_name(sym->pos);
561f5207bJohn Levon	if (macro &&
571f5207bJohn Levon	    (strncmp("SYSCALL_DEFINE", macro, strlen("SYSCALL_DEFINE")) == 0 ||
581f5207bJohn Levon	     strncmp("COMPAT_SYSCALL_DEFINE", macro, strlen("COMPAT_SYSCALL_DEFINE")) == 0))
591f5207bJohn Levon		is_syscall = 1;
601f5207bJohn Levon
611f5207bJohn Levon	name = get_function();
621f5207bJohn Levon
631f5207bJohn Levon	/*
641f5207bJohn Levon	if (!option_no_db && get_state(my_id, "this_function", NULL) != &called) {
651f5207bJohn Levon		if (name && strncmp(name, "sys_", 4) == 0)
661f5207bJohn Levon			is_syscall = 1;
671f5207bJohn Levon	}
681f5207bJohn Levon	*/
691f5207bJohn Levon
701f5207bJohn Levon	/* Ignore compat_sys b/c syzkaller doesn't fuzz these?
711f5207bJohn Levon	if (name && strncmp(name, "compat_sys_", 11) == 0)
721f5207bJohn Levon		is_syscall = 1;
731f5207bJohn Levon	*/
741f5207bJohn Levon
751f5207bJohn Levon	if (!is_syscall)
761f5207bJohn Levon		return;
771f5207bJohn Levon	printf("-------------------------\n");
781f5207bJohn Levon	printf("\nsyscall found: %s at: ", name);
791f5207bJohn Levon	prefix(); printf("\n");
801f5207bJohn Levon	cur_syscall = sym;
811f5207bJohn Levon
821f5207bJohn Levon	/*
831f5207bJohn Levon	FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
841f5207bJohn Levon		set_state(my_id, arg->ident->name, arg, &user_data_set);
851f5207bJohn Levon	} END_FOR_EACH_PTR(arg);
861f5207bJohn Levon	*/
871f5207bJohn Levon}
881f5207bJohn Levon
891f5207bJohn Levonstatic void match_after_syscall(struct symbol *sym) {
901f5207bJohn Levon    if (cur_syscall && sym == cur_syscall) {
911f5207bJohn Levon	printf("\n"); prefix();
921f5207bJohn Levon	printf("exiting scope of syscall %s\n", get_function());
931f5207bJohn Levon	printf("-------------------------\n");
941f5207bJohn Levon	cur_syscall = NULL;
951f5207bJohn Levon    }
961f5207bJohn Levon}
971f5207bJohn Levon
981f5207bJohn Levonstatic void print_member_type(struct expression *expr)
991f5207bJohn Levon{
1001f5207bJohn Levon	char *member;
1011f5207bJohn Levon
1021f5207bJohn Levon	member = get_member_name(expr);
1031f5207bJohn Levon	if (!member)
1041f5207bJohn Levon		return;
1051f5207bJohn Levon	// sm_msg("info: uses %s", member);
1061f5207bJohn Levon	prefix();
1071f5207bJohn Levon	printf("info: uses %s\n", member);
1081f5207bJohn Levon	free_string(member);
1091f5207bJohn Levon}
1101f5207bJohn Levon
1111f5207bJohn Levonstatic void match_condition(struct expression *expr) {
1121f5207bJohn Levon    if (!cur_syscall)
1131f5207bJohn Levon	return;
1141f5207bJohn Levon
1151f5207bJohn Levon    /*
1161f5207bJohn Levon    prefix();
1171f5207bJohn Levon    printf("found conditional %s on line %d\n", expression_type_name(expr->type), get_lineno());
1181f5207bJohn Levon    printf("expr_str: %s\n", expr_to_str(expr));
1191f5207bJohn Levon    */
1201f5207bJohn Levon
1211f5207bJohn Levon    /*
1221f5207bJohn Levon    switch (expr->type) {
1231f5207bJohn Levon	case EXPR_COMPARE:
1241f5207bJohn Levon	    match_condition(expr->left);
1251f5207bJohn Levon	    match_condition(expr->right);
1261f5207bJohn Levon	    break;
1271f5207bJohn Levon	case EXPR_SYMBOL:
1281f5207bJohn Levon	    printf("symbol: %s\n", expr->symbol_name->name);
1291f5207bJohn Levon	    break;
1301f5207bJohn Levon	case EXPR_CALL:
1311f5207bJohn Levon	    break;
1321f5207bJohn Levon    }
1331f5207bJohn Levon    */
1341f5207bJohn Levon
1351f5207bJohn Levon    prefix(); printf("-- condition found\n");
1361f5207bJohn Levon
1371f5207bJohn Levon    if (expr->type == EXPR_COMPARE || expr->type == EXPR_BINOP
1381f5207bJohn Levon	    || expr->type == EXPR_LOGICAL
1391f5207bJohn Levon	    || expr->type == EXPR_ASSIGNMENT
1401f5207bJohn Levon	    || expr->type == EXPR_COMMA) {
1411f5207bJohn Levon	    match_condition(expr->left);
1421f5207bJohn Levon	    match_condition(expr->right);
1431f5207bJohn Levon	    return;
1441f5207bJohn Levon    }
1451f5207bJohn Levon    print_member_type(expr);
1461f5207bJohn Levon
1471f5207bJohn Levon}
1481f5207bJohn Levon
1491f5207bJohn Levonstatic void match_function_call(struct expression *expr) {
1501f5207bJohn Levon    if (!cur_syscall)
1511f5207bJohn Levon	return;
1521f5207bJohn Levon    prefix();
1531f5207bJohn Levon    printf("function call %s\n", expression_type_name(expr->type));
1541f5207bJohn Levon}
1551f5207bJohn Levon
1561f5207bJohn Levonvoid check_implicit_dependencies_tester(int id)
1571f5207bJohn Levon{
1581f5207bJohn Levon    my_id = id;
1591f5207bJohn Levon
1601f5207bJohn Levon    if (option_project != PROJ_KERNEL)
1611f5207bJohn Levon	return;
1621f5207bJohn Levon
1631f5207bJohn Levon    add_hook(&match_syscall_definition, AFTER_DEF_HOOK);
1641f5207bJohn Levon    add_hook(&match_after_syscall, AFTER_FUNC_HOOK);
1651f5207bJohn Levon    add_hook(&match_condition, CONDITION_HOOK);
1661f5207bJohn Levon    add_hook(&match_function_call, FUNCTION_CALL_HOOK);
1671f5207bJohn Levon}
1681f5207bJohn Levon
169