Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'hyperv-fixes-signed-20250427' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv fixes from Wei Liu:

- Bug fixes for the Hyper-V driver and kvp_daemon

* tag 'hyperv-fixes-signed-20250427' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
Drivers: hv: Fix bad ref to hv_synic_eventring_tail when CPU goes offline
tools/hv: update route parsing in kvp daemon
Drivers: hv: Fix bad pointer dereference in hv_get_partition_id

+90 -28
+6 -4
drivers/hv/hv_common.c
··· 307 307 308 308 local_irq_save(flags); 309 309 output = *this_cpu_ptr(hyperv_pcpu_input_arg); 310 - status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, &output); 310 + status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output); 311 311 pt_id = output->partition_id; 312 312 local_irq_restore(flags); 313 313 ··· 566 566 * originally allocated memory is reused in hv_common_cpu_init(). 567 567 */ 568 568 569 - synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail); 570 - kfree(*synic_eventring_tail); 571 - *synic_eventring_tail = NULL; 569 + if (hv_root_partition()) { 570 + synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail); 571 + kfree(*synic_eventring_tail); 572 + *synic_eventring_tail = NULL; 573 + } 572 574 573 575 return 0; 574 576 }
+84 -24
tools/hv/hv_kvp_daemon.c
··· 24 24 25 25 #include <sys/poll.h> 26 26 #include <sys/utsname.h> 27 + #include <stdbool.h> 27 28 #include <stdio.h> 28 29 #include <stdlib.h> 29 30 #include <unistd.h> ··· 678 677 pclose(file); 679 678 } 680 679 680 + static bool kvp_verify_ip_address(const void *address_string) 681 + { 682 + char verify_buf[sizeof(struct in6_addr)]; 683 + 684 + if (inet_pton(AF_INET, address_string, verify_buf) == 1) 685 + return true; 686 + if (inet_pton(AF_INET6, address_string, verify_buf) == 1) 687 + return true; 688 + return false; 689 + } 690 + 691 + static void kvp_extract_routes(const char *line, void **output, size_t *remaining) 692 + { 693 + static const char needle[] = "via "; 694 + const char *match, *haystack = line; 695 + 696 + while ((match = strstr(haystack, needle))) { 697 + const char *address, *next_char; 698 + 699 + /* Address starts after needle. */ 700 + address = match + strlen(needle); 701 + 702 + /* The char following address is a space or end of line. */ 703 + next_char = strpbrk(address, " \t\\"); 704 + if (!next_char) 705 + next_char = address + strlen(address) + 1; 706 + 707 + /* Enough room for address and semicolon. */ 708 + if (*remaining >= (next_char - address) + 1) { 709 + memcpy(*output, address, next_char - address); 710 + /* Terminate string for verification. */ 711 + memcpy(*output + (next_char - address), "", 1); 712 + if (kvp_verify_ip_address(*output)) { 713 + /* Advance output buffer. */ 714 + *output += next_char - address; 715 + *remaining -= next_char - address; 716 + 717 + /* Each address needs a trailing semicolon. */ 718 + memcpy(*output, ";", 1); 719 + *output += 1; 720 + *remaining -= 1; 721 + } 722 + } 723 + haystack = next_char; 724 + } 725 + } 726 + 727 + static void kvp_get_gateway(void *buffer, size_t buffer_len) 728 + { 729 + static const char needle[] = "default "; 730 + FILE *f; 731 + void *output = buffer; 732 + char *line = NULL; 733 + size_t alloc_size = 0, remaining = buffer_len - 1; 734 + ssize_t num_chars; 735 + 736 + /* Show route information in a single line, for each address family */ 737 + f = popen("ip --oneline -4 route show;ip --oneline -6 route show", "r"); 738 + if (!f) { 739 + /* Convert buffer into C-String. */ 740 + memcpy(output, "", 1); 741 + return; 742 + } 743 + while ((num_chars = getline(&line, &alloc_size, f)) > 0) { 744 + /* Skip short lines. */ 745 + if (num_chars <= strlen(needle)) 746 + continue; 747 + /* Skip lines without default route. */ 748 + if (memcmp(line, needle, strlen(needle))) 749 + continue; 750 + /* Remove trailing newline to simplify further parsing. */ 751 + if (line[num_chars - 1] == '\n') 752 + line[num_chars - 1] = '\0'; 753 + /* Search routes after match. */ 754 + kvp_extract_routes(line + strlen(needle), &output, &remaining); 755 + } 756 + /* Convert buffer into C-String. */ 757 + memcpy(output, "", 1); 758 + free(line); 759 + pclose(f); 760 + } 761 + 681 762 static void kvp_get_ipconfig_info(char *if_name, 682 763 struct hv_kvp_ipaddr_value *buffer) 683 764 { ··· 768 685 char *p; 769 686 FILE *file; 770 687 771 - /* 772 - * Get the address of default gateway (ipv4). 773 - */ 774 - sprintf(cmd, "%s %s", "ip route show dev", if_name); 775 - strcat(cmd, " | awk '/default/ {print $3 }'"); 776 - 777 - /* 778 - * Execute the command to gather gateway info. 779 - */ 780 - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, 781 - (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); 782 - 783 - /* 784 - * Get the address of default gateway (ipv6). 785 - */ 786 - sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name); 787 - strcat(cmd, " | awk '/default/ {print $3 }'"); 788 - 789 - /* 790 - * Execute the command to gather gateway info (ipv6). 791 - */ 792 - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, 793 - (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); 794 - 688 + kvp_get_gateway(buffer->gate_way, sizeof(buffer->gate_way)); 795 689 796 690 /* 797 691 * Gather the DNS state.