From 36f5331e316186f8b5e80367c37f07ee50337355 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 3 Aug 2017 17:30:13 +0100 Subject: [PATCH] Fix supermin crash with truncated vmlinuz file (RHBZ#1477758). - Include all upstream patches since 5.1.18. --- ...-debugging-of-config-files-creating-.patch | 38 ++++ ...efactor-code-for-locating-the-kernel.patch | 178 ++++++++++++++++++ 0003-kernel-Tweak-debug-messages.patch | 110 +++++++++++ ...nel-Rearrange-the-order-of-functions.patch | 90 +++++++++ ...boot-kernels-using-has_modpath-later.patch | 60 ++++++ ...s_modpath-function-so-it-checks-for-.patch | 42 +++++ ...ow-kernel-version-information-is-fou.patch | 150 +++++++++++++++ ...ow-End_of_file-exception-to-escape-i.patch | 35 ++++ ...naming-to-make-find_kernel_from_-fun.patch | 33 ++++ ...plausibly-small-kernels-in-lib-modul.patch | 45 +++++ supermin.spec | 19 +- 11 files changed, 799 insertions(+), 1 deletion(-) create mode 100644 0001-prepare-Add-some-debugging-of-config-files-creating-.patch create mode 100644 0002-kernel-Refactor-code-for-locating-the-kernel.patch create mode 100644 0003-kernel-Tweak-debug-messages.patch create mode 100644 0004-kernel-Rearrange-the-order-of-functions.patch create mode 100644 0005-kernel-Filter-boot-kernels-using-has_modpath-later.patch create mode 100644 0006-kernel-Change-has_modpath-function-so-it-checks-for-.patch create mode 100644 0007-kernel-Replace-how-kernel-version-information-is-fou.patch create mode 100644 0008-kernel-Don-t-allow-End_of_file-exception-to-escape-i.patch create mode 100644 0009-kernel-Simple-renaming-to-make-find_kernel_from_-fun.patch create mode 100644 0010-kernel-Reject-implausibly-small-kernels-in-lib-modul.patch diff --git a/0001-prepare-Add-some-debugging-of-config-files-creating-.patch b/0001-prepare-Add-some-debugging-of-config-files-creating-.patch new file mode 100644 index 0000000..6bc83e4 --- /dev/null +++ b/0001-prepare-Add-some-debugging-of-config-files-creating-.patch @@ -0,0 +1,38 @@ +From 8518865218063cb2db1e7a7ab7dfc3fc0a80561c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 29 Jul 2017 10:39:43 +0100 +Subject: [PATCH 01/10] prepare: Add some debugging of config files / creating + base.tar.gz. + +--- + src/mode_prepare.ml | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/mode_prepare.ml b/src/mode_prepare.ml +index e8cf058..7c8221e 100644 +--- a/src/mode_prepare.ml ++++ b/src/mode_prepare.ml +@@ -146,6 +146,10 @@ let prepare debug (copy_kernel, format, host_cpu, + with Sys_error _ -> false + ) config_files in + ++ if debug >= 1 then ++ printf "supermin: there are %d config files\n" ++ (List.length config_files); ++ + (* Put the list of config files into a file, for tar to read. *) + let files_from = tmpdir // "files-from.txt" in + let chan = open_out files_from in +@@ -158,6 +162,7 @@ let prepare debug (copy_kernel, format, host_cpu, + let base = outputdir // "base.tar.gz" in + if debug >= 1 then printf "supermin: writing %s\n%!" base; + let cmd = +- sprintf "tar -C %s -zcf %s -T %s" +- (quote dir) (quote base) (quote files_from) in ++ sprintf "tar%s -C %s -zcf %s -T %s" ++ (if debug >=1 then " -v" else "") ++ (quote dir) (quote base) (quote files_from) in + run_command cmd; +-- +2.13.1 + diff --git a/0002-kernel-Refactor-code-for-locating-the-kernel.patch b/0002-kernel-Refactor-code-for-locating-the-kernel.patch new file mode 100644 index 0000000..b32e42e --- /dev/null +++ b/0002-kernel-Refactor-code-for-locating-the-kernel.patch @@ -0,0 +1,178 @@ +From 137dc8b5a0b7427cd80d774604f2f048259b7926 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 12:19:35 +0100 +Subject: [PATCH 02/10] kernel: Refactor code for locating the kernel. + +Refactor the code for locating the kernel into separate functions, +making clear the purpose of each part of the code. + +This is pure refactoring and doesn't change the meaning of the code. +--- + src/format_ext2_kernel.ml | 126 ++++++++++++++++++++++++++-------------------- + 1 file changed, 72 insertions(+), 54 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index 5d1ae66..a12fbd2 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -40,49 +40,21 @@ let patt_of_cpu host_cpu = + List.map (fun model -> sprintf "vmlinu?-*-%s" model) models + + let rec build_kernel debug host_cpu copy_kernel kernel = +- (* Locate the kernel. *) ++ (* Locate the kernel. ++ * SUPERMIN_* environment variables override everything. If those ++ * are not present then we look in /lib/modules and /boot. ++ *) + let kernel_file, kernel_name, kernel_version, modpath = +- try +- let kernel_env = getenv "SUPERMIN_KERNEL" in +- if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL environment variable %s\n%!" +- kernel_env; +- let kernel_version = +- try +- let v = getenv "SUPERMIN_KERNEL_VERSION" in +- if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL_VERSION environment variable %s\n%!" v; +- v +- with Not_found -> get_kernel_version_from_file kernel_env in +- if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL version %s\n%!" +- kernel_version; +- let kernel_name = Filename.basename kernel_env in +- let modpath = find_modpath debug kernel_version in +- kernel_env, kernel_name, kernel_version, modpath +- with Not_found -> +- let kernels = +- let files = glob "/lib/modules/*/vmlinuz" [GLOB_NOSORT; GLOB_NOESCAPE] in +- let files = Array.to_list files in +- let kernels = +- List.map ( +- fun f -> +- let modpath = Filename.dirname f in +- f, Filename.basename f, Filename.basename modpath, modpath +- ) files in +- List.sort ( +- fun (_, _, a, _) (_, _, b, _) -> compare_version b a +- ) kernels in +- +- if kernels <> [] then ( +- let kernel = List.hd kernels in +- if debug >= 1 then ( +- let kernel_file, _, _, _ = kernel in +- printf "supermin: kernel: picked vmlinuz %s\n%!" kernel_file; +- ); +- kernel +- ) else +- find_kernel debug host_cpu kernel in ++ match find_kernel_from_env_vars debug with ++ | Some k -> k ++ | None -> ++ match find_kernel_from_lib_modules debug with ++ | Some k -> k ++ | None -> ++ match find_kernel_from_boot debug host_cpu with ++ | Some k -> k ++ | None -> ++ error_no_kernels host_cpu in + + if debug >= 1 then ( + printf "supermin: kernel: kernel_version %s\n" kernel_version; +@@ -93,7 +65,52 @@ let rec build_kernel debug host_cpu copy_kernel kernel = + + (kernel_version, modpath) + +-and find_kernel debug host_cpu kernel = ++and find_kernel_from_env_vars debug = ++ try ++ let kernel_env = getenv "SUPERMIN_KERNEL" in ++ if debug >= 1 then ++ printf "supermin: kernel: SUPERMIN_KERNEL environment variable %s\n%!" ++ kernel_env; ++ let kernel_version = ++ try ++ let v = getenv "SUPERMIN_KERNEL_VERSION" in ++ if debug >= 1 then ++ printf "supermin: kernel: SUPERMIN_KERNEL_VERSION environment variable %s\n%!" v; ++ v ++ with Not_found -> get_kernel_version_from_file kernel_env in ++ if debug >= 1 then ++ printf "supermin: kernel: SUPERMIN_KERNEL version %s\n%!" ++ kernel_version; ++ let kernel_name = Filename.basename kernel_env in ++ let modpath = find_modpath debug kernel_version in ++ Some (kernel_env, kernel_name, kernel_version, modpath) ++ with Not_found -> None ++ ++and find_kernel_from_lib_modules debug = ++ let kernels = ++ let files = glob "/lib/modules/*/vmlinuz" [GLOB_NOSORT; GLOB_NOESCAPE] in ++ let files = Array.to_list files in ++ let kernels = ++ List.map ( ++ fun f -> ++ let modpath = Filename.dirname f in ++ f, Filename.basename f, Filename.basename modpath, modpath ++ ) files in ++ List.sort ( ++ fun (_, _, a, _) (_, _, b, _) -> compare_version b a ++ ) kernels in ++ ++ if kernels <> [] then ( ++ let kernel = List.hd kernels in ++ if debug >= 1 then ( ++ let kernel_file, _, _, _ = kernel in ++ printf "supermin: kernel: picked vmlinuz %s\n%!" kernel_file; ++ ); ++ Some kernel ++ ) else ++ None ++ ++and find_kernel_from_boot debug host_cpu = + let is_arm = + String.length host_cpu >= 3 && + host_cpu.[0] = 'a' && host_cpu.[1] = 'r' && host_cpu.[2] = 'm' in +@@ -111,19 +128,20 @@ and find_kernel debug host_cpu kernel = + (* In original: ls -1dvr /boot/vmlinuz-* 2>/dev/null | grep -v xen *) + kernel_filter ["vmlinu?-*"] is_arm all_files in + +- if files = [] then no_kernels host_cpu; +- +- let files = List.sort (fun a b -> compare_version b a) files in +- let kernel_name = List.hd files in +- let kernel_version = get_kernel_version kernel_name in ++ if files = [] then None ++ else ( ++ let files = List.sort (fun a b -> compare_version b a) files in ++ let kernel_name = List.hd files in ++ let kernel_version = get_kernel_version kernel_name in + +- if debug >= 1 then +- printf "supermin: kernel: picked kernel %s\n%!" kernel_name; ++ if debug >= 1 then ++ printf "supermin: kernel: picked kernel %s\n%!" kernel_name; + +- (* Get the kernel modules. *) +- let modpath = find_modpath debug kernel_version in ++ (* Get the kernel modules. *) ++ let modpath = find_modpath debug kernel_version in + +- ("/boot" // kernel_name), kernel_name, kernel_version, modpath ++ Some (("/boot" // kernel_name), kernel_name, kernel_version, modpath) ++ ) + + and kernel_filter patterns is_arm all_files = + let files = +@@ -143,7 +161,7 @@ and kernel_filter patterns is_arm all_files = + ) in + List.filter (fun filename -> has_modpath filename) files + +-and no_kernels host_cpu = ++and error_no_kernels host_cpu = + error "\ + failed to find a suitable kernel (host_cpu=%s). + +-- +2.13.1 + diff --git a/0003-kernel-Tweak-debug-messages.patch b/0003-kernel-Tweak-debug-messages.patch new file mode 100644 index 0000000..c18999f --- /dev/null +++ b/0003-kernel-Tweak-debug-messages.patch @@ -0,0 +1,110 @@ +From 44d0d1d9cd57feb4f6bd31c0530e90f6d7ede2f5 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 12:27:09 +0100 +Subject: [PATCH 03/10] kernel: Tweak debug messages. + +Rework the debug messages so it's clearer in debugging messages how +the kernel was located. Also removes duplicated debugging +information. + +This is cleanup, there is no functional change. +--- + src/format_ext2_kernel.ml | 35 ++++++++++++++--------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index a12fbd2..90fa56f 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -45,20 +45,27 @@ let rec build_kernel debug host_cpu copy_kernel kernel = + * are not present then we look in /lib/modules and /boot. + *) + let kernel_file, kernel_name, kernel_version, modpath = ++ if debug >= 1 then ++ printf "supermin: kernel: looking for kernel using environment variables ...\n%!"; + match find_kernel_from_env_vars debug with + | Some k -> k + | None -> ++ if debug >= 1 then ++ printf "supermin: kernel: looking for kernels in /lib/modules/*/vmlinuz ...\n%!"; + match find_kernel_from_lib_modules debug with + | Some k -> k + | None -> ++ if debug >= 1 then ++ printf "supermin: kernel: looking for kernels in /boot ...\n%!"; + match find_kernel_from_boot debug host_cpu with + | Some k -> k + | None -> + error_no_kernels host_cpu in + + if debug >= 1 then ( ++ printf "supermin: kernel: picked vmlinuz %s\n%!" kernel_file; + printf "supermin: kernel: kernel_version %s\n" kernel_version; +- printf "supermin: kernel: modules %s\n%!" modpath; ++ printf "supermin: kernel: modpath %s\n%!" modpath; + ); + + copy_or_symlink_file copy_kernel kernel_file kernel; +@@ -69,18 +76,14 @@ and find_kernel_from_env_vars debug = + try + let kernel_env = getenv "SUPERMIN_KERNEL" in + if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL environment variable %s\n%!" +- kernel_env; ++ printf "supermin: kernel: SUPERMIN_KERNEL=%s\n%!" kernel_env; + let kernel_version = + try + let v = getenv "SUPERMIN_KERNEL_VERSION" in + if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL_VERSION environment variable %s\n%!" v; ++ printf "supermin: kernel: SUPERMIN_KERNEL_VERSION=%s\n%!" v; + v + with Not_found -> get_kernel_version_from_file kernel_env in +- if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_KERNEL version %s\n%!" +- kernel_version; + let kernel_name = Filename.basename kernel_env in + let modpath = find_modpath debug kernel_version in + Some (kernel_env, kernel_name, kernel_version, modpath) +@@ -100,15 +103,9 @@ and find_kernel_from_lib_modules debug = + fun (_, _, a, _) (_, _, b, _) -> compare_version b a + ) kernels in + +- if kernels <> [] then ( +- let kernel = List.hd kernels in +- if debug >= 1 then ( +- let kernel_file, _, _, _ = kernel in +- printf "supermin: kernel: picked vmlinuz %s\n%!" kernel_file; +- ); +- Some kernel +- ) else +- None ++ match kernels with ++ | kernel :: _ -> Some kernel ++ | [] -> None + + and find_kernel_from_boot debug host_cpu = + let is_arm = +@@ -134,9 +131,6 @@ and find_kernel_from_boot debug host_cpu = + let kernel_name = List.hd files in + let kernel_version = get_kernel_version kernel_name in + +- if debug >= 1 then +- printf "supermin: kernel: picked kernel %s\n%!" kernel_name; +- + (* Get the kernel modules. *) + let modpath = find_modpath debug kernel_version in + +@@ -176,8 +170,7 @@ and find_modpath debug kernel_version = + try + let modpath = getenv "SUPERMIN_MODULES" in + if debug >= 1 then +- printf "supermin: kernel: SUPERMIN_MODULES environment variable = %s\n%!" +- modpath; ++ printf "supermin: kernel: SUPERMIN_MODULES=%s\n%!" modpath; + modpath + with Not_found -> + let modpath = "/lib/modules/" ^ kernel_version in +-- +2.13.1 + diff --git a/0004-kernel-Rearrange-the-order-of-functions.patch b/0004-kernel-Rearrange-the-order-of-functions.patch new file mode 100644 index 0000000..0844709 --- /dev/null +++ b/0004-kernel-Rearrange-the-order-of-functions.patch @@ -0,0 +1,90 @@ +From cb080ba09e0e2b78cf33d88acd510641118c07ca Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 12:34:47 +0100 +Subject: [PATCH 04/10] kernel: Rearrange the order of functions. + +Rearrange the order of functions more logically. + +Just code motion, no functional change. +--- + src/format_ext2_kernel.ml | 50 +++++++++++++++++++++++------------------------ + 1 file changed, 25 insertions(+), 25 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index 90fa56f..e2f8e4b 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -24,21 +24,6 @@ open Ext2fs + open Fnmatch + open Glob + +-let patt_of_cpu host_cpu = +- let models = +- match host_cpu with +- | "mips" | "mips64" -> [host_cpu; "*-malta"] +- | "ppc" | "powerpc" | "powerpc64" -> ["ppc"; "powerpc"; "powerpc64"] +- | "sparc" | "sparc64" -> ["sparc"; "sparc64"] +- | "amd64" | "x86_64" -> ["amd64"; "x86_64"] +- | "parisc" | "parisc64" -> ["hppa"; "hppa64"] +- | "ppc64el" -> ["powerpc64le"] +- | _ when host_cpu.[0] = 'i' && host_cpu.[2] = '8' && host_cpu.[3] = '6' -> ["?86"] +- | _ when String.length host_cpu >= 5 && String.sub host_cpu 0 5 = "armv7" -> ["armmp"] +- | _ -> [host_cpu] +- in +- List.map (fun model -> sprintf "vmlinu?-*-%s" model) models +- + let rec build_kernel debug host_cpu copy_kernel kernel = + (* Locate the kernel. + * SUPERMIN_* environment variables override everything. If those +@@ -72,6 +57,17 @@ let rec build_kernel debug host_cpu copy_kernel kernel = + + (kernel_version, modpath) + ++and error_no_kernels host_cpu = ++ error "\ ++failed to find a suitable kernel (host_cpu=%s). ++ ++I looked for kernels in /boot and modules in /lib/modules. ++ ++If this is a Xen guest, and you only have Xen domU kernels ++installed, try installing a fullvirt kernel (only for ++supermin use, you shouldn't boot the Xen guest with it)." ++ host_cpu ++ + and find_kernel_from_env_vars debug = + try + let kernel_env = getenv "SUPERMIN_KERNEL" in +@@ -155,16 +151,20 @@ and kernel_filter patterns is_arm all_files = + ) in + List.filter (fun filename -> has_modpath filename) files + +-and error_no_kernels host_cpu = +- error "\ +-failed to find a suitable kernel (host_cpu=%s). +- +-I looked for kernels in /boot and modules in /lib/modules. +- +-If this is a Xen guest, and you only have Xen domU kernels +-installed, try installing a fullvirt kernel (only for +-supermin use, you shouldn't boot the Xen guest with it)." +- host_cpu ++and patt_of_cpu host_cpu = ++ let models = ++ match host_cpu with ++ | "mips" | "mips64" -> [host_cpu; "*-malta"] ++ | "ppc" | "powerpc" | "powerpc64" -> ["ppc"; "powerpc"; "powerpc64"] ++ | "sparc" | "sparc64" -> ["sparc"; "sparc64"] ++ | "amd64" | "x86_64" -> ["amd64"; "x86_64"] ++ | "parisc" | "parisc64" -> ["hppa"; "hppa64"] ++ | "ppc64el" -> ["powerpc64le"] ++ | _ when host_cpu.[0] = 'i' && host_cpu.[2] = '8' && host_cpu.[3] = '6' -> ["?86"] ++ | _ when String.length host_cpu >= 5 && String.sub host_cpu 0 5 = "armv7" -> ["armmp"] ++ | _ -> [host_cpu] ++ in ++ List.map (fun model -> sprintf "vmlinu?-*-%s" model) models + + and find_modpath debug kernel_version = + try +-- +2.13.1 + diff --git a/0005-kernel-Filter-boot-kernels-using-has_modpath-later.patch b/0005-kernel-Filter-boot-kernels-using-has_modpath-later.patch new file mode 100644 index 0000000..0896671 --- /dev/null +++ b/0005-kernel-Filter-boot-kernels-using-has_modpath-later.patch @@ -0,0 +1,60 @@ +From fb7164c23b4e5161d22eaf266abd3e0bf55e7b1e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 12:47:49 +0100 +Subject: [PATCH 05/10] kernel: Filter /boot kernels using has_modpath later. + +/boot kernels are filtered using the has_modpath function. +This change just moves the test later, which has no effect +here but makes subsequent cleanups simpler. +--- + src/format_ext2_kernel.ml | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index e2f8e4b..c44ae23 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -121,17 +121,22 @@ and find_kernel_from_boot debug host_cpu = + (* In original: ls -1dvr /boot/vmlinuz-* 2>/dev/null | grep -v xen *) + kernel_filter ["vmlinu?-*"] is_arm all_files in + +- if files = [] then None +- else ( +- let files = List.sort (fun a b -> compare_version b a) files in +- let kernel_name = List.hd files in +- let kernel_version = get_kernel_version kernel_name in ++ let files = List.sort (fun a b -> compare_version b a) files in ++ let kernels = ++ List.map ( ++ fun kernel_name -> ++ let kernel_version = get_kernel_version kernel_name in ++ let kernel_file = "/boot" // kernel_name in ++ let modpath = find_modpath debug kernel_version in ++ (kernel_file, kernel_name, kernel_version, modpath) ++ ) files in + +- (* Get the kernel modules. *) +- let modpath = find_modpath debug kernel_version in ++ let kernels = ++ List.filter (fun (_, kernel_name, _, _) -> has_modpath kernel_name) kernels in + +- Some (("/boot" // kernel_name), kernel_name, kernel_version, modpath) +- ) ++ match kernels with ++ | kernel :: _ -> Some kernel ++ | [] -> None + + and kernel_filter patterns is_arm all_files = + let files = +@@ -149,7 +154,7 @@ and kernel_filter patterns is_arm all_files = + find filename "tegra" = -1 + ) files + ) in +- List.filter (fun filename -> has_modpath filename) files ++ files + + and patt_of_cpu host_cpu = + let models = +-- +2.13.1 + diff --git a/0006-kernel-Change-has_modpath-function-so-it-checks-for-.patch b/0006-kernel-Change-has_modpath-function-so-it-checks-for-.patch new file mode 100644 index 0000000..65c391a --- /dev/null +++ b/0006-kernel-Change-has_modpath-function-so-it-checks-for-.patch @@ -0,0 +1,42 @@ +From 407bf152a24399c78eae114589100ba0923ef70a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 12:53:54 +0100 +Subject: [PATCH 06/10] kernel: Change has_modpath function so it checks for + modpath // modules.dep. + +--- + src/format_ext2_kernel.ml | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index c44ae23..0bb67fe 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -132,7 +132,7 @@ and find_kernel_from_boot debug host_cpu = + ) files in + + let kernels = +- List.filter (fun (_, kernel_name, _, _) -> has_modpath kernel_name) kernels in ++ List.filter (fun (_, _, _, modpath) -> has_modpath modpath) kernels in + + match kernels with + | kernel :: _ -> Some kernel +@@ -183,12 +183,9 @@ and find_modpath debug kernel_version = + printf "supermin: kernel: picked modules path %s\n%!" modpath; + modpath + +-and has_modpath kernel_name = +- try +- let kv = get_kernel_version kernel_name in +- modules_dep_exists kv +- with +- | Not_found -> false ++and has_modpath modpath = ++ try (stat (modpath // "modules.dep")).st_kind = S_REG ++ with Unix_error _ -> false + + and get_kernel_version kernel_name = + if (string_prefix "vmlinuz-" kernel_name) || +-- +2.13.1 + diff --git a/0007-kernel-Replace-how-kernel-version-information-is-fou.patch b/0007-kernel-Replace-how-kernel-version-information-is-fou.patch new file mode 100644 index 0000000..91dfcfe --- /dev/null +++ b/0007-kernel-Replace-how-kernel-version-information-is-fou.patch @@ -0,0 +1,150 @@ +From c859939113b939b5ad4237e8f4835cd33290357f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 13:06:41 +0100 +Subject: [PATCH 07/10] kernel: Replace how kernel version information is + found. + +The old code was fairly bogus. In the new code there is one "public" +function: + + val get_kernel_version : bool -> string -> string option + +which takes a full vmlinuz path and returns the kernel version from it +if possible (or None if not). This function first looks at the file +content to see if the version can be extracted, and if that fails +looks at the filename. + +As a side effect of making this change, we also filter out kernels +from /boot where we cannot read the kernel version. +--- + src/format_ext2_kernel.ml | 78 +++++++++++++++++++++++++++++++---------------- + 1 file changed, 51 insertions(+), 27 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index 0bb67fe..55c5af9 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -79,7 +79,10 @@ and find_kernel_from_env_vars debug = + if debug >= 1 then + printf "supermin: kernel: SUPERMIN_KERNEL_VERSION=%s\n%!" v; + v +- with Not_found -> get_kernel_version_from_file kernel_env in ++ with Not_found -> ++ match get_kernel_version debug kernel_env with ++ | Some v -> v ++ | None -> raise Not_found in + let kernel_name = Filename.basename kernel_env in + let modpath = find_modpath debug kernel_version in + Some (kernel_env, kernel_name, kernel_version, modpath) +@@ -123,17 +126,17 @@ and find_kernel_from_boot debug host_cpu = + + let files = List.sort (fun a b -> compare_version b a) files in + let kernels = +- List.map ( ++ filter_map ( + fun kernel_name -> +- let kernel_version = get_kernel_version kernel_name in + let kernel_file = "/boot" // kernel_name in +- let modpath = find_modpath debug kernel_version in +- (kernel_file, kernel_name, kernel_version, modpath) ++ match get_kernel_version debug kernel_file with ++ | None -> None ++ | Some kernel_version -> ++ let modpath = find_modpath debug kernel_version in ++ if not (has_modpath modpath) then None ++ else Some (kernel_file, kernel_name, kernel_version, modpath) + ) files in + +- let kernels = +- List.filter (fun (_, _, _, modpath) -> has_modpath modpath) kernels in +- + match kernels with + | kernel :: _ -> Some kernel + | [] -> None +@@ -187,24 +190,43 @@ and has_modpath modpath = + try (stat (modpath // "modules.dep")).st_kind = S_REG + with Unix_error _ -> false + +-and get_kernel_version kernel_name = +- if (string_prefix "vmlinuz-" kernel_name) || +- (string_prefix "vmlinux-" kernel_name) then ( +- let kv = String.sub kernel_name 8 (String.length kernel_name - 8) in +- if modules_dep_exists kv then kv +- else get_kernel_version_from_name kernel_name +- ) else get_kernel_version_from_name kernel_name +- +-and modules_dep_exists kv = +- try (lstat ("/lib/modules/" ^ kv ^ "/modules.dep")).st_kind = S_REG +- with Unix_error _ -> false +- +-and get_kernel_version_from_name kernel_name = +- get_kernel_version_from_file ("/boot" // kernel_name) ++(* Extract the kernel version from a Linux kernel file. ++ * ++ * This first sees if we can get the information from the file ++ * content (see below) and if that fails tries to parse the ++ * filename. ++ *) ++and get_kernel_version debug kernel_file = ++ if debug >= 1 then ++ printf "supermin: kernel: kernel version of %s%!" kernel_file; ++ match get_kernel_version_from_file_content kernel_file with ++ | Some version -> ++ if debug >= 1 then printf " = %s (from content)\n%!" version; ++ Some version ++ | None -> ++ (* Try to work it out from the filename instead. *) ++ let basename = Filename.basename kernel_file in ++ if string_prefix "vmlinuz-" basename || string_prefix "vmlinux-" basename ++ then ( ++ let version = String.sub basename 8 (String.length basename - 8) in ++ (* Does the version look reasonable? *) ++ let modpath = "/lib/modules" // version in ++ if has_modpath modpath then ( ++ if debug >= 1 then printf " = %s (from filename)\n%!" version; ++ Some version ++ ) else ( ++ if debug >= 1 then printf " = error, no modpath\n%!"; ++ None ++ ) ++ ) ++ else ( ++ if debug >= 1 then printf " = error, cannot parse filename\n%!"; ++ None ++ ) + + (* Extract the kernel version from a Linux kernel file. + * +- * Returns a string containing the version or [Not_found] if the ++ * Returns a string containing the version or [None] if the + * file can't be read, is not a Linux kernel, or the version can't + * be found. + * +@@ -217,7 +239,7 @@ and get_kernel_version_from_name kernel_name = + * + * Bugs: probably limited to x86 kernels. + *) +-and get_kernel_version_from_file file = ++and get_kernel_version_from_file_content file = + try + let chan = open_in file in + let buf = read_string chan 514 4 in +@@ -247,10 +269,12 @@ and get_kernel_version_from_file file = + ) + else raise Not_found + in +- loop 0 ++ let version = loop 0 in ++ Some version + with +- | Sys_error _ -> raise Not_found +- | Invalid_argument _ -> raise Not_found ++ | Not_found ++ | Sys_error _ ++ | Invalid_argument _ -> None + + (* Read an unsigned little endian short at a specified offset in a file. *) + and read_leshort chan offset = +-- +2.13.1 + diff --git a/0008-kernel-Don-t-allow-End_of_file-exception-to-escape-i.patch b/0008-kernel-Don-t-allow-End_of_file-exception-to-escape-i.patch new file mode 100644 index 0000000..bfbdf16 --- /dev/null +++ b/0008-kernel-Don-t-allow-End_of_file-exception-to-escape-i.patch @@ -0,0 +1,35 @@ +From 1cb54ab90e813e148e218cb274c97b08b610e3b9 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 13:09:06 +0100 +Subject: [PATCH 08/10] kernel: Don't allow End_of_file exception to escape if + kernel is bogus (RHBZ#1477758). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the kernel file is truncated (zero length or too short) then +functions such as ‘really_input’ raise End_of_file. Unfortunately +this exception could escape and kill the program. What we want to do +instead is to ignore such kernels. The combination of this commit and +the last commit ignores such kernels if they are found in /boot. + +Reported by Charlie Martinez. +--- + src/format_ext2_kernel.ml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index 55c5af9..e329adb 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -273,6 +273,7 @@ and get_kernel_version_from_file_content file = + Some version + with + | Not_found ++ | End_of_file + | Sys_error _ + | Invalid_argument _ -> None + +-- +2.13.1 + diff --git a/0009-kernel-Simple-renaming-to-make-find_kernel_from_-fun.patch b/0009-kernel-Simple-renaming-to-make-find_kernel_from_-fun.patch new file mode 100644 index 0000000..a6c0d69 --- /dev/null +++ b/0009-kernel-Simple-renaming-to-make-find_kernel_from_-fun.patch @@ -0,0 +1,33 @@ +From bc33663a38bc401a5b5883e253cc93b0d3e67ef2 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 13:48:37 +0100 +Subject: [PATCH 09/10] kernel: Simple renaming to make find_kernel_from_* + functions consistent. + +No functional change, just renaming variables. +--- + src/format_ext2_kernel.ml | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index e329adb..44ba035 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -94,9 +94,11 @@ and find_kernel_from_lib_modules debug = + let files = Array.to_list files in + let kernels = + List.map ( +- fun f -> +- let modpath = Filename.dirname f in +- f, Filename.basename f, Filename.basename modpath, modpath ++ fun kernel_file -> ++ let kernel_name = Filename.basename kernel_file in ++ let modpath = Filename.dirname kernel_file in ++ let kernel_version = Filename.basename modpath in ++ kernel_file, kernel_name, kernel_version, modpath + ) files in + List.sort ( + fun (_, _, a, _) (_, _, b, _) -> compare_version b a +-- +2.13.1 + diff --git a/0010-kernel-Reject-implausibly-small-kernels-in-lib-modul.patch b/0010-kernel-Reject-implausibly-small-kernels-in-lib-modul.patch new file mode 100644 index 0000000..bd66692 --- /dev/null +++ b/0010-kernel-Reject-implausibly-small-kernels-in-lib-modul.patch @@ -0,0 +1,45 @@ +From ea3b3dce6bb77dbe57f91044c30ab49693e88e2b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 3 Aug 2017 13:09:06 +0100 +Subject: [PATCH 10/10] kernel: Reject implausibly small kernels in + /lib/modules (RHBZ#1477758). + +Previous changes will reject truncated / implausibly small kernel +files found under /boot, but because the code that looks for kernels +in /lib/modules works slightly differently it would not work there. +This uses a simple stat check to reject kernels there too. + +Reported by Charlie Martinez. +--- + src/format_ext2_kernel.ml | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/src/format_ext2_kernel.ml b/src/format_ext2_kernel.ml +index 44ba035..d5d529d 100644 +--- a/src/format_ext2_kernel.ml ++++ b/src/format_ext2_kernel.ml +@@ -93,12 +93,16 @@ and find_kernel_from_lib_modules debug = + let files = glob "/lib/modules/*/vmlinuz" [GLOB_NOSORT; GLOB_NOESCAPE] in + let files = Array.to_list files in + let kernels = +- List.map ( ++ filter_map ( + fun kernel_file -> +- let kernel_name = Filename.basename kernel_file in +- let modpath = Filename.dirname kernel_file in +- let kernel_version = Filename.basename modpath in +- kernel_file, kernel_name, kernel_version, modpath ++ let size = try (stat kernel_file).st_size with Unix_error _ -> 0 in ++ if size < 10000 then None ++ else ( ++ let kernel_name = Filename.basename kernel_file in ++ let modpath = Filename.dirname kernel_file in ++ let kernel_version = Filename.basename modpath in ++ Some (kernel_file, kernel_name, kernel_version, modpath) ++ ) + ) files in + List.sort ( + fun (_, _, a, _) (_, _, b, _) -> compare_version b a +-- +2.13.1 + diff --git a/supermin.spec b/supermin.spec index b3892ab..2aba38c 100644 --- a/supermin.spec +++ b/supermin.spec @@ -31,7 +31,7 @@ Summary: Tool for creating supermin appliances Name: supermin Version: 5.1.18 -Release: 3%{?dist} +Release: 4%{?dist} License: GPLv2+ %if 0%{?rhel} >= 7 @@ -49,6 +49,19 @@ Source1: http://libguestfs.org/download/supermin/%{name}-%{version}.tar.gz Source2: libguestfs.keyring %endif +# All upstream patches since 5.1.18. +Patch0001: 0001-prepare-Add-some-debugging-of-config-files-creating-.patch +# Fix supermin crash with truncated vmlinuz file (RHBZ#1477758). +Patch0002: 0002-kernel-Refactor-code-for-locating-the-kernel.patch +Patch0003: 0003-kernel-Tweak-debug-messages.patch +Patch0004: 0004-kernel-Rearrange-the-order-of-functions.patch +Patch0005: 0005-kernel-Filter-boot-kernels-using-has_modpath-later.patch +Patch0006: 0006-kernel-Change-has_modpath-function-so-it-checks-for-.patch +Patch0007: 0007-kernel-Replace-how-kernel-version-information-is-fou.patch +Patch0008: 0008-kernel-Don-t-allow-End_of_file-exception-to-escape-i.patch +Patch0009: 0009-kernel-Simple-renaming-to-make-find_kernel_from_-fun.patch +Patch0010: 0010-kernel-Reject-implausibly-small-kernels-in-lib-modul.patch + BuildRequires: /usr/bin/pod2man BuildRequires: /usr/bin/pod2html BuildRequires: rpm @@ -170,6 +183,10 @@ make check || { %changelog +* Thu Aug 03 2017 Richard W.M. Jones - 5.1.18-4 +- Fix supermin crash with truncated vmlinuz file (RHBZ#1477758). +- Include all upstream patches since 5.1.18. + * Thu Aug 03 2017 Fedora Release Engineering - 5.1.18-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild