dracutdevs / dracut

dracut the event driven initramfs infrastructure
https://github.com/dracutdevs/dracut/wiki
GNU General Public License v2.0
599 stars 399 forks source link

Kernel command line duplicated, leading to failed handling of ip=dhcp #833

Closed mwberry closed 4 years ago

mwberry commented 4 years ago

I'm using dracut to generate a UEFI executable for use as a netboot target. When machines run this executable, they report that "Sorry, 'ip=dhcp' does not make sense for multiple interface configurations". I found this confusing because they are single NIC machines and I believed there was only a single "ip=dhcp" on the kernel command line.

I instrumented a few dracut modules and found that getcmdline gathers one copy of the kernel command line from /proc/cmdline and a second copy from /etc/cmdline.d/01-default.conf, resulting in all command line arguments being duplicated. For most arguments this will not matter, but ip= is sensitive to the number of times it is specified.

My dracut configuration file is:

add_dracutmodules+="livenet network"
kernel_cmdline="ip=dhcp root=live:tftp://10.0.0.2/netboot.squashfs rd.luks=0 rd.lvm=0 rd.md=0 rd.dm=0 rd.shell=1"
uefi_splash_image="/usr/share/systemd/bootctl/splash-arch.bmp"

I invoke dracut like:

$ dracut --uefi --kver 5.6.15-arch1-1 /tftp/netboot.efi
dracut: Executing: /usr/bin/dracut --uefi --kver 5.6.15-arch1-1 /tftp/netboot.efi
dracut: dracut module 'bootchart' will not be installed, because command '/sbin/bootchartd' could not be found!
dracut: dracut module 'bootchart' will not be installed, because command '/sbin/bootchartd' could not be found!
dracut: dracut module 'dash' will not be installed, because command '/bin/dash' could not be found!
dracut: dracut module 'mksh' will not be installed, because command '/bin/mksh' could not be found!
dracut: dracut module 'busybox' will not be installed, because command 'busybox' could not be found!
dracut: dracut module 'rngd' will not be installed, because command 'rngd' could not be found!
dracut: dracut module 'lvmmerge' will not be installed, because command 'lvm' could not be found!
dracut: dracut module 'btrfs' will not be installed, because command 'btrfs' could not be found!
dracut: dracut module 'dmraid' will not be installed, because command 'dmraid' could not be found!
dracut: dracut module 'dmsquash-live-ntfs' will not be installed, because command 'ntfs-3g' could not be found!
dracut: dracut module 'lvm' will not be installed, because command 'lvm' could not be found!
dracut: dracut module 'mdraid' will not be installed, because command 'mdadm' could not be found!
dracut: dracut module 'multipath' will not be installed, because command 'multipath' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'stratisd-init' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'thin_check' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'thin_repair' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'mkfs.xfs' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'xfs_admin' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'xfs_growfs' could not be found!
dracut: dracut module 'cifs' will not be installed, because command 'mount.cifs' could not be found!
dracut: dracut module 'fcoe' will not be installed, because command 'dcbtool' could not be found!
dracut: dracut module 'fcoe' will not be installed, because command 'fipvlan' could not be found!
dracut: dracut module 'fcoe' will not be installed, because command 'lldpad' could not be found!
dracut: dracut module 'fcoe' will not be installed, because command 'fcoemon' could not be found!
dracut: dracut module 'fcoe' will not be installed, because command 'fcoeadm' could not be found!
dracut: dracut module 'fcoe-uefi' will not be installed, because command 'dcbtool' could not be found!
dracut: dracut module 'fcoe-uefi' will not be installed, because command 'fipvlan' could not be found!
dracut: dracut module 'fcoe-uefi' will not be installed, because command 'lldpad' could not be found!
dracut: dracut module 'iscsi' will not be installed, because command 'iscsi-iname' could not be found!
dracut: dracut module 'iscsi' will not be installed, because command 'iscsiadm' could not be found!
dracut: dracut module 'iscsi' will not be installed, because command 'iscsid' could not be found!
dracut: dracut module 'nbd' will not be installed, because command 'nbd-client' could not be found!
dracut: 95nfs: Could not find any command of 'rpcbind portmap'!
dracut: dracut module 'ssh-client' will not be installed, because command 'ssh' could not be found!
dracut: dracut module 'ssh-client' will not be installed, because command 'scp' could not be found!
dracut: dracut module 'biosdevname' will not be installed, because command 'biosdevname' could not be found!
dracut: *** Including module: bash ***
dracut: *** Including module: systemd ***
Failed to add dependency on unit, unit systemd-ask-password-plymouth.service does not exist.
dracut: *** Including module: systemd-initrd ***
dracut: *** Including module: modsign ***
dracut: *** Including module: i18n ***
dracut: *** Including module: network-legacy ***
dracut: *** Including module: network ***
dracut: *** Including module: url-lib ***
/usr/lib/dracut/modules.d/45url-lib/module-setup.sh: line 33: warning: command substitution: ignored null byte in input
/usr/lib/dracut/modules.d/45url-lib/module-setup.sh: line 33: warning: command substitution: ignored null byte in input
/usr/lib/dracut/modules.d/45url-lib/module-setup.sh: line 33: warning: command substitution: ignored null byte in input
/usr/lib/dracut/modules.d/45url-lib/module-setup.sh: line 33: warning: command substitution: ignored null byte in input
dracut: *** Including module: crypt ***
dracut: *** Including module: dm ***
dracut: Skipping udev rule: 64-device-mapper.rules
dracut: Skipping udev rule: 60-persistent-storage-dm.rules
dracut: Skipping udev rule: 55-dm.rules
dracut: *** Including module: dmsquash-live ***
dracut: *** Including module: kernel-modules ***
dracut: *** Including module: kernel-modules-extra ***
dracut: *** Including module: kernel-network-modules ***
dracut: *** Including module: livenet ***
dracut: *** Including module: qemu ***
dracut: *** Including module: qemu-net ***
dracut: *** Including module: lunmask ***
dracut: *** Including module: resume ***
dracut: *** Including module: rootfs-block ***
dracut: *** Including module: terminfo ***
dracut: *** Including module: udev-rules ***
dracut: Skipping udev rule: 40-redhat.rules
dracut: Skipping udev rule: 50-firmware.rules
dracut: Skipping udev rule: 50-udev.rules
dracut: Skipping udev rule: 91-permissions.rules
dracut: Skipping udev rule: 80-drivers-modprobe.rules
dracut: *** Including module: dracut-systemd ***
dracut: *** Including module: usrmount ***
dracut: *** Including module: base ***
dracut: *** Including module: fs-lib ***
dracut: *** Including module: img-lib ***
dracut: *** Including module: shutdown ***
dracut: *** Including modules done ***
dracut: *** Installing kernel module dependencies ***
dracut: *** Installing kernel module dependencies done ***
dracut: *** Resolving executable dependencies ***
dracut: *** Resolving executable dependencies done ***
dracut: *** Generating early-microcode cpio image ***
dracut: *** Store current command line parameters ***
dracut: *** Stripping files ***
dracut: *** Stripping files done ***
dracut: *** Creating image file '/boot/netboot.efi' ***
dracut: Using UEFI kernel cmdline:
dracut: ip=dhcp root=live:tftp://10.0.0.2/netboot.squashfs rd.luks=0 rd.lvm=0 rd.md=0 rd.dm=0 rd.shell=1
dracut: *** Creating UEFI image file '/boot/netboot.efi' done ***

This appears to happen because the kernel command line sourced from the config (or read from the command line) is both written into 01-default.conf in the initramfs and written into the UEFI executable.

From /usr/bin/dracut:

    516         --kernel-cmdline) kernel_cmdline_l+=("$2");           PARMS_TO_STORE+=" '$2'"; shift;;
...
    705 # source our config file
    706 [[ -f $conffile ]] && . "$conffile"
    707 
    708 # source our config dir
    709 for f in $(dropindirs_sort ".conf" "$confdir" "$dracutbasedir/dracut.conf.d"); do
    710     [[ -e $f ]] && . "$f"
    711 done
...
   1599 if [[ $kernel_only != yes ]]; then
   1600     (( ${#install_items[@]} > 0 )) && inst_multiple ${install_items[@]}
   1601     (( ${#install_optional_items[@]} > 0 )) && inst_multiple -o ${install_optional_items[@]}
   1602 
   1603     [[ $kernel_cmdline ]] && printf "%s\n" "$kernel_cmdline" >> "${initdir}/etc/cmdline.d/01-default.conf"
...
   2039     if objcopy \
   2040            ${uefi_osrelease:+--add-section .osrel=$uefi_osrelease --change-section-vma .osrel=0x20000} \
   2041            --add-section .cmdline="${uefi_outdir}/cmdline.txt" --change-section-vma .cmdline=0x30000 \
   2042            ${uefi_splash_image:+--add-section .splash="$uefi_splash_image" --change-section-vma .splash=0x40000} \
   2043            --add-section .linux="$kernel_image" --change-section-vma .linux=0x2000000 \
   2044            --add-section .initrd="${DRACUT_TMPDIR}/initramfs.img" --change-section-vma .initrd=0x3000000 \
   2045            "$uefi_stub" "${uefi_outdir}/linux.efi"; then

A minor patch that only writes 01-default.conf when $uefi != yes addresses the issue.

As a tangentially related question: why is --uefi only a command line option but not a configuration file option, while all other UEFI options are both?

mwberry commented 4 years ago
$ pacman -Qi dracut
Name            : dracut
Version         : 050-1
mwberry commented 4 years ago

Seems to still be present on master:

Writing to 01-default: https://github.com/dracutdevs/dracut/blob/dfe2247a43d6a216d9af533825c9a103e3b056cd/dracut.sh#L1612-L1616

Call to objcopy: https://github.com/dracutdevs/dracut/blob/dfe2247a43d6a216d9af533825c9a103e3b056cd/dracut.sh#L2052-L2054