From e1ec6a007eba3b990b9d67c175dcf704fb6008c0b0f88d398d775598bb4ca15d Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Tue, 21 Mar 2017 10:35:03 +0000 Subject: [PATCH] Accepting request 481686 from home:michael-chang:branches:Base:System - Fix out of memory error on lvm detection (bsc#1016536) (bsc#1027401) * grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch - Fix boot failure if /boot is separate btrfs partition (bsc#1023160) * grub2-btrfs-06-subvol-mount.patch OBS-URL: https://build.opensuse.org/request/show/481686 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=266 --- grub2-btrfs-06-subvol-mount.patch | 49 ++++--- ...te-metadata-buffer-from-raw-contents.patch | 126 ++++++++++++++++++ grub2.changes | 8 ++ grub2.spec | 2 + 4 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch diff --git a/grub2-btrfs-06-subvol-mount.patch b/grub2-btrfs-06-subvol-mount.patch index c3accb7..07636e3 100644 --- a/grub2-btrfs-06-subvol-mount.patch +++ b/grub2-btrfs-06-subvol-mount.patch @@ -1,7 +1,7 @@ -Index: grub-2.02~rc1/grub-core/fs/btrfs.c +Index: grub-2.02~rc2/grub-core/fs/btrfs.c =================================================================== ---- grub-2.02~rc1.orig/grub-core/fs/btrfs.c -+++ grub-2.02~rc1/grub-core/fs/btrfs.c +--- grub-2.02~rc2.orig/grub-core/fs/btrfs.c ++++ grub-2.02~rc2/grub-core/fs/btrfs.c @@ -32,6 +32,7 @@ #include #include @@ -264,10 +264,10 @@ Index: grub-2.02~rc1/grub-core/fs/btrfs.c cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols", grub_cmd_btrfs_list_subvols, 0, "[-p|-n] [-o var] DEVICE", -Index: grub-2.02~rc1/grub-core/osdep/linux/getroot.c +Index: grub-2.02~rc2/grub-core/osdep/linux/getroot.c =================================================================== ---- grub-2.02~rc1.orig/grub-core/osdep/linux/getroot.c -+++ grub-2.02~rc1/grub-core/osdep/linux/getroot.c +--- grub-2.02~rc2.orig/grub-core/osdep/linux/getroot.c ++++ grub-2.02~rc2/grub-core/osdep/linux/getroot.c @@ -107,6 +107,14 @@ struct btrfs_ioctl_search_key grub_uint32_t unused[9]; }; @@ -412,7 +412,7 @@ Index: grub-2.02~rc1/grub-core/osdep/linux/getroot.c } } else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) -@@ -1144,6 +1258,34 @@ grub_util_get_grub_dev_os (const char *o +@@ -1148,6 +1262,34 @@ grub_util_get_grub_dev_os (const char *o return grub_dev; } @@ -447,11 +447,11 @@ Index: grub-2.02~rc1/grub-core/osdep/linux/getroot.c char * grub_make_system_path_relative_to_its_root_os (const char *path) { -Index: grub-2.02~rc1/util/grub-install.c +Index: grub-2.02~rc2/util/grub-install.c =================================================================== ---- grub-2.02~rc1.orig/util/grub-install.c -+++ grub-2.02~rc1/util/grub-install.c -@@ -1560,6 +1560,42 @@ main (int argc, char *argv[]) +--- grub-2.02~rc2.orig/util/grub-install.c ++++ grub-2.02~rc2/util/grub-install.c +@@ -1560,6 +1560,55 @@ main (int argc, char *argv[]) prefix_drive = xasprintf ("(%s)", grub_drives[0]); } @@ -462,12 +462,17 @@ Index: grub-2.02~rc1/util/grub-install.c + { + char *subvol = NULL; + char *mount_path = NULL; ++ char **rootdir_devices = NULL; ++ char *rootdir_path = grub_util_path_concat (2, "/", rootdir); + -+ if (!load_cfg_f) -+ load_cfg_f = grub_util_fopen (load_cfg, "wb"); -+ have_load_cfg = 1; ++ if (grub_util_is_directory (rootdir_path)) ++ rootdir_devices = grub_guess_root_devices (rootdir_path); + -+ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path); ++ free (rootdir_path); ++ ++ if (rootdir_devices && rootdir_devices[0]) ++ if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0) ++ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path); + + if (subvol && mount_path) + { @@ -477,12 +482,20 @@ Index: grub-2.02~rc1/util/grub-install.c + + if (def_subvol) + { ++ if (!load_cfg_f) ++ load_cfg_f = grub_util_fopen (load_cfg, "wb"); ++ have_load_cfg = 1; ++ + if (grub_strcmp (subvol, def_subvol) != 0) + fprintf (load_cfg_f, "btrfs-mount-subvol ($root) %s %s\n", mount_path, subvol); + free (def_subvol); + } + } + ++ for (curdev = rootdir_devices; *curdev; curdev++) ++ free (*curdev); ++ if (rootdir_devices) ++ free (rootdir_devices); + if (subvol) + free (subvol); + if (mount_path) @@ -494,10 +507,10 @@ Index: grub-2.02~rc1/util/grub-install.c char mkimage_target[200]; const char *core_name = NULL; -Index: grub-2.02~rc1/include/grub/emu/getroot.h +Index: grub-2.02~rc2/include/grub/emu/getroot.h =================================================================== ---- grub-2.02~rc1.orig/include/grub/emu/getroot.h -+++ grub-2.02~rc1/include/grub/emu/getroot.h +--- grub-2.02~rc2.orig/include/grub/emu/getroot.h ++++ grub-2.02~rc2/include/grub/emu/getroot.h @@ -53,6 +53,11 @@ char ** grub_find_root_devices_from_mountinfo (const char *dir, char **relroot); #endif diff --git a/grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch b/grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch new file mode 100644 index 0000000..d8e2beb --- /dev/null +++ b/grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch @@ -0,0 +1,126 @@ +From 87636b6eb33d10fad13739c39128029cde076c03 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 20 Mar 2017 14:59:41 +0800 +Subject: [PATCH] Allocate LVM metadata buffer from raw contents + +The size reserved for on disk LVM metadata area can be exceedingly large that +may trigger out of memory error for allocating buffer based on it. Refine the +buffer allocation to use size of raw LVM metadata contents and read them from +within the metadata area as we only need to parse the JSON formatted contents +rather than the entire metadata area. This reduced the size significantly and +the likelihood to out of memory error. +--- + grub-core/disk/lvm.c | 65 ++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 45 insertions(+), 20 deletions(-) + +diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c +index 7b265c7..47aae05 100644 +--- a/grub-core/disk/lvm.c ++++ b/grub-core/disk/lvm.c +@@ -102,9 +102,11 @@ grub_lvm_detect (grub_disk_t disk, + { + grub_err_t err; + grub_uint64_t mda_offset, mda_size; ++ grub_uint64_t mda_raw_offset, mda_raw_size; + char buf[GRUB_LVM_LABEL_SIZE]; + char vg_id[GRUB_LVM_ID_STRLEN+1]; + char pv_id[GRUB_LVM_ID_STRLEN+1]; ++ char mdah_buf[sizeof (struct grub_lvm_mda_header) + sizeof (struct grub_lvm_raw_locn)]; + char *metadatabuf, *p, *q, *vgname; + struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf; + struct grub_lvm_pv_header *pvh; +@@ -167,21 +169,15 @@ grub_lvm_detect (grub_disk_t disk, + + dlocn++; + mda_offset = grub_le_to_cpu64 (dlocn->offset); +- mda_size = grub_le_to_cpu64 (dlocn->size); + + /* It's possible to have multiple copies of metadata areas, we just use the + first one. */ +- +- /* Allocate buffer space for the circular worst-case scenario. */ +- metadatabuf = grub_malloc (2 * mda_size); +- if (! metadatabuf) ++ err = grub_disk_read (disk, 0, mda_offset, sizeof (mdah_buf), mdah_buf); ++ if (err) + goto fail; + +- err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf); +- if (err) +- goto fail2; ++ mdah = (struct grub_lvm_mda_header *) mdah_buf; + +- mdah = (struct grub_lvm_mda_header *) metadatabuf; + if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC, + sizeof (mdah->magic))) + || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION)) +@@ -191,26 +187,55 @@ grub_lvm_detect (grub_disk_t disk, + #ifdef GRUB_UTIL + grub_util_info ("unknown LVM metadata header"); + #endif +- goto fail2; ++ goto fail; + } + + rlocn = mdah->raw_locns; +- if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) > +- grub_le_to_cpu64 (mdah->size)) ++ ++ mda_size = grub_le_to_cpu64 (mdah->size); ++ mda_raw_size = grub_le_to_cpu64 (rlocn->size); ++ mda_raw_offset = grub_le_to_cpu64 (rlocn->offset); ++ ++ metadatabuf = grub_malloc (mda_raw_size); ++ ++ if (! metadatabuf) ++ goto fail; ++ ++ if (mda_raw_offset > mda_size) ++ goto fail2; ++ ++ if (mda_raw_offset + mda_raw_size > mda_size) + { ++ err = grub_disk_read (disk, 0, ++ mda_offset + mda_raw_offset, ++ mda_size - mda_raw_offset, ++ metadatabuf); ++ if (err) ++ goto fail2; ++ + /* Metadata is circular. Copy the wrap in place. */ +- grub_memcpy (metadatabuf + mda_size, +- metadatabuf + GRUB_LVM_MDA_HEADER_SIZE, +- grub_le_to_cpu64 (rlocn->offset) + +- grub_le_to_cpu64 (rlocn->size) - +- grub_le_to_cpu64 (mdah->size)); ++ err = grub_disk_read (disk, 0, ++ mda_offset + GRUB_LVM_MDA_HEADER_SIZE, ++ mda_raw_offset + mda_raw_size - mda_size, ++ metadatabuf + mda_size - mda_raw_offset); ++ if (err) ++ goto fail2; ++ } ++ else ++ { ++ err = grub_disk_read (disk, 0, ++ mda_offset + mda_raw_offset, ++ mda_raw_size, ++ metadatabuf); ++ if (err) ++ goto fail2; + } +- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset); ++ p = q = metadatabuf; + +- while (*q != ' ' && q < metadatabuf + mda_size) ++ while (*q != ' ' && q < metadatabuf + mda_raw_size) + q++; + +- if (q == metadatabuf + mda_size) ++ if (q == metadatabuf + mda_raw_size) + { + #ifdef GRUB_UTIL + grub_util_info ("error parsing metadata"); +-- +2.6.6 + diff --git a/grub2.changes b/grub2.changes index 9003d72..3112a86 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Mon Mar 20 09:43:58 UTC 2017 - mchang@suse.com + +- Fix out of memory error on lvm detection (bsc#1016536) (bsc#1027401) + * grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch +- Fix boot failure if /boot is separate btrfs partition (bsc#1023160) + * grub2-btrfs-06-subvol-mount.patch + ------------------------------------------------------------------- Fri Mar 17 06:22:42 UTC 2017 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index ef6e6bc..2d6385d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -207,6 +207,7 @@ Patch77: grub2-s390x-08-workaround-part-to-disk.patch Patch78: grub2-commands-introduce-read_file-subcommand.patch Patch79: grub2-efi-chainload-harder.patch Patch80: grub2-emu-4-all.patch +Patch81: grub2-lvm-allocate-metadata-buffer-from-raw-contents.patch # Btrfs snapshot booting related patches Patch101: grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch Patch102: grub2-btrfs-02-export-subvolume-envvars.patch @@ -468,6 +469,7 @@ swap partition while in resuming %patch78 -p1 %patch79 -p1 %patch80 -p1 +%patch81 -p1 %patch101 -p1 %patch102 -p1 %patch103 -p1