如何使用ebpf kprobe探测内核函数

news2024/12/23 14:56:04

前言

    在这之前, 我也曾使用过ebpf来改造我自己的项目, 最后也成功引入了项目, 有兴趣的同学可以查看此文章.

如何用ebpf开启tun网卡的TUNSETSTEERINGEBPF功能_我不买vip的博客-CSDN博客

    但是该文章里并没有实质性的内容, 比如ebpf的map未曾涉及, 探测类型也未曾涉及, 只是一个空壳ebpf程序, 虽然能用, 但是是依赖内核开发者已开发出来的功能, 并未真正使用ebpf.

    最近一段时间, 公司让我优化某个项目, 就借此机会又研究了下ebpf. 当然了, 研究ebpf最好的方法肯定是研究linux源码下samples/bpf的相关例子. 本文也是根据samples/bpf的例子改造的.

    该文章主要目的是如何使用kprobe探测内核函数. 而在本文里则是ebpf的内核态代码用kprobe探测connect的系统调用函数__sys_connect, 并在探测时解析出dest port作为key, 获取应用层pid(比如本文里的测试程序iperf3)作为value放入map里. 而ebpf的用户态程序遍历此map, 并打印相关信息.

环境

    Ubuntu-22.10环境, 5.19.0-23-generic内核, x86_64架构, 所下载的linux源码为5.19.0.

编译

    关于如何编译linux源码下的samples/bpf程序, 可以参考此文章.

如何使用linux源码编译bpf_我不买vip的博客-CSDN博客

    注意, ubuntu20编译linux-5.4.0和ubuntu22编译linux-5.19.0方法的最后一步不一样, 该篇文章编译的最后一步为

make VMLINUX_BTF=/sys/kernel/btf/vmlinux -C samples/bpf

源码

   源码包含两个部分, for_conn_kern.c和for_conn_user.c两部分, 分别对应ebpf的内核态程序和ebpf的用户态程序. 实际代码如下:

     for_conn_kern.c

// for_conn_kern.c

#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/version.h>
#include <uapi/linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <net/sock.h>
#include "trace_common.h"

#define MAX_ENTRIES 1024

struct {
	__uint(type, BPF_MAP_TYPE_HASH);
	__type(key, u32);
	__type(value, u32);
	__uint(max_entries, MAX_ENTRIES);
} port_2_pid_map SEC(".maps");

SEC("kprobe/__sys_connect")
int trace_sys_conn(struct pt_regs *ctx)
{
	int ret = 0;
	u16 port = 0;
	u32 key = 0;
        u32 pid = 0;

	struct sockaddr_in *in4 = (struct sockaddr_in *)PT_REGS_PARM2_CORE(ctx);
	if ((ret = bpf_probe_read_user(&port, sizeof(port), &in4->sin_port)))
	{
		return 0;
	}
	key = ntohs(port);
	pid = bpf_get_current_pid_tgid() >> 32;

	bpf_map_update_elem(&port_2_pid_map, &key, &pid, BPF_ANY);
	return 0;
}

char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;

     for_conn_user.c

// for_conn_user.c

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <sys/types.h>
#include <asm/unistd.h>
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <errno.h>

#include <bpf/bpf.h>
#include <bpf/libbpf.h>

int main(int argc, char **argv)
{
        struct bpf_object *obj = NULL;
        int i = 0;
        int mfd = 0;
        struct bpf_link *link = NULL;
	struct bpf_program *prog;
	char filename[256];
        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

        //-----------------//
	obj = bpf_object__open_file(filename, NULL);
	if (libbpf_get_error(obj)) 
        {
		fprintf(stderr, "ERROR: opening BPF object file failed\n");
		return -1;
	}
	if (bpf_object__load(obj)) 
        {
		fprintf(stderr, "ERROR: loading BPF object file failed\n");
		goto END;
	}

        //-----------------//
        prog = bpf_object__find_program_by_name(obj, "trace_sys_conn");
	if (!prog) 
        {
		printf("finding a prog in obj file failed\n");
		goto END;
	}

        //-----------------//
        mfd = bpf_object__find_map_fd_by_name(obj, "port_2_pid_map");
        if (mfd < 0)
        {
		fprintf(stderr, "ERROR: finding a map fd in obj file failed\n");
		goto END;    
        }

        //-----------------//
	link = bpf_program__attach(prog);
	if (libbpf_get_error(link)) 
        {
		fprintf(stderr, "ERROR: bpf_program__attach link failed\n");
		link = NULL;
		goto END;
	}

        for (i = 0; i < 1000; i++)
        {
                unsigned int key = 0;
                unsigned int next_key = 0;
                while (bpf_map_get_next_key(mfd, &key, &next_key) == 0) 
                {
                        unsigned int value = 0;
                        bpf_map_lookup_elem(mfd, &next_key, &value);
                        fprintf(stdout, "port: %u, pid: %d\n", next_key, value);
                        key = next_key;
                }
                printf("-----------------------\n");
                sleep(1);
        }
        
END:
        bpf_link__destroy(link);
        bpf_object__close(obj);
	return 0;
}

    其实在<<编译>>部分, 我们已经编译好了samples/bpf程序, 现在只需要把for_conn_kern.c和for_conn_user.c加入到samples/bpf/Makefile文件里即可, 而我们可以根据tracex3在对应的部分添加这两个文件即可. 比如:

测试 

1, 在一台服务器用iperf3启动一个tcp服务, 比如: iperf3 -s 0.0.0.0 -p 6230

2, 启动该ebpf程序, ./for_conn

3, 在本机启动一个iperf3客户端, 连接6230端口, 比如: iperf3 -s 192.168.20.1xx -p 6230

4, 查看本机iperf3进程id, 查看./for_conn打印信息

    测试结果入下图:

    可以看到, ps获取的iperf3的信息跟打印的信息匹配, 说明kprobe探测成功.

结束

    ebpf的功能远不止于此, 我对此的探索也没有终止. 下一篇文章准备写如何用ebpf统计某个端口的流量. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汽车蓄电池低压报警设计

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1 选题背景及意义 1 1.2 国内外发展状况 2 1.2.1国内发展现状 2 1.2.2 国外蓄电池监测系统研究现状 2 1.3 研究主要内容 4 第2章 系统总体设计与算法确定 5 2.1 监测系统总体设计原理 5 2.2 主控芯片的选择 6 2.2.1 89C51单片机的概…

JAVA 中的代码生成包 CGLIB (Code Generation Library)

JAVA 中的代码生成包 CGLIB &#xff08;Code Generation Library&#xff09; CGLIB 是一个功能强大&#xff0c;高性能的代码生成包。它为没有实现接口的类提供代理&#xff0c;为 JDK 的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理&#xff0c;但当要代…

【DL with Pytorch】第 4 章 : 卷积神经网络

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

nablet Elements released处理视频的组件

nablet Elements released处理视频的组件 mediaEngine-一个转码工厂&#xff0c;为视频工作流从贡献到分发提供动力。 HeightScreen-AI驱动的工具&#xff0c;用于将视频转换为垂直屏幕&#xff0c;自动选择感兴趣的区域。 Shrynk-AI驱动的解决方案&#xff0c;可自动完成高亮编…

电商的噩梦:全国快递网点停摆65%?

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 今年应该是所有行业最难最艰苦的一年&#xff0c;据龚文祥爆料&#xff0c;全国当前有三分之一的地区停发快递&#xff0c;电商到了最艰难的时刻&#xff0c;所有电商交易立即下降30%。而知名数码博…

Java中使用JDBC操作Postgresql

目录 在Rocky Linux上安装postgresql 用IntelliJ创建JavaFx项目 画一个表格 建立数据库访问 在Rocky Linux上安装postgresql Rocky的仓库中自带了postgresql安装包&#xff0c;我们直接用dnf安装即可&#xff1a; dnf install postgresql-server -y 安装好之后&#xff0c;…

大数据下一代变革之必研究数据湖技术Hudi原理实战双管齐下-下

文章目录集成Spark开发Spark编程读写示例DeltaStreamer集成Flink环境准备sql-clent使用启动插入数据流式读取Bucket索引Hudi Catalog集成Spark开发 Spark编程读写示例 通过IDE如Idea编程实质上和前面的spark-shell和spark-sql相似&#xff0c;其他都是Spark编程的知识&#x…

自定义对象_JavaScript

自定义对象_JavaScript 学习路线&#xff1a;JavaScript基础语法&#xff08;输出语句&#xff09;->JavaScript基础语法&#xff08;变量&#xff09;->JavaScript基础语法&#xff08;数据类型&#xff09;->JavaScript基础语法&#xff08;运算符&#xff09;->…

IB心理学如何记住大量的内容?

将在这篇文章中探讨一下怎样在IB心理学中搞定studies。 一. 为什么要记studies&#xff1f; 学IB心理学的同学们都知道&#xff0c;这个课程很大一部分就是学习&#xff0c;理解&#xff0c;并在考试中熟练应用心理学中的研究&#xff08;studies&#xff09;。为了在考试中应答…

CAS:1516551-46-4,BCN-琥珀酰亚胺酯,BCN-NHS点击试剂供应

一&#xff1a;产品描述 1、名称&#xff1a; BCN-NHS BCN-活性酯 BCN-NHS 酯 丙烷环辛炔-活性酯 BCN-琥珀酰亚胺酯 BCN-succinimidylester 2、CAS编号&#xff1a;1516551-46-4 3、质量控制&#xff1a;95% 4、分子量&#xff1a;291.30 5、分子式&#xff1a;C15H…

Redis哨兵模式详解

文章目录一、概念二、原理三、多哨兵模式的工作过程四、客户端的工作过程五、应用1、配置sentinel哨兵&#xff08;单个&#xff09;2、启动哨兵3、模拟主服务器意外宕机情况一、概念 在 Redis 主从复制模式中&#xff0c;因为系统不具备自动恢复的功能&#xff0c;所以当主服…

传奇战盟GOM引擎登录器配置教程

战盟GOM引擎配置器教程&#xff0c;先到战盟官方网站下载登录器配置器&#xff0c;下载好后按下面说明使用。战盟GOM登录器教程大分类目录引导说明 一、解压配置器文件包后&#xff0c;打开KEY文件夹然后选择KEY 二、复制你选择好的 Key.Lic 复制到 战盟GOM配置器 相同路径文件…

外汇天眼:乐天证券扩大了交易工具!进入数字资产市场!

根据一份商业声明&#xff0c;这些从今天开始可以访问的新成员包括在纽约证券交易所、纳斯达克和上海证券交易所上市的公司。 随着客户对接触受监管市场的需求不断增长&#xff0c;该经纪商将其产品范围扩大到涵盖货币、商品、股票和指数。新股票的加入不仅有助于提高其客户的交…

网络面试-0x11 TCP为什么需要三次握手和四次挥手?

网络面试-0x11 TCP为什么需要三次握手和四次挥手&#xff1f; 一、三次握手 三次握手[three-way-handshake]&#xff1a;客户端和服务器总共发送3个包&#xff0c;以建立TCP连接。 什么是连接了&#xff1f;主要作用是什么&#xff1f; 连接&#xff1a; 主要作用&#xff1a;为…

基于Redis实现特殊的消息队列

特殊场景的消息队列 消息队列使用比较多的产品kafka&#xff0c;在各个领域都发挥了很大的作用&#xff0c;但是在以下的几种场景是无法满足需求。 场景 消息重复概率比较高时&#xff0c;需要对重复消息进行合并处理避免浪费有限的资源&#xff0c;减少延迟需要根据业务自定…

正大国际期货:投资外盘期货如何用布林线判断走势?

外盘期货的投资者越来越多&#xff0c;每个投资者判断大盘走势的方式也不尽相同&#xff0c;那么今天正大IxxxuanI就来简单的和大家说说外盘期货投资如何用布林线判断走势吧。 1、当布林线多条轨道向上或是向下运行时&#xff0c;这能非常有效的说明走势强劲程度。投资者应牢牢…

接触非线性分析不收敛? 写给ABAQUS初学者的N个经验

接触&#xff0c;在仿真分析中&#xff0c;绝对是个看似青铜实则王者级别的难题。一些通用的解决办法&#xff0c;在帮助文件的Interaction → Contact Difficulties and Diagnostics中找到&#xff0c;例如初始接触状况、穿透、突然分离造成的局部不稳定等等。 但是确实没有一…

slam定位学习笔记(七)-g2o学习

主要学习的是这篇文章&#xff0c;但大佬并没有在文章里面仔细的讲g2o&#xff0c;所以我在网上找了这几篇介绍g2o的文章&#xff0c;讲的十分详细&#xff0c;对入门十分友好&#xff1a;文章一、文章二、文章三&#xff0c;这三篇都是一个作者写的&#xff0c;主要是针对编程…

第五届“强网”拟态防御国际精英挑战赛——特邀战队篇

第五届“强网”拟态防御国际精英挑战赛即将在南京隆重开赛&#xff01;本届大赛面向全球顶尖CTF战队&#xff0c;在创新应用场景与技术的基础上&#xff0c;拓展升级赛道&#xff0c;全面覆盖典型网络设备。大赛汇集国内外60支精英战队&#xff0c;参赛阵容、数量再创新高。 本…

35岁了,月薪还不足2W,辞职又怕找不到工作,该何去何从?

今天看到网上有人在吐槽&#xff1a;“马上就35岁了&#xff0c;月薪还不到2W&#xff0c;公司发展缓慢&#xff0c;想离职又怕找不到工作&#xff0c;不知道怎么办&#xff1f;” 单看月薪两万&#xff0c;好像也不少&#xff0c;不过收入跟行业和地域也有很大关系。薪资&…