diff --git a/0001-daemon-always-provide-stdin-when-running-chroot-comm.patch b/0001-daemon-always-provide-stdin-when-running-chroot-comm.patch new file mode 100644 index 0000000..5f8d60d --- /dev/null +++ b/0001-daemon-always-provide-stdin-when-running-chroot-comm.patch @@ -0,0 +1,71 @@ +From 1c553ea3cd03017547a25221db79c423c83d1005 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 19 Nov 2015 17:34:11 +0100 +Subject: [PATCH 1/5] daemon: always provide stdin when running chroot commands + (RHBZ#1280029) + +When running commands in the mounted guest (using the "command" API, and +APIs based on it), provide the /dev/null from the appliance as open fd +for stdin. Commands usually assume stdin is open if they didn't close +it explicitly, so this should avoid crashes or misbehavings due to that. + +(cherry picked from commit fd2f175ee79d29df101d353e2f380db27b19553a) +--- + daemon/command.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/daemon/command.c b/daemon/command.c +index 1593de9..27a4d0c 100644 +--- a/daemon/command.c ++++ b/daemon/command.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + + #include "guestfs_protocol.h" + #include "daemon.h" +@@ -242,7 +244,7 @@ do_command (char *const *argv) + { + char *out; + CLEANUP_FREE char *err = NULL; +- int r; ++ int r, dev_null_fd, flags; + CLEANUP_BIND_STATE struct bind_state bind_state = { .mounted = false }; + CLEANUP_RESOLVER_STATE struct resolver_state resolver_state = + { .mounted = false }; +@@ -259,6 +261,17 @@ do_command (char *const *argv) + return NULL; + } + ++ /* Provide /dev/null as stdin for the command, since we want ++ * to make sure processes have an open stdin, and it is not ++ * possible to rely on the guest to provide it (Linux guests ++ * get /dev dynamically populated at runtime by udev). ++ */ ++ dev_null_fd = open ("/dev/null", O_RDONLY|O_CLOEXEC); ++ if (dev_null_fd == -1) { ++ reply_with_perror ("/dev/null"); ++ return NULL; ++ } ++ + if (bind_mount (&bind_state) == -1) + return NULL; + if (enable_network) { +@@ -266,8 +279,10 @@ do_command (char *const *argv) + return NULL; + } + ++ flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | dev_null_fd; ++ + CHROOT_IN; +- r = commandv (&out, &err, (const char * const *) argv); ++ r = commandvf (&out, &err, flags, (const char * const *) argv); + CHROOT_OUT; + + free_bind_state (&bind_state); +-- +2.5.0 + diff --git a/0002-mllib-Add-Common_utils-may-function.patch b/0002-mllib-Add-Common_utils-may-function.patch new file mode 100644 index 0000000..3fde5ac --- /dev/null +++ b/0002-mllib-Add-Common_utils-may-function.patch @@ -0,0 +1,56 @@ +From f57dc38c05f3b8b002b8daa823a21ad25f5d682d Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 10 Nov 2015 20:07:56 +0000 +Subject: [PATCH 2/5] mllib: Add Common_utils 'may' function. + +This higher order function encapsulates the following pattern: + + match x with + | None -> () + | Some x -> f x + +(replaced with: `may f x`) + +This is taken from OCaml lablgtk (Gtk bindings) where this pattern is +used frequently. + +See also: https://ocaml.org/learn/tutorials/labels.html + +(cherry picked from commit 9a2c5b7c4d367aae665ab66f85e463f9d244e465) +--- + mllib/common_utils.ml | 4 ++++ + mllib/common_utils.mli | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml +index c714cb3..dfee615 100644 +--- a/mllib/common_utils.ml ++++ b/mllib/common_utils.ml +@@ -254,6 +254,10 @@ let rec assoc ?(cmp = compare) ~default x = function + | (y, y') :: _ when cmp x y = 0 -> y' + | _ :: ys -> assoc ~cmp ~default x ys + ++let may f = function ++ | None -> () ++ | Some x -> f x ++ + let istty chan = + Unix.isatty (Unix.descr_of_out_channel chan) + +diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli +index 39e05a1..081e4a4 100644 +--- a/mllib/common_utils.mli ++++ b/mllib/common_utils.mli +@@ -65,6 +65,9 @@ val assoc : ?cmp:('a -> 'a -> int) -> default:'b -> 'a -> ('a * 'b) list -> 'b + (** Like {!List.assoc} but with a user-defined comparison function, and + instead of raising [Not_found], it returns the [~default] value. *) + ++val may : ('a -> unit) -> 'a option -> unit ++(** [may f (Some x)] runs [f x]. [may f None] does nothing. *) ++ + val prog : string + (** The program name (derived from {!Sys.executable_name}). *) + +-- +2.5.0 + diff --git a/0003-resize-Use-may-pattern-in-various-places.patch b/0003-resize-Use-may-pattern-in-various-places.patch new file mode 100644 index 0000000..b1a235b --- /dev/null +++ b/0003-resize-Use-may-pattern-in-various-places.patch @@ -0,0 +1,38 @@ +From d059cbc9a24c2087be34c1e39fcd53d0a6342f07 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 10 Nov 2015 20:34:46 +0000 +Subject: [PATCH 3/5] resize: Use 'may' pattern in various places. + +This is upstream commit be1b9315ac79e866c4638b60997a48960959ff15, but +only the parts that apply to virt-resize. +--- + resize/resize.ml | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +diff --git a/resize/resize.ml b/resize/resize.ml +index 7b03f07..5c881a9 100644 +--- a/resize/resize.ml ++++ b/resize/resize.ml +@@ -1151,17 +1151,8 @@ read the man page virt-resize(1). + if p.p_bootable then + g#part_set_bootable "/dev/sdb" p.p_target_partnum true; + +- (match p.p_label with +- | Some label -> +- g#part_set_name "/dev/sdb" p.p_target_partnum label; +- | None -> () +- ); +- +- (match p.p_guid with +- | Some guid -> +- g#part_set_gpt_guid "/dev/sdb" p.p_target_partnum guid; +- | None -> () +- ); ++ may (g#part_set_name "/dev/sdb" p.p_target_partnum) p.p_label; ++ may (g#part_set_gpt_guid "/dev/sdb" p.p_target_partnum) p.p_guid; + + match parttype, p.p_id with + | GPT, GPT_Type gpt_type -> +-- +2.5.0 + diff --git a/0004-resize-Work-around-regression-in-sfdisk-RHBZ-1285847.patch b/0004-resize-Work-around-regression-in-sfdisk-RHBZ-1285847.patch new file mode 100644 index 0000000..7258635 --- /dev/null +++ b/0004-resize-Work-around-regression-in-sfdisk-RHBZ-1285847.patch @@ -0,0 +1,84 @@ +From daf51b61dc081bfea6c73d0fa2c753a390443f43 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 27 Nov 2015 10:25:17 +0000 +Subject: [PATCH 4/5] resize: Work around regression in sfdisk (RHBZ#1285847). + +'sfdisk --part-type' used to merely set the MBR ID byte in the +partition. However since sfdisk was rewritten, it now "helpfully" +corrupts the first sector of the partition if you change the type byte +from an ordinary partition to an extended partition. + +So we need to change the order in which we sets the partition type +byte, to do it before copying the partition content. + +This fixes a major regression in the way that virt-resize handles any +guest with logical partitions (specifically Ubuntu guests). + +(cherry picked from commit abe63eeaf2b1056a7c5d941f4aaecb5a050c3fee) +--- + resize/resize.ml | 42 ++++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 20 deletions(-) + +diff --git a/resize/resize.ml b/resize/resize.ml +index 5c881a9..2196316 100644 +--- a/resize/resize.ml ++++ b/resize/resize.ml +@@ -1100,6 +1100,28 @@ read the man page virt-resize(1). + g#part_add "/dev/sdb" "primary" p.p_target_start p.p_target_end + ) partitions; + ++ (* Set bootable and MBR IDs. Do this *before* copying over the data, ++ * because the rewritten sfdisk "helpfully" overwrites the partition ++ * table in the first sector of an extended partition if a partition ++ * is changed from primary to extended. Thus we need to set the ++ * MBR ID before doing the copy so sfdisk doesn't corrupt things. ++ *) ++ let set_partition_bootable_and_id p = ++ if p.p_bootable then ++ g#part_set_bootable "/dev/sdb" p.p_target_partnum true; ++ ++ may (g#part_set_name "/dev/sdb" p.p_target_partnum) p.p_label; ++ may (g#part_set_gpt_guid "/dev/sdb" p.p_target_partnum) p.p_guid; ++ ++ match parttype, p.p_id with ++ | GPT, GPT_Type gpt_type -> ++ g#part_set_gpt_type "/dev/sdb" p.p_target_partnum gpt_type ++ | MBR, MBR_ID mbr_id -> ++ g#part_set_mbr_id "/dev/sdb" p.p_target_partnum mbr_id ++ | GPT, (No_ID|MBR_ID _) | MBR, (No_ID|GPT_Type _) -> () ++ in ++ List.iter set_partition_bootable_and_id partitions; ++ + (* Copy over the data. *) + let copy_partition p = + match p.p_operation with +@@ -1143,26 +1165,6 @@ read the man page virt-resize(1). + in + List.iter copy_partition partitions; + +- (* Set bootable and MBR IDs. Do this *after* copying over the data, +- * so that we can magically change the primary partition to an extended +- * partition if necessary. +- *) +- let set_partition_bootable_and_id p = +- if p.p_bootable then +- g#part_set_bootable "/dev/sdb" p.p_target_partnum true; +- +- may (g#part_set_name "/dev/sdb" p.p_target_partnum) p.p_label; +- may (g#part_set_gpt_guid "/dev/sdb" p.p_target_partnum) p.p_guid; +- +- match parttype, p.p_id with +- | GPT, GPT_Type gpt_type -> +- g#part_set_gpt_type "/dev/sdb" p.p_target_partnum gpt_type +- | MBR, MBR_ID mbr_id -> +- g#part_set_mbr_id "/dev/sdb" p.p_target_partnum mbr_id +- | GPT, (No_ID|MBR_ID _) | MBR, (No_ID|GPT_Type _) -> () +- in +- List.iter set_partition_bootable_and_id partitions; +- + (* Fix the bootloader if we aligned the first partition. *) + if align_first_partition_and_fix_bootloader then ( + (* See can_fix_boot_loader above. *) +-- +2.5.0 + diff --git a/0005-resize-Add-a-regression-test-for-RHBZ-1285847.patch b/0005-resize-Add-a-regression-test-for-RHBZ-1285847.patch new file mode 100644 index 0000000..204c73b --- /dev/null +++ b/0005-resize-Add-a-regression-test-for-RHBZ-1285847.patch @@ -0,0 +1,113 @@ +From 759cb25ba96f2d1a028ae727dc45da55b950cc39 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 27 Nov 2015 09:52:49 +0000 +Subject: [PATCH 5/5] resize: Add a regression test for RHBZ#1285847. + +(cherry picked from commit 9d5abaa4b879440b44fc671f5d1b1a702f582397) +--- + tests/regressions/Makefile.am | 2 ++ + tests/regressions/rhbz1285847.sh | 72 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 74 insertions(+) + create mode 100755 tests/regressions/rhbz1285847.sh + +diff --git a/tests/regressions/Makefile.am b/tests/regressions/Makefile.am +index c4f60ae..a641859 100644 +--- a/tests/regressions/Makefile.am ++++ b/tests/regressions/Makefile.am +@@ -45,6 +45,7 @@ EXTRA_DIST = \ + rhbz1175196.sh \ + rhbz1232192.sh \ + rhbz1232192.xml \ ++ rhbz1285847.sh \ + test-noexec-stack.pl + + TESTS = \ +@@ -71,6 +72,7 @@ TESTS = \ + rhbz1091803.sh \ + rhbz1175196.sh \ + rhbz1232192.sh \ ++ rhbz1285847.sh \ + test-big-heap \ + test-noexec-stack.pl + +diff --git a/tests/regressions/rhbz1285847.sh b/tests/regressions/rhbz1285847.sh +new file mode 100755 +index 0000000..f34fe54 +--- /dev/null ++++ b/tests/regressions/rhbz1285847.sh +@@ -0,0 +1,72 @@ ++#!/bin/bash - ++# libguestfs ++# Copyright (C) 2015 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++# Regression test for virt-resize handling of logical volumes ++# https://bugzilla.redhat.com/1285847 ++ ++set -e ++export LANG=C ++ ++if [ -n "$SKIP_TEST_RHBZ1285847_SH" ]; then ++ echo "$0: test skipped because environment variable is set" ++ exit 77 ++fi ++ ++if ! ../../resize/virt-resize --help >/dev/null 2>&1; then ++ echo "$0: test skipped because virt-resize was not built" ++ exit 77 ++fi ++ ++rm -f rhbz1285847.img rhbz1285847-2.img rhbz1285847.out ++ ++# Create a disk with logical volumes. ++guestfish < rhbz1285847.out ++ ++if [ "$(cat rhbz1285847.out)" != "/dev/sda1: ext4 ++/dev/sda2: unknown ++/dev/sda5: swap" ]; then ++ echo "$0: unexpected result:" ++ cat rhbz1285847.out ++ exit 1 ++fi ++ ++rm rhbz1285847.img rhbz1285847-2.img rhbz1285847.out +-- +2.5.0 + diff --git a/libguestfs.spec b/libguestfs.spec index 30078a4..d2a1b97 100644 --- a/libguestfs.spec +++ b/libguestfs.spec @@ -25,13 +25,21 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 Version: 1.30.5 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPLv2+ # Source and patches. URL: http://libguestfs.org/ Source0: http://libguestfs.org/download/1.29-development/%{name}-%{version}.tar.gz +# RHBZ#1280029 +Patch1: 0001-daemon-always-provide-stdin-when-running-chroot-comm.patch +# RHBZ#1285847 +Patch2: 0002-mllib-Add-Common_utils-may-function.patch +Patch3: 0003-resize-Use-may-pattern-in-various-places.patch +Patch4: 0004-resize-Work-around-regression-in-sfdisk-RHBZ-1285847.patch +Patch5: 0005-resize-Add-a-regression-test-for-RHBZ-1285847.patch + # Basic build requirements: BuildRequires: perl(Pod::Simple) BuildRequires: perl(Pod::Man) @@ -787,6 +795,11 @@ for %{name}. %setup -q # Apply patches, if any, here. +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 # For Python 3 we must build libguestfs twice. This creates: # %{name}-%{version}/ @@ -1354,6 +1367,10 @@ popd %changelog +* Fri Nov 27 2015 Richard W.M. Jones - 1:1.30.5-2 +- Fix data loss bug in virt-resize (RHBZ#1285847, RHBZ#1266658). +- Fix dnf failing when Sys.stdin == None (RHBZ#1280029). + * Thu Nov 19 2015 Richard W.M. Jones - 1:1.30.5-1 - New upstream version 1.30.5.