Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Active broadcast of the last kernel dmesg information after the system panic-an almost usable scheme

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

In "remote trigger SYSRQ to get the latest dmesg information-an almost useless solution", I think remote trigger SYSRQ is of no practical use. When the system does not hang, it would be much better to use standard methods such as SSH. When the system hangs, the remote trigger will not get a response in most cases. So is there any way to notify the outside world when the system panic?

Of course, using crash kexec kernel will be a good way, but after all, it is for debug, sometimes just want to know the last few lines of dmesg, you know that at this time the system has no chance to record log, any process in user mode has been wiped out. But don't forget that there is one more way to send the last message, and that is the Internet. In order to make the information more likely to be received, I think it would be better to use broadcasting. I have given the exact way at the end of "remotely triggering SYSRQ to get the latest dmesg information-a solution that is almost useless." The main purpose of this article is to give a code that can actually run. This code is different from the usual code, that is, the code is triggered after the system has been panic, and the system is likely to be completely chaotic, so the best thing to do at this time is:

1. Reduce memory operations

two。 Do not handle exception flow

3. Simplify as much as possible and no longer calculate the check value

4. Avoid ARP interaction and broadcast directly.

The logic of the code is as follows:

1. Load module: pre-allocate skb and get device in order not to process memory after panic; register notification chain.

After 2.panic: invokes the notification operation of the notification chain to broadcast packets without a check code in the simplest way.

The code is as follows:

# include # include # include struct sk_buff * skb = NULL;struct net_device * dev = NULL;u8 ethhdr [ETH_HLEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0c, 0x29, 0xdd, 0xaa, 0xfd, 0x00, 0x00} U8 iphdr [20] = {0x45, 0x00, 0x00, 0x00, / / total length 0x00, 0x00, / / ID 0x40, 0x00, / / Don't fragment 0x40, / / TTL 0xff, / / UDP? 0x00, 0x00, / / checksum 0x02, 0x02, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff}; U8 data [1024] = {0} Void do_nothing (struct sk_buff * skb) {/ * does not perform any memory operations * / dev_put (skb- > dev);} static int send_last_msg (struct notifier_block * self, unsigned long event, void * unused) {int ret; struct ethhdr * eth; struct iphdr * ip; char * p / * get the data in the kernel buffer * / kernel_log_buffer (data, sizeof (data)); skb- > dev = dev; skb- > pkt_type = PACKET_OTHERHOST; skb- > protocol = htons (ETH_P_IP); skb- > ip_summed = CHECKSUM_NONE; skb- > destructor = do_nothing; skb- > priority = 0 / * keep the skb region * / skb_reserve (skb, 2 + ETH_HLEN + sizeof (struct iphdr) + sizeof (data)); / * construct the data area (it would be better to use UDP, but lazily encapsulate it) * / p = skb_push (skb, sizeof (data)); memcpy (p, & data [0], sizeof (data)); skb_reset_transport_header (skb) / * construct IP head * / p = skb_push (skb, sizeof (struct iphdr)); memcpy (p, & iphdr, sizeof (struct iphdr)); ip = (struct iphdr*) p; ip- > tot_len = htons (sizeof (data) + sizeof (struct iphdr)); skb_reset_network_header (skb); / * construct Ethernet head * / p = skb_push (skb, sizeof (struct ethhdr)) Eth = (struct ethhdr*) p; eth- > h_proto = htons (ETH_P_IP); memcpy (p, hdr, sizeof (struct ethhdr)); skb_reset_mac_header (skb); / * launch * / ret = dev_queue_xmit (skb); if (ret < 0) {/ * due to panic, no memory processing, no exception flow handling * / / kfree_skb (skb) / / dev_put (dev); goto out;} out: return ret;} static struct notifier_block on_panic_send = {.notifier _ call = send_last_msg,}; static int _ initpanic_sendmsg_init (void) {int ret =-1; dev = dev_get_by_name (& init_net, "eth3"); if (! dev) {printk ("Can't get device\ n") Goto out;} / * is not assigned in the notification chain, because it was already panic, so pre-assigned * / skb = alloc_skb (1500, GFP_ATOMIC); if (! skb) {dev_put (dev); printk ("Alloc skb failed\ n"); goto out } / * Registration * / ret = atomic_notifier_chain_register (& panic_notifier_list, & on_panic_send); if (ret) {dev_put (dev); kfree_skb (skb); printk ("Register notifier chain failed\ n"); goto out;} return 0 out: return ret } static void _ exitpanic_sendmsg_exit (void) {atomic_notifier_chain_unregister (& panic_notifier_list, & on_panic_send); if (dev) {dev_put (dev);} if (skb) {kfree_skb (skb);}} module_init (panic_sendmsg_init); module_exit (panic_sendmsg_exit); MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("marywangran")

What needs to be pointed out is the kernel_log_buffer interface, which I added into the kernel and EXPORT out myself. I think this is necessary because printk places the information in a buffer area of the kernel that can be read by user-mode processes through syslog system calls. We know that the conventional approach is that kernel information is read by the syslog daemon and then sent to the network or saved as a file. But what happened after panic? Now that the user mode is no longer running, there is no hope of keeping logs through any daemon. Of course, it is possible to directly manipulate the disk log files in the kernel panic notification chain hook, but that is too unreliable, because the disk IO logic also exists in the kernel state code or driver code, and the kernel is already panic. Although the panic kernel execution stream is also used to send data from the network, after all, the protocol stack operation is much shallower than the call depth of the disk operation (the final interpretation, sorting, and saving operations of the data are all carried out on the opposite side, while the disk IO is not).

In any case, whether it is a disk operation or a network operation, you need to dump the memory in the kernel log buffer. However, the kernel log buffer itself is not EXPORT, it can only be obtained through a few system call interfaces, and these interfaces are difficult to call in the kernel, so I added one myself:

Int kernel_log_buffer (char * buf, int max_len)

Where buf is the buffer to which the kernel log is saved, max_len is the length of buf, and the return value is the length of the actual returned information. This interface is completely similar to the read system call.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report