Package: partman-base
Version: 226
Affects: partman-cros partman-efi partman-lvm partman-md partman-partitioning partman-prep

Background:

Partman is based on libparted which uses "flags" as an abstraction for different kinds of partition properties:
- attribute (boot on msdos, legacy_boot and hidden on gpt...)
- type identifier (esp, lvm, raid...)
- type modifier (hidden and lba on msdos)
- name (root and swap on mac)

Attribute flags can be combined but type flags are exclusive. When sending a SET_FLAGS command with multiple type flags to parted_server, only the one with the highest priority will be set. Type flag priorities are as follows: linux-home > bls_boot > chromeos_kernel > esp > irst > msftdata > diag > atvrecv > bios_grub > msftres > prep > palo, hp-service > lvm > raid > swap > boot

When a partition usage ("method") is changed, synchronization scripts for each supported method/flag are executed in a fixed order and set or remove a type flag on the partition by performing the following actions:
- send GET_FLAGS and read the current flags
- if the script manages the new method, send SET_FLAGS with current flags and the managed type flag - if the script does not manage the new method, send SET_FLAGS with current flags except the managed type flag

Current synchronization scripts order (may not exist in all architectures): biosgrub_sync_flag cros_sync_flag efi_sync_flag lvm_sync_flag prep_sync_flag md_sync_flag

This can lead to unexpected results when changing partition usage.

Problem description:

If the new type flag has a lower priority than the current type flag, then it is ignored. When the script which sets a lower priority type flag is executed before the script which removes a higher priority type flag (or no script manages it), then the lower priority type flag is not set and the resulting partition type does not match the new usage.

It is not only confusing when the partition type is informative only (LVM, RAID...) but it can also be troublesome when the partition type has a special meaning for platform firmware, boot loaders or operating systems (ChromeOS kernel, EFI, BIOS boot, PReP).

Some scripts needlessly remove some low priority flags (lvm, raid, swap) when setting another flag but do not remove higher priority flags which may still be set (chromeos_kernel, esp, msftdata, bios_grub, msftres...).

Examples:
- gpt: Change a partition usage from "ChromeOS" or "EFI" to "BIOS boot" -> bios_grub not set. - gpt, msdos on powerpc, ppc64, ppc64el: Change a partition usage from "PReP" to "RAID" -> raid not set. - gpt: Change a partition usage from "FAT16", "FAT32" or "NTFS" to "BIOS boot", "PReP", "LVM" "RAID" -> msftdata set, new flag not set. - gpt: Use an existing partition of type "Linux home" or "BLS extended boot" as "ChromeOS", "EFI" or "BIOS boot" -> old flag set, new flag not set. - gpt, msdos: Use an existing partition of type "Linux home", "BLS extended boot" or "Microsoft Reserved" as "PReP", "LVM" or "RAID" -> old flag set, new flag not set.

Possible mitigations/solutions:

1) Change the execution order of synchronization scripts to match type flag priorities so that higher priority flags are removed before low priority flags are set: cros_sync_flag efi_sync_flag biosgrub_sync_flag prep_sync_flag lvm_sync_flag md_sync_flag. Downsides: high priority type flags which are not managed by partman scripts (linux-home, bls_boot, msftdata, msftres...) still cannot be removed; requires a change in some affected packages.

2) Remove type flags (and keep only attribute and modifier flags) before setting a type flag in synchronization scripts; the scripts could call a new function defined in a common library. Downsides: requires a change in all affected packages; needs to be updated whenever libparted supports a new flag.

3) Modify parted_server to set only the last type flag when processing a SET_FLAGS command (all scripts send the new flag last).
Advantage: no need to change affected packages.
Downsides: changes SET_FLAGS behaviour; needs to be updated whenever libparted supports a new flag.

4) Modify parted_server to add a new SET_FLAG command which sets a single flag and use it in synchronization scripts.
Downside: requires a change in all affected packages.

I think solution #3 is the best because it requires changes only in partman-base to fully fix the issue. However modifying parted_server does not seem easy and my C is rusty, so I began to work on solution #2. Meanwhile, maybe solution #1 could be implemented quickly even if it does not fix the issue on existing partitions, at least it fixes the issue on partitions created by partman.

Reply via email to