Written by: Helio Loureiro
Category: Linux
Hits: 7478

Eu gosto de usar os kernels mais recentes e compilar minhas próprias versões.  Às vezes adiciono patches pra melhorar resposta de temporeal, às vezes um suporte pra AUFS no docker.

Atualmente estou com o 4.14-rc2, um pouco antigo nesse momento mas que me deu um uptime de 25 dias sem problemas até agora.

Linux elxaf7qtt32 4.14.0-rc2-helio #12 SMP PREEMPT Fri Sep 29 13:50:19 CEST 2017 x86_64 x86_64 x86_64 OSI/Linux

(é... troquei GNU/Linux por OSI/Linux... por diversão e usando sed na saída do uname)

E descobri que o VirtualBox versão 5.2 simplesmente não consegue rodar o comando /sbin/vboxconfig.  Olhando o erro um pouco mais de perto pelo log:

 

  gcc -Wp,-MD,/tmp/vbox.0/linux/.SUPR0IdcClient-linux.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -
I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototyp
es -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -
mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -
DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG
_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -O2 --param=allow-
store-data-races=0 -DCC_HAVE_ASM_GOTO -Wframe-larger-than=1024 -fstack-protector-strong -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracki
ng-assignments -g -gdwarf-4 -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-pro
totypes -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -include /tmp/vbox.0/include/VBox/SUPDrvMangling.h -fno-pie -I/lib/modules/4.14.0-rc2-helio/build/i
nclude -I/tmp/vbox.0/ -I/tmp/vbox.0/include -I/tmp/vbox.0/r0drv/linux -D__KERNEL__ -DMODULE -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 -DIN_SUP_R0 -DVBOX -DRT_WITH_VBOX -DVBOX_WITH_HARDENING 
-Wno-declaration-after-statement -DRT_ARCH_AMD64 -DVBOX_WITH_64_BITS_GUESTS  -DMODULE  -DKBUILD_BASENAME='"SUPR0IdcClient_linux"'  -DKBUILD_MODNAME='"vboxnetflt"' -c -o /tmp/vbox.0/lin
ux/.tmp_SUPR0IdcClient-linux.o /tmp/vbox.0/linux/SUPR0IdcClient-linux.c
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/SUPR0IdcClient.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/SUPR0IdcClient.o"; fi; fi;
(cat /dev/null;   echo kernel//tmp/vbox.0/vboxnetflt.ko;) > /tmp/vbox.0/modules.order
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/linux/SUPR0IdcClient-linux.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/linux/SUPR0IdcClient-linux.o"; fi; fi;
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/VBoxNetFlt.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/VBoxNetFlt.o"; fi; fi;
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxSkBufFromSG’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:741:24: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
             fGsoType = SKB_GSO_UDP;
                        ^
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:741:24: note: each undeclared identifier is reported only once for each function it appears in
In file included from /tmp/vbox.0/include/iprt/types.h:29:0,
                 from /tmp/vbox.0/r0drv/linux/the-linux-kernel.h:34,
                 from /tmp/vbox.0/linux/VBoxNetFlt-linux.c:24:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxCanForwardAsGso’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:1276:53: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
     if (RT_UNLIKELY( skb_shinfo(pSkb)->gso_type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCPV6 | SKB_GSO_TCPV4) ))
                                                     ^
/tmp/vbox.0/include/iprt/cdefs.h:1616:53: note: in definition of macro ‘RT_UNLIKELY’
 #  define RT_UNLIKELY(expr)     __builtin_expect(!!(expr), 0)
                                                     ^
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxForwardToIntNetInner’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:1526:47: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
         if (   (skb_shinfo(pBuf)->gso_type & (SKB_GSO_UDP | SKB_GSO_TCPV6 | SKB_GSO_TCPV4))
                                               ^
scripts/Makefile.build:311: recipe for target '/tmp/vbox.0/linux/VBoxNetFlt-linux.o' failed
make[2]: *** [/tmp/vbox.0/linux/VBoxNetFlt-linux.o] Error 1
Makefile:1498: recipe for target '_module_/tmp/vbox.0' failed
make[1]: *** [_module_/tmp/vbox.0] Error 2
/tmp/vbox.0/Makefile.include.footer:97: recipe for target 'vboxnetflt' failed

Foi algo relacionado com a variável SKB_GSO_UDP, que parece não existir no kernel mais recente ou no VirtualBox.

Buscando pelo termo pude encontrar que realmente existe uma diferença entre ambos um patch precisa ser aplicado, descrito aqui:

Fonte: https://gist.github.com/herbmillerjr/039c129e9c25b047b906e19ad1f23a59

diff --git a/work/vboxnetflt/linux/VBoxNetFlt-linux.c b/work/vboxnetflt/linux/VBoxNetFlt-linux.c
index f824654..b61d82c 100644
--- work/vboxnetflt/linux/VBoxNetFlt-linux.c
+++ work/vboxnetflt/linux/VBoxNetFlt-linux.c
@@ -126,6 +126,10 @@ typedef struct VBOXNETFLTNOTIFIER *PVBOXNETFLTNOTIFIER;
 # endif
 #endif

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+#define SKB_GSO_UDP 0
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
 # define VBOX_HAVE_SKB_VLAN
 #else
diff --git a/work/vboxpci/linux/VBoxPci-linux.c b/work/vboxpci/linux/VBoxPci-linux.c
index 2dbf47f..e361ef3 100644
--- work/vboxpci/linux/VBoxPci-linux.c
+++ work/vboxpci/linux/VBoxPci-linux.c
@@ -353,12 +353,16 @@ static void  vboxPciFileClose(struct file* file)
 static int vboxPciFileWrite(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size)
 {
     int          ret;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+    ret = kernel_write(file, data, size, &offset);
+#else
     mm_segment_t fs_save;

     fs_save = get_fs();
     set_fs(get_ds());
     ret = vfs_write(file, data, size, &offset);
     set_fs(fs_save);
+#endif
     if (ret < 0)
         printk(KERN_DEBUG "vboxPciFileWrite: error %d\n", ret);

Mas como minha versão de VirtualBox não era exatamente a mesma que essa descrita, acabei fazendo o patch manualmente, que adiciona a variável SKB_GSO_UDP ao VirtualBox caso seja um kernel 4.14.0 ou superior.  Os arquivos para serem modificados no Ubuntu (e possivelmente Debian) são:

depois basta rodar novamente como root o comando /sbin/vboxconfig para criar os módulos de kernel necessários pro funcionamento do VirtualBox.

SKB_GSO_UDP

SKB: SocKet Buffer

GSO: Generic Segmentation Offloading

UDP: User Datagram Protocol

Não tenho idéia do que isso faz exatamente mas parece ser uma chamada de um pacote UDP encapsulado.