#18945 closed defect (fixed)
Linux 5.4: no more arbitrary executable pages and more changes
Reported by: | Frank Batschulat (Oracle) | Owned by: | Frank Batschulat (Oracle) |
---|---|---|---|
Component: | host support | Version: | VirtualBox 6.0.12 |
Keywords: | linux54 exec page | Cc: | |
Guest type: | other | Host type: | Linux |
Description
It was kindly pointed out that the Linux 5.4 kernel will no longer make interfaces available so that arbitrary kernel modules may modify page attributes to turn the executable bit on/off. Virtualbox currently is one of such kernel modules doing that.
From: "Larry Finger" <Larry.Finger@xxxxxxxx> To: vbox-dev@virtualbox.org Subject: [vbox-dev] Problem with kernel 5.4 Date: Wed, 18 Sep 2019 21:16:12 +0200 In kernel 5.4, the wrapper routines set_pages_x() and set_pages_nx() that enable/disable execution of memory are removed. The underlying routines set_memory_x() and set_memory_nx() are not, and will not be exported. See [http://lkml.iu.edu/hypermail/linux/kernel/1909.2/02763.html] for a discussion of the issue. I have currently disabled the only calls to these routines, which occur in alloc-r0drv-linux.c. My test VMs appear to work OK. Is there some case where allocated pages really need to be executable? If so, then the developers at Oracle will need to consult with Linus to develop a method that will be acceptable. In the meantime, I have developed a patch that allows a build with kernel 5.4 that eliminates the offending calls. Larry
https://www.virtualbox.org/pipermail/vbox-dev/2019-September/015343.html
http://lkml.iu.edu/hypermail/linux/kernel/1909.2/02763.html
http://lkml.iu.edu/hypermail/linux/kernel/1909.2/02837.html
Lets see where and how we get that:
trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
339 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) 340 # define MY_SET_PAGES_EXEC(pPages, cPages) set_pages_x(pPages, cPages) 341 # define MY_SET_PAGES_NOEXEC(pPages, cPages) set_pages_nx(pPages, cPages) 342 #else 343 # define MY_SET_PAGES_EXEC(pPages, cPages) \ 344 do { \ 345 if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \ 346 MY_CHANGE_PAGE_ATTR(pPages, cPages, MY_PAGE_KERNEL_EXEC); \ 347 } while (0) 348 # define MY_SET_PAGES_NOEXEC(pPages, cPages) \ 349 do { \ 350 if (pgprot_val(MY_PAGE_KERNEL_EXEC) != pgprot_val(PAGE_KERNEL)) \ 351 MY_CHANGE_PAGE_ATTR(pPages, cPages, PAGE_KERNEL); \ 352 } while (0) 353 #endif
C symbol: MY_SET_PAGES_EXEC
File Function Line 0 the-linux-kernel.h <global> 340 #define MY_SET_PAGES_EXEC(pPages, cPages) set_pages_x(pPages, cPages) 1 the-linux-kernel.h <global> 343 #define MY_SET_PAGES_EXEC(pPages, cPages) \ 2 alloc-r0drv-linux.c RTMemContAlloc 447 MY_SET_PAGES_EXEC(&paPages[iPage], 1); 3 memobj-r0drv-linux.c rtR0MemObjLinuxAllocPages 374 MY_SET_PAGES_EXEC(pMemLnx->apPages[iPage], 1);
trunk/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
385 * Allocates physical contiguous memory (below 4GB). 386 * The allocation is page aligned and the content is undefined. 387 * 388 * @returns Pointer to the memory block. This is page aligned. 389 * @param pPhys Where to store the physical address. 390 * @param cb The allocation size in bytes. This is always 391 * rounded up to PAGE_SIZE. 392 */ 393 RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) [...] 428 * Reserve the pages and mark them executable. 429 */ 430 unsigned iPage; 431 for (iPage = 0; iPage < cPages; iPage++) [...] 445 SetPageReserved(&paPages[iPage]); 446 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 20) /** @todo find the exact kernel where change_page_attr was introdu ced. */ 447 MY_SET_PAGES_EXEC(&paPages[iPage], 1); 448 #endif 449 }
trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
282 * Internal worker that allocates physical pages and creates the memory object for them. 283 * 284 * @returns IPRT status code. 285 * @param ppMemLnx Where to store the memory object pointer. 286 * @param enmType The object type. 287 * @param cb The number of bytes to allocate. 288 * @param uAlignment The alignment of the physical memory. 289 * Only valid if fContiguous == true, ignored otherwise. 290 * @param fFlagsLnx The page allocation flags (GPFs). 291 * @param fContiguous Whether the allocation must be contiguous. 292 * @param rcNoMem What to return when we're out of pages. 293 */ 294 static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE enmType, size_t cb, 295 size_t uAlignment, gfp_t fFlagsLnx, bool fContiguous, int rcNoMem) 296 { [...] 323 * Allocate the pages. 324 * For small allocations we'll try contiguous first and then fall back on page by page. 325 */ 326 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22) 327 if ( fContiguous 328 || cb <= PAGE_SIZE * 2) 329 { [...] 363 #else /* < 2.4.22 */ 364 /** @todo figure out why we didn't allocate page-by-page on 2.4.21 and older... */ 365 paPages = alloc_pages(fFlagsLnx, rtR0MemObjLinuxOrder(cPages)); 366 if (!paPages) 367 { 368 rtR0MemObjDelete(&pMemLnx->Core); 369 return rcNoMem; 370 } 371 for (iPage = 0; iPage < cPages; iPage++) 372 { 373 pMemLnx->apPages[iPage] = &paPages[iPage]; 374 MY_SET_PAGES_EXEC(pMemLnx->apPages[iPage], 1); 375 if (PageHighMem(pMemLnx->apPages[iPage])) 376 BUG(); 377 } 378 379 fContiguous = true; 380 #endif /* < 2.4.22 */
I'll investigate why we'd possibly think we need this anyways and seek to remove that code.
Attachments (1)
Change History (21)
comment:1 by , 5 years ago
Keywords: | linux54 exec page added |
---|---|
Owner: | set to |
Status: | new → accepted |
comment:3 by , 5 years ago
3) DRIVER_PRIME
/home/ws/vb54/trunk/out/linux.amd64/debug/obj/tstvboxvideo-src_mod/vbox_drv.c:308:6: error: ‘DRIVER_PRIME’ undeclared here (not in a function); did you mean ‘DRIVER_NAME’? 308 | DRIVER_PRIME, | ^~~~~~~~~~~~ | DRIVER_NAME
Format of Module.symvers has changed adding extra tab and namespace the symbol is in if any. [1] Per file build flags now must include the path to the file instead of just the filename. [2] DRIVER_PRIME flag is dropped as redundant. [3]
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cb9b55d21fe06ca5e4ba244bb5aac0afeb745c8e
[2]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54b8ae66ae1a3454a7645d159a482c31cd89ab33
[3]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ee8375d5dc5bbb50b03bedfb0020d3e1c27ceacb
comment:4 by , 5 years ago
4) struct ttm_buffer_object, member vma_node moved:
[PATCH 5/6] drm/ttm: use gem vma_node https://lists.gt.net/linux/kernel/3353093
/home/ws/vb54/trunk/out/linux.amd64/debug/obj/tstvboxvideo-src_mod/vbox_main.c: In function ‘vbox_bo_mmap_offset’: /home/ws/vb54/trunk/out/linux.amd64/debug/obj/tstvboxvideo-src_mod/vbox_main.c:622:41: error: ‘struct ttm_buffer_object’ has no member named ‘vma_node’ 622 | return drm_vma_node_offset_addr(&bo->bo.vma_node); | ^ /home/ws/vb54/trunk/out/linux.amd64/debug/obj/tstvboxvideo-src_mod/vbox_main.c:624:1: error: control reaches end of non-void function [-Werror=return-type] 624 | } | ^
In kernel 5.4.rc1 the structure member vma_node formerly in truct ttm_buffer_object:
https://elixir.bootlin.com/linux/v5.3.5/source/include/drm/ttm/ttm_bo_api.h
moved to a new structure:
https://elixir.bootlin.com/linux/v5.4-rc1/source/include/drm/ttm/ttm_bo_api.h
struct ttm_buffer_object { struct drm_gem_object base;
in:
https://elixir.bootlin.com/linux/v5.4-rc1/source/include/drm/drm_gem.h#L171
struct drm_gem_object { [...] struct drm_vma_offset_node vma_node;
so we need to change the line to be instead:
trunk/src/VBox/Additions/linux/drm/vbox_main.c
--- return drm_vma_node_offset_addr(&bo->bo.vma_node); +++ return drm_vma_node_offset_addr(&bo->bo.base.vma_node);
comment:5 by , 5 years ago
These are the current changes I have UNIT tested right now against:
https://git.kernel.org/torvalds/t/linux-5.4-rc2.tar.gz
VBox/Trunk fbatschu@lserver trunk $ svn status M src/VBox/Additions/linux/drm/vbox_drv.c M src/VBox/Additions/linux/drm/vbox_main.c M src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c M src/VBox/Runtime/r0drv/linux/the-linux-kernel.h M src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c
VBox/Trunk fbatschu@lserver trunk $ svn diff Index: src/VBox/Additions/linux/drm/vbox_drv.c =================================================================== --- src/VBox/Additions/linux/drm/vbox_drv.c (revision 133811) +++ src/VBox/Additions/linux/drm/vbox_drv.c (working copy) @@ -305,12 +305,16 @@ } static struct drm_driver driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && !defined(RHEL_81) +# if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && !defined(RHEL_81) DRIVER_IRQ_SHARED | -#endif +# endif DRIVER_PRIME, +#else /* >= KERNEL_VERSION(5, 4, 0) */ + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ, +#endif /* < KERNEL_VERSION(5, 4, 0) */ .dev_priv_size = 0, #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) Index: src/VBox/Additions/linux/drm/vbox_main.c =================================================================== --- src/VBox/Additions/linux/drm/vbox_main.c (revision 133811) +++ src/VBox/Additions/linux/drm/vbox_main.c (working copy) @@ -621,7 +621,9 @@ static inline u64 vbox_bo_mmap_offset(struct vbox_bo *bo) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_70) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + return drm_vma_node_offset_addr(&bo->bo.base.vma_node); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_70) return bo->bo.addr_space_offset; #else return drm_vma_node_offset_addr(&bo->bo.vma_node); Index: src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c =================================================================== --- src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c (revision 133811) +++ src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c (working copy) @@ -924,8 +924,13 @@ for (i = 0; i < skb_shinfo(pBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pBuf)->frags[i]; +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + pSG->aSegs[iSeg].cb = pFrag->bv_len; + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; +# else /* < KERNEL_VERSION(5, 4, 0) */ pSG->aSegs[iSeg].cb = pFrag->size; pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; +# endif /* >= KERNEL_VERSION(5, 4, 0) */ Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); @@ -940,8 +945,13 @@ for (i = 0; i < skb_shinfo(pFragBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pFragBuf)->frags[i]; +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + pSG->aSegs[iSeg].cb = pFrag->bv_len; + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; +# else /* < KERNEL_VERSION(5, 4, 0) */ pSG->aSegs[iSeg].cb = pFrag->size; pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; +# endif /* >= KERNEL_VERSION(5, 4, 0) */ Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); Index: src/VBox/Runtime/r0drv/linux/the-linux-kernel.h =================================================================== --- src/VBox/Runtime/r0drv/linux/the-linux-kernel.h (revision 133811) +++ src/VBox/Runtime/r0drv/linux/the-linux-kernel.h (working copy) @@ -336,7 +336,11 @@ # endif #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +/* XXX The 5.4 kernel has no interface anymore to make kernel pages execcutable */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +# define MY_SET_PAGES_EXEC(pPages, cPages) do {} while (0) +# define MY_SET_PAGES_NOEXEC(pPages, cPages) do {} while (0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) # define MY_SET_PAGES_EXEC(pPages, cPages) set_pages_x(pPages, cPages) # define MY_SET_PAGES_NOEXEC(pPages, cPages) set_pages_nx(pPages, cPages) #else Index: src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c =================================================================== --- src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c (revision 133811) +++ src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c (working copy) @@ -36,6 +36,9 @@ #include <iprt/errcore.h> #include "internal/thread.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + #include <uapi/linux/sched/types.h> +#endif RTDECL(RTTHREAD) RTThreadSelf(void) {
The following config has been UNIT tested with these changes:
### Guest:
OpenSuse 15.1
Linux linux-hzpw 4.12.14-lp151.28.16-default #1 SMP Wed Sep 18 05:32:19 UTC 2019 (3e458e0) x86_64 x86_64 x86_64 GNU/Linux
### Guest Winows 10_1903_V1
### Host:
Fedora Rawhide/32
Linux lserver 5.4.0-0.rc2.git1.1.fc32.x86_64 #1 SMP Tue Oct 8 17:04:36 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
VirtualBox VM 6.1.0_BETA1 r133811 linux.amd64 (Oct 10 2019 09:49:04) release log
Oracle VM VirtualBox Extension Pack (Version: 6.1.0_BETA1 r133811; VRDE Module: VBoxVRDP)
Oracle VBoxDTrace Extension Pack (Version: 6.1.0_BETA1 r133811; VRDE Module: )
the above cited changes applied to this trunk state.
comment:6 by , 5 years ago
Summary: | Linux 5.4: no more arbitrary executable pages → Linux 5.4: no more arbitrary executable pages and more changes |
---|
comment:7 by , 5 years ago
On Fri, 18 Oct 2019 18:12:32 +0200, Larry Finger <> wrote:
Kernel 5.4.0-rc3 introduced a new incompatibility in that a new statement "fallthrough" was created. This change broke the fall through definitions used in VB. The following single line change fixes the problem:
Index: VirtualBox-6.0.12/include/iprt/cdefs.h =================================================================== --- VirtualBox-6.0.12.orig/include/iprt/cdefs.h +++ VirtualBox-6.0.12/include/iprt/cdefs.h @@ -1166,7 +1166,7 @@ * Tell the compiler that we're falling through to the next case in a switch. * @sa RT_FALL_THRU */ #if RT_GNUC_PREREQ(7, 0) -# define RT_FALL_THROUGH() __attribute__((fallthrough)) +# define RT_FALL_THROUGH() __attribute__((__fallthrough__)) #else # define RT_FALL_THROUGH() (void)0 #endif
Larry
comment:8 by , 5 years ago
5) fallthrough statement change in kernel version 5.4-rc3
This has been introduced with:
Linux 5.4-rc3 https://lkml.org/lkml/2019/10/13/174
Joe Perches (3): net: sctp: Rename fallthrough label to unhandled compiler_attributes.h: Add 'fallthrough' pseudo keyword for switch/case use Documentation/process: Add fallthrough pseudo-keyword
https://github.com/torvalds/linux/commit/b9918bdcac1ff7bf11f1ab64708267c73f9b2552
https://lkml.org/lkml/2019/10/5/178
https://lkml.org/lkml/2019/10/5/181
https://lore.kernel.org/patchwork/patch/1135570/
https://lwn.net/Articles/794944/
### past baackround from kernel 5.2 days:
https://www.phoronix.com/scan.php?page=news_item&px=Kernel-Wimplicit-fallthrough
### this pull request for Linux 5.2-rc1 that is marking more switch-fallthroughs as expected.
http://lkml.iu.edu/hypermail/linux/kernel/1905.0/04622.html
### Compiler Attributes: add support for fallthrough (gcc >= 7.1)
https://github.com/ojeda/linux/commit/668f011a2706ea555987e263f609a5deba9c7fc4
https://lkml.org/lkml/2018/10/21/150
"In C mode, GCC supports the fallthrough attribute since 7.1,"
https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/error=login_required&state=8ab39b36-33d7-4552-9d4a-40d0c2143376
https://gcc.gnu.org/gcc-7/changes.html
https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html
https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax
"You may optionally specify attribute names with "__"
preceding and following the name. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use the attribute name noreturn instead of noreturn."
comment:9 by , 5 years ago
the actual compiler errors against 5.4-rc3 related to the fallthrough change look like this:
kBuild: Linking VBoxOGLTest kBuild: Generating /home/ws/vb/trunk/out/linux.amd64/debug/obj/webservice/vboxwebsrv.nsmap In file included from ././include/linux/compiler_types.h:59:0, from <command-line>:0: /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/VBoxGuestR0LibHGCMInternal.c: In function ‘vbglR0HGCMInternalPreprocessCall’: ./include/linux/compiler_attributes.h:200:41: error: expected ‘)’ before ‘__attribute__’ # define fallthrough __attribute__((__fallthrough__)) ^ /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/include/iprt/cdefs.h:1173:48: note: in expansion of macro ‘fallthrough’ # define RT_FALL_THROUGH() __attribute__((fallthrough)) ^~~~~~~~~~~ /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/include/iprt/cdefs.h:1180:33: note: in expansion of macro ‘RT_FALL_THROUGH’ #define RT_FALL_THRU() RT_FALL_THROUGH() ^~~~~~~~~~~~~~~ ...and so on and so on... In file included from /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/include/internal/iprt.h:33:0, from /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/combined-agnostic.c:28: /home/ws/vb/trunk/out/linux.amd64/debug/obj/tstvboxguest-src_mod/include/iprt/cdefs.h:1173:60: error: expected identifier or ‘(’ before ‘)’ token # define RT_FALL_THROUGH() __attribute__((fallthrough)) ... ^
comment:10 by , 5 years ago
diffs for the fallthrough issue:
Index: include/iprt/cdefs.h =================================================================== --- include/iprt/cdefs.h (revision 134159) +++ include/iprt/cdefs.h (working copy) @@ -1170,7 +1170,7 @@ * Tell the compiler that we're falling through to the next case in a switch. * @sa RT_FALL_THRU */ #if RT_GNUC_PREREQ(7, 0) -# define RT_FALL_THROUGH() __attribute__((fallthrough)) +# define RT_FALL_THROUGH() __attribute__((__fallthrough__)) #else # define RT_FALL_THROUGH() (void)0 #endif
comment:11 by , 5 years ago
all the changes have been successfully run against the 5.4-rc4 kernel release:
comment:12 by , 5 years ago
The falltrhough changes uncovered another minor nit we're going to fix along with this chanegset:
kBuild: Compiling VBoxRT - /home/ws/vbtrunk/trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp In file included from /home/ws/vbtrunk/trunk/include/iprt/fsvfs.h:32, from /home/ws/vbtrunk/trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp:32: /home/ws/vbtrunk/trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp: In function ‘int rtFsNtfsAttr_ParseExtents(PRTFSNTFSATTR, PRTFSNTFSEXTENTS, uint8_t, int64_t, uint64_t, PRTERRINFO, uint64_t, uint32_t)’: /home/ws/vbtrunk/trunk/include/iprt/cdefs.h:1161:33: warning: attribute ‘fallthrough’ not preceding a case label or default label 1161 | # define RT_FALL_THROUGH() __attribute__((__fallthrough__)) | ^~~~~~~~~~~~~ /home/ws/vbtrunk/trunk/include/iprt/cdefs.h:1168:33: note: in expansion of macro ‘RT_FALL_THROUGH’ 1168 | #define RT_FALL_THRU() RT_FALL_THROUGH() | ^~~~~~~~~~~~~~~ /home/ws/vbtrunk/trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp:1055:86: note: in expansion of macro ‘RT_FALL_THRU’ 1055 | case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; RT_FALL_THRU(); | ^~~~~~~~~~~~
trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp
1046 switch (cbRunField) 1047 { 1048 case 8: cClustersInRun |= (uint64_t)pbPairs[offPairs + 7] << 56; RT_FALL_THRU(); 1049 case 7: cClustersInRun |= (uint64_t)pbPairs[offPairs + 6] << 48; RT_FALL_THRU(); 1050 case 6: cClustersInRun |= (uint64_t)pbPairs[offPairs + 5] << 40; RT_FALL_THRU(); 1051 case 5: cClustersInRun |= (uint64_t)pbPairs[offPairs + 4] << 32; RT_FALL_THRU(); 1052 case 4: cClustersInRun |= (uint32_t)pbPairs[offPairs + 3] << 24; RT_FALL_THRU(); 1053 case 3: cClustersInRun |= (uint32_t)pbPairs[offPairs + 2] << 16; RT_FALL_THRU(); 1054 case 2: cClustersInRun |= (uint16_t)pbPairs[offPairs + 1] << 8; RT_FALL_THRU(); 1055 case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; RT_FALL_THRU(); 1056 }
with the diffs:
Index: trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp =================================================================== --- trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp (revision 134297) +++ trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp (working copy) @@ -1052,7 +1052,7 @@ case 4: cClustersInRun |= (uint32_t)pbPairs[offPairs + 3] << 24; RT_FALL_THRU(); case 3: cClustersInRun |= (uint32_t)pbPairs[offPairs + 2] << 16; RT_FALL_THRU(); case 2: cClustersInRun |= (uint16_t)pbPairs[offPairs + 1] << 8; RT_FALL_THRU(); - case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; RT_FALL_THRU(); + case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; } offPairs += cbRunField; AssertBreakStmt(cClustersInRun <= cMaxClustersInRun,
comment:13 by , 5 years ago
The part concerning the executable page setting has been fixed and taken care of by the following changes:
https://www.virtualbox.org/changeset/81587/vbox
https://www.virtualbox.org/changeset/81586/vbox
in trunk, r134333 and r134334 ,
The remaining 5.4 kernel and glibc fixes have been integrated into trunk with the changeset revision r134407 .
remaining diffs for this bug report:
trunk $ svn status M include/iprt/cdefs.h X kBuild M src/VBox/Additions/linux/drm/vbox_drv.c M src/VBox/Additions/linux/drm/vbox_main.c M src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c M src/VBox/Runtime/common/fs/ntfsvfs.cpp M src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c trunk $ svn diff Index: include/iprt/cdefs.h =================================================================== --- include/iprt/cdefs.h (revision 134405) +++ include/iprt/cdefs.h (working copy) @@ -1158,7 +1158,7 @@ * Tell the compiler that we're falling through to the next case in a switch. * @sa RT_FALL_THRU */ #if RT_GNUC_PREREQ(7, 0) -# define RT_FALL_THROUGH() __attribute__((fallthrough)) +# define RT_FALL_THROUGH() __attribute__((__fallthrough__)) #else # define RT_FALL_THROUGH() (void)0 #endif Index: src/VBox/Additions/linux/drm/vbox_drv.c =================================================================== --- src/VBox/Additions/linux/drm/vbox_drv.c (revision 134405) +++ src/VBox/Additions/linux/drm/vbox_drv.c (working copy) @@ -305,12 +305,16 @@ } static struct drm_driver driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && !defined(RHEL_81) +# if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && !defined(RHEL_81) DRIVER_IRQ_SHARED | -#endif +# endif /* < KERNEL_VERSION(5, 1, 0) && !defined(RHEL_81) */ DRIVER_PRIME, +#else /* >= KERNEL_VERSION(5, 4, 0) */ + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ, +#endif /* < KERNEL_VERSION(5, 4, 0) */ .dev_priv_size = 0, #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) Index: src/VBox/Additions/linux/drm/vbox_main.c =================================================================== --- src/VBox/Additions/linux/drm/vbox_main.c (revision 134405) +++ src/VBox/Additions/linux/drm/vbox_main.c (working copy) @@ -621,11 +621,13 @@ static inline u64 vbox_bo_mmap_offset(struct vbox_bo *bo) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_70) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + return drm_vma_node_offset_addr(&bo->bo.base.vma_node); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_70) return bo->bo.addr_space_offset; #else return drm_vma_node_offset_addr(&bo->bo.vma_node); -#endif +#endif /* >= KERNEL_VERSION(5, 4, 0) */ } int Index: src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c =================================================================== --- src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c (revision 134405) +++ src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c (working copy) @@ -924,8 +924,13 @@ for (i = 0; i < skb_shinfo(pBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pBuf)->frags[i]; +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + pSG->aSegs[iSeg].cb = pFrag->bv_len; + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; +# else /* < KERNEL_VERSION(5, 4, 0) */ pSG->aSegs[iSeg].cb = pFrag->size; pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; +# endif /* >= KERNEL_VERSION(5, 4, 0) */ Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); @@ -940,8 +945,13 @@ for (i = 0; i < skb_shinfo(pFragBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pFragBuf)->frags[i]; +# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + pSG->aSegs[iSeg].cb = pFrag->bv_len; + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; +# else /* < KERNEL_VERSION(5, 4, 0) */ pSG->aSegs[iSeg].cb = pFrag->size; pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; +# endif /* >= KERNEL_VERSION(5, 4, 0) */ Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); Index: src/VBox/Runtime/common/fs/ntfsvfs.cpp =================================================================== --- src/VBox/Runtime/common/fs/ntfsvfs.cpp (revision 134405) +++ src/VBox/Runtime/common/fs/ntfsvfs.cpp (working copy) @@ -1052,7 +1052,7 @@ case 4: cClustersInRun |= (uint32_t)pbPairs[offPairs + 3] << 24; RT_FALL_THRU(); case 3: cClustersInRun |= (uint32_t)pbPairs[offPairs + 2] << 16; RT_FALL_THRU(); case 2: cClustersInRun |= (uint16_t)pbPairs[offPairs + 1] << 8; RT_FALL_THRU(); - case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; RT_FALL_THRU(); + case 1: cClustersInRun |= (uint16_t)pbPairs[offPairs + 0] << 0; } offPairs += cbRunField; AssertBreakStmt(cClustersInRun <= cMaxClustersInRun, Index: src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c =================================================================== --- src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c (revision 134405) +++ src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c (working copy) @@ -36,6 +36,9 @@ #include <iprt/errcore.h> #include "internal/thread.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + #include <uapi/linux/sched/types.h> +#endif /* >= KERNEL_VERSION(4, 11, 0) */ RTDECL(RTTHREAD) RTThreadSelf(void) {
All 3 changeset have been verified against:
https://git.kernel.org/torvalds/t/linux-5.4-rc5.tar.gz
comment:14 by , 5 years ago
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
comment:15 by , 5 years ago
a new set of trunk (aka development release) builds have been produced an uploaded that contain the 5.4 changes mentioned above, section "Development snapshots"
https://www.virtualbox.org/wiki/Testbuilds
do not forgett the host and the guest both needs updating to the version.
comment:16 by , 5 years ago
All the mentioned 5.4 kernel changes above have been backported to
the 6.X branch as: r134337, r134335 and r134477.
and to the 5.2 branch as: r134341, r134336 and r134482.
Also they have been verified against:
https://git.kernel.org/torvalds/t/linux-5.4-rc6.tar.gz
comment:17 by , 5 years ago
I forgot to mention, that the changes for:
src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux
are required by 5.4-rc1 kernel revision, so a 5.4-rc0 kernel will fall over this changeset and needs upgrading to at least 5.4-rc1.
That chnage in Linux was:
[PATCH v3 0/7] Convert skb_frag_t to bio_vec
https://www.spinics.net/lists/netdev/msg585545.html
comment:18 by , 5 years ago
VirtualBox 6.1 Release Candidate 1 released
contains these fixes, refer to:
Linux host and guest: Support Linux 5.4 (bug #18945)
http://download.virtualbox.org/virtualbox/6.1.0_RC1
https://forums.virtualbox.org/viewtopic.php?f=15&t=95711&sid=c2076288e2e8b73544150a5687336462
comment:19 by , 5 years ago
I tried to install this on Ubuntu 18.04.3 running Linux 5.4.0 kernel and this is what I get:
$ sudo dpkg -i virtualbox-6.1_6.1.0_rc1-134891_Ubuntu_bionic_amd64.deb Selecting previously unselected package virtualbox-6.1. (Reading database ... 235409 files and directories currently installed.) Preparing to unpack virtualbox-6.1_6.1.0_rc1-134891_Ubuntu_bionic_amd64.deb ... Unpacking virtualbox-6.1 (6.1.0~rc1-134891~Ubuntu~bionic) ... Setting up virtualbox-6.1 (6.1.0~rc1-134891~Ubuntu~bionic) ... addgroup: The group `vboxusers' already exists as a system group. Exiting. vboxdrv.sh: failed: Look at /var/log/vbox-setup.log to find out what went wrong. There were problems setting up VirtualBox. To re-start the set-up process, run /sbin/vboxconfig as root. If your system is using EFI Secure Boot you may need to sign the kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load them. Please see your Linux system's documentation for more information. Processing triggers for systemd (237-3ubuntu10.33) ... Processing triggers for ureadahead (0.100.0-21) ... Processing triggers for desktop-file-utils (0.23-1ubuntu3.18.04.2) ... Processing triggers for gnome-menus (3.13.3-11ubuntu1.1) ... Processing triggers for mime-support (3.60ubuntu1) ... Processing triggers for hicolor-icon-theme (0.17-2) ... Processing triggers for shared-mime-info (1.9-2) ... $ sudo /sbin/vboxconfig vboxdrv.sh: Stopping VirtualBox services. vboxdrv.sh: Starting VirtualBox services. vboxdrv.sh: Building VirtualBox kernel modules. vboxdrv.sh: failed: Look at /var/log/vbox-setup.log to find out what went wrong. There were problems setting up VirtualBox. To re-start the set-up process, run /sbin/vboxconfig as root. If your system is using EFI Secure Boot you may need to sign the kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load them. Please see your Linux system's documentation for more information.
Looking in /var/log/vbox-setup.log I see lots of errors:
ERROR: "__cpuhp_remove_state" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "native_write_cr4" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "del_timer" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "gdt_page" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "autoremove_wake_function" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__x86_indirect_thunk_r12" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "hrtimer_cancel" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__x86_indirect_thunk_r9" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__platform_driver_register" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "smp_call_function_many" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "map_vm_area" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "hrtimer_start_range_ns" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__cpu_online_mask" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "vmap" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__x86_indirect_thunk_r13" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "destroy_workqueue" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "down" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "platform_device_unregister" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__cpuhp_setup_state" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "flush_workqueue" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "vm_insert_page" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__sw_hweight64" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "find_vma" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "smp_call_function" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "platform_device_register" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "ioremap_nocache" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "cpu_tlbstate" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "get_user_pages" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "high_memory" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "get_user_pages_remote" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "sched_setscheduler" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__get_vm_area" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "ex_handler_default" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "schedule_hrtimeout_range" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "vm_mmap" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "vunmap" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "remap_pfn_range" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "prepare_to_wait" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "hrtimer_init" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__cpu_present_mask" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "up" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "scnprintf" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "vm_munmap" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "hrtimer_try_to_cancel" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "platform_driver_unregister" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "ktime_get_ts64" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "__msecs_to_jiffies" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "alloc_workqueue" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "smp_call_function_single" [/tmp/vbox.0/vboxdrv.ko] undefined! ERROR: "yield" [/tmp/vbox.0/vboxdrv.ko] undefined! scripts/Makefile.modpost:93: recipe for target '__modpost' failed make[2]: *** [__modpost] Error 1 Makefile:1609: recipe for target 'modules' failed make[1]: *** [modules] Error 2 /tmp/vbox.0/Makefile-footer.gmk:114: recipe for target 'vboxdrv' failed make: *** [vboxdrv] Error 2
comment:20 by , 5 years ago
Ah, I just noticed that I set CONFIG_TRIM_UNUSED_KSYMS option during kernel configuration and that is probably what is causing it. Recompiling the kernel to check... (will update this comment once everything is sorted out).
UPDATE: Yes, that was the reason, so VirtualBox 6.1-RC1 works fine on 5.4.0 kernel.
However, there is still a small bug in vboxdrv.sh because it tries to unload the module vboxpci (but I always compile the kernel with CONFIG_MODULE_UNLOAD not set, because that is much safer --- at least that was the case 20 years ago and I hope nothing much changes in computers in a decade or two :)
The compile errors against the 5.4rc1 kernel in detail:
/home/ws/lin54/trunk
$ kmk KERN_VER=linux-5.4-rc1 KERN_DIR=/home/ws/linux-5.4-rc1
1.) struct sched_param VBox/Trunk fbatschu@lserver linux-5.4-rc1 $ grep sched_param ./include/uapi/linux/sched/types.h
VBox/Trunk fbatschu@lserver linux-5.4-rc1 $ head ./include/uapi/linux/sched/types.h
vrs: /usr$ grep sched_param ./src/linux-headers-4.15.0-20/include/uapi/linux/sched/types.h
/usr$ head ./src/linux-headers-4.15.0-20/include/uapi/linux/sched/types.h
=> we should check how far back this really goes, we might not need an #ifdef here at all
This first appears with the release kernel 4.11:
https://elixir.bootlin.com/linux/v4.11/source/include/uapi/linux/sched/types.h
and with the development release canidiate kernel 4.11-rc1:
https://elixir.bootlin.com/linux/v4.11-rc1/source/include/uapi/linux/sched/types.h
=> so here we can actually go way more back to include that header file then the suggested kernel version 5.4.0, let's make this instead:
2.) set_pages_x()/ set_pages_nx()
Linux change details already discussed in the inital bug description. Should probably be removed entirely from the code unless we can dig out some information as to why that was needed in:
There is no comment left in the code as to why that had been introduced. Maybe we should just disable it for the 5.4.0 kernel only though initially. However looking around in the code, there's is more code involved around the executable pages. In Trunk we find:
trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
C symbol: MY_SET_PAGES_EXEC
trunk/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
C symbol: MY_SET_PAGES_NOEXEC
trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
C symbol: MY_PAGE_KERNEL_EXEC
trunk/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
Summary:
1) Only on Linux we apparently have this request for executable kernel pages?
2) r0drv RTMemContAlloc() sets pages executable only for:
using: MY_SET_PAGES_EXEC()
3) r0drv rtR0MemObjLinuxAllocPages() sets pages executable only for:
using: MY_SET_PAGES_EXEC()
This is not very consistent in its usage. One time, we do it for kernels above KERNEL_VERSION(2, 4, 20) and the other time we do it only for kernels lower then KERNEL_VERSION(2, 4, 22). Ie. the first form does include kernel versions 2.4.21/22 and will exclude kernel versions 2.4.20 and below while the second form does include kernel versions 2.4.21/20 and will exclude kernel versions 2.4.22 and above.
4) r0drv rtR0MemAllocEx) also allocates executable kernel memory for:
using: vmalloc(MY_PAGE_KERNEL_EXEC)
trunk/src/VBox/Runtime/r0drv/alloc-r0drv.h
RTMEMHDR_FLAG_EXEC is only set in 1 place:
trunk/src/VBox/Runtime/r0drv/alloc-r0drv.cpp
trunk/include/iprt/mem.h
which finally brings us to one place where we load code and execute it:
trunk/src/VBox/Devices/testcase/tstDevice.cpp
Also callers of RTMemExecAllocTag() will request executable memory:
trunk/src/VBox/Runtime/r0drv/alloc-r0drv.cpp
which brings us back to the before mentioned r0drv: rtR0MemAllocEx()
Functions calling this function: RTMemExecAllocTag
trunk/include/iprt/mem.h
Functions calling this function: RTMemExecAlloc
A lot of this is obviously related to the recompiler but also to the runtime itself.