kobject_uevent.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c
  2. use super::KObject;
  3. use super::KobjUeventEnv;
  4. use super::KobjectAction;
  5. use super::{UEVENT_BUFFER_SIZE, UEVENT_NUM_ENVP};
  6. use crate::driver::base::kobject::{KObjectManager, KObjectState};
  7. use crate::init::initcall::INITCALL_POSTCORE;
  8. use crate::libs::mutex::Mutex;
  9. use crate::libs::rwlock::RwLock;
  10. use crate::net::socket::netlink::af_netlink::netlink_has_listeners;
  11. use crate::net::socket::netlink::af_netlink::NetlinkSocket;
  12. use crate::net::socket::netlink::af_netlink::{netlink_broadcast, NetlinkSock};
  13. use crate::net::socket::netlink::skbuff::SkBuff;
  14. use crate::net::socket::netlink::{
  15. netlink_kernel_create, NetlinkKernelCfg, NETLINK_KOBJECT_UEVENT, NL_CFG_F_NONROOT_RECV,
  16. };
  17. use alloc::boxed::Box;
  18. use alloc::collections::LinkedList;
  19. use alloc::string::{String, ToString};
  20. use alloc::sync::Arc;
  21. use alloc::vec::Vec;
  22. use core::fmt::Write;
  23. use num::Zero;
  24. use system_error::SystemError;
  25. use unified_init::macros::unified_init;
  26. // 全局变量
  27. pub static UEVENT_SEQNUM: u64 = 0;
  28. // #ifdef CONFIG_UEVENT_HELPER
  29. // char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
  30. // #endif
  31. struct UeventSock {
  32. inner: NetlinkSock,
  33. }
  34. impl UeventSock {
  35. pub fn new(inner: NetlinkSock) -> Self {
  36. UeventSock { inner }
  37. }
  38. }
  39. // 用于存储所有用于发送 uevent 消息的 netlink sockets。这些 sockets 用于在内核和用户空间之间传递设备事件通知。
  40. // 每当需要发送 uevent 消息时,内核会遍历这个链表,并通过其中的每一个 socket 发送消息。
  41. // 使用 Mutex 保护全局链表
  42. lazy_static::lazy_static! {
  43. static ref UEVENT_SOCK_LIST: Mutex<LinkedList<UeventSock>> = Mutex::new(LinkedList::new());
  44. }
  45. // 回调函数,当接收到 uevent 消息时调用
  46. fn uevent_net_rcv() {
  47. // netlink_rcv_skb(skb, &uevent_net_rcv_skb);
  48. }
  49. /// 内核初始化的时候,在设备初始化之前执行
  50. #[unified_init(INITCALL_POSTCORE)]
  51. fn kobejct_uevent_init() -> Result<(), SystemError> {
  52. // todo: net namespace
  53. return uevent_net_init();
  54. }
  55. // TODO:等net namespace实现后添加 net 参数和相关操作
  56. // 内核启动的时候,即使没有进行网络命名空间的隔离也需要调用这个函数
  57. // 支持 net namespace 之后需要在每个 net namespace 初始化的时候调用这个函数
  58. /// 为每一个 net namespace 初始化 uevent
  59. fn uevent_net_init() -> Result<(), SystemError> {
  60. let cfg = NetlinkKernelCfg {
  61. groups: 1,
  62. flags: NL_CFG_F_NONROOT_RECV,
  63. ..Default::default()
  64. };
  65. // 创建一个内核 netlink socket
  66. let ue_sk = UeventSock::new(netlink_kernel_create(NETLINK_KOBJECT_UEVENT, Some(cfg)).unwrap());
  67. // todo: net namespace
  68. // net.uevent_sock = ue_sk;
  69. // 每个 net namespace 向链表中添加一个新的 uevent socket
  70. UEVENT_SOCK_LIST.lock().push_back(ue_sk);
  71. log::info!("uevent_net_init finish");
  72. return Ok(());
  73. }
  74. // 系统关闭时清理
  75. fn uevent_net_exit() {
  76. // 清理链表
  77. UEVENT_SOCK_LIST.lock().clear();
  78. }
  79. /// kobject_uevent,和kobject_uevent_env功能一样,只是没有指定任何的环境变量
  80. pub fn kobject_uevent(kobj: Arc<dyn KObject>, action: KobjectAction) -> Result<(), SystemError> {
  81. // kobject_uevent和kobject_uevent_env功能一样,只是没有指定任何的环境变量
  82. match kobject_uevent_env(kobj, action, Vec::new()) {
  83. Ok(_) => Ok(()),
  84. Err(e) => Err(e),
  85. }
  86. }
  87. /// kobject_uevent_env,以 envp 为环境变量,上报一个指定 action 的 uevent。环境变量的作用是为执行用户空间程序指定运行环境。
  88. pub fn kobject_uevent_env(
  89. kobj: Arc<dyn KObject>,
  90. action: KobjectAction,
  91. envp_ext: Vec<String>,
  92. ) -> Result<i32, SystemError> {
  93. log::info!("kobject_uevent_env: kobj: {:?}, action: {:?}", kobj, action);
  94. let mut state = KObjectState::empty();
  95. let mut top_kobj = kobj.parent().unwrap().upgrade().unwrap();
  96. let mut retval: i32;
  97. let action_string = match action {
  98. KobjectAction::KOBJADD => "add".to_string(),
  99. KobjectAction::KOBJREMOVE => "remove".to_string(),
  100. KobjectAction::KOBJCHANGE => "change".to_string(),
  101. KobjectAction::KOBJMOVE => "move".to_string(),
  102. KobjectAction::KOBJONLINE => "online".to_string(),
  103. KobjectAction::KOBJOFFLINE => "offline".to_string(),
  104. KobjectAction::KOBJBIND => "bind".to_string(),
  105. KobjectAction::KOBJUNBIND => "unbind".to_string(),
  106. };
  107. /*
  108. * Mark "remove" event done regardless of result, for some subsystems
  109. * do not want to re-trigger "remove" event via automatic cleanup.
  110. */
  111. if let KobjectAction::KOBJREMOVE = action {
  112. log::info!("kobject_uevent_env: action: remove");
  113. state.insert(KObjectState::REMOVE_UEVENT_SENT);
  114. }
  115. // 不断向上查找,直到找到最顶层的kobject
  116. while let Some(weak_parent) = top_kobj.parent() {
  117. log::info!("kobject_uevent_env: top_kobj: {:?}", top_kobj);
  118. top_kobj = weak_parent.upgrade().unwrap();
  119. }
  120. /* 查找当前kobject或其parent是否从属于某个kset;如果都不从属于某个kset,则返回错误。(说明一个kobject若没有加入kset,是不会上报uevent的) */
  121. if kobj.kset().is_none() && top_kobj.kset().is_none() {
  122. log::info!("attempted to send uevent without kset!\n");
  123. return Err(SystemError::EINVAL);
  124. }
  125. let kset = top_kobj.kset();
  126. // 判断该 kobject 的状态是否设置了uevent_suppress,如果设置了,则忽略所有的uevent上报并返回
  127. if kobj.kobj_state().contains(KObjectState::UEVENT_SUPPRESS) {
  128. log::info!("uevent_suppress caused the event to drop!");
  129. return Ok(0);
  130. }
  131. // 如果所属的kset的kset->filter返回的是0,过滤此次上报
  132. if let Some(kset_ref) = kset.as_ref() {
  133. if let Some(uevent_ops) = &kset_ref.uevent_ops {
  134. if uevent_ops.filter() == Some(0) {
  135. log::info!("filter caused the event to drop!");
  136. return Ok(0);
  137. }
  138. }
  139. }
  140. // 判断所属的kset是否有合法的名称(称作subsystem,和前期的内核版本有区别),否则不允许上报uevent
  141. // originating subsystem
  142. let subsystem: String = if let Some(kset_ref) = kset.as_ref() {
  143. if let Some(uevent_ops) = &kset_ref.uevent_ops {
  144. let name = uevent_ops.uevent_name();
  145. if !name.is_empty() {
  146. name
  147. } else {
  148. kobj.name()
  149. }
  150. } else {
  151. kobj.name()
  152. }
  153. } else {
  154. kobj.name()
  155. };
  156. if subsystem.is_empty() {
  157. log::info!("unset subsystem caused the event to drop!");
  158. }
  159. log::info!("kobject_uevent_env: subsystem: {}", subsystem);
  160. // 创建一个用于环境变量的缓冲区
  161. let mut env = Box::new(KobjUeventEnv {
  162. argv: Vec::with_capacity(UEVENT_NUM_ENVP),
  163. envp: Vec::with_capacity(UEVENT_NUM_ENVP),
  164. envp_idx: 0,
  165. buf: vec![0; UEVENT_BUFFER_SIZE],
  166. buflen: 0,
  167. });
  168. if env.buf.is_empty() {
  169. log::error!("kobject_uevent_env: failed to allocate buffer");
  170. return Err(SystemError::ENOMEM);
  171. }
  172. // 获取设备的完整对象路径
  173. let devpath: String = KObjectManager::kobject_get_path(&kobj);
  174. log::info!("kobject_uevent_env: devpath: {}", devpath);
  175. if devpath.is_empty() {
  176. retval = SystemError::ENOENT.to_posix_errno();
  177. // goto exit
  178. drop(devpath);
  179. drop(env);
  180. log::warn!("kobject_uevent_env: devpath is empty");
  181. return Ok(retval);
  182. }
  183. retval = add_uevent_var(&mut env, "ACTION=%s", &action_string).unwrap();
  184. log::info!("kobject_uevent_env: retval: {}", retval);
  185. if !retval.is_zero() {
  186. drop(devpath);
  187. drop(env);
  188. log::info!("add_uevent_var failed ACTION");
  189. return Ok(retval);
  190. };
  191. retval = add_uevent_var(&mut env, "DEVPATH=%s", &devpath).unwrap();
  192. if !retval.is_zero() {
  193. drop(devpath);
  194. drop(env);
  195. log::info!("add_uevent_var failed DEVPATH");
  196. return Ok(retval);
  197. };
  198. retval = add_uevent_var(&mut env, "SUBSYSTEM=%s", &subsystem).unwrap();
  199. if !retval.is_zero() {
  200. drop(devpath);
  201. drop(env);
  202. log::info!("add_uevent_var failed SUBSYSTEM");
  203. return Ok(retval);
  204. };
  205. /* keys passed in from the caller */
  206. for var in envp_ext {
  207. let retval = add_uevent_var(&mut env, "%s", &var).unwrap();
  208. if !retval.is_zero() {
  209. drop(devpath);
  210. drop(env);
  211. log::info!("add_uevent_var failed");
  212. return Ok(retval);
  213. }
  214. }
  215. if let Some(kset_ref) = kset.as_ref() {
  216. if let Some(uevent_ops) = kset_ref.uevent_ops.as_ref() {
  217. if uevent_ops.uevent(&env) != 0 {
  218. retval = uevent_ops.uevent(&env);
  219. if retval.is_zero() {
  220. log::info!("kset uevent caused the event to drop!");
  221. // goto exit
  222. drop(devpath);
  223. drop(env);
  224. return Ok(retval);
  225. }
  226. }
  227. }
  228. }
  229. match action {
  230. KobjectAction::KOBJADD => {
  231. state.insert(KObjectState::ADD_UEVENT_SENT);
  232. }
  233. KobjectAction::KOBJUNBIND => {
  234. zap_modalias_env(&mut env);
  235. }
  236. _ => {}
  237. }
  238. //mutex_lock(&uevent_sock_mutex);
  239. /* we will send an event, so request a new sequence number */
  240. retval = add_uevent_var(&mut env, "SEQNUM=%llu", &(UEVENT_SEQNUM + 1).to_string()).unwrap();
  241. if !retval.is_zero() {
  242. drop(devpath);
  243. drop(env);
  244. log::info!("add_uevent_var failed");
  245. return Ok(retval);
  246. }
  247. retval = kobject_uevent_net_broadcast(kobj, &env, &action_string, &devpath);
  248. // todo: 设置了 UEVENT_HELP 编译条件之后,使用 handle_uevent_helper() 对指定的 uevent 进行处理,通常是热插拔程序 mdev、udev 等
  249. drop(devpath);
  250. drop(env);
  251. log::info!("kobject_uevent_env: retval: {}", retval);
  252. return Ok(retval);
  253. }
  254. /// 以格式化字符的形式,将环境变量copy到env指针中。
  255. pub fn add_uevent_var(
  256. env: &mut Box<KobjUeventEnv>,
  257. format: &str,
  258. args: &str,
  259. ) -> Result<i32, SystemError> {
  260. log::info!("add_uevent_var: format: {}, args: {}", format, args);
  261. if env.envp_idx >= env.envp.capacity() {
  262. log::info!("add_uevent_var: too many keys");
  263. return Err(SystemError::ENOMEM);
  264. }
  265. let mut buffer = String::new();
  266. write!(&mut buffer, "{} {}", format, args).map_err(|_| SystemError::ENOMEM)?;
  267. let len = buffer.len();
  268. if len >= env.buf.capacity() - env.buflen {
  269. log::info!("add_uevent_var: buffer size too small");
  270. return Err(SystemError::ENOMEM);
  271. }
  272. // Convert the buffer to bytes and add to env.buf
  273. env.buf.extend_from_slice(buffer.as_bytes());
  274. env.buf.push(0); // Null-terminate the string
  275. env.buflen += len + 1;
  276. // Add the string to envp
  277. env.envp.push(buffer);
  278. env.envp_idx += 1;
  279. Ok(0)
  280. }
  281. // 用于处理设备树中与模块相关的环境变量
  282. fn zap_modalias_env(env: &mut Box<KobjUeventEnv>) {
  283. // 定义一个静态字符串
  284. const MODALIAS_PREFIX: &str = "MODALIAS=";
  285. let mut len: usize;
  286. let mut i = 0;
  287. while i < env.envp_idx {
  288. // 如果是以 MODALIAS= 开头的字符串
  289. if env.envp[i].starts_with(MODALIAS_PREFIX) {
  290. len = env.envp[i].len() + 1;
  291. // 如果不是最后一个元素
  292. if i != env.envp_idx - 1 {
  293. // 将后续的环境变量向前移动,以覆盖掉 "MODALIAS=" 前缀的环境变量
  294. for j in i..env.envp_idx - 1 {
  295. env.envp[j] = env.envp[j + 1].clone();
  296. }
  297. }
  298. // 减少环境变量数组的索引,因为一个变量已经被移除
  299. env.envp_idx -= 1;
  300. // 减少环境变量的总长度
  301. env.buflen -= len;
  302. } else {
  303. i += 1;
  304. }
  305. }
  306. }
  307. // 用于处理网络相关的uevent(通用事件)广播
  308. // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c#381
  309. pub fn kobject_uevent_net_broadcast(
  310. kobj: Arc<dyn KObject>,
  311. env: &KobjUeventEnv,
  312. action_string: &str,
  313. devpath: &str,
  314. ) -> i32 {
  315. // TODO: net namespace
  316. // 如果有网络命名空间,则广播标记的uevent;如果没有,则广播未标记的uevent
  317. let ret = uevent_net_broadcast_untagged(env, action_string, devpath);
  318. log::info!("kobject_uevent_net_broadcast finish. ret: {}", ret);
  319. ret
  320. }
  321. /// 分配一个用于 uevent 消息的 skb(socket buffer)。
  322. pub fn alloc_uevent_skb<'a>(
  323. env: &'a KobjUeventEnv,
  324. action_string: &'a str,
  325. devpath: &'a str,
  326. ) -> Arc<RwLock<SkBuff>> {
  327. let skb = Arc::new(RwLock::new(SkBuff::new(None)));
  328. skb
  329. }
  330. // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c#309
  331. /// 广播一个未标记的 uevent 消息
  332. pub fn uevent_net_broadcast_untagged(
  333. env: &KobjUeventEnv,
  334. action_string: &str,
  335. devpath: &str,
  336. ) -> i32 {
  337. log::info!(
  338. "uevent_net_broadcast_untagged: action_string: {}, devpath: {}",
  339. action_string,
  340. devpath
  341. );
  342. let mut retval = 0;
  343. let mut skb = Arc::new(RwLock::new(SkBuff::new(None)));
  344. // 锁定 UEVENT_SOCK_LIST 并遍历
  345. let ue_sk_list = UEVENT_SOCK_LIST.lock();
  346. for ue_sk in ue_sk_list.iter() {
  347. // 如果没有监听者,则跳过
  348. if netlink_has_listeners(&ue_sk.inner, 1) == 0 {
  349. log::info!("uevent_net_broadcast_untagged: no listeners");
  350. continue;
  351. }
  352. // 如果 skb 为空,则分配一个新的 skb
  353. if skb.read().inner.is_empty() {
  354. log::info!("uevent_net_broadcast_untagged: alloc_uevent_skb failed");
  355. retval = SystemError::ENOMEM.to_posix_errno();
  356. skb = alloc_uevent_skb(env, action_string, devpath);
  357. if skb.read().inner.is_empty() {
  358. continue;
  359. }
  360. }
  361. log::info!("next is netlink_broadcast");
  362. let netlink_socket = Arc::new(ue_sk.inner.clone());
  363. retval = match netlink_broadcast(&netlink_socket, Arc::clone(&skb), 0, 1, 1) {
  364. Ok(_) => 0,
  365. Err(err) => err.to_posix_errno(),
  366. };
  367. log::info!("finished netlink_broadcast");
  368. // ENOBUFS should be handled in userspace
  369. if retval == SystemError::ENOBUFS.to_posix_errno()
  370. || retval == SystemError::ESRCH.to_posix_errno()
  371. {
  372. retval = 0;
  373. }
  374. }
  375. // consume_skb(skb);
  376. retval
  377. }