Blame kexec-tools-2.0.23-01-_PATCH_v2_1_3_add_generic_cycle_detection.patch

Philipp Rudo 90da03
 commit feae3d1754d2b0788ce1f18b0cd4b40098ff52ff
Philipp Rudo 90da03
 Author: Philipp Rudo <prudo@redhat.com>
Philipp Rudo 90da03
 Date:   Mon Mar 14 17:04:29 2022 +0100
Philipp Rudo 90da03
 
Philipp Rudo 90da03
     [PATCH v2 1/3] add generic cycle detection
Philipp Rudo 90da03
     
Philipp Rudo 90da03
     In order to work makedumpfile needs to interpret data read from the
Philipp Rudo 90da03
     dump. This can cause problems as the data from the dump cannot be
Philipp Rudo 90da03
     trusted (otherwise the kernel wouldn't have panicked in the first
Philipp Rudo 90da03
     place). This also means that every loop which stop condition depend on
Philipp Rudo 90da03
     data read from the dump has a chance to loop forever. Thus add a generic
Philipp Rudo 90da03
     cycle detection mechanism that allows to detect and handle such
Philipp Rudo 90da03
     situations appropriately.
Philipp Rudo 90da03
     
Philipp Rudo 90da03
     For cycle detection use Brent's algorithm [1] as it has constant memory
Philipp Rudo 90da03
     usage. With this it can also be used in the kdump kernel without the
Philipp Rudo 90da03
     danger that it runs oom when iterating large data structures.
Philipp Rudo 90da03
     Furthermore it only depends on some pointer arithmetic. Thus the
Philipp Rudo 90da03
     performance impact (as long as no cycle was detected) should be
Philipp Rudo 90da03
     comparatively small.
Philipp Rudo 90da03
     
Philipp Rudo 90da03
     [1] https://en.wikipedia.org/wiki/Cycle_detection#Brent's_algorithm
Philipp Rudo 90da03
     
Philipp Rudo 90da03
     Suggested-by: Dave Wysochanski <dwysocha@redhat.com>
Philipp Rudo 90da03
     Signed-off-by: Philipp Rudo <prudo@redhat.com>
Philipp Rudo 90da03
     Reviewed-and-tested-by: Dave Wysochanski <dwysocha@redhat.com>
Philipp Rudo 90da03
 
Philipp Rudo 90da03
 diff --git a/makedumpfile-1.7.0/Makefile b/makedumpfile-1.7.0/Makefile
Philipp Rudo 90da03
 index f118b31e45989d9590ae075fb9b8ed2f27353a92..3441364cb6c7103a20072bd50ec58f1eed01ab69 100644
Philipp Rudo 90da03
 --- a/makedumpfile-1.7.0/Makefile
Philipp Rudo 90da03
 +++ b/makedumpfile-1.7.0/Makefile
Philipp Rudo 90da03
 @@ -45,7 +45,7 @@ CFLAGS_ARCH += -m32
Philipp Rudo 90da03
  endif
Philipp Rudo 90da03
  
Philipp Rudo 90da03
  SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
Philipp Rudo 90da03
 -SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c
Philipp Rudo 90da03
 +SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c detect_cycle.c
Philipp Rudo 90da03
  OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
Philipp Rudo 90da03
  SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c arch/mips64.c
Philipp Rudo 90da03
  OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
Philipp Rudo 90da03
 diff --git a/makedumpfile-1.7.0/detect_cycle.c b/makedumpfile-1.7.0/detect_cycle.c
Philipp Rudo 90da03
 new file mode 100644
Philipp Rudo 90da03
 index 0000000000000000000000000000000000000000..6b551a75d1c83d64fba2c078be8133efbc791fbe
Philipp Rudo 90da03
 --- /dev/null
Philipp Rudo 90da03
 +++ b/makedumpfile-1.7.0/detect_cycle.c
Philipp Rudo 90da03
 @@ -0,0 +1,99 @@
Philipp Rudo 90da03
 +/*
Philipp Rudo 90da03
 + * detect_cycle.c  --  Generic cycle detection using Brent's algorithm
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * Created by: Philipp Rudo <prudo@redhat.com>
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * Copyright (c) 2022 Red Hat, Inc. All rights reserved.
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * This program is free software; you can redistribute it and/or modify
Philipp Rudo 90da03
 + * it under the terms of the GNU General Public License as published by
Philipp Rudo 90da03
 + * the Free Software Foundation; either version 2 of the License, or
Philipp Rudo 90da03
 + * (at your option) any later version.
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * This program is distributed in the hope that it will be useful,
Philipp Rudo 90da03
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
Philipp Rudo 90da03
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Philipp Rudo 90da03
 + * GNU General Public License for more details.
Philipp Rudo 90da03
 + */
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +#include <stdlib.h>
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +#include "detect_cycle.h"
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +struct detect_cycle {
Philipp Rudo 90da03
 +	/* First entry of the list */
Philipp Rudo 90da03
 +	void *head;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	/* Variables required by Brent's algorithm */
Philipp Rudo 90da03
 +	void *fast_p;
Philipp Rudo 90da03
 +	void *slow_p;
Philipp Rudo 90da03
 +	unsigned long length;
Philipp Rudo 90da03
 +	unsigned long power;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	/* Function to get the next entry in the list */
Philipp Rudo 90da03
 +	dc_next_t next;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	/* Private data passed to next */
Philipp Rudo 90da03
 +	void *data;
Philipp Rudo 90da03
 +};
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +struct detect_cycle *dc_init(void *head, void *data, dc_next_t next)
Philipp Rudo 90da03
 +{
Philipp Rudo 90da03
 +	struct detect_cycle *new;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	new = malloc(sizeof(*new));
Philipp Rudo 90da03
 +	if (!new)
Philipp Rudo 90da03
 +		return NULL;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	new->next = next;
Philipp Rudo 90da03
 +	new->data = data;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	new->head = head;
Philipp Rudo 90da03
 +	new->slow_p = head;
Philipp Rudo 90da03
 +	new->fast_p = head;
Philipp Rudo 90da03
 +	new->length = 0;
Philipp Rudo 90da03
 +	new->power  = 2;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	return new;
Philipp Rudo 90da03
 +}
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +int dc_next(struct detect_cycle *dc, void **next)
Philipp Rudo 90da03
 +{
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	if (dc->length == dc->power) {
Philipp Rudo 90da03
 +		dc->length = 0;
Philipp Rudo 90da03
 +		dc->power *= 2;
Philipp Rudo 90da03
 +		dc->slow_p = dc->fast_p;
Philipp Rudo 90da03
 +	}
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	dc->fast_p = dc->next(dc->fast_p, dc->data);
Philipp Rudo 90da03
 +	dc->length++;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	if (dc->slow_p == dc->fast_p)
Philipp Rudo 90da03
 +		return 1;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	*next = dc->fast_p;
Philipp Rudo 90da03
 +	return 0;
Philipp Rudo 90da03
 +}
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +void dc_find_start(struct detect_cycle *dc, void **first, unsigned long *len)
Philipp Rudo 90da03
 +{
Philipp Rudo 90da03
 +	void *slow_p, *fast_p;
Philipp Rudo 90da03
 +	unsigned long tmp;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	slow_p = fast_p = dc->head;
Philipp Rudo 90da03
 +	tmp = dc->length;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	while (tmp) {
Philipp Rudo 90da03
 +		fast_p = dc->next(fast_p, dc->data);
Philipp Rudo 90da03
 +		tmp--;
Philipp Rudo 90da03
 +	}
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	while (slow_p != fast_p) {
Philipp Rudo 90da03
 +		slow_p = dc->next(slow_p, dc->data);
Philipp Rudo 90da03
 +		fast_p = dc->next(fast_p, dc->data);
Philipp Rudo 90da03
 +	}
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +	*first = slow_p;
Philipp Rudo 90da03
 +	*len = dc->length;
Philipp Rudo 90da03
 +}
Philipp Rudo 90da03
 diff --git a/makedumpfile-1.7.0/detect_cycle.h b/makedumpfile-1.7.0/detect_cycle.h
Philipp Rudo 90da03
 new file mode 100644
Philipp Rudo 90da03
 index 0000000000000000000000000000000000000000..2ca75c78b59a98274fc5a98666b1be74f7bbfc2c
Philipp Rudo 90da03
 --- /dev/null
Philipp Rudo 90da03
 +++ b/makedumpfile-1.7.0/detect_cycle.h
Philipp Rudo 90da03
 @@ -0,0 +1,40 @@
Philipp Rudo 90da03
 +/*
Philipp Rudo 90da03
 + * detect_cycle.h  --  Generic cycle detection using Brent's algorithm
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * Created by: Philipp Rudo <prudo@redhat.com>
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * Copyright (c) 2022 Red Hat, Inc. All rights reserved.
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * This program is free software; you can redistribute it and/or modify
Philipp Rudo 90da03
 + * it under the terms of the GNU General Public License as published by
Philipp Rudo 90da03
 + * the Free Software Foundation; either version 2 of the License, or
Philipp Rudo 90da03
 + * (at your option) any later version.
Philipp Rudo 90da03
 + *
Philipp Rudo 90da03
 + * This program is distributed in the hope that it will be useful,
Philipp Rudo 90da03
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
Philipp Rudo 90da03
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Philipp Rudo 90da03
 + * GNU General Public License for more details.
Philipp Rudo 90da03
 + */
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +struct detect_cycle;
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +typedef void *(*dc_next_t)(void *prev, void *data);
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +/*
Philipp Rudo 90da03
 + * Initialize cycle detection.
Philipp Rudo 90da03
 + * Returns a pointer to allocated struct detect_cycle. The caller is
Philipp Rudo 90da03
 + * responsible to free the memory after use.
Philipp Rudo 90da03
 + */
Philipp Rudo 90da03
 +struct detect_cycle *dc_init(void *head, void *data, dc_next_t next);
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +/*
Philipp Rudo 90da03
 + * Get next entry in the list using dc->next.
Philipp Rudo 90da03
 + * Returns 1 when cycle was detected, 0 otherwise.
Philipp Rudo 90da03
 + */
Philipp Rudo 90da03
 +int dc_next(struct detect_cycle *dc, void **next);
Philipp Rudo 90da03
 +
Philipp Rudo 90da03
 +/*
Philipp Rudo 90da03
 + * Get the start and length of the cycle. Must only be called after cycle was
Philipp Rudo 90da03
 + * detected by dc_next.
Philipp Rudo 90da03
 + */
Philipp Rudo 90da03
 +void dc_find_start(struct detect_cycle *dc, void **first, unsigned long *len);