iw添加wlan0导致crash问题分析

比如通过日下命令,创建一个wlan0接口

iw phy phy0 interface add wlan0 type managed

会产生如下panic内容

<1> [54245.466372] Unable to handle kernel NULL pointer dereference at virtual address 00000010
<1> [54245.474729] pgd = c1794000
<1> [54245.477443] [00000010] *pgd=01090831, *pte=00000000, *ppte=00000000
<0> [54245.483879] Internal error: Oops: 17 [#1] PREEMPT THUMB2
<4> [54245.638361] CPU: 0 PID: 21542 Comm: iw Not tainted 3.10.33 #2
<4> [54245.644095] task: c1348000 ti: c13e2000 task.ti: c13e2000
<4> [54245.649524] PC is at nl80211_send_iface+0xc/0x160
<4> [54245.654221] LR is at nl80211_new_interface+0x1cf/0x224
<4> [54245.659345] pc : [<c02956ec>]    lr : [<c029a56f>]    psr: 40000033
sp : c13e3c40  ip : 0000005d  fp : 00000000
<4> [54245.670813] r10: 00000014  r9 : c13e3ca0  r8 : c0923100
<4> [54245.676028] r7 : 00000002  r6 : c17b8000  r5 : 00000000  r4 : c0923100
<4> [54245.682555] r3 : 00000000  r2 : 673be4b6  r1 : 00005426  r0 : c0923100
<4> [54245.689082] Flags: nZcv  IRQs on  FIQs on  Mode SVC_32  ISA Thumb  Segment user
<4> [54245.696372] Control: 50c53c7d  Table: 01794059  DAC: 00000015

nl80211_send_iface的wdev这个参数为空指针 ;看看nl80211_new_interface调用nl80211_send_iface之前,是怎么给wdev赋值的,如下述代码是从rdev_add_virtual_intf获取wdev这个wireless_dev结构体;也就是要找到这个函数为什么返回空指针

static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{struct cfg80211_registered_device *rdev = info->user_ptr[0];struct vif_params params;struct wireless_dev *wdev;struct sk_buff *msg;int err;enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;/* to avoid failing a new interface creation due to pending removal */cfg80211_destroy_ifaces(rdev);memset(&params, 0, sizeof(params));if (!info->attrs[NL80211_ATTR_IFNAME])return -EINVAL;if (info->attrs[NL80211_ATTR_IFTYPE]) {type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);if (type > NL80211_IFTYPE_MAX)return -EINVAL;}if (!rdev->ops->add_virtual_intf ||!(rdev->wiphy.interface_modes & (1 << type)))return -EOPNOTSUPP;if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&info->attrs[NL80211_ATTR_MAC]) {nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],ETH_ALEN);if (!is_valid_ether_addr(params.macaddr))return -EADDRNOTAVAIL;}if (info->attrs[NL80211_ATTR_4ADDR]) {params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);if (err)return err;}err = nl80211_parse_mon_options(rdev, type, info, &params);if (err < 0)return err;msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);if (!msg)return -ENOMEM;wdev = rdev_add_virtual_intf(rdev,nla_data(info->attrs[NL80211_ATTR_IFNAME]),NET_NAME_USER, type, &params);if (WARN_ON(!wdev)) {nlmsg_free(msg);return -EPROTO;} else if (IS_ERR(wdev)) {nlmsg_free(msg);return PTR_ERR(wdev);}if (info->attrs[NL80211_ATTR_SOCKET_OWNER])wdev->owner_nlportid = info->snd_portid;switch (type) {case NL80211_IFTYPE_MESH_POINT:if (!info->attrs[NL80211_ATTR_MESH_ID])break;wdev_lock(wdev);BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=IEEE80211_MAX_MESH_ID_LEN);wdev->mesh_id_up_len =nla_len(info->attrs[NL80211_ATTR_MESH_ID]);memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),wdev->mesh_id_up_len);wdev_unlock(wdev);break;case NL80211_IFTYPE_NAN:case NL80211_IFTYPE_P2P_DEVICE:/** P2P Device and NAN do not have a netdev, so don't go* through the netdev notifier and must be added here*/mutex_init(&wdev->mtx);INIT_LIST_HEAD(&wdev->event_list);spin_lock_init(&wdev->event_lock);INIT_LIST_HEAD(&wdev->mgmt_registrations);spin_lock_init(&wdev->mgmt_registrations_lock);wdev->identifier = ++rdev->wdev_id;list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);rdev->devlist_generation++;break;default:break;}if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,rdev, wdev, false) < 0) {nlmsg_free(msg);return -ENOBUFS;}/** For wdevs which have no associated netdev object (e.g. of type* NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.* For all other types, the event will be generated from the* netdev notifier*/if (!wdev->netdev)nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);return genlmsg_reply(msg, info);
}

rdev_add_virtual_intf调用的是cfg80211_registered_device的ops成员的add_virtual_intf函数指针

static inline struct wireless_dev
*rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name,unsigned char name_assign_type,enum nl80211_iftype type,struct vif_params *params)
{struct wireless_dev *ret;trace_rdev_add_virtual_intf(&rdev->wiphy, name, type);ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, name_assign_type,type, params);trace_rdev_return_wdev(&rdev->wiphy, ret);return ret;
}

wifi驱动会调用wiphy_new来分配一个cfg80211_registered_device,并且将cfg80211_ops赋值给这个cfg80211_registered_device的ops成员

struct cfg80211_ops wifi_cfg80211_ops = {.add_virtual_intf = wifi_interface_add,.del_virtual_intf = wifi_interface_del.....
}
wiphy_new(&ssv_cfg80211_ops, sizeof(struct ssv_softc));

wiphy_new的实现如下:主要是申请一块cfg80211_registered_device的内存,并将第一个ops参数赋值给ops成员

struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,const char *requested_name)
{....struct cfg80211_registered_device *rdev;rdev = kzalloc(alloc_size, GFP_KERNEL);rdev->ops = ops;wiphy_net_set(&rdev->wiphy, &init_net);....
}

解决办法如下:通过__dev_get_by_name从网络命令空间init_net查找wlan0这个net_device是否已经被注册到系统,检测到直接返回wireless_dev;不然直接再通过register_netdevice注册一个wlan0,就返回NULL了

--- a/package/kernel/wifi/src/fmac/netdev_ops.c
+++ b/package/kernel/wifi/src/fmac/netdev_ops.c
@@ -498,6 +498,10 @@ struct wireless_dev *wifi_interface_add(struct ssv_softc *sc,struct net_device *ndev;int min_idx, max_idx;int vif_idx = -1;int i;
+
+       ndev = __dev_get_by_name(&init_net, "wlan0");
+       if (ndev)
+               return ndev->ieee80211_ptr;ndev = alloc_netdev(sizeof(*vif), name, ssv_netdev_setup);if (!ndev)return NULL;....if (register_netdevice(ndev))return NULL;

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

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

相关文章

k8s -20241119

用于管理云平台中多个主机上的容器化的应用&#xff0c;Kubernetes的目标是让部署容器化的应用简单并且高效&#xff08;powerful&#xff09;,Kubernetes提供了应用部署&#xff0c;规划&#xff0c;更新&#xff0c;维护的一种机制通过部署容器方式实现&#xff0c;每个容器之…

Linux 查看磁盘空间使用情况

1. df命令 功能&#xff1a;显示文件系统的整体磁盘空间使用情况。工作原理&#xff1a;读取文件系统的超级块信息&#xff0c;显示文件系统的总容量、已用空间、可用空间以及挂载点。特点&#xff1a; 显示的是整个分区的空间使用情况&#xff0c;而不是单个文件或目录的空间…

详解Rust的数据类型和语法

文章目录 基本数据类型复杂数据类型字符串基本语法 Rust是一种强调安全性和性能的系统编程语言。它的设计目标之一是防止内存安全错误同时提供丰富的功能和灵活的语法。下面介绍一下Rust语言的基本数据类型和语法。 基本数据类型 1.整数类型 有符号整数: i8, i16, i32, i64, i…

golang对日期格式化

1.对日期格式化为 YYYY-mm-dd, 并且没有数据时&#xff0c;返回空 import ("encoding/json""time" )type DateTime time.Timetype SysRole struct {RoleId int64 gorm:"type:bigint(20);primary_key;auto_increment;角色ID;" json:&quo…

MySQL系列之数据授权(privilege)

导览 前言Q&#xff1a;如何对MySQL数据库进行授权管理一、MySQL的“特权”1. 权限级别2. 权限清单 二、授权操作1. 查看权限2. 分配权限3. 回收权限 结语精彩回放 前言 看过博主上一篇的盆友&#xff0c;可以Get到一个知识点&#xff1a;数据授权&#xff08;eg&#xff1a;g…

项目进度计划表:详细的甘特图的制作步骤

甘特图&#xff08;Gantt chart&#xff09;&#xff0c;又称为横道图、条状图&#xff08;Bar chart&#xff09;&#xff0c;是一种用于管理时间和任务活动的工具。 甘特图由亨利劳伦斯甘特&#xff08;Henry Laurence Gantt&#xff09;发明&#xff0c;是一种通过条状图来…

抽象工厂方法模式

工厂方法模式&#xff08;Factory Method Pattern&#xff09; 工厂方法模式是一种 创建型设计模式&#xff0c;它定义了一个创建对象的接口&#xff0c;但让子类决定实例化哪一个具体类。通过这种方式&#xff0c;工厂方法将对象的创建延迟到子类&#xff0c;避免了直接依赖具…

【Redis】Redis实现的消息队列

一、用list实现【这是数据类型所以支持持久化】 消息基于redis存储不会因为受jvm内存上限的限制&#xff0c;支持消息的有序性&#xff0c;基于redis的持久化机制&#xff0c;只支持单一消费者订阅&#xff0c;无法避免消息丢失。 二、用PubSub【这不是数据类型&#xff0c;是…

Linux登录指令last详解

引言 在Linux系统中&#xff0c;了解用户登录记录是系统管理和安全审计的重要任务之一。last指令作为Linux系统中用于检索和展示用户登录信息的工具&#xff0c;扮演着至关重要的角色。本文将详细介绍last指令的定义、架构、原理、企业应用以及常见的命令体系&#xff0c;帮助…

CSP-X2024山东小学组T2:消灭怪兽

题目链接 题目名称 题目描述 怪兽入侵了地球&#xff01; 为了抵抗入侵&#xff0c;人类设计出了按顺序排列好的 n n n 件武器&#xff0c;其中第 i i i 件武器的攻击力为 a i a_i ai​&#xff0c;可以造成 a i a_i ai​ 的伤害。 武器已经排列好了&#xff0c;因此不…

网络安全常见练习靶场

DVWA (Dam Vulnerable Web Application) DVWA是用PHPMysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了SQL注入、XSS、盲注等常见的一些安全漏洞。 链接地址&#xff1a;http://www.dvwa.co.uk mutillidaemutillidae mutillidaemutillidae是一个免费&am…

【操作系统笔记】目录

【操作系统笔记】操作系统框架https://blog.csdn.net/Resurgence03/article/details/142624262 【操作系统笔记】CPU管理https://blog.csdn.net/Resurgence03/article/details/142621526 【操作系统笔记】内存管理https://blog.csdn.net/Resurgence03/article/details/142669…

用 Python 与 Turtle 创作属于你的“冰墩墩”!

用 Python 与 Turtle 创作属于你的“冰墩墩”&#xff01; &#x1f980; 前言 &#x1f980;&#x1f40b; 效果图 &#x1f40b;&#x1f409; 代码 &#x1f409; &#x1f980; 前言 &#x1f980; 冰墩墩是2022年北京冬季奥林匹克运动会的官方吉祥物。以熊猫为原型&#x…

C++将整形数据转换为字符串

在 C 中&#xff0c;将整数转换为字符串有多种方法&#xff0c;以下是几种常见的方式&#xff1a; 1. 使用 std::to_string 函数&#xff08;C11 及以后版本可用&#xff09; 函数介绍&#xff1a;std::to_string 是 C 标准库提供的一个非常方便的函数&#xff0c;它位于 <…

基于SSM的农家乐管理系统+论文示例参考

1.项目介绍 功能模块&#xff1a;管理员&#xff08;农家乐管理、美食信息管理、住宿信息管理、活动信息、用户管理、活动报名、论坛等&#xff09;&#xff0c;普通用户&#xff08;注册登录、活动报名、客房预订、用户评价、收藏管理、模拟支付等&#xff09;技术选型&#…

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台 传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#x…

提取repo的仓库和工作树(无效)

问题 从供应商处获取的.repo的git仓库裸(project-object)仓库和工作树(projects)是分开的。 解决方案 根据工作树的软链接路劲&#xff0c;将工作树合并到project-object下。 import os import shutil import argparse import logging# 设置日志配置 logging.basicConfig(l…

关于ES的查询

查询结果那么多字段都是什么&#xff1f; 为什么会提到这个问题呢&#xff0c;因为默认ES查询的结果会有很多信息&#xff0c;我们可能并不希望要那么多数据&#xff0c;所以你需要了解这些字段都表示什么&#xff0c;并正确的返回和使用它们。 took– Elasticsearch 运行查询…

集群聊天服务器(8)用户登录业务

目录 登录状态业务层代码数据模型层代码记录用户的连接信息以及线程安全问题客户端异常退出业务 登录状态 登录且状态变为online 业务层代码 #include "chatservice.hpp" #include "public.hpp" #include <string> #include <muduo/base/Loggi…

04 - Clickhouse-21.7.3.14-2单机版安装

目录 一、准备工作 1、确定防火墙处于关闭状态 2、CentOS 取消打开文件数限制 3、安装依赖 4、CentOS取消SELINUX 二、单机安装 2.1、下载安装 2.2、安装这4个rpm包 2.3、修改配置文件 2.4、启动服务 2.5、关闭开机自启 2.6、使用Client连接server 一、准备工作 1…