1 /*
2 * Copyright (c) 2021 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #include "defs.h"
9 #include "list.h"
10 #include "poke.h"
11
12 static struct list_item *poke_data_vec;
13 static size_t poke_data_vec_capacity; /* size of the arena */
14 static size_t poke_data_vec_size; /* size of the used arena */
15
16 static void
17 expand_poke_data_vec(void)
18 {
19 const size_t old_capacity = poke_data_vec_capacity;
20 poke_data_vec = xgrowarray(poke_data_vec, &poke_data_vec_capacity,
21 sizeof(*poke_data_vec));
22 memset(poke_data_vec + old_capacity, 0,
23 (poke_data_vec_capacity - old_capacity)
24 * sizeof(*poke_data_vec));
25 }
26
27 uint16_t
28 alloc_poke_data(void)
29 {
30 const uint16_t rval = poke_data_vec_size;
31
32 if (rval < poke_data_vec_size)
33 error_func_msg_and_die("poke index overflow");
34
35 if (poke_data_vec_size == poke_data_vec_capacity)
36 expand_poke_data_vec();
37
38 poke_data_vec_size++;
39
40 list_init(&poke_data_vec[rval]);
41 return rval;
42 }
43
44 bool
45 poke_add(uint16_t poke_idx, struct poke_payload *poke)
46 {
47 struct poke_payload *i;
48 list_foreach(i, &poke_data_vec[poke_idx], l)
49 if ((i->is_enter == poke->is_enter) &&
50 (i->arg_no == poke->arg_no))
51 /* duplicate */
52 return 1;
53
54 list_insert(&poke_data_vec[poke_idx], &poke->l);
55 return 0;
56 }
57
58 void
59 poke_tcb(struct tcb *tcp, uint16_t poke_idx, bool is_enter)
60 {
61 if (poke_idx >= poke_data_vec_size)
62 error_func_msg_and_die("poke_idx >= poke_data_vec_size");
63
64 debug_func_msg("poking pid %d on %s",
65 tcp->pid, is_enter ? "enter" : "exit");
66
67 bool poked = false;
68 struct poke_payload *i;
69 list_foreach(i, &poke_data_vec[poke_idx], l) {
70 if (i->is_enter != is_enter)
71 continue;
72 if (n_args(tcp) < i->arg_no) {
73 error_func_msg("Failed to tamper with process %d:"
74 " requested to tamper with argument #%u,"
75 " but system call '%s' has only %u arguments",
76 tcp->pid, i->arg_no,
77 tcp_sysent(tcp)->sys_name,
78 n_args(tcp));
79 continue;
80 }
81 unsigned int nwritten = upoken(tcp, tcp->u_arg[i->arg_no - 1],
82 i->data_len, i->data);
83 if (!nwritten)
84 error_func_msg("Failed to tamper with process %d:"
85 " couldn't poke",
86 tcp->pid);
87 else
88 poked = true;
89 }
90
91 if (poked)
92 tcp->flags |= TCB_TAMPERED_POKED;
93 }