The system panic then actively broadcasts the last kernel dmesg information-an almost usable solution, panicdmesg

Source: Internet
Author: User
Tags dmesg

The system panic then actively broadcasts the last kernel dmesg information-an almost usable solution, panicdmesg
In remote SYSRQ trigger to obtain the latest dmesg information-a nearly useless solution, I think remote triggering of SYSRQ is of no practical use. When the system is not suspended, using SSH or other standard methods will be much better. When the system is suspended, remote triggering will not respond in most cases. So is there any way to notify the outside when the system panic is used?
Of course, using the crash kexec kernel method will be a good method, but it is generated for debug after all. Sometimes it is just necessary to know the last few lines of dmesg, you know that the system has no chance to record logs at this time, and all processes in the user State have been completely replaced. But don't forget that there is another interface that can send the final information, that is, the network. In order to make the information more likely to be received, I think it would be better to adopt broadcast. The specific method is provided at the end of "remotely trigger SYSRQ to obtain the latest dmesg information-a nearly useless SOLUTION. This article mainly provides a practical code. This code is different from the current Code, that is, the code is triggered after the system has been panic, and the system may be completely chaotic. Therefore, the best practice at this time is:
1. Reduce memory operations;
2. Do not handle abnormal streams;
3. Simplify as much as possible without calculating the verification value;
4. Avoid ARP interaction and broadcast directly.
The Code logic is as follows:
1. Loading module: skb and get device are pre-allocated. In order not to process memory after panic, register the notification chain.
2. After panic: Call the notification operation of the notification chain to broadcast packets without verification codes in the simplest way.

The Code is as follows:


# Include <linux/module. h> # include <linux/skbuff. h> # include <net/ip. h> 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) {/* No 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; /* obtain 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; /* retain the skb Region */skb_reserve (skb, 2 + ETH_HLEN + sizeof (struct iphdr) + sizeof (data);/* construct the data zone (it is better to use UDP, but it is too lazy to encapsulate) */p = skb_push (skb, sizeof (data); memcpy (p, & data [0], sizeof (data )); skb_reset_transport_header (skb);/* construct the IP header */p = skb_push (skb, sizeof (struct iphd) R); 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 the Ethernet header */p = skb_push (skb, sizeof (struct ethhdr); eth = (struct ethhdr *) p; eth-> h_proto = htons (ETH_P_IP); memcpy (p, semi hdr, sizeof (struct ethhdr); skb_reset_mac_header (skb ); /* launch */ret = dev_queue_xmit (skb); if (ret <0) {/* due to panic, no Re-process the memory, without handling abnormal streams * // 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, "eth2"); if (! Dev) {printk ("Can't get device \ n"); goto out;}/* is not allocated in the notification chain because it was already panic, therefore, pre-allocate */skb = alloc_skb (1500, GFP_ATOMIC); if (! Skb) {dev_put (dev); printk ("Alloc skb failed \ n"); goto out;}/* Register */ret = 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) {response (& panic_notifier_list, & on_panic_send); if (dev) {dev_put (dev) ;}if (skb) {kfree_skb (skb) ;}} module_init (panic_sendmsg_init); module_exit (modules); MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("marywangran <marywangran@126.com> ");

It should be noted that the kernel_log_buffer interface is added to the kernel and EXPORT by myself. I think this is necessary. printk places information in a buffer zone of the kernel, which can be read by user-State processes through the syslog system call. We know that the conventional approach is to read the kernel information by the syslog daemon and then send it to the network or save it as a file. But after panic? Since the user State is no longer running, there is no hope of storing logs through any daemon process. Of course, you can directly operate the disk log file 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. At this time, the kernel has been panic... although the kernel execution stream of panic is also used to send data from the network, the protocol stack operation is much deeper than the calling depth of the disk operation (the final interpretation and sorting of data, the Save operation is performed on the peer end, and the disk IO operation is not performed ).

In any case, whether it is disk or network operations, the memory in the kernel log buffer needs to be dumped. 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 be called in the kernel, so I added one myself:


int kernel_log_buffer(char *buf, int max_len);

The buf is the buffer to which the kernel log is saved, max_len is the length of the buf, and the returned value is the length of the actually returned information. This interface is similar to a read system call.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.