内核中启动看门狗时不加保护引起内核crack

如果直接在iTCO_wdt.c中这样开启看门狗:

static int __init iTCO_wdt_init_module(void)
{
	int err;

	printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
		DRV_VERSION);

	err = platform_driver_register(&iTCO_wdt_driver);
	if (err)
		return err;

	iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
								-1, NULL, 0);
	if (IS_ERR(iTCO_wdt_platform_device)) {
		err = PTR_ERR(iTCO_wdt_platform_device);
		goto unreg_platform_driver;
	}

	iTCO_wdt_start();

	if (iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT))
	{
			return -EINVAL;
	}
	
	iTCO_wdt_keepalive();
	

	return 0;

unreg_platform_driver:
	platform_driver_unregister(&iTCO_wdt_driver);
	return err;
}



会在某些情况下导致内核崩溃

跟踪一下:

iTCO_wdt_probe()

--> iTCO_wdt_init():

static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
		const struct pci_device_id *ent, struct platform_device *dev)
{
	...	
	 if (iTCO_wdt_private.iTCO_version == 2) 
	{  
		pci_read_config_dword(pdev, 0xf0, &base_address);  
 		RCBA = base_address & 0xffffc000;  
		iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); 
	}
	...
	/* Check chipset's NO_REBOOT bit */
	if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
					"reboot disabled by hardware\n");
		ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
		goto out;
	}

	...
out:
	if (iTCO_wdt_private.iTCO_version == 2)
		iounmap(iTCO_wdt_private.gcs);
	pci_dev_put(iTCO_wdt_private.pdev);
	iTCO_wdt_private.ACPIBASE = 0;
	return ret;
}

在iTCO_wdt_init()中会调用iTCO_wdt_unset_NO_REBOOT_bit()函数,如果这个函数中NO_REBOOT是硬件禁止的(这里和南桥的SPKR信号有关,即和蜂鸣器的那个信号有关),在我们产品上应该去掉SPKR上的电阻R894,否则,内核启动时会出现:

iTCO_wdt: failed to reset NO_REBOOT flag, reboot disabled by hardware

这种打印。

     继续关注:如果这里出现了这种打印,也就是说这里会执行goto out

在out:中会将iTCO_wdt_private.gcs申请的内存释放掉,那么:

iTCO_wdt_init_module()中再去调用iTCO_wdt_start(),然后iTCO_wdt_start()会调用iTCO_wdt_unset_NO_REBOOT_bit(),

iTCO_wdt_unset_NO_REBOOT_bit()仍会对iTCO_wdt_private.gcs进行访问,那么内核就会访问被释放掉的内存,那么内核就可能会crack!

 解决方案:

需要在iTCO_wdt_init_module()中调用iTCO_wdt_start()时,先判断iTCO_wdt_private.ACPIBASE该值是否为0,如果是0,则不去调用,否则才调用:

 	if(0 != iTCO_wdt_private.ACPIBASE)
	{
		iTCO_wdt_start();

		if (iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT))
		{
				return -EINVAL;
		}
	
		iTCO_wdt_keepalive();
	}



 

你可能感兴趣的:(timer,struct,Module,null,产品)