Ubuntu 如何解决GRUB启动错误:"符号'grub_calloc'未找到

How to fix a grub boot error : "symbol 'grub_calloc' not found


问题

刚刚在20.04(Xubuntu)上运行了最新的一批更新,现在我得到了一个GRUB错误:

symbol 'grub_calloc' not found

我被扔到了 "grub救援 "的外壳中,但不知道在那里做什么可能有用。对我来说,"未找到符号 "意味着grub软件包的某种构建错误,但我并不真正了解grub的工作原理。我注意到这次更新还包括 "固件",不知道这是否与此有关。我最好的办法是用活CD启动,看看我是否能以某种方式回滚到grub的更新?

编辑补充:

好的,感谢很多人!我想我现在的情况是这样的。以下是我认为我现在理解的内容。

  1. 在 "非UEFI "系统上,grub是分两部分安装的。第一部分,也就是最基本的部分,是在开机时启动的部分。但是为了实现它的大部分功能,它需要第二部分。这些部分必须是一致的--任何部分都不能要求另一部分的任何功能,而这些功能实际上是不存在的。

    当这些部分没有被对齐,并且没有提供grub_calloc函数时,可见的、运行时的问题就会发生。我不太清楚grub_calloc是属于第二个较大的部分,还是属于第一个部分。我本来以为是第二部分,但grub构建系统是一个相当大的艺术作品,所以我不知道:)。

  2. 问题的根本原因是,grub的更新没有确保 两个 部分都被更新。理想情况下,没有做到这一点应该导致grub安装失败,而系统应该恢复到安全状态。这种情况并没有发生。

    这实际上对我来说仍然是一个谜。默认情况下,更新需要做的是把每个部件放在当前部件所在的地方,因为很明显,这起了作用。如果安装位置/驱动器是配置驱动的,而其中一个位置无法到达,那么在配置数据和现实之间就出现了某种程度的不匹配。只要各部分之间没有引入新的依赖关系,这可能不会显示为一个问题。

所有类型的解决方案都涉及重新安装grub,以确保这两个部分是一致的。实际上没有必要回到以前的版本(尽管那也可以),因为坏掉的不是grub运行时间本身。有许多方法可以实现这一点,这取决于你的环境,但运行Boot-repair live disk对我来说很有效。

为了避免将来出现这种错位,确保你系统上的grub安装程序被配置为安装到正确的设备上可能是有用的。

这个更新解决了一些重要的bug( 参见Ubuntu安全公告4432 )。如果你为了解决这个问题而还原了grub,请注意你会暴露在这些问题之下。

我不明白,但它似乎比一个bug更严重! - "警示GRUB安全咨询" cyber.gc.ca/en/alerts/grub-security-advisory - "GRUB2 UEFI SecureBoot漏洞 - 'BootHole'" debian.org/security/2020-GRUB-UEFI-secureBoot
Ubuntu安全团队正在追踪和记录这个回归。 wiki.ubuntu.com/SecurityTeam/KnowledgeBase/...
我不喜欢它,因为它在生产中出现了这样的退步。我使用Ubuntu Budgie 18.04 LTS,我也受到了影响。
答案1

在一个简单的2个分区安装中使用Linux Mint 19.3 bios grub设置。

在GRUB2更新后,机器在重启时崩溃并进入救援模式。

error: symbol 'grub_calloc' not found    

为了恢复GRUB,我启动了Linux Mint 19.3 Live USB stick,并在终端发出以下命令:

sudo mount /dev/sda1  /mnt    
sudo grub-install --root-directory=/mnt/  /dev/sda    

重新启动后,桌面很好地显示出来。

首先,LM在这里偏离了主题,其次,不清楚重新安装grub2应该如何解决这个问题。
考虑到不同的发行版、救援启动方式和根分区,给出的命令解决了这个问题。谢谢! 方法是:用U盘、CDROM或BIOS linux启动你的电脑,挂载根分区,将grub安装到你的启动设备上(调整根挂载路径和启动设备)
我不得不做类似的事情。我在kubuntu上,我有一个单盘,有两个分区,一个是未加密的/boot,另一个是加密的lvm,承载着系统的其他部分。由于某些原因,"启动修复 "对我来说不起作用,它没有显示 "修复建议 "按钮,而且关于grub的高级标签是灰色的。也许是因为这个设置,总之,我从一个活的usb启动,挂上启动分区,在上面运行grub安装,现在工作正常了。
这就成功了。在这个过程中,我遇到了另一个错误,在这里描述并修复。 s uperuser.com/questions/1293793/...
答案2

我和Rick N的情况一样,有两块磁盘,但它们不是在RAID中。我使用了这个工具 https://sourceforge.net/p/boot-repair-cd/home/Home/

我从Ubuntu帮助页面找到了这个工具 https://help.ubuntu.com/community/Boot-Repair

它似乎安装了一些以前没有的GUI功能(从我记得的时候起,这个系统就只用CLI),但我又开始运行了,这才是重要的部分。

感谢其他人,在这里,给予的指导。

好吧,我设法用启动修复工具来 "修复 "这个问题,这很好。但我认为它只是安装了一个以前的GRUB版本,所以如果以后的更新继续推送坏的版本,它可能不是一个 "真正的 "修复。总之,谢谢。
是的,我也有点担心,但考虑到它昨晚制造的大量噪音,我希望它能被更新来修复这个问题。只是需要注意grub的更新,而且在可预见的未来,我将事先进行快照。
我昨晚在Mint 20.06上遇到了完全相同的问题。我无法自己解决这个问题,而且还没有一个像样的系统备份程序,我带着沉重的心情**睡觉了。但我只花了不到5分钟就下载了 "boot-repair-disk.iso",并将其复制到我的Windows电脑上的Rufus的U盘上。我只是从USB重启了失败的机器,并接受了几个默认值,之后一切都很顺利。谢谢你 s o much!
我使用的是Ubuntu 20.04.1 LTS,通过简单地运行Boot repair usb解决了这个错误。
不同问题的答案,但又是另一种解释 如何使用Boot Repair与VirtualBox guest
答案3

这是我们在 Azure Ubuntu 18.04服务器上修复这个问题的一些工作

问题似乎是升级grub的尝试失败。问题发生在安全升级后的无人值守重启。

然后我们从Ubuntu bug的评论中找到了这个问题的说明: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889509/comments/16

请注意,我稍微修改了一下,下面是我的修改版本,我在后来的bug评论中提到了( https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889509/comments/45 )

对于在寻找这个bug的时候最终来到这里的Azure用户(在任何云中都应该是一样的,只要稍作修改),恢复的步骤是。

使用AzCli部署一个恢复的虚拟机,或者只是将受影响的操作系统vm磁盘的副本附加到一个救援虚拟机上。 一旦完成,连接到救援虚拟机并。

$ sudo su -
# lsblk <-- this will identify the attached disk, usualy /dev/sdc, but can be /dev/sda or /dev/sdb
# mkdir /rescue
# mount /dev/sdc1 /rescue <-- this assumes /dev/sdc is the attached data disk
# for fs in {proc,sys,tmp,dev}; do mount -o bind /$fs /rescue/$fs; done
# cd /rescue
# chroot /rescue
# grub-install /dev/sdc <-- this assumes /dev/sdc is the attached data disk
# exit
# cd /
# for fs in {proc,sys,tmp,dev}; do umount /rescue/$fs; done
# umount /rescue
# rmdir /rescue

现在你应该可以将修复后的磁盘换回受影响的虚拟机了。

第一次尝试修复

我们发现以下Azure文档链接很有用:

好的,一步一步来:

部署一个恢复的虚拟机

那是什么样的虚拟机?试图创建一个普通的Ubuntu 18.04 LTS VM。这就是你想要的--创建一个与损坏的服务器相匹配的恢复性虚拟机

除了连接到现有磁盘外,一切正常。看起来你不能连接到一个磁盘,除非你先以某种方式从另一台机器上移动它(分离它)。

将受影响的操作系统vm磁盘的副本附加到一个救援虚拟机上。

为了创建一个副本,你可以对磁盘进行只读快照,然后根据快照创建一个新的托管磁盘。

你需要快照的唯一磁盘是 操作系统 磁盘,而不是数据磁盘。

你可以在没有数据盘的情况下创建恢复虚拟机,只是自动创建的操作系统盘。

然后你可以把托管磁盘的操作系统快照作为数据磁盘添加到恢复虚拟机中。

然后你可以登录到恢复虚拟机中,并按照上面的步骤进行操作。

所有的步骤都完成了,没有错误--我们可以复制和粘贴确切的信息

关键线路正在运行 grub-install 你应该看到以下内容。

root@recoveryVM:/# grub-install /dev/sdc
Installing for i386-pc platform.
Installation finished. No error reported.

然后注销并停止虚拟机。

然后你可以进入被破坏的虚拟机,在虚拟机的磁盘部分选择'交换操作系统磁盘'。

Reddit的小线程解释了所需的挂载: https://www.reddit.com/r/Ubuntu/comments/i0vlf0/repair_grub_boot_error_symbol_grub_calloc_not/

重复步骤

  1. 给 "坏掉的 "操作系统磁盘做一个快照 (postfix _snap )
  2. 从快照中创建一个托管磁盘 - 这必须和旧的操作系统磁盘是同一个等级 因为我们要用这个磁盘完全替换旧的操作系统磁盘 (postfix _recovery ) - 源类型的快照,并使用刚刚创建的快照
  3. 将管理的操作系统磁盘连接到恢复虚拟机(不需要停止/启动恢复虚拟机)
  4. 通过SSH登录,运行恢复步骤。
  5. 从恢复的虚拟机上分离托管的操作系统磁盘(编辑虚拟机磁盘并分离恢复的操作系统磁盘)
  6. 停止 "坏掉的 "虚拟机(可能没有必要,因为操作系统磁盘的交换使其停止)
  7. 在 "坏掉的 "虚拟机磁盘中点击 "交换操作系统磁盘 "并选择恢复的操作系统磁盘作为替代
  8. 启动 "恢复的 "虚拟机
  9. 清理快照--但暂时保留损坏的操作系统磁盘。

最后关闭恢复的虚拟机,并在一个月后将其删除

一些服务器的问题

我们遇到了一个问题,两台服务器的修复程序没有工作。所有的命令都成功完成了--但我们在启动虚拟机时得到了同样的grub错误。

进一步调查发现,在恢复型虚拟机上, /dev/sda/dev/sdb/dev/sdc 发生了变化。我不知道为什么会发生这种情况。

这是你 s 在sudo(但非chroot)模式下运行 lsblk 时应该 得到的结果(注意 sda 是恢复性虚拟机操作系统, sdc 是要恢复的附加数据盘)。

NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda       8:0    0   30G  0 disk
├─sda1    8:1    0 29.9G  0 part /
├─sda14   8:14   0    4M  0 part
└─sda15   8:15   0  106M  0 part /boot/efi
sdb       8:16   0   16G  0 disk
└─sdb1    8:17   0   16G  0 part /mnt
sdc       8:32   0   30G  0 disk
├─sdc1    8:33   0 29.9G  0 part
├─sdc14   8:46   0    4M  0 part
└─sdc15   8:47   0  106M  0 part
sr0      11:0    1  628K  0 rom
这就是正确的解决方案。我只是简单地恢复了一个备份磁盘,并将其作为新的操作系统磁盘进行交换,但在看到你的回答后重新进行了修复,这样我就可以保留原始磁盘。
答案4

我在今天早些时候安装了Lubuntu 20.04(在一台旧的笔记本电脑上,Bios安装,不是EFI)并让它进行升级后,也遇到了同样的错误和无法启动的系统。它出现了一个非常混乱的对话框,说要在我的第一个分区和Lubuntu分区上更新GRUB。它似乎建议更新两个分区,我照做了。然后,在重启时,它在加载DE之前就崩溃了。

总之,我找到了一个解决方法,而不是解决这个问题的方法。由于GRUB似乎是问题所在(不管是什么原因),我重新安装了Lubuntu,当它第一次启动时,我打开了一个终端窗口,手动进行升级,并排除了对grub的更新:

sudo apt update

sudo apt list --upgradable |grep grub

这显示。

grub-common/focal-updates 2.04-1ubuntu26.1 amd64 [upgradable from: 2.04-1ubuntu26]
grub-pc-bin/focal-updates 2.04-1ubuntu26.1 amd64 [upgradable from: 2.04-1ubuntu26]
grub-pc/focal-updates 2.04-1ubuntu26.1 amd64 [upgradable from: 2.04-1ubuntu26]
grub2-common/focal-updates 2.04-1ubuntu26.1 amd64 [upgradable from: 2.04-1ubuntu26]

然后我把这些grub的更新 "搁置 "起来:

sudo apt-mark hold grub*

...然后继续进行升级:

sudo apt full-upgrade

我重新启动了机器,它又回到了桌面上,没有出错。

我不知道不更新GRUB会产生什么不良影响,但到目前为止,它在桌面会话中表现正常。 这样做会使你的系统永远处于BootHole漏洞集的攻击之下。最好是执行 $ sudo dpkg-reconfigure grub-pc 确保所有预期的启动驱动器都被提到用于安装grub BIOS核心图像。移除保留,升级,并重新启动。

@Dima,这应该是一个临时的解决方案,直到grub维护者修复他们的破损补丁。
答案5

我也是用linux mint 20 cinnamon和bios(相对于EFI)grub设置。

有没有人可以提供一些帮助?

编辑。我找到了我的问题的根本原因和解决方案。 我的问题的根本原因是,我有一个由4个磁盘组成的RAID5,而且,我想,在软件包升级过程中,自动的grub安装只更新了 "磁盘2"。由于我的BIOS是从 "磁盘1 "启动的,它有一个旧的grub,因此它无法启动。我把 BIOS 改为一次从每个磁盘启动(即:"disk1"、"disk2"、"disk3"、"disk4"),唯一能工作的是 "disk2"。

为了解决这个问题,我从 "disk2 "启动并执行:

sudo grub-install /dev/sda  
sudo grub-install /dev/sdc  
sudo grub-install /dev/sdd  
# ("disk2" is /dev/sdb and it was already working properly so I didn't install grub in that disk)  
sudo update-grub  
sudo reboot  

然后重新配置我的 BIOS,从 "disk1 "引导回来。这样,每次grub更新时,我都会遇到类似的问题,这会提醒我去grub-install,grub-update其他的磁盘。

我希望这能帮助其他遇到同样情况的人。

谢谢 @juan-fra 我在2020年7月29日Ubuntu MATE 20.04的Grub更新之后也遇到了同样的问题,因为我有4个内部驱动器。正如这个答案所描述的,我通过BIOS尝试了3个不同的驱动器,我能够登录。然后在3个硬盘上运行 grub-install ,现在桌面启动正常了:) 编辑:我根本就没有任何RAID设置。
一些有趣的观察,谢谢你。我正在运行一个RAID 0+1配置(2个硬盘在Raid 0中,2个硬盘在Raid 1中,由Intel RAID bios处理)。 Raid 0对是系统盘,在此基础上我使用了LVM。我可以启动实时光盘,看到我的磁盘/卷,但我不清楚更新是否有可能只写到Raid 0设备中的一个,这将破坏Raid,所以我不相信这是我的问题。
我认为这不是我的原因。我有两个装有grub的磁盘--m.2磁盘和sata磁盘。在sata上我安装了旧的系统和旧的grub,已经一年没有更新了。在更新了m.2上的grub后(实际上这是我目前工作的系统),我无法再从m.2上启动,出现了上面的错误。旧的系统从sata启动很正常,安装在sata上的grub也能从m.2启动我的系统。我不明白额外的sata磁盘和旧的grub如何影响到其他磁盘上的独立系统。
这并不是一个完整的解决方案。因为这样做,不会更新debconf数据库,也不会在下次推送grub更新的时候记住哪些硬盘需要安装grub。请执行 $ sudo dpkg-reconfigure grub-pc ,指定所有你想让grub一直安装到的驱动器,而不是手动调用grub-install。这不仅可以解决当前的启动失败问题,还可以确保在下次有软件包更新时,所有的grub都能正确更新。这样就不需要再手动执行grub-install了。
答案6

我在这里使用Linux Mint,也发生了同样的情况。似乎它是由最近的一个安全更新引起的,因为我在谷歌上找不到其他的东西,除了 这个更新公告

通过启动Mint Live USB并使用Timeshift恢复到我更新grub2之前的时间点解决了。

最近(10小时前),有大量的提交到grub git head。如果一个10小时前的提交被作为更新推送,我会感到惊讶,但其中一个提交做了大量的修改,所有这些都是使用grub_calloc来代替其他内存分配函数。另一个提交文件定义了grub_calloc函数并将其导出。所以我越来越认为这个问题的根本原因是,在某些情况下,由于某种原因,安装时没有确保grub_calloc被正确安装。
我刚刚在我的Debian Sid机器上得到了同样的错误。所以这是grub的全局问题,降级后它又能工作了。你有没有向他们报告这个问题?
@mderouss 今天,grub2软件包被更新到2.04-1ubuntu26.1版本,grub2-signed软件包被更新到1.142.3+2.04-1ubuntu26.1版本。也许这些变化存在于这个版本中?
有关 嗯,把mallocs改成callocs本身并不能解决缓冲区溢出的问题。没有任何提交信息说 "修复了CVE-2020-10713"。我认为我在git中看到的只是一个收紧内存管理的总体举措。让我困惑的是,发行版似乎只是直接从grub master上抓取最新的修改,而不是等待grub维护者发布新的版本(最后一个版本是13个月前的grub 2.04)。事情通常是这样的吗?
答案7

我肯定解决了这个问题。

enter image description here

  1. 进入页面, 点击这里 并下载 BOOT-REPAIR-DISK

  2. 把它刻录到DVD盘上,或制作一个不超过4GB、USB 2.0的USB可启动盘(我推荐DVD盘4GB)。

  3. 在插入DVD盘或USB可启动盘的情况下,接通PC电源。

  4. 一旦屏幕显示 "Boot-Repair-Disk "的标题,有两个选项,你必须选择。点击第一个,即上面的 64位会议

    enter image description here

  5. 一旦屏幕显示桌面,就会显示关于更新Boot-Repair-Disk,点击 NO ,因为没有必要。

  6. 一旦屏幕显示两个选项,你必须选择,如下图所示,点击第一个 推荐修复(修复最常见的问题)

    enter image description here

  7. 一旦完成这个过程,重新启动电脑,它必须启动Ubuntu操作系统。

这就是全部。祝您好运!

更多信息,请看这里。 https://help.ubuntu.com/community/Boot-Repair

答案8

我们有许多生产系统都有这个确切的问题:(以下步骤是用Debian DVD完成的,但在ubuntu上应该非常相似或适用)

  1. 从一个救援磁盘开始
  2. 只需点击问题
  3. 忽略网络
  4. s 选择你的根磁盘被挂载
  5. s 同时选择/boot被挂载
  6. 将一个shell放入选定的根磁盘
  7. grub-install DISKNAMEWITHOUTPARTITION ( 但没有分区标识(1,2,3....),例如 grub-install /dev/sda
  8. 重新启动

我们以非交互方式进行了更新。交互式的报告如下。

grub-install: error: cannot find a GRUB drive for /dev/vda. 检查你的device.map。

尽管在我们的例子中,磁盘应该是xvda而不是vda。 它破坏了驻扎在硬盘上一个特殊位置的MBR,这就是为什么你必须输入不带分区号的磁盘。

Ubuntu Bug报告

Debian Bug报告

当我们用 debconf-show grub-pc 查看当前的debconf-values时,我们看到 grub-pc/install_devices。/dev/vda 作为输出。我们用 echo "grub-pc/install_devices: /dev/xvda" | debconf-communicate 把这个值改成正确的,然后升级就顺利进行了。这是由我们的成像解决方案造成的,它的驱动器名称(vda)比我们实际运行的系统(xvda)要多
答案9

惊喜:

在最近的一次更新后,我得到了同样的错误:

错误:没有找到符号 grub_calloc .
进入救援模式 ...
grub rescue> _

不同点:

在我的情况下,与这里列出的所有其他答案,以及在OP的帖子中提到的 编辑 的要点相比,不同的是,我有 UEFI !

另外,我有一个Windows 10和Debian 10的双启动系统(而不是Ubuntu,我知道,这个论坛是 askubuntu ,但它是在网络上搜索 'grub_calloc not found' 错误时的第一个点击)。

修复方法:

  • 我读了所有关于grub分为两部分的讨论,等等,在这个论坛和其他地方都是如此。我重新安装了 grub (和 grub-common ,以及 grub-efi-amd64-bingrub-efi-amd64-bin-signedgrub2-common ),希望能有一些 "重新调整"。 grub-pc 以前没有安装在我的系统上,所以我也安装了它,以利于衡量。对我来说还是没有什么变化。

  • 安装到MBR对我来说不是一个选项。这台笔记本上的Windows 10是用UEFI安装的。

  • 我没有RAID,没有LVM设置。甚至不知道那些东西是什么。所以其他答案都没有帮助我。

从EFI-文件启动:

我希望尽快有一个错误修复,因为这个错误让系统无法启动,无法使用。与此同时,我仍然可以同时启动Windows 10和Debian 10,方法是:

  1. 在启动笔记本电脑时按下ESCAPE键进入"'BIOS'设置",
  2. 然后选择 "从EFI文件启动 "选项,而不是 "从操作系统管理器启动",
  3. 然后从文件夹 BootdebianHPMicrosoft 进入⑧,
  4. 然后选择⑾文件,

这将带来通常的grub菜单,其中列出了常见的操作系统选择。也许这个选项是我的笔记本电脑所特有的,我不能说。(我想,也可以通过使用Live USB/CD来达到类似的效果)。

起作用的修复:

总之,在等待了一个星期左右的时间后,我厌倦了每天早上通过BIOS设置来启动笔记本的这种常规。今天早上启动到Debian 10之后,我做了以下工作。

  1. 我查看了EFI下的 Boot 文件夹中的内容,在那里我发现只有一个文件 bootx64.efi
  2. 我对 bootx64.efi 文件做了一个备份---> bootx64.efi.bak 放在同一个文件夹中。
  3. 然后我把debian文件夹中的 grubx64.efi 复制到 Boot 文件夹中,作为新的 bootx64.efi
  4. 重新启动笔记本,出现了grub菜单,干净利落,没有任何跳跃性的动作。

我想同样的事情也可以从一个活的USB/CD中完成。

我不知道这个解决方案有多安全,或者说有多笨拙(或者说它是否对每个使用UEFI的人都是一个解决方案)。


  • 在修复前启动。

Error

答案10

我遇到了这个错误,把一堆服务器从Ubuntu 16.04升级到18.04。在我的案例中,有一台机器有一个单独的启动卷,在 /dev/md0 (mdraid阵列)上,使用 /dev/sda1/dev/sdb1 作为RAID卷。修复方法是:

  • 从18.04的U盘启动到 "LiveCD "模式。
  • 使用 blkid 找到卷的UUIDs和驱动器。确定 /dev/md127 为mdraid阵列,通常显示为 /dev/md0
  • 然后。
    apt install grub2-common grub-pc
    mkdir -p /mnt/root/boot
    mount /dev/md127 /mnt/root/boot
    
  • 在两个物理驱动器上安装MBR,这样在发生故障后任何一个都能工作
    grub-install --root-directory=/mnt/root /dev/sdb
    grub-install --root-directory=/mnt/root /dev/sda
    
  • 确认在 /mnt/root/boot/grub 里有新的grub文件。
    ls -alR /mnt/root
    
  • 重新启动

之后,服务器就恢复了。

答案11

像Juan Fra一样--我有两个磁盘,但不是RAID。我怀疑GRUB是在两个磁盘上。我使用的是Ubuntu,所以从CD启动,安装了 "boot-repair"(网上有说明),它更新了所有grub分区。现在一切正常。

但只适用于现在..... 为了确保debconf数据库记住所有需要升级grub的驱动器,请执行 $ sudo dpkg-reconfigure grub-pc 以确保所有你期望可以启动的驱动器都列在那里。这样一来,下次升级软件包就会把 grub 安装到所有的驱动器上,而不需要人工干预。