Linux

Grub“不兼容的許可證”錯誤

  • April 30, 2013

前幾天,當它的鍵盤開始起作用時,我正在使用一台筆記型電腦作為普通台式機使用。鍵盤右側的大多數鍵完全停止工作,並且Ctrl``u出現了不應該出現的字元組合等組合鍵。退格鍵表現出最奇怪的行為;它以某種方式能夠導致 shell 提示符中的刪除字元。

我無法乾淨地重新啟動電腦,所以我進行了硬關機。當我再次打開電腦時,我收到了來自 Grub 的這條消息:

GRUB loading.
Welcome to GRUB!

incompatible license
Aborted. Press any key to exit.

我按下了任意鍵,Grub 回復了

Operating System Not Found.

按另一個鍵會使第一條消息再次出現。之後按另一個鍵會導致出現第二條消息……等等。

如果我讓筆記型電腦開機幾分鐘,它的風扇會顯著加速,就好像筆記型電腦正在執行 CPU 密集型程序一樣。

我從筆記型電腦中取出硬碟,將其安裝在伺服器上,然後環顧四周。我沒有看到任何奇怪的東西/boot

筆記型電腦正在執行 Arch Linux。該驅動器使用 GPT 進行分區。筆記型電腦可以與另一台機器的硬碟一起正常工作。並且其他機器不能與筆記型電腦的硬碟一起工作。

我不確定鍵盤問題是否與 Grub 問題直接相關。

什麼可能導致我遇到的問題?或者,我應該怎麼做才能找出或縮小潛在原因的範圍?

以防萬一它是相關的,這裡*(已刪除)*是一個 tarball,/boot這裡/etc/grub.d是我的 Grub 配置:

#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
insmod part_gpt
insmod part_msdos
if [ -s $prefix/grubenv ]; then
 load_env
fi
set default="0"

if [ x"${feature_menuentry_id}" = xy ]; then
 menuentry_id_option="--id"
else
 menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
 set saved_entry="${prev_saved_entry}"
 save_env saved_entry
 set prev_saved_entry=
 save_env prev_saved_entry
 set boot_once=true
fi

function savedefault {
 if [ -z "${boot_once}" ]; then
   saved_entry="${chosen}"
   save_env saved_entry
 fi
}

function load_video {
 if [ x$feature_all_video_module = xy ]; then
   insmod all_video
 else
   insmod efi_gop
   insmod efi_uga
   insmod ieee1275_fb
   insmod vbe
   insmod vga
   insmod video_bochs
   insmod video_cirrus
 fi
}

if [ x$feature_default_font_path = xy ] ; then
  font=unicode
else
insmod part_gpt
insmod ext2
set root='hd0,gpt1'
if [ x$feature_platform_search_hint = xy ]; then
 search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1  d44f2a2f-c369-456b-81f1-efa13f9caae2
else
 search --no-floppy --fs-uuid --set=root d44f2a2f-c369-456b-81f1-efa13f9caae2
fi
   font="/usr/share/grub/unicode.pf2"
fi

if loadfont $font ; then
 set gfxmode=auto
 load_video
 insmod gfxterm
 set locale_dir=$prefix/locale
 set lang=en_US
 insmod gettext
fi
terminal_input console
terminal_output gfxterm
set timeout=5
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Arch GNU/Linux, with Linux PARA kernel' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-PARA kernel-true-d44f2a2f-c369-456b-81f1-efa13f9caae2' {
   load_video
   set gfxpayload=keep
   insmod gzio
   insmod part_gpt
   insmod ext2
   set root='hd1,gpt1'
   if [ x$feature_platform_search_hint = xy ]; then
     search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt1 --hint-efi=hd1,gpt1 --hint-baremetal=ahci1,gpt1  b4fbf4f8-303c-49bd-a52f-6049e1623a26
   else
     search --no-floppy --fs-uuid --set=root b4fbf4f8-303c-49bd-a52f-6049e1623a26
   fi
   echo    'Loading Linux PARA kernel ...'
   linux   /boot/vmlinuz-linux-PARA root=UUID=d44f2a2f-c369-456b-81f1-efa13f9caae2 ro  quiet
   echo    'Loading initial ramdisk ...'
   initrd  /boot/initramfs-linux-PARA.img
}
menuentry 'Arch GNU/Linux, with Linux core repo kernel' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-core repo kernel-true-d44f2a2f-c369-456b-81f1-efa13f9caae2' {
   load_video
   set gfxpayload=keep
   insmod gzio
   insmod part_gpt
   insmod ext2
   set root='hd1,gpt1'
   if [ x$feature_platform_search_hint = xy ]; then
     search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt1 --hint-efi=hd1,gpt1 --hint-baremetal=ahci1,gpt1  b4fbf4f8-303c-49bd-a52f-6049e1623a26
   else
     search --no-floppy --fs-uuid --set=root b4fbf4f8-303c-49bd-a52f-6049e1623a26
   fi
   echo    'Loading Linux core repo kernel ...'
   linux   /boot/vmlinuz-linux root=UUID=d44f2a2f-c369-456b-81f1-efa13f9caae2 ro  quiet
   echo    'Loading initial ramdisk ...'
   initrd  /boot/initramfs-linux.img
}
menuentry 'Arch GNU/Linux, with Linux core repo kernel (Fallback initramfs)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-core repo kernel-fallback-d44f2a2f-c369-456b-81f1-efa13f9caae2' {
   load_video
   set gfxpayload=keep
   insmod gzio
   insmod part_gpt
   insmod ext2
   set root='hd1,gpt1'
   if [ x$feature_platform_search_hint = xy ]; then
     search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt1 --hint-efi=hd1,gpt1 --hint-baremetal=ahci1,gpt1  b4fbf4f8-303c-49bd-a52f-6049e1623a26
   else
     search --no-floppy --fs-uuid --set=root b4fbf4f8-303c-49bd-a52f-6049e1623a26
   fi
   echo    'Loading Linux core repo kernel ...'
   linux   /boot/vmlinuz-linux root=UUID=d44f2a2f-c369-456b-81f1-efa13f9caae2 ro  quiet
   echo    'Loading initial ramdisk ...'
   initrd  /boot/initramfs-linux-fallback.img
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/20_memtest86+ ###
menuentry "Memory test (memtest86+)" --class memtest86 --class gnu --class tool {
 insmod part_gpt
 insmod ext2
 set root='hd1,gpt1'
 if [ x$feature_platform_search_hint = xy ]; then
   search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt1 --hint-efi=hd1,gpt1 --hint-baremetal=ahci1,gpt1  b4fbf4f8-303c-49bd-a52f-6049e1623a26
 else
   search --no-floppy --fs-uuid --set=root b4fbf4f8-303c-49bd-a52f-6049e1623a26
 fi
 linux16 ($root)/boot/memtest86+/memtest.bin
}
### END /etc/grub.d/20_memtest86+ ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
 source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
 source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###

更新

昨晚安裝 LILO 後,電腦至少啟動了一次。今天早上啟動電腦時,我遇到了核心恐慌:

Initramfs unpacking failed: junk in compressed archive
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,1)
Pid: 1, comm: swapper/0 Not tainted 3.8.7-1-ARCH #1
Call Trace:
...

是核心恐慌的圖片。

更新 2

我重新安裝了 LILO,並且在啟動時不再收到核心崩潰。

更新2:

忘了你貼了焦油球。太糟糕了。無論如何,.mod使用以下程式碼對您的文件進行了測試,並且:

./grum_lic_test32 evan_teitelman/boot/grub/i386-pc/*.mod

這產生了以下錯誤:

...
bufio.mod                 License: LICENSE=GPLv3+            OK
cacheinfo.mod             License: LICENSE=NONE_FOUND        ERR
cat.mod                   License: LICENSE=GPLv3+            OK
chain.mod                 License: LICENSE=GPLv3+            OK
...

但該文件與 Archlinux 下載的文件相同,因此應該不是問題。換句話說,不是原因。

另外,現在首先,請注意您已經安裝了 LILO,並且猜測該案例已關閉。如果不是,總是有關於 GPT 和 BIOS + 其他問題的問題。你是第一次安裝嗎?可能是在第一次安裝時涉及一些調整,重新安裝 GRUB 沒有修復。


***更新1:***好的。固定的。應該適用於 32 位和 64 位ELF


GRUB進入載入模組的階段時,它會檢查ELF每個模組的文件中嵌入的許可證。如果發現無效,則忽略該模組 - 並列印該特定錯誤。可能是一個或多個模組損壞。

如果它是一個必不可少的模組,那麼一切都會變糟。說例如part_gpt.modpart_msdos.mod

接受的許可證是GPLv2+和。GPLv3``GPLv3+

當然也可能是其他原因;但其中之一可能是損壞的模組文件。

模組似乎是有效ELF文件,因為它們在許可證測試之前已經過驗證。如:如果ELF測試失敗,則不執行許可證測試。

我需要檢查各種模組的另一個問題,提取了該程式碼的一部分並將其製成快速許可證測試器。您可以測試每個*.mod文件/boot/grub/*以查看哪些文件已損壞。

此程式碼不會驗證ELF或其他任何內容。僅嘗試找到許可證字元串並進行檢查。此外,它僅在 i386/32 位下進行測試。從中提取它的原始程式碼也適用於 x86-64 - 但這裡有很多被剝離和破解,所以我不確定結果。如果它在 64 位下不起作用,它很可能只列印License: LICENSE=NONE_FOUND.

(如上面編輯中所述,我現在已經測試了 32 位和 64 位英特爾。)

作為一個單獨的測試,然後將執行以下操作:

xxd file.mod | grep -C1 LIC

不是最漂亮的程式碼——但作為一種快速而骯髒的檢查。

(如;你可以試試。

編譯指令例如:

gcc -o grub_lic_test32 source.c         # 32-bit variant
gcc -o grub_lic_test64 source.c -DELF64 # 64-bit variant

跑:

./grub_lic_test32 /path/to/mods/*.mod

列印每個文件和許可證,例如:

./grub_lic_test32 tar.mod gettext.mod pxe.mod
tar.mod                   License: LICENSE=GPLv1+            BAD
gettext.mod               License: LICENSE=GPLv3+            OK
pxe.mod                   License: LICENSE=GPLv3+            OK

程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>

#ifdef ELF64
struct ELF_hdr
{
   unsigned char dummy0[16];
   uint32_t dummy1[6];
   uint64_t sh_off;
   uint16_t dummy2[5];
   uint16_t sh_entsize;
   uint16_t sh_num;
   uint16_t sh_strndx;
};
struct ELF_sect_hdr
{
   uint32_t sh_name;
   uint32_t dummy0[5];
   uint64_t sh_offset;
};
#else
struct ELF_hdr
{
   unsigned char dummy0[16];
   uint32_t dummy1[4];
   uint32_t sh_off;
   uint16_t dummy2[5];
   uint16_t sh_entsize;
   uint16_t sh_num;
   uint16_t sh_strndx;
};
struct ELF_sect_hdr
{
   uint32_t sh_name;
   uint32_t dummy[3];
   uint32_t sh_offset;
};
#endif

enum {
   ERR_FILE_OPEN = 1,
   ERR_FILE_READ,
   ERR_MEM,
   ERR_BAD_LICENSE,
   ERR_ELF_SECT_CORE_BREACH
};

int file_size(FILE *fh, size_t *fs)
{
   size_t cp;

   cp = ftell(fh);
   fseek(fh, 0, SEEK_END);
   *fs = ftell(fh);
   fseek(fh, cp, SEEK_SET);

   return 0;
}

static const char *valid_licenses[] = {
   "LICENSE=GPLv2+",
   "LICENSE=GPLv3",
   "LICENSE=GPLv3+",
   NULL
};

int grub_check_license(struct ELF_hdr *e)
{
   struct ELF_sect_hdr *s;
   const char *txt;
   const char *lic;
   unsigned i, j = 0;

   s = (struct ELF_sect_hdr *)
       ((char *) e + e->sh_off + e->sh_strndx * e->sh_entsize);

   txt = (char *) e + s->sh_offset;

   s = (struct ELF_sect_hdr *) ((char *) e + e->sh_off);

   for (i = 0; i < e->sh_num; ++i) {
       if (strcmp (txt + s->sh_name, ".module_license") == 0) {
           lic = (char*) e + s->sh_offset;

           if (j)
               fprintf(stdout, "%25s", "");
           fprintf(stdout, "License: %-25s ", lic);

           for (j = 0; valid_licenses[j]; ++j) {
               if (!strcmp (lic, valid_licenses[j])) {
                   fprintf(stdout, "OK\n");
                   return 0;
               }
           }
           fprintf(stdout, "BAD\n");
       }
       s = (struct ELF_sect_hdr *) ((char *) s + e->sh_entsize);
   }

   if (!j)
       fprintf(stdout, "License: %-25s ERR\n", "LICENSE=NONE_FOUND");

   return ERR_BAD_LICENSE;
}

int grub_check_module(void *buf, size_t size, int verbose)
{
   struct ELF_hdr *e = buf;

   /* Make sure that every section is within the core.  */
   if (e->sh_off + e->sh_entsize * e->sh_num > size) {
       fprintf(stderr, "ERR: Sections outside core\n");
       if (verbose)
           fprintf(stderr,
               "  %*s: %u bytes\n"
#ifdef ELF64
               "  %*s  %u < %llu\n"
               "  %*s: %llu\n"
#else
               "  %*s  %u < %u\n"
               "  %*s: %u\n"
#endif
               "  %*s: %u\n"
               "  %*s: %u\n"
               ,
               -25, "file-size", size,
               -25, "",
               size, e->sh_off + e->sh_entsize * e->sh_num,
               -25, "sector header offset", e->sh_off,
               -25, "sector header entry size", e->sh_entsize,
               -25, "sector header num", e->sh_num
           );
       return ERR_ELF_SECT_CORE_BREACH;
   }

   return grub_check_license(e);
}

int grub_check_module_file(const char *fn, int verbose)
{
   FILE *fh;
   void *buf;
   size_t fs;
   int eno;
   char *base_fn;

   if (!(base_fn = strrchr(fn, '/')))
       base_fn = (char*)fn;
   else
       ++base_fn;

   fprintf(stderr, "%-25s ", base_fn);

   if (!(fh = fopen(fn, "rb"))) {
       fprintf(stderr, "ERR: Unable to open `%s'\n", fn);
       perror("fopen");
       return ERR_FILE_OPEN;
   }
   file_size(fh, &fs);
   if (!(buf = malloc(fs))) {
       fprintf(stderr, "ERR: Memory.\n");
       fclose(fh);
       return ERR_MEM;
   }
   if (fread(buf, 1, fs, fh) != fs) {
       fprintf(stderr, "ERR: Reading `%s'\n", fn);
       perror("fread");
       free(buf);
       fclose(fh);
       return ERR_FILE_READ;
   }
   fclose(fh);

   eno = grub_check_module(buf, fs, verbose);
   free(buf);

   return eno;
}


int main(int argc, char *argv[])
{
   int i = 1;
   int eno = 0;
   int verbose = 0;

   if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'v') {
       verbose = 1;
       ++i;
   }

   if (argc - i < 1) {
       fprintf(stderr, "Usage: %s [-v] <FILE>[, FILE[, ...]]\n", argv[0]);
       return 1;
   }


   for (; i < argc; ++i) {
       eno |= grub_check_module_file(argv[i], verbose);
       if (eno == ERR_MEM)
           return eno;
   }

   return eno;
}

引用自:https://unix.stackexchange.com/questions/74087