iokit驱动程序中的全局变量

时间:2018-08-06 13:30:41

标签: macos kernel global-variables iokit kernel-extension

我在基于iokit的驱动程序中使用了一些全局变量,即在主类实例之外。但是,这会由于使用未初始化的全局变量或尝试双倍释放而在驱动程序启动时引起一些意外的紧急情况 拆卸时的全局变量。

iokit驱动程序生命周期中的全局变量的生命周期是多少? 如果我在声明时设置了全局变量,

例如,如果我有类型lck_grp_t * my_lock_grp的全局变量...

  1. 当我的iokit驱动程序到达::start方法时,我可以假定我的全局变量已经分配并准备好进行设置吗? (my_lock_grp = lck_grp_alloc_init("my-locks", my_lock_grp_attr);

  2. 当我尝试在iokit ::free方法中释放全局变量时,可以假定我的全局变量仍然有效吗? (lck_grp_free(my_lock_grp)

  3. 通常的问题是,与驱动程序实例本身相比,基于iokit的驱动程序中的全局变量的生命周期是多少。

1 个答案:

答案 0 :(得分:1)

生命周期肯定会与kext的生命周期相同。 IOKit的init / start / stop / free函数将在kext start和stop函数之间发生(您可能没有明确的kext start和stop函数),并且全局构造函数在kext start函数之前运行,同样,全局析构函数在kext停止功能之后运行。全局/静态变量的内存分配/重新分配是由动态内核链接程序完成的,同时又加载和卸载了kext的代码本身。

我可以想到三件事:

  1. IOService start()free()函数不匹配-即使从未调用free(),也会调用start()。因此,例如,如果您有一个probe()函数,并且调用了该函数并返回了nullptr,那么就永远不会调用start(),但是肯定会free(),并且它会尝试释放从未分配的锁组。同样,如果init()函数返回false-start()将永远不会运行,但free()会运行。与free()等效的是init()成员函数家族,因此只能无条件地破坏(无nullptr检查)free()中所有可能的init…函数中无条件创建的内容。 / p>

  2. 可以在不同的实例上多次调用
  3. start(),因此,如果您始终在my_lock_grp = lck_grp_alloc_init()中运行start()并且创建了2个实例,则仅my_lock_grp记住最后一个,因此如果您的类的两个实例都被释放,您最终将试图释放一个锁组两次,而另一个则完全没有。这显然是个坏消息。为了初始化/销毁真正的全局状态,我建议使用kext start和stop函数或全局构造函数/析构函数。

  4. 否则,我怀疑您可能正在遇到这样一种情况,正在运行的内核的其他部分仍具有悬挂引用,该引用超出了已卸载kext的位置,例如,如果您创建了一个新的内核线程,并且此线程仍在运行,或者如果尚未注销已注册的所有回调,或者已经注销了回调但不能保证已完成所有调用,则该线程仍在运行。 (kauth监听器因后一种情况而臭名昭著)

如果这些听起来都不是问题,我建议发布受影响的代码和紧急日志,如果我们有一些硬数据,也许我们可以对问题有更多的了解。