Skip to content

Commit 0419a79

Browse files
authored
Merge pull request #35 from OpenCloudOS/dev
some bug fix
2 parents c57f26d + 573c4d8 commit 0419a79

7 files changed

Lines changed: 149 additions & 59 deletions

File tree

component/sys_utils.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,16 @@ int exec(char *cmd, char *output)
3333
strcat(output + strlen(output), buf);
3434
}
3535

36-
pr_debug("command: %s\n", cmd);
3736
status = pclose(f);
37+
pr_debug("command: %s, status:%d\n", cmd, WEXITSTATUS(status));
3838
return WEXITSTATUS(status);
3939
}
4040

4141
int execf(char *output, char *fmt, ...)
4242
{
43-
char *cmd = malloc(1024);
43+
static char cmd[1024];
4444
va_list valist;
4545

46-
if (!cmd)
47-
return -ENOMEM;
48-
4946
va_start(valist, fmt);
5047
vsprintf(cmd, fmt, valist);
5148
va_end(valist);

src/gen_trace.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,40 @@
2323
}
2424

2525

26+
def parse_names(trace, children):
27+
names = trace['names']
28+
first = names[0]
29+
prev = None
30+
if isinstance(first, str):
31+
trace['name'] = first
32+
else:
33+
trace['name'] = first['name']
34+
trace['cond'] = first['cond'].replace('"', '\\"')
35+
36+
del trace['names']
37+
prev = trace
38+
39+
for index in range(1, len(names)):
40+
name = names[index]
41+
new_child = dict(trace)
42+
43+
if isinstance(name, str):
44+
new_child['name'] = name
45+
del new_child['cond']
46+
else:
47+
new_child['name'] = name['name']
48+
if 'cond' in name:
49+
new_child['cond'] = name['cond'].replace('"', '\\"')
50+
else:
51+
del new_child['cond']
52+
53+
prev['next'] = new_child
54+
prev = new_child
55+
children.append(new_child)
56+
57+
prev['next'] = trace
58+
59+
2660
def parse_group(group):
2761
""" parse group in yaml file """
2862
if 'children' not in group:
@@ -34,13 +68,8 @@ def parse_group(group):
3468
if not isinstance(child, str):
3569
parse_group(child)
3670
i += 1
37-
names = child['name']
38-
if isinstance(names, list):
39-
child['name'] = names[0]
40-
for name in names[1:]:
41-
new_child = dict(child)
42-
new_child['name'] = name
43-
children.append(new_child)
71+
if 'names' in child:
72+
parse_names(child, children)
4473
name_split = child['name'].split(':')
4574
if len(name_split) > 1:
4675
child['name'] = name_split[0]
@@ -146,7 +175,7 @@ def gen_trace(trace, group, p_name):
146175
(rule_str, _init_str) = gen_rules(rules, trace_name)
147176
init_str += _init_str
148177

149-
if_str = f'\n\t.if_str = "{trace.get("if")}",' if 'if' in trace else ''
178+
cond_str = f'\n\t.cond = "{trace["cond"]}",' if 'cond' in trace else ''
150179
reg_str = f'\n\t.regex = "{trace["regex"]}",' if 'regex' in trace else ''
151180
msg_str = f'\n\t.msg = "{trace["msg"]}",' if 'msg' in trace else ''
152181
default = True
@@ -159,18 +188,19 @@ def gen_trace(trace, group, p_name):
159188
target = trace.get('target') or trace['name']
160189
define_str = f'''trace_t {trace_name} = {{
161190
\t.name = "{target}",
162-
\t.desc = "{trace.get('desc')}",{skb_str}{if_str}{default}
191+
\t.desc = "{trace.get('desc') or ''}",{skb_str}{cond_str}{default}
163192
\t.type = {trace_type},{reg_str}{analyzer}{msg_str}
164193
\t.index = INDEX_{name},
165194
\t.prog = "__trace_{name}",
166195
\t.parent = &{p_name},
167196
\t.rules = LIST_HEAD_INIT({trace_name}.rules),
197+
\t.mutex = {'true' if trace.get('mutex') else 'false'},
168198
}};
169199
{rule_str}
170200
'''
171201
init_str += f'''\tlist_add_tail(&{trace_name}.list, &{p_name}.traces);
172202
\tall_traces[INDEX_{name}] = &{trace_name};
173-
\tlist_add_tail(&{trace_name}.sibling, &trace_list);
203+
\tlist_add_tail(&{trace_name}.all, &trace_list);
174204
'''
175205
global_status['trace_index'] += 1
176206

@@ -217,6 +247,13 @@ def gen_group(group, is_root=False):
217247
else:
218248
gen_append(result, gen_trace(child, group, p_name))
219249

250+
for child in group['children']:
251+
if 'children' in child:
252+
continue
253+
sibling = 'NULL'
254+
if 'next' in child:
255+
sibling = f"&trace_{child['next']['define_name']}"
256+
result['init_str'] += f"\ttrace_{child['define_name']}.sibling = {sibling};\n"
220257
return result
221258

222259

src/progs/kprobe.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ static try_inline int handle_exit(struct pt_regs *regs, int func)
190190
}
191191

192192
/* one trace may have more than one implement */
193-
#define __DEFINE_KPROBE_RAW(name, func_name, skb_init) \
193+
#define __DEFINE_KPROBE_INIT(name, func_name, skb_init) \
194194
static try_inline int fake__##name(struct pt_regs *ctx, \
195195
struct sk_buff *skb, \
196196
int func); \
@@ -209,11 +209,15 @@ static try_inline int handle_exit(struct pt_regs *regs, int func)
209209
struct sk_buff *skb, \
210210
int func)
211211

212-
#define DEFINE_KPROBE_RAW(name, skb_init) \
213-
__DEFINE_KPROBE_RAW(name, name, skb_init)
212+
#define DEFINE_KPROBE_INIT(name, skb_init) \
213+
__DEFINE_KPROBE_INIT(name, name, skb_init)
214214

215215
#define DEFINE_KPROBE(name, skb_index) \
216-
DEFINE_KPROBE_RAW(name, PT_REGS_PARM##skb_index(ctx))
216+
DEFINE_KPROBE_INIT(name, PT_REGS_PARM##skb_index(ctx))
217+
218+
#define DEFINE_KPROBE_TARGET(name, func_name, skb_index) \
219+
__DEFINE_KPROBE_INIT(name, func_name, \
220+
PT_REGS_PARM##skb_index(ctx))
217221

218222
#define KPROBE_DEFAULT(name, skb_index) \
219223
DEFINE_KPROBE(name, skb_index) \
@@ -262,23 +266,37 @@ DEFINE_TP(kfree_skb, skb, kfree_skb, 8)
262266
return 0;
263267
}
264268

265-
__DEFINE_KPROBE_RAW(__netif_receive_skb_core_pskb, __netif_receive_skb_core,
266-
_(*(void **)(PT_REGS_PARM1(ctx))))
269+
__DEFINE_KPROBE_INIT(__netif_receive_skb_core_pskb, __netif_receive_skb_core,
270+
_(*(void **)(PT_REGS_PARM1(ctx))))
267271
{
268272
return default_handle_entry(ctx, skb, func);
269273
}
270274

275+
#define bpf_ipt_do_table() \
276+
{ \
277+
nf_event_t e = { \
278+
.event = { .func = func, }, \
279+
.hook = _C(state, hook), \
280+
}; \
281+
\
282+
bpf_probe_read(e.table, sizeof(e.table) - 1, _C(table, name)); \
283+
return handle_entry(ctx, skb, &e.event, sizeof(e), func); \
284+
}
285+
271286
DEFINE_KPROBE(ipt_do_table, 1)
272287
{
273288
struct nf_hook_state *state = (void *)PT_REGS_PARM2(ctx);
274289
struct xt_table *table = (void *)PT_REGS_PARM3(ctx);
275-
nf_event_t e = {
276-
.event = { .func = func, },
277-
.hook = _C(state, hook),
278-
};
279290

280-
bpf_probe_read(e.table, sizeof(e.table) - 1, _C(table, name));
281-
return handle_entry(ctx, skb, &e.event, sizeof(e), func);
291+
bpf_ipt_do_table();
292+
}
293+
294+
DEFINE_KPROBE_TARGET(ipt_do_table_new, ipt_do_table, 2)
295+
{
296+
struct nf_hook_state *state = (void *)PT_REGS_PARM3(ctx);
297+
struct xt_table *table = (void *)PT_REGS_PARM1(ctx);
298+
299+
bpf_ipt_do_table();
282300
}
283301

284302
DEFINE_KPROBE(nf_hook_slow, 1)

src/progs/nft_do_chain.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@ static try_inline int BPF_NAME(struct pt_regs *ctx, int func)
8181
}
8282

8383
/* another magical macro definiation */
84-
#define ___DEFINE_KPROBE_RAW(name, target) \
85-
__DEFINE_KPROBE_RAW(name, target, NULL)
84+
#define ___DEFINE_KPROBE_INIT(name, target) \
85+
__DEFINE_KPROBE_INIT(name, target, NULL)
8686

8787
/**
8888
* This function is used to the kernel version that don't support
8989
* kernel module BTF.
9090
*/
91-
___DEFINE_KPROBE_RAW(NFT_NAME, nft_do_chain)
91+
___DEFINE_KPROBE_INIT(NFT_NAME, nft_do_chain)
9292
{
9393
return BPF_NAME(ctx, func);
9494
}

src/trace.c

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include "analysis.h"
1111
#include "dropreason.h"
1212

13+
const char *cond_pre = "verlte() { [ \"$1\" = \"$2\" ] && echo 0 && return; "
14+
"[ \"$1\" = \"$(/bin/echo -e \"$1\\n$2\" | sort -V | head -n1)\" ] "
15+
"&& echo -1 && return; echo 1; }";
16+
1317
trace_context_t trace_ctx = {
1418
.mode = TRACE_MODE_TIMELINE,
1519
};
@@ -272,40 +276,52 @@ static int trace_prepare_args()
272276
return -1;
273277
}
274278

279+
static void trace_exec_cond()
280+
{
281+
trace_t *trace, *sibling;
282+
bool mutexed;
283+
284+
trace_for_each(trace) {
285+
if (trace->mutex && (sibling = trace->sibling)) {
286+
mutexed = false;
287+
while (sibling != trace) {
288+
if ((sibling->status & TRACE_CHECKED) &&
289+
!trace_is_invalid(sibling)) {
290+
mutexed = true;
291+
break;
292+
}
293+
sibling = sibling->sibling;
294+
}
295+
if (mutexed) {
296+
trace_set_invalid(trace);
297+
pr_debug("mutex happens in %s\n", trace->name);
298+
goto next;
299+
}
300+
}
301+
302+
if (trace->cond) {
303+
if (execf(NULL, "%s; %s", cond_pre, trace->cond))
304+
trace_set_invalid(trace);
305+
}
306+
next:
307+
trace->status |= TRACE_CHECKED;
308+
}
309+
}
310+
275311
static int trace_prepare_traces()
276312
{
277313
char func[128], name[136], *fmt;
278314
trace_t *trace;
279315
int sym_type;
280316

281-
/* high version kernel (>=5.4) use (struct sk_buff**) */
282-
if (kv_compare(5, 4, 0) < 0)
283-
trace_set_invalid(&trace___netif_receive_skb_core_pskb);
284-
else
285-
trace_set_invalid(&trace___netif_receive_skb_core);
317+
trace_exec_cond();
286318

287319
/* from v5.14, the struct of nft_pktinfo changed */
288320
if (kv_compare(5, 14, 0) >= 0) {
289321
trace_ctx.bpf_args.nft_high = true;
290322
pr_debug("nft high version founded\n");
291323
}
292324

293-
sym_type = sym_get_type("nft_do_chain");
294-
if (sym_type == SYM_NOT_EXIST) {
295-
trace_set_invalid(&trace_nft_do_chain_compat);
296-
trace_set_invalid(&trace_nft_do_chain);
297-
} else if (!kernel_has_config("DEBUG_INFO_BTF_MODULES") &&
298-
sym_type == SYM_MODULE) {
299-
300-
/* BTF modules is not supported and nft is a modules, we
301-
* need to use compat mode, which will not use CO-RE
302-
* read.
303-
*/
304-
trace_set_invalid(&trace_nft_do_chain);
305-
} else {
306-
trace_set_invalid(&trace_nft_do_chain_compat);
307-
}
308-
309325
pr_debug("begin to resolve kernel symbol...\n");
310326

311327
/* make the programs that target kernel function can't be found
@@ -333,6 +349,9 @@ static int trace_prepare_traces()
333349

334350
pr_verb("following traces are enabled:\n");
335351
trace_for_each(trace) {
352+
if (trace_is_invalid(trace) || !trace_is_enable(trace))
353+
continue;
354+
336355
if (trace_is_func(trace)) {
337356
if (trace_is_ret(trace))
338357
fmt = "kprobe/kretprobe";

src/trace.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ struct analyzer;
2525
#define TRACE_RET (1 << 3)
2626
#define TRACE_STACK (1 << 4)
2727
#define TRACE_ATTACH_MANUAL (1 << 5)
28+
#define TRACE_CHECKED (1 << 6)
2829

29-
#define trace_for_each(pos) list_for_each_entry(pos, &trace_list, sibling)
30+
#define trace_for_each(pos) list_for_each_entry(pos, &trace_list, all)
3031

3132
typedef struct trace_group {
3233
char *name;
@@ -44,19 +45,25 @@ typedef struct trace {
4445
/* name of the eBPF program */
4546
char *prog;
4647
enum trace_type type;
47-
char *if_str;
48+
char *cond;
4849
char *regex;
4950
char *tp;
5051
int skb;
51-
struct list_head sibling;
52+
/* traces in a global list */
53+
struct list_head all;
54+
/* traces in the same group */
5255
struct list_head list;
56+
/* list head of rules that belongs to this trace */
5357
struct list_head rules;
58+
/* traces that share the same target */
59+
struct trace *sibling;
5460
int index;
5561
u32 status;
5662
trace_group_t *parent;
5763
struct analyzer *analyzer;
5864
/* if this trace should be enabled by default */
5965
bool def;
66+
bool mutex;
6067
} trace_t;
6168

6269
typedef struct trace_args {

src/trace.yaml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ children:
5151
- <<: *rule_ret_err
5252
msg: XDP failed to redirect skb
5353
adv: check if the target ifindex exist
54-
- name: __netif_receive_skb_core:0
55-
- name: __netif_receive_skb_core_pskb
54+
- names:
55+
- name: __netif_receive_skb_core_pskb
56+
cond: '[ ! $(verlte "$(uname -r)" "5.4") -eq -1 ]' # valid when kernel >= 5.4
57+
- name: __netif_receive_skb_core:0
5658
target: __netif_receive_skb_core
59+
mutex: true
5760
- name: link-out
5861
desc: link layer (L2) of packet out
5962
visual: true
@@ -125,8 +128,13 @@ children:
125128
desc: base netfilter entry
126129
visual: true
127130
children:
128-
- name: ipt_do_table
131+
- names:
132+
- name: ipt_do_table
133+
cond: '[ $(verlte "$(uname -r)" "5.16") -eq -1 ]' # valid when kernel < 5.16
134+
- name: ipt_do_table_new
129135
analyzer: iptable
136+
mutex: true
137+
target: ipt_do_table
130138
rules:
131139
- exp: eq 0
132140
level: error
@@ -135,11 +143,15 @@ children:
135143
- exp: eq 1
136144
level: info
137145
msg: packet is accepted
138-
- name:
139-
- nft_do_chain
146+
- names:
147+
- name: nft_do_chain
148+
cond: >-
149+
zcat /proc/config.gz | grep DEBUG_INFO_BTF_MODULES ||
150+
cat /proc/kallsyms | grep " nft_do_chain$"
140151
- nft_do_chain_compat
141152
analyzer: iptable
142153
target: nft_do_chain
154+
mutex: true
143155
rules:
144156
- exp: eq 0
145157
level: error

0 commit comments

Comments
 (0)