2 * Copyright (C) 2011 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 /* The below code is an adjustment of the smatch_kernel_user_data.c to
19 * track (untrusted and potentially malicious) data received by a guest
20 * kernel via various low-level port IO, MMIO, MSR, CPUID and PCI config
21 * space access functions (see func_table for a full list) from an
22 * untrusted host/VMM under confidential computing threat model
23 * (where a guest VM does not trust the host/VMM).
24 * We call this data as 'host' data here. Being able to track host data
25 * allows creating new smatch patterns that can perform various checks
26 * on such data, i.e. verify that that there are no spectre v1 gadgets
27 * on this attack surface or even simply report locations where host data
28 * is being processed in the kernel source code (useful for a targeted code
30 * Similar as smatch_kernel_user_data.c it works with
31 * smatch_points_to_host_input.c code.
33 * Copyright (C) 2022 Elena Reshetova Intel Corporation.
37 #include "smatch_slist.h"
38 #include "smatch_extra.h"
45 const sval_t
*implies_start
, *implies_end
;
49 static struct host_fn_info func_table
[] = {
50 /* Functions that return host data as return value */
51 { "inb", HOST_DATA
, -1, "$" },
52 { "inw", HOST_DATA
, -1, "$" },
53 { "inl", HOST_DATA
, -1, "$" },
54 { "__inb", HOST_DATA
, -1, "$" },
55 { "__inw", HOST_DATA
, -1, "$" },
56 { "__inl", HOST_DATA
, -1, "$" },
57 { "ioread8", HOST_DATA
, -1, "$" },
58 { "ioread16", HOST_DATA
, -1, "$" },
59 { "ioread32", HOST_DATA
, -1, "$" },
60 { "ioread16be", HOST_DATA
, -1, "$" },
61 { "ioread32be", HOST_DATA
, -1, "$" },
62 { "ioread64_lo_hi", HOST_DATA
, -1, "$" },
63 { "ioread64_hi_lo", HOST_DATA
, -1, "$" },
64 { "ioread64be_lo_hi", HOST_DATA
, -1, "$" },
65 { "ioread64be_hi_lo", HOST_DATA
, -1, "$" },
66 { "iomap_readq", HOST_DATA
, -1, "$" },
67 { "iomap_readb", HOST_DATA
, -1, "$" },
68 { "iomap_readw", HOST_DATA
, -1, "$" },
69 { "iomap_readl", HOST_DATA
, -1, "$" },
70 { "readb", HOST_DATA
, -1, "$" },
71 { "readw", HOST_DATA
, -1, "$" },
72 { "readl", HOST_DATA
, -1, "$" },
73 { "readq", HOST_DATA
, -1, "$" },
74 { "__raw_readb", HOST_DATA
, -1, "$" },
75 { "__raw_readw", HOST_DATA
, -1, "$" },
76 { "__raw_readl", HOST_DATA
, -1, "$" },
77 { "__raw_readq", HOST_DATA
, -1, "$" },
78 { "__readq", HOST_DATA
, -1, "$" },
79 { "__readl", HOST_DATA
, -1, "$" },
80 { "__readb", HOST_DATA
, -1, "$" },
81 { "__readw", HOST_DATA
, -1, "$" },
82 { "native_read_msr", HOST_DATA
, -1, "$" },
83 { "native_read_msr_safe", HOST_DATA
, -1, "$" },
84 { "__rdmsr", HOST_DATA
, -1, "$" },
85 { "paravirt_read_msr", HOST_DATA
, -1, "$" },
86 { "paravirt_read_msr_safe", HOST_DATA
, -1, "$" },
87 /* the below 3 apic funcs are needed
88 * since they unwrap to apic->read(reg),
89 * apic->icr_read() and *(APIC_BASE + reg) */
90 { "apic_read", HOST_DATA
, -1, "$" },
91 { "apic_icr_read", HOST_DATA
, -1, "$" },
92 { "native_apic_mem_read", HOST_DATA
, -1, "$" },
93 /* the below one is x86_apic_ops.io_apic_read */
94 { "io_apic_read", HOST_DATA
, -1, "$" },
95 /* virtio_cread8/16/32/64 funcs are needed
96 * since they call vdev->config->get */
97 { "virtio_cread8", HOST_DATA
, -1, "$" },
98 { "virtio_cread16", HOST_DATA
, -1, "$" },
99 { "virtio_cread32", HOST_DATA
, -1, "$" },
100 { "virtio_cread64", HOST_DATA
, -1, "$" },
101 { "__virtio16_to_cpu", HOST_DATA
, -1, "$" },
102 { "__virtio32_to_cpu", HOST_DATA
, -1, "$" },
103 { "__virtio64_to_cpu", HOST_DATA
, -1, "$" },
104 { "serial_dl_read", HOST_DATA
, -1, "$" },
105 { "serial_in", HOST_DATA
, -1, "$" },
106 { "serial_port_in", HOST_DATA
, -1, "$" },
107 { "cpuid_eax", HOST_DATA
, -1, "$" },
108 { "cpuid_ebx", HOST_DATA
, -1, "$" },
109 { "cpuid_ecx", HOST_DATA
, -1, "$" },
110 { "cpuid_edx", HOST_DATA
, -1, "$" },
111 /* Functions that return host data as argument 1 */
112 { "memcpy_fromio", HOST_DATA
, 0, "*$" },
113 /* Functions that return host data as argument 2 */
114 { "acpi_os_read_iomem", HOST_DATA
, 1, "*$" },
115 { "mmio_insb", HOST_DATA
, 1, "*$" },
116 { "mmio_insw", HOST_DATA
, 1, "*$" },
117 { "mmio_insl", HOST_DATA
, 1, "*$" },
118 { "acpi_read_bit_register", HOST_DATA
, 1, "*$" },
119 /* Functions that return host data as argument 3 */
120 { "rdmsrl_on_cpu", HOST_DATA
, 2, "*$" },
121 { "rdmsrl_safe_on_cpu", HOST_DATA
, 2, "*$" },
122 { "__virtio_cread_many", HOST_DATA
, 2, "*$" },
123 { "pci_user_read_config_word", HOST_DATA
, 2, "*$" },
124 { "pci_user_read_config_dword", HOST_DATA
, 2, "*$" },
125 { "pci_user_read_config_byte", HOST_DATA
, 2, "*$" },
126 /* Functions that return host data as argument 4 */
127 { "pci_bus_read_config_byte", HOST_DATA
, 3, "*$" },
128 { "pci_bus_read_config_word", HOST_DATA
, 3, "*$" },
129 { "pci_bus_read_config_dword", HOST_DATA
, 3, "*$" },
130 /* Functions that return host data as arguments 3 and 4 */
131 { "rdmsr_on_cpu", HOST_DATA
, 2, "*$" },
132 { "rdmsr_on_cpu", HOST_DATA
, 3, "*$" },
133 { "rdmsr_safe_on_cpu", HOST_DATA
, 2, "*$" },
134 { "rdmsr_safe_on_cpu", HOST_DATA
, 3, "*$" },
135 /* Functions that return host data as argument 6 */
136 { "raw_pci_read", HOST_DATA
, 5, "*$" },
137 /* Functions that return host data as arguments 2-5 */
138 { "cpuid", HOST_DATA
, 1, "*$" },
139 { "cpuid", HOST_DATA
, 2, "*$" },
140 { "cpuid", HOST_DATA
, 3, "*$" },
141 { "cpuid", HOST_DATA
, 4, "*$" },
142 /* Functions that return host data as arguments 3-6 */
143 { "cpuid_count", HOST_DATA
, 2, "*$" },
144 { "cpuid_count", HOST_DATA
, 3, "*$" },
145 { "cpuid_count", HOST_DATA
, 4, "*$" },
146 { "cpuid_count", HOST_DATA
, 5, "*$" },
150 static unsigned long func_gets_host_data
;
151 static struct stree
*start_states
;
153 static struct smatch_state
*empty_state(struct sm_state
*sm
)
155 return alloc_estate_empty();
158 static struct smatch_state
*new_state(struct symbol
*type
)
160 struct smatch_state
*state
;
162 if (!type
|| type_is_ptr(type
))
165 state
= alloc_estate_whole(type
);
166 estate_set_new(state
);
170 static void pre_merge_hook(struct sm_state
*cur
, struct sm_state
*other
)
172 struct smatch_state
*kernel
= cur
->state
;
173 struct smatch_state
*extra
;
174 struct smatch_state
*state
;
175 struct range_list
*rl
;
177 extra
= __get_state(SMATCH_EXTRA
, cur
->name
, cur
->sym
);
180 rl
= rl_intersection(estate_rl(kernel
), estate_rl(extra
));
181 state
= alloc_estate_rl(clone_rl(rl
));
182 if (estate_capped(kernel
) || is_capped_var_sym(cur
->name
, cur
->sym
))
183 estate_set_capped(state
);
184 if (estates_equiv(state
, cur
->state
))
186 if (estate_new(cur
->state
))
187 estate_set_new(state
);
188 set_state(my_id
, cur
->name
, cur
->sym
, state
);
191 static void extra_nomod_hook(const char *name
, struct symbol
*sym
, struct expression
*expr
, struct smatch_state
*state
)
193 struct smatch_state
*host
, *new;
194 struct range_list
*rl
;
196 host
= __get_state(my_id
, name
, sym
);
200 rl
= rl_intersection(estate_rl(host
), estate_rl(state
));
201 if (rl_equiv(rl
, estate_rl(host
)))
203 new = alloc_estate_rl(rl
);
204 if (estate_capped(host
))
205 estate_set_capped(new);
206 set_state(my_id
, name
, sym
, new);
209 static void store_type_info(struct expression
*expr
, struct smatch_state
*state
)
212 char *type_str
, *member
;
214 if (__in_fake_assign
)
217 if (!estate_rl(state
))
220 expr
= strip_expr(expr
);
221 if (!expr
|| expr
->type
!= EXPR_DEREF
|| !expr
->member
)
224 type
= get_type(expr
->deref
);
225 if (!type
|| !type
->ident
)
228 type_str
= type_to_str(type
);
231 member
= get_member_name(expr
);
235 sql_insert_function_type_info(HOST_DATA
, type_str
, member
, state
->name
);
238 static void set_host_data(struct expression
*expr
, struct smatch_state
*state
)
240 store_type_info(expr
, state
);
241 set_state_expr(my_id
, expr
, state
);
244 static bool host_rl_known(struct expression
*expr
)
246 struct range_list
*rl
;
249 if (!get_host_rl(expr
, &rl
))
252 close_to_max
= sval_type_max(rl_type(rl
));
253 close_to_max
.value
-= 100;
255 if (sval_cmp(rl_max(rl
), close_to_max
) >= 0)
260 static bool is_array_index_mask_nospec(struct expression
*expr
)
262 struct expression
*orig
;
264 orig
= get_assigned_expr(expr
);
265 if (!orig
|| orig
->type
!= EXPR_CALL
)
267 return sym_name_is("array_index_mask_nospec", orig
->fn
);
270 static bool binop_capped(struct expression
*expr
)
272 struct range_list
*left_rl
;
276 if (expr
->op
== '-' && get_host_rl(expr
->left
, &left_rl
)) {
277 if (host_rl_capped(expr
->left
))
279 comparison
= get_comparison(expr
->left
, expr
->right
);
280 if (comparison
&& show_special(comparison
)[0] == '>')
285 if (expr
->op
== '&' || expr
->op
== '%') {
286 bool left_host
, left_capped
, right_host
, right_capped
;
288 if (!get_value(expr
->right
, &sval
) && is_capped(expr
->right
))
290 if (is_array_index_mask_nospec(expr
->right
))
292 if (is_capped(expr
->left
))
294 left_host
= is_host_rl(expr
->left
);
295 right_host
= is_host_rl(expr
->right
);
296 if (!left_host
&& !right_host
)
299 left_capped
= host_rl_capped(expr
->left
);
300 right_capped
= host_rl_capped(expr
->right
);
302 if (left_host
&& left_capped
) {
305 if (right_host
&& right_capped
)
309 if (right_host
&& right_capped
) {
318 * Generally "capped" means that we capped it to an unknown value.
319 * This is useful because if Smatch doesn't know what the value is then
320 * we have to trust that it is correct. But if we known cap value is
321 * 100 then we can check if 100 is correct and complain if it's wrong.
323 * So then the problem is with BINOP when we take a capped variable
324 * plus a host variable which is clamped to a known range (uncapped)
325 * the result should be capped.
327 if ((host_rl_capped(expr
->left
) || host_rl_known(expr
->left
)) &&
328 (host_rl_capped(expr
->right
) || host_rl_known(expr
->right
)))
333 bool host_rl_capped(struct expression
*expr
)
335 struct smatch_state
*state
;
336 struct range_list
*rl
;
339 expr
= strip_expr(expr
);
342 if (get_value(expr
, &sval
))
344 if (expr
->type
== EXPR_BINOP
)
345 return binop_capped(expr
);
346 if ((expr
->type
== EXPR_PREOP
|| expr
->type
== EXPR_POSTOP
) &&
347 (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
))
348 return host_rl_capped(expr
->unop
);
349 state
= get_state_expr(my_id
, expr
);
351 return estate_capped(state
);
353 if (!get_host_rl(expr
, &rl
)) {
355 * The non host data parts of a binop are capped and
356 * also empty host rl states are capped.
361 if (rl_to_sval(rl
, &sval
))
364 return false; /* uncapped host data */
367 static void tag_inner_struct_members(struct expression
*expr
, struct symbol
*member
)
369 struct expression
*edge_member
;
370 struct symbol
*base
= get_real_base_type(member
);
374 expr
= member_expression(expr
, '.', member
->ident
);
376 FOR_EACH_PTR(base
->symbol_list
, tmp
) {
379 type
= get_real_base_type(tmp
);
383 if (type
->type
== SYM_UNION
|| type
->type
== SYM_STRUCT
) {
384 tag_inner_struct_members(expr
, tmp
);
391 edge_member
= member_expression(expr
, '.', tmp
->ident
);
392 set_host_data(edge_member
, new_state(type
));
393 } END_FOR_EACH_PTR(tmp
);
396 static void tag_struct_members(struct symbol
*type
, struct expression
*expr
)
399 struct expression
*member
;
402 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&') {
403 expr
= strip_expr(expr
->unop
);
407 FOR_EACH_PTR(type
->symbol_list
, tmp
) {
408 type
= get_real_base_type(tmp
);
412 if (type
->type
== SYM_UNION
|| type
->type
== SYM_STRUCT
) {
413 tag_inner_struct_members(expr
, tmp
);
420 member
= member_expression(expr
, op
, tmp
->ident
);
421 if (type
->type
== SYM_ARRAY
) {
422 set_points_to_host_data(member
, true);
424 set_host_data(member
, new_state(get_type(member
)));
426 } END_FOR_EACH_PTR(tmp
);
429 static void tag_base_type(struct expression
*expr
)
431 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
432 expr
= strip_expr(expr
->unop
);
434 expr
= deref_expression(expr
);
435 set_host_data(expr
, new_state(get_type(expr
)));
438 static void tag_as_host_data(struct expression
*expr
)
442 expr
= strip_expr(expr
);
443 type
= get_type(expr
);
448 if (type
->type
== SYM_PTR
){
449 type
= get_real_base_type(type
);
452 if (type
== &void_ctype
) {
453 set_host_data(deref_expression(expr
), new_state(&ulong_ctype
));
456 if (type
->type
== SYM_BASETYPE
) {
457 if (expr
->type
!= EXPR_PREOP
&& expr
->op
!= '&')
458 set_points_to_host_data(expr
, true);
462 if (type
->type
== SYM_STRUCT
|| type
->type
== SYM_UNION
) {
463 if (expr
->type
!= EXPR_PREOP
|| expr
->op
!= '&')
464 expr
= deref_expression(expr
);
466 set_host_data(deref_expression(expr
), new_state(&ulong_ctype
));
467 tag_struct_members(type
, expr
);
472 if (expr
->type
== EXPR_DEREF
) {
473 type
= get_type(expr
->deref
);
474 expr
= strip_expr(expr
->deref
);
477 sm_msg("%s: no type\n", __func__
);
482 if (type
->type
== SYM_BASETYPE
) {
483 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*')
484 set_points_to_host_data(expr
->unop
, true);
485 set_host_data(expr
, new_state(get_type(expr
)));
488 if (type
->type
== SYM_STRUCT
|| type
->type
== SYM_UNION
) {
489 set_host_data(expr
, new_state(&ulong_ctype
));
490 tag_struct_members(type
, expr
);
494 static int get_rl_from_function(struct expression
*expr
, struct range_list
**rl
)
499 if (expr
->type
!= EXPR_CALL
|| expr
->fn
->type
!= EXPR_SYMBOL
||
500 !expr
->fn
->symbol_name
|| !expr
->fn
->symbol_name
->name
)
503 for (int i
= 0; i
< ARRAY_SIZE(func_table
); i
++) {
504 if ((strcmp(expr
->fn
->symbol_name
->name
, func_table
[i
].name
) == 0) &&
505 (func_table
[i
].param
== -1)) {
506 *rl
= alloc_whole_rl(get_type(expr
));
513 static bool state_is_new(struct expression
*expr
)
515 struct smatch_state
*state
;
517 state
= get_state_expr(my_id
, expr
);
518 if (estate_new(state
))
521 if (expr
->type
== EXPR_BINOP
) {
522 if (state_is_new(expr
->left
))
524 if (state_is_new(expr
->right
))
530 static void handle_derefed_pointers(struct expression
*expr
, bool is_new
)
532 expr
= strip_expr(expr
);
533 if (expr
->type
!= EXPR_PREOP
||
536 expr
= strip_expr(expr
->unop
);
537 set_points_to_host_data(expr
, is_new
);
540 static bool handle_op_assign(struct expression
*expr
)
542 struct expression
*binop_expr
;
543 struct smatch_state
*state
;
544 struct range_list
*rl
;
548 case SPECIAL_ADD_ASSIGN
:
549 case SPECIAL_SUB_ASSIGN
:
550 case SPECIAL_AND_ASSIGN
:
551 case SPECIAL_MOD_ASSIGN
:
552 case SPECIAL_SHL_ASSIGN
:
553 case SPECIAL_SHR_ASSIGN
:
554 case SPECIAL_OR_ASSIGN
:
555 case SPECIAL_XOR_ASSIGN
:
556 case SPECIAL_MUL_ASSIGN
:
557 case SPECIAL_DIV_ASSIGN
:
558 binop_expr
= binop_expression(expr
->left
,
559 op_remove_assign(expr
->op
),
561 if (!get_host_rl(binop_expr
, &rl
))
563 rl
= cast_rl(get_type(expr
->left
), rl
);
564 state
= alloc_estate_rl(rl
);
565 if (expr
->op
== SPECIAL_AND_ASSIGN
||
566 expr
->op
== SPECIAL_MOD_ASSIGN
||
567 host_rl_capped(binop_expr
))
568 estate_set_capped(state
);
569 is_new
= state_is_new(binop_expr
);
571 estate_set_new(state
);
572 estate_set_assigned(state
);
573 set_host_data(expr
->left
, state
);
574 handle_derefed_pointers(expr
->left
, is_new
);
580 static void match_assign_host(struct expression
*expr
)
582 struct symbol
*left_type
, *right_type
;
583 struct range_list
*rl
= NULL
;
584 static struct expression
*handled
;
585 struct smatch_state
*state
;
586 struct expression
*faked
;
587 bool is_capped
= false;
593 left_type
= get_type(expr
->left
);
594 if (left_type
== &void_ctype
)
597 faked
= get_faked_expression();
599 /* FIXME: handle fake array assignments frob(&host_array[x]); */
602 faked
->type
== EXPR_ASSIGNMENT
&&
603 points_to_host_data(faked
->right
)) {
604 rl
= alloc_whole_rl(get_type(expr
->left
));
609 if (faked
&& faked
== handled
)
611 if (is_fake_call(expr
->right
))
612 goto clear_old_state
;
613 if (points_to_host_data(expr
->right
) &&
614 is_struct_ptr(get_type(expr
->left
))) {
616 // This should be handled by smatch_points_to_host_data.c
617 //set_points_to_host_data(expr->left);
620 if (handle_op_assign(expr
))
623 goto clear_old_state
;
625 /* Handled by DB code */
626 if (expr
->right
->type
== EXPR_CALL
)
630 disable_type_val_lookups();
631 get_host_rl(expr
->right
, &rl
);
633 enable_type_val_lookups();
635 goto clear_old_state
;
637 is_capped
= host_rl_capped(expr
->right
);
638 is_new
= state_is_new(expr
->right
);
641 if (type_is_ptr(left_type
)) {
642 right_type
= get_type(expr
->right
);
643 if (right_type
&& right_type
->type
== SYM_ARRAY
)
644 set_points_to_host_data(expr
->left
, is_new
);
648 rl
= cast_rl(left_type
, rl
);
649 state
= alloc_estate_rl(rl
);
651 estate_set_new(state
);
653 estate_set_capped(state
);
654 estate_set_assigned(state
);
655 set_host_data(expr
->left
, state
);
656 handle_derefed_pointers(expr
->left
, is_new
);
662 * HACK ALERT!!! This should be at the start of the function. The
663 * the problem is that handling "pointer = array;" assignments is
664 * handled in this function instead of in kernel_points_to_host_data.c.
666 if (type_is_ptr(left_type
))
669 if (get_state_expr(my_id
, expr
->left
))
670 set_host_data(expr
->left
, alloc_estate_empty());
673 static void handle_eq_noteq(struct expression
*expr
)
675 struct smatch_state
*left_orig
, *right_orig
;
677 left_orig
= get_state_expr(my_id
, expr
->left
);
678 right_orig
= get_state_expr(my_id
, expr
->right
);
680 if (!left_orig
&& !right_orig
)
682 if (left_orig
&& right_orig
)
686 set_true_false_states_expr(my_id
, expr
->left
,
687 expr
->op
== SPECIAL_EQUAL
? alloc_estate_empty() : NULL
,
688 expr
->op
== SPECIAL_EQUAL
? NULL
: alloc_estate_empty());
690 set_true_false_states_expr(my_id
, expr
->right
,
691 expr
->op
== SPECIAL_EQUAL
? alloc_estate_empty() : NULL
,
692 expr
->op
== SPECIAL_EQUAL
? NULL
: alloc_estate_empty());
696 static struct range_list
*strip_negatives(struct range_list
*rl
)
698 sval_t min
= rl_min(rl
);
699 sval_t minus_one
= { .type
= rl_type(rl
), .value
= -1 };
700 sval_t over
= { .type
= rl_type(rl
), .value
= INT_MAX
+ 1ULL };
701 sval_t max
= sval_type_max(rl_type(rl
));
706 if (type_unsigned(rl_type(rl
)) && type_bits(rl_type(rl
)) > 31)
707 return remove_range(rl
, over
, max
);
709 return remove_range(rl
, min
, minus_one
);
712 static void handle_compare(struct expression
*expr
)
714 struct expression
*left
, *right
;
715 struct range_list
*left_rl
= NULL
;
716 struct range_list
*right_rl
= NULL
;
717 struct range_list
*host_rl
;
718 struct smatch_state
*capped_state
;
719 struct smatch_state
*left_true
= NULL
;
720 struct smatch_state
*left_false
= NULL
;
721 struct smatch_state
*right_true
= NULL
;
722 struct smatch_state
*right_false
= NULL
;
726 left
= strip_expr(expr
->left
);
727 right
= strip_expr(expr
->right
);
729 while (left
->type
== EXPR_ASSIGNMENT
)
730 left
= strip_expr(left
->left
);
733 * Conditions are mostly handled by smatch_extra.c, but there are some
734 * times where the exact values are not known so we can't do that.
736 * Normally, we might consider using smatch_capped.c to supliment smatch
737 * extra but that doesn't work when we merge unknown uncapped kernel
738 * data with unknown capped host data. The result is uncapped host
739 * data. We need to keep it separate and say that the host data is
740 * capped. In the past, I would have marked this as just regular
741 * kernel data (not host data) but we can't do that these days because
742 * we need to track host data for Spectre.
744 * The other situation which we have to handle is when we do have an
745 * int and we compare against an unknown unsigned kernel variable. In
746 * that situation we assume that the kernel data is less than INT_MAX.
747 * Otherwise then we get all sorts of array underflow false positives.
751 /* Handled in smatch_extra.c */
752 if (get_implied_value(left
, &sval
) ||
753 get_implied_value(right
, &sval
))
756 get_host_rl(left
, &left_rl
);
757 get_host_rl(right
, &right_rl
);
760 if (!left_rl
&& !right_rl
)
762 /* if both sides are host data that's not a good limit */
763 if (left_rl
&& right_rl
)
771 type
= get_type(expr
);
772 if (type_unsigned(type
))
773 host_rl
= strip_negatives(host_rl
);
774 capped_state
= alloc_estate_rl(host_rl
);
775 estate_set_capped(capped_state
);
779 case SPECIAL_UNSIGNED_LT
:
781 case SPECIAL_UNSIGNED_LTE
:
783 left_true
= capped_state
;
785 right_false
= capped_state
;
788 case SPECIAL_UNSIGNED_GT
:
790 case SPECIAL_UNSIGNED_GTE
:
792 left_false
= capped_state
;
794 right_true
= capped_state
;
797 set_true_false_states_expr(my_id
, left
, left_true
, left_false
);
798 set_true_false_states_expr(my_id
, right
, right_true
, right_false
);
801 static void match_condition_host(struct expression
*expr
)
806 if (expr
->type
!= EXPR_COMPARE
)
809 if (expr
->op
== SPECIAL_EQUAL
||
810 expr
->op
== SPECIAL_NOTEQUAL
) {
811 handle_eq_noteq(expr
);
814 handle_compare(expr
);
817 static void match_returns_host_rl(const char *fn
, struct expression
*expr
, void *unused
)
819 func_gets_host_data
= true;
822 static int has_host_data(struct symbol
*sym
)
824 struct sm_state
*tmp
;
826 FOR_EACH_MY_SM(my_id
, __get_cur_stree(), tmp
) {
829 } END_FOR_EACH_SM(tmp
);
833 bool we_pass_host_data(struct expression
*call
)
835 struct expression
*arg
;
838 FOR_EACH_PTR(call
->args
, arg
) {
839 if (points_to_host_data(arg
))
841 sym
= expr_to_sym(arg
);
844 if (has_host_data(sym
))
846 } END_FOR_EACH_PTR(arg
);
851 static int db_returned_host_rl(struct expression
*call
, struct range_list
**rl
)
853 struct smatch_state
*state
;
856 if (is_fake_call(call
))
858 snprintf(buf
, sizeof(buf
), "return %p", call
);
859 state
= get_state(my_id
, buf
, NULL
);
860 if (!state
|| !estate_rl(state
))
862 *rl
= estate_rl(state
);
866 struct stree
*get_host_stree(void)
868 return get_all_states_stree(my_id
);
871 static int host_data_flag
;
872 static int no_host_data_flag
;
874 struct range_list
*var_host_rl(struct expression
*expr
)
876 struct smatch_state
*state
;
877 struct range_list
*rl
;
878 struct range_list
*absolute_rl
;
880 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&') {
881 no_host_data_flag
= 1;
885 if (expr
->type
== EXPR_BINOP
&& expr
->op
== '%') {
886 struct range_list
*left
, *right
;
888 if (!get_host_rl(expr
->right
, &right
))
890 get_absolute_rl(expr
->left
, &left
);
891 rl
= rl_binop(left
, '%', right
);
895 if (expr
->type
== EXPR_BINOP
&& expr
->op
== '/') {
896 struct range_list
*left
= NULL
;
897 struct range_list
*right
= NULL
;
898 struct range_list
*abs_right
;
900 get_host_rl(expr
->left
, &left
);
901 get_host_rl(expr
->right
, &right
);
902 get_absolute_rl(expr
->right
, &abs_right
);
904 if (left
&& !right
) {
905 rl
= rl_binop(left
, '/', abs_right
);
906 if (sval_cmp(rl_max(left
), rl_max(rl
)) < 0)
907 no_host_data_flag
= 1;
913 if (get_rl_from_function(expr
, &rl
))
916 state
= get_state_expr(my_id
, expr
);
917 if (state
&& estate_rl(state
)) {
918 rl
= estate_rl(state
);
922 if (expr
->type
== EXPR_CALL
&& db_returned_host_rl(expr
, &rl
))
925 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*' &&
926 points_to_host_data(expr
->unop
)) {
927 rl
= var_to_absolute_rl(expr
);
931 if (is_array(expr
)) {
932 struct expression
*array
= get_array_base(expr
);
934 if (!get_state_expr(my_id
, array
)) {
935 no_host_data_flag
= 1;
943 absolute_rl
= var_to_absolute_rl(expr
);
944 return clone_rl(rl_intersection(rl
, absolute_rl
));
947 static bool is_ptr_subtract(struct expression
*expr
)
949 expr
= strip_expr(expr
);
952 if (expr
->type
== EXPR_BINOP
&& expr
->op
== '-' &&
953 type_is_ptr(get_type(expr
->left
))) {
959 int get_host_rl(struct expression
*expr
, struct range_list
**rl
)
961 if (is_ptr_subtract(expr
))
965 no_host_data_flag
= 0;
966 custom_get_absolute_rl(expr
, &var_host_rl
, rl
);
967 if (!host_data_flag
|| no_host_data_flag
)
972 int is_host_rl(struct expression
*expr
)
974 struct range_list
*tmp
;
976 return get_host_rl(expr
, &tmp
) && tmp
;
979 int get_host_rl_var_sym(const char *name
, struct symbol
*sym
, struct range_list
**rl
)
981 struct smatch_state
*state
;
983 state
= get_state(my_id
, name
, sym
);
984 if (state
&& estate_rl(state
)) {
985 *rl
= estate_rl(state
);
991 static void return_info_callback_host(int return_id
, char *return_ranges
,
992 struct expression
*returned_expr
,
994 const char *printed_name
,
997 struct smatch_state
*extra
;
998 struct range_list
*rl
;
1002 if (strcmp(printed_name
, "$") == 0)
1004 if (!estate_assigned(sm
->state
) &&
1005 !estate_new(sm
->state
))
1008 rl
= estate_rl(sm
->state
);
1011 extra
= get_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
);
1012 if (estate_rl(extra
))
1013 rl
= rl_intersection(estate_rl(sm
->state
), estate_rl(extra
));
1017 snprintf(buf
, sizeof(buf
), "%s%s%s",
1019 estate_capped(sm
->state
) ? "[c]" : "", "");
1020 sql_insert_return_states(return_id
, return_ranges
,
1021 estate_new(sm
->state
) ? HOST_DATA_SET
: HOST_DATA
,
1022 param
, printed_name
, buf
);
1026 static void caller_info_callback_host(struct expression
*call
, int param
, char *printed_name
, struct sm_state
*sm
)
1028 struct smatch_state
*state
;
1029 struct range_list
*rl
;
1030 struct symbol
*type
;
1034 * Smatch uses a hack where if we get an unsigned long we say it's
1035 * both host data and it points to host data. But if we pass it to a
1036 * function which takes an int, then it's just host data. There's not
1037 * enough bytes for it to be a pointer.
1040 type
= get_arg_type(call
->fn
, param
);
1041 if (strcmp(printed_name
, "$") != 0 && type
&& type_bits(type
) < type_bits(&ptr_ctype
))
1044 if (strcmp(sm
->state
->name
, "") == 0)
1047 state
= __get_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
);
1048 if (!state
|| !estate_rl(state
))
1049 rl
= estate_rl(sm
->state
);
1051 rl
= rl_intersection(estate_rl(sm
->state
), estate_rl(state
));
1056 snprintf(buf
, sizeof(buf
), "%s%s%s", show_rl(rl
),
1057 estate_capped(sm
->state
) ? "[c]" : "", "");
1058 sql_insert_caller_info(call
, HOST_DATA
, param
, printed_name
, buf
);
1061 static void db_param_set(struct expression
*expr
, int param
, char *key
, char *value
)
1063 struct expression
*arg
;
1066 struct smatch_state
*state
;
1068 while (expr
->type
== EXPR_ASSIGNMENT
)
1069 expr
= strip_expr(expr
->right
);
1070 if (expr
->type
!= EXPR_CALL
)
1073 arg
= get_argument_from_call_expr(expr
->args
, param
);
1077 name
= get_variable_from_key(arg
, key
, &sym
);
1081 state
= get_state(my_id
, name
, sym
);
1085 set_state(my_id
, name
, sym
, alloc_estate_empty());
1090 static bool param_data_capped(const char *value
)
1092 if (strstr(value
, ",c") || strstr(value
, "[c"))
1097 static void set_param_host_data(const char *name
, struct symbol
*sym
, char *key
, char *value
)
1099 struct expression
*expr
;
1100 struct range_list
*rl
= NULL
;
1101 struct smatch_state
*state
;
1102 struct symbol
*type
;
1105 expr
= symbol_expression(sym
);
1106 fullname
= get_variable_from_key(expr
, key
, NULL
);
1110 type
= get_member_type_from_key(expr
, key
);
1111 if (type
&& type
->type
== SYM_STRUCT
)
1117 str_to_rl(type
, value
, &rl
);
1118 rl
= swap_mtag_seed(expr
, rl
);
1119 state
= alloc_estate_rl(rl
);
1120 if (param_data_capped(value
) || is_capped(expr
))
1121 estate_set_capped(state
);
1122 set_state(my_id
, fullname
, sym
, state
);
1128 static void store_host_data_return(struct expression
*expr
, char *key
, char *value
, bool is_new
)
1130 struct smatch_state
*state
;
1131 struct range_list
*rl
;
1132 struct symbol
*type
;
1138 type
= get_type(expr
);
1139 snprintf(buf
, sizeof(buf
), "return %p%s", expr
, key
+ 1);
1140 call_results_to_rl(expr
, type
, value
, &rl
);
1142 state
= alloc_estate_rl(rl
);
1144 estate_set_new(state
);
1145 set_state(my_id
, buf
, NULL
, state
);
1148 static void set_to_host_data(struct expression
*expr
, char *key
, char *value
, bool is_new
)
1150 struct smatch_state
*state
;
1153 struct symbol
*type
;
1154 struct range_list
*rl
= NULL
;
1156 type
= get_member_type_from_key(expr
, key
);
1157 name
= get_variable_from_key(expr
, key
, &sym
);
1161 call_results_to_rl(expr
, type
, value
, &rl
);
1163 state
= alloc_estate_rl(rl
);
1164 if (param_data_capped(value
))
1165 estate_set_capped(state
);
1167 estate_set_new(state
);
1168 estate_set_assigned(state
);
1169 set_state(my_id
, name
, sym
, state
);
1174 static void returns_param_host_data(struct expression
*expr
, int param
, char *key
, char *value
)
1176 struct expression
*arg
;
1177 struct expression
*call
;
1180 while (call
->type
== EXPR_ASSIGNMENT
)
1181 call
= strip_expr(call
->right
);
1182 if (call
->type
!= EXPR_CALL
)
1185 if (!we_pass_host_data(call
))
1189 if (expr
->type
!= EXPR_ASSIGNMENT
) {
1190 store_host_data_return(expr
, key
, value
, OLD
);
1193 set_to_host_data(expr
->left
, key
, value
, OLD
);
1197 arg
= get_argument_from_call_expr(call
->args
, param
);
1200 set_to_host_data(arg
, key
, value
, OLD
);
1203 static void returns_param_host_data_set(struct expression
*expr
, int param
, char *key
, char *value
)
1205 struct expression
*arg
;
1207 func_gets_host_data
= true;
1210 if (expr
->type
!= EXPR_ASSIGNMENT
) {
1211 store_host_data_return(expr
, key
, value
, NEW
);
1214 set_to_host_data(expr
->left
, key
, value
, NEW
);
1218 while (expr
->type
== EXPR_ASSIGNMENT
)
1219 expr
= strip_expr(expr
->right
);
1220 if (expr
->type
!= EXPR_CALL
)
1223 arg
= get_argument_from_call_expr(expr
->args
, param
);
1226 set_to_host_data(arg
, key
, value
, NEW
);
1229 static void returns_param_capped_host(struct expression
*expr
, int param
, char *key
, char *value
)
1231 struct smatch_state
*state
, *new;
1235 name
= get_name_sym_from_param_key(expr
, param
, key
, &sym
);
1239 state
= get_state(my_id
, name
, sym
);
1240 if (!state
|| estate_capped(state
))
1243 new = clone_estate(state
);
1244 estate_set_capped(new);
1246 set_state(my_id
, name
, sym
, new);
1251 struct param_key_data
{
1252 param_key_hook
*call_back
;
1258 static void match_function_def(struct symbol
*sym
)
1260 if (is_host_data_fn(sym
))
1261 func_gets_host_data
= true;
1264 static void set_param_host_input_data(struct expression
*expr
, const char *name
,
1265 struct symbol
*sym
, void *data
)
1267 struct expression
*arg
;
1269 func_gets_host_data
= true;
1270 arg
= gen_expression_from_name_sym(name
, sym
);
1271 tag_as_host_data(arg
);
1274 void register_kernel_host_data(int id
)
1277 struct host_fn_info
*info
;
1281 if (option_project
!= PROJ_KERNEL
)
1284 set_dynamic_states(my_id
);
1285 add_function_data(&func_gets_host_data
);
1286 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
1288 add_function_data((unsigned long *)&start_states
);
1289 add_unmatched_state_hook(my_id
, &empty_state
);
1290 add_extra_nomod_hook(&extra_nomod_hook
);
1291 add_pre_merge_hook(my_id
, &pre_merge_hook
);
1292 add_merge_hook(my_id
, &merge_estates
);
1295 for (i
= 0; i
< ARRAY_SIZE(func_table
); i
++) {
1296 info
= &func_table
[i
];
1297 add_function_param_key_hook_late(info
->name
, &set_param_host_input_data
,
1298 info
->param
, info
->key
, info
);
1301 for (i
= 0; i
< ARRAY_SIZE(func_table
); i
++) {
1302 if (func_table
[i
].param
== -1)
1303 add_function_hook(func_table
[i
].name
, &match_returns_host_rl
, NULL
);
1306 add_hook(&match_assign_host
, ASSIGNMENT_HOOK
);
1307 select_return_states_hook(PARAM_SET
, &db_param_set
);
1308 add_hook(&match_condition_host
, CONDITION_HOOK
);
1310 add_caller_info_callback(my_id
, caller_info_callback_host
);
1311 add_return_info_callback(my_id
, return_info_callback_host
);
1312 select_caller_info_hook(set_param_host_data
, HOST_DATA
);
1313 select_return_states_hook(HOST_DATA
, &returns_param_host_data
);
1314 select_return_states_hook(HOST_DATA_SET
, &returns_param_host_data_set
);
1315 select_return_states_hook(CAPPED_DATA
, &returns_param_capped_host
);