Skip to content

Commit 1e3af0d

Browse files
committed
简化代码,支持输出read/write的部分内容
1 parent 23c7d3e commit 1e3af0d

4 files changed

Lines changed: 138 additions & 135 deletions

File tree

pkg/util/helper.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,29 @@ func dumpByteSlice(b []byte, perfix string) *bytes.Buffer {
191191
return bb
192192
}
193193

194+
func PrettyByteSlice(buffer []byte) string {
195+
var out strings.Builder
196+
for _, b := range buffer {
197+
if b >= 32 && b <= 126 {
198+
out.WriteByte(b)
199+
} else {
200+
out.WriteString(fmt.Sprintf("\\x%02x", b))
201+
}
202+
}
203+
return out.String()
204+
}
205+
194206
func HexDump(buffer []byte, color string) string {
195207
b := dumpByteSlice(buffer, color)
196208
b.WriteString(COLORRESET)
197209
return b.String()
198210
}
199211

212+
func HexDumpPure(buffer []byte) string {
213+
b := dumpByteSlice(buffer, "")
214+
return b.String()
215+
}
216+
200217
func HexDumpGreen(buffer []byte) string {
201218
b := dumpByteSlice(buffer, COLORGREEN)
202219
b.WriteString(COLORRESET)

src/stack.c

Lines changed: 78 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -185,93 +185,22 @@ struct {
185185
__uint(max_entries, 1);
186186
} syscall_filter SEC(".maps");
187187

188-
189-
// static __always_inline u32 read_args(program_data_t p, struct syscall_point_args_t* syscall_point_args, args_t* args, u32 check_flag, u32 next_arg_index, u32 read_) {
190-
// u32 point_arg_count = MAX_POINT_ARG_COUNT;
191-
// if (syscall_point_args->count <= point_arg_count) {
192-
// point_arg_count = syscall_point_args->count;
193-
// }
194-
// for (int i = 0; i < point_arg_count; i++) {
195-
// u64 ptr = args->args[i];
196-
// // 保存参数的寄存器
197-
// save_to_submit_buf(p.event, (void *)ptr, sizeof(u64), next_arg_index);
198-
// next_arg_index += 1;
199-
// struct point_arg_t* point_arg = (struct point_arg_t*) &syscall_point_args->point_args[i];
200-
// if (point_arg->read_flag != SYS_ENTER_EXIT) {
201-
// if (point_arg->read_flag != check_flag) {
202-
// continue;
203-
// }
204-
// }
205-
// if (point_arg->type == TYPE_NONE) {
206-
// continue;
207-
// }
208-
// if (point_arg->type == TYPE_NUM) {
209-
// // 这种具体类型转换交给前端做
210-
// continue;
211-
// }
212-
// if (point_arg->type == TYPE_STRING) {
213-
// u32 buf_off = 0;
214-
// buf_t *string_p = get_buf(STRING_BUF_IDX);
215-
// if (string_p == NULL) {
216-
// continue;
217-
// }
218-
// int status = bpf_probe_read_user(&string_p->buf[buf_off], MAX_STRING_SIZE, (void *)ptr);
219-
// if (status < 0) {
220-
// // MTE 其实也正常读取到了
221-
// bpf_probe_read_user_str(&string_p->buf[buf_off], MAX_STRING_SIZE, (void *)ptr);
222-
// }
223-
// save_str_to_buf(p.event, &string_p->buf[buf_off], next_arg_index);
224-
// next_arg_index += 1;
225-
// continue;
226-
// }
227-
// if (point_arg->type == TYPE_STRING_ARR && ptr != 0) {
228-
// save_str_arr_to_buf(p.event, (const char *const *) ptr /*ptr*/, next_arg_index);
229-
// next_arg_index += 1;
230-
// continue;
231-
// }
232-
// if (point_arg->type == TYPE_POINTER) {
233-
// // 指针类型 通常读一下对应指针的数据即可 后续记得考虑兼容下32位
234-
235-
// // point_arg->alias_type
236-
// // 某些成员是指针 有可能有必要再深入读取
237-
// // 这个时候可以根据 alias_type 取出对应的参数配置 然后解析保存
238-
// // 这个后面增补
239-
240-
// // if (point_arg->alias_type == TYPE_BY) {
241-
242-
// // }
243-
244-
// u64 addr = 0;
245-
// bpf_probe_read_user(&addr, sizeof(addr), (void*) ptr);
246-
// save_to_submit_buf(p.event, (void *) &addr, sizeof(u64), next_arg_index);
247-
// next_arg_index += 1;
248-
// continue;
249-
// }
250-
// if (point_arg->type == TYPE_STRUCT && ptr != 0) {
251-
// // 结构体类型 直接读取对应大小的数据 具体转换交给前端
252-
// u32 struct_size = MAX_BYTES_ARR_SIZE;
253-
// if (point_arg->size <= struct_size) {
254-
// struct_size = point_arg->size;
255-
// }
256-
// // 修复 MTE 读取可能不正常的情况
257-
// int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), struct_size, next_arg_index);
258-
// if (status == 0) {
259-
// // 保存失败的情况 比如 ptr 是一个非法的地址 ...
260-
// buf_t *zero_p = get_buf(ZERO_BUF_IDX);
261-
// if (zero_p == NULL) {
262-
// continue;
263-
// }
264-
// // 这个时候填充一个全0的内容进去 不然前端不好解析
265-
// save_bytes_to_buf(p.event, &zero_p->buf[0], struct_size, next_arg_index);
266-
// next_arg_index += 1;
267-
// } else {
268-
// next_arg_index += 1;
269-
// }
270-
// }
271-
// }
272-
// return next_arg_index;
273-
// }
274-
static __always_inline u32 read_arg(program_data_t p, struct point_arg_t* point_arg, u64 ptr, u32 read_len, u32 next_arg_index) {
188+
static __always_inline u32 save_bytes_with_len(program_data_t p, u64 ptr, u32 read_len, u32 next_arg_index) {
189+
if (read_len > MAX_BUF_READ_SIZE) {
190+
read_len = MAX_BUF_READ_SIZE;
191+
}
192+
int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), read_len, next_arg_index);
193+
if (status == 0) {
194+
buf_t *zero_p = get_buf(ZERO_BUF_IDX);
195+
if (zero_p == NULL) {
196+
return next_arg_index;
197+
}
198+
save_bytes_to_buf(p.event, &zero_p->buf[0], read_len, next_arg_index);
199+
}
200+
next_arg_index += 1;
201+
return next_arg_index;
202+
}
203+
static __always_inline u32 read_arg(program_data_t p, struct point_arg_t* point_arg, u64 ptr, u32 read_count, u32 next_arg_index) {
275204
if (point_arg->type == TYPE_NONE) {
276205
return next_arg_index;
277206
}
@@ -306,13 +235,10 @@ static __always_inline u32 read_arg(program_data_t p, struct point_arg_t* point_
306235
// 某些成员是指针 有可能有必要再深入读取
307236
// 这个时候可以根据 alias_type 取出对应的参数配置 然后解析保存
308237
// 这个后面增补
309-
310238
if (point_arg->alias_type == TYPE_BUFFER_T) {
311-
u32 aaa = MAX_BUF_READ_SIZE
312-
if (read_len <= aaa) {
313-
aaa = read_len;
314-
}
315-
int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), aaa, next_arg_index);
239+
// buffer 的单个元素长度就是 1 所以这里就是 read_count
240+
u32 read_len = read_count * 1;
241+
int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), read_len, next_arg_index);
316242
if (status == 0) {
317243
buf_t *zero_p = get_buf(ZERO_BUF_IDX);
318244
if (zero_p == NULL) {
@@ -333,6 +259,32 @@ static __always_inline u32 read_arg(program_data_t p, struct point_arg_t* point_
333259
return next_arg_index;
334260
}
335261
if (point_arg->type == TYPE_STRUCT && ptr != 0) {
262+
263+
if (point_arg->alias_type == TYPE_IOVEC) {
264+
struct iovec iovec_ptr;
265+
int errno = bpf_probe_read_user(&iovec_ptr, sizeof(iovec_ptr), (void*) ptr);
266+
if (errno == 0) {
267+
save_to_submit_buf(p.event, (void *)&iovec_ptr, sizeof(iovec_ptr), next_arg_index);
268+
next_arg_index += 1;
269+
// 目前这样只是读取了第一个 iov 实际上要多次读取 数量是 iovcnt
270+
// 但是注意多个缓冲区并不是连续的
271+
u64 iov_base = (u64)iovec_ptr.iov_base;
272+
u32 iov_len = (u64)iovec_ptr.iov_len;
273+
// u32 read_len = read_count * iov_len;
274+
u32 read_len = iov_len;
275+
if (read_len > MAX_BUF_READ_SIZE) {
276+
read_len = MAX_BUF_READ_SIZE;
277+
}
278+
// save_to_submit_buf(p.event, (void *)&iov_base, sizeof(iov_base), next_arg_index);
279+
// next_arg_index += 1;
280+
// // 注意 这里存放的大小是 u64 与结构体大小保持一致
281+
// save_to_submit_buf(p.event, (void *)&read_len, sizeof(read_len), next_arg_index);
282+
// next_arg_index += 1;
283+
next_arg_index = save_bytes_with_len(p, iov_base, read_len, next_arg_index);
284+
return next_arg_index;
285+
}
286+
}
287+
336288
// 结构体类型 直接读取对应大小的数据 具体转换交给前端
337289
u32 struct_size = MAX_BYTES_ARR_SIZE;
338290
if (point_arg->size <= struct_size) {
@@ -520,9 +472,6 @@ int raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) {
520472
point_arg_count = syscall_point_args->count;
521473
}
522474

523-
524-
// int next_arg_index = read_args(p, syscall_point_args, &args, SYS_ENTER, 4);
525-
526475
int next_arg_index = 4;
527476
// #pragma unroll
528477
for (int i = 0; i < point_arg_count; i++) {
@@ -533,31 +482,23 @@ int raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) {
533482
if (point_arg->read_flag != SYS_ENTER) {
534483
continue;
535484
}
536-
// 如果是要读取 buffer
537-
// u32 read_len = 0;
538-
// if (point_arg->alias_type == TYPE_BUFFER_T) {
539-
// u32 item_count = args.args[point_arg->item_countindex];
540-
// u32 item_persize = point_arg->item_persize;
541-
// if (item_count <= MAX_BUF_READ_SIZE && item_persize < MAX_BUF_READ_SIZE) {
542-
// read_len = item_count * item_persize;
543-
// }
544-
// // u32 item_count = args.args[point_arg->item_countindex];
545-
// // if (item_count <= MAX_BUF_READ_SIZE) {
546-
// // read_len = item_count;
547-
// // } else {
548-
// // read_len = MAX_BUF_READ_SIZE;
549-
// // }
550-
// }
551-
// if (read_len >= MAX_BUF_READ_SIZE) {
552-
// read_len = MAX_BUF_READ_SIZE;
553-
// }
554-
555-
u32 read_len = MAX_BUF_READ_SIZE;
556-
if (args.args[point_arg->item_countindex] <= read_len) {
557-
read_len = args.args[point_arg->item_countindex];
485+
u32 read_count = MAX_BUF_READ_SIZE;
486+
if (point_arg->item_countindex >= 0) {
487+
// math between fp pointer and register with unbounded min value is not allowed
488+
// 后面取寄存器可能存在越界 所以必须保证索引必须是在正确的范围内
489+
// 这里必须把 item_countindex 赋值给临时变量 并且必须转换类型
490+
// 然后通过 if 比较来明确它不会越界 然后后面再用它作为取寄存器的索引
491+
// 最后计算要读取数据的最终大小 当然这里也必须有一个上限大小
492+
u32 item_index = (u32) point_arg->item_countindex;
493+
if (item_index >= 6) {
494+
return 0;
495+
}
496+
u32 item_count = (u32) args.args[item_index];
497+
if (item_count <= read_count) {
498+
read_count = item_count;
499+
}
558500
}
559-
560-
next_arg_index = read_arg(p, point_arg, args.args[i], read_len, next_arg_index);
501+
next_arg_index = read_arg(p, point_arg, args.args[i], read_count, next_arg_index);
561502
}
562503
events_perf_submit(&p, SYSCALL_ENTER);
563504
return 0;
@@ -662,8 +603,6 @@ int raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) {
662603
save_to_submit_buf(p.event, (void *) &syscallno, sizeof(u32), next_arg_index);
663604
next_arg_index += 1;
664605

665-
// next_arg_index = read_args(p, syscall_point_args, &saved_args, SYS_EXIT, next_arg_index);
666-
667606
u32 point_arg_count = MAX_POINT_ARG_COUNT;
668607
if (syscall_point_args->count <= point_arg_count) {
669608
point_arg_count = syscall_point_args->count;
@@ -677,7 +616,23 @@ int raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) {
677616
if (point_arg->read_flag != SYS_EXIT) {
678617
continue;
679618
}
680-
next_arg_index = read_arg(p, point_arg, saved_args.args[i], 0, next_arg_index);
619+
u32 read_count = MAX_BUF_READ_SIZE;
620+
if (point_arg->item_countindex >= 0) {
621+
// math between fp pointer and register with unbounded min value is not allowed
622+
// 后面取寄存器可能存在越界 所以必须保证索引必须是在正确的范围内
623+
// 这里必须把 item_countindex 赋值给临时变量 并且必须转换类型
624+
// 然后通过 if 比较来明确它不会越界 然后后面再用它作为取寄存器的索引
625+
// 最后计算要读取数据的最终大小 当然这里也必须有一个上限大小
626+
u32 item_index = (u32) point_arg->item_countindex;
627+
if (item_index >= 6) {
628+
return 0;
629+
}
630+
u32 item_count = (u32) saved_args.args[item_index];
631+
if (item_count <= read_count) {
632+
read_count = item_count;
633+
}
634+
}
635+
next_arg_index = read_arg(p, point_arg, saved_args.args[i], read_count, next_arg_index);
681636
}
682637
// 读取返回值
683638
u64 ret = READ_KERN(regs->regs[0]);

user/config/config_syscall.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ var TIMEZONE = AT(TYPE_TIMEZONE, TYPE_STRUCT, uint32(unsafe.Sizeof(TimeZone_t{})
301301
var BUFFER_T = AT(TYPE_BUFFER_T, TYPE_POINTER, uint32(unsafe.Sizeof(uint64(0))))
302302
var READ_BUFFER_T = BUFFER_T.SetIndex(2)
303303
var WRITE_BUFFER_T = BUFFER_T.SetIndex(2)
304+
var IOVEC_T = IOVEC.SetIndex(2)
304305

305306
// 64 位下这个是 unsigned long sig[_NSIG_WORDS]
306307
// #define _NSIG 64
@@ -390,8 +391,8 @@ func init() {
390391
Register(&SArgs{64, PA("write", []PArg{A("fd", INT), A("buf", WRITE_BUFFER_T), A("count", INT)})})
391392
Register(&SArgs{65, PA("readv", []PArg{A("fd", INT), B("iov", IOVEC), A("iovcnt", INT)})})
392393
Register(&SArgs{66, PA("writev", []PArg{A("fd", INT), A("iov", IOVEC), A("iovcnt", INT)})})
393-
Register(&SArgs{67, PA("pread64", []PArg{A("fd", INT), B("buf", INT), A("count", INT), A("offset", INT)})})
394-
Register(&SArgs{68, PA("pwrite64", []PArg{A("fd", INT), A("buf", INT), A("count", INT), A("offset", INT)})})
394+
Register(&SArgs{67, PA("pread64", []PArg{A("fd", INT), B("buf", READ_BUFFER_T), A("count", INT), A("offset", INT)})})
395+
Register(&SArgs{68, PA("pwrite64", []PArg{A("fd", INT), A("buf", WRITE_BUFFER_T), A("count", INT), A("offset", INT)})})
395396
Register(&SArgs{69, PA("preadv", []PArg{A("fd", INT), B("iov", IOVEC), A("iovcnt", INT), A("offset", INT)})})
396397
Register(&SArgs{70, PA("pwritev", []PArg{A("fd", INT), A("iov", IOVEC), A("iovcnt", INT), A("offset", INT)})})
397398
Register(&SArgs{71, PA("sendfile", []PArg{A("out_fd", INT), A("in_fd", INT), A("offset", INT), A("count", INT)})})

user/event/event_raw_syscalls.go

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ func (this *Arg_TimeZone_t) Format() string {
9898
return fmt.Sprintf("{%s}", strings.Join(fields, ", "))
9999
}
100100

101+
type Arg_Buffer_t struct {
102+
Arg_str
103+
Payload []byte
104+
}
105+
106+
func (this *Arg_Buffer_t) Format() string {
107+
// hexdump := util.HexDumpPure(this.Payload)
108+
hexdump := util.PrettyByteSlice(this.Payload)
109+
return fmt.Sprintf("(%s)", hexdump)
110+
}
111+
101112
type Arg_Timeval struct {
102113
Index uint8
103114
Len uint32
@@ -228,16 +239,20 @@ func (this *Arg_RawSockaddrUnix) Format() string {
228239

229240
type Arg_Iovec struct {
230241
Index uint8
231-
Len uint32
232242
Base uint64
233243
BufLen uint64
234-
// syscall.Iovec
235244
}
236245

237-
func (this *Arg_Iovec) Format() string {
246+
type Arg_Iovec_t struct {
247+
Arg_Iovec
248+
Payload []byte
249+
}
250+
251+
func (this *Arg_Iovec_t) Format() string {
238252
var fields []string
239253
fields = append(fields, fmt.Sprintf("base=0x%x", this.Base))
240254
fields = append(fields, fmt.Sprintf("len=0x%x", this.BufLen))
255+
fields = append(fields, fmt.Sprintf("buf=(%s)", util.PrettyByteSlice(this.Payload)))
241256
return fmt.Sprintf("{%s}", strings.Join(fields, ", "))
242257
}
243258

@@ -407,14 +422,24 @@ func (this *SyscallEvent) ParseArg(point_arg *config.PointArg, ptr Arg_reg) (err
407422
break
408423
case config.TYPE_NUM:
409424
break
425+
case config.TYPE_BUFFER_T:
426+
var arg Arg_Buffer_t
427+
if err = binary.Read(this.buf, binary.LittleEndian, &arg.Arg_str); err != nil {
428+
panic(fmt.Sprintf("binary.Read err:%v", err))
429+
}
430+
payload := make([]byte, arg.Len)
431+
if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil {
432+
panic(fmt.Sprintf("binary.Read err:%v", err))
433+
}
434+
arg.Payload = payload
435+
point_arg.AppendValue(arg.Format())
410436
case config.TYPE_STRING:
411-
var arg_str Arg_str
412-
if err = binary.Read(this.buf, binary.LittleEndian, &arg_str); err != nil {
437+
var arg Arg_str
438+
if err = binary.Read(this.buf, binary.LittleEndian, &arg); err != nil {
413439
panic(fmt.Sprintf("binary.Read err:%v", err))
414440
}
415-
payload := make([]byte, arg_str.Len)
441+
payload := make([]byte, arg.Len)
416442
if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil {
417-
this.logger.Printf("SyscallEvent eventid:%d RawSample:\n%s", this.eventid, util.HexDump(this.rec.RawSample, util.COLORGREEN))
418443
panic(fmt.Sprintf("binary.Read err:%v", err))
419444
}
420445
point_arg.AppendValue(fmt.Sprintf("(%s)", util.B2STrim(payload)))
@@ -531,11 +556,16 @@ func (this *SyscallEvent) ParseArg(point_arg *config.PointArg, ptr Arg_reg) (err
531556
}
532557
point_arg.AppendValue(arg_rusage.Format())
533558
case config.TYPE_IOVEC:
534-
var arg_iovec Arg_Iovec
535-
if err = binary.Read(this.buf, binary.LittleEndian, &arg_iovec); err != nil {
559+
var arg Arg_Iovec_t
560+
if err = binary.Read(this.buf, binary.LittleEndian, &arg.Arg_Iovec); err != nil {
536561
panic(fmt.Sprintf("binary.Read err:%v", err))
537562
}
538-
point_arg.AppendValue(arg_iovec.Format())
563+
payload := make([]byte, arg.BufLen)
564+
if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil {
565+
panic(fmt.Sprintf("binary.Read err:%v", err))
566+
}
567+
arg.Payload = payload
568+
point_arg.AppendValue(arg.Format())
539569
case config.TYPE_EPOLLEVENT:
540570
var arg_epollevent Arg_EpollEvent
541571
if err = binary.Read(this.buf, binary.LittleEndian, &arg_epollevent); err != nil {

0 commit comments

Comments
 (0)