Page 1 of 1

NVIDIA-Linux-x86_64-361.16.run

PostPosted: Wed Jan 06, 2016 9:02 pm
by x14sg1
Hello,

The latest version of the NVIDIA drivers (above) has modified the Unified Virtual Memory code to call NV_KMEM_CACHE_CREATE 41 times.
All the calls currently have 2 arguments. In a previous patch supplied by paxguy1, kernel/common/inc/nv-linux.h and kernel/nvidia/nv.c were modified for SLAB_USERCOPY. The 41 calls are below (formatted to fit one per line).

uvm8_range_group.c: g_uvm_range_group_cache = NV_KMEM_CACHE_CREATE("uvm_range_group_t", uvm_range_group_t);
uvm8_thread_context.c: g_uvm_thread_context_cache = NV_KMEM_CACHE_CREATE("uvm_thread_context_t", uvm_thread_context_t);
uvm8_va_block.c: g_uvm_va_block_cache = NV_KMEM_CACHE_CREATE("uvm_va_block_t", uvm_va_block_t);
uvm8_va_range.c: g_uvm_va_range_cache = NV_KMEM_CACHE_CREATE("uvm_va_range_t", uvm_va_range_t);
uvm_channel_mgmt.c: g_uvmChannelManagerCache = NV_KMEM_CACHE_CREATE("uvm_channel_manager_t", UvmChannelManager);
uvm_channel_mgmt.c: g_uvmRingbufferCache = NV_KMEM_CACHE_CREATE("uvm_ringbuffer_t", UvmRingbuffer);
uvm_channel_mgmt.c: g_uvmChannelCache = NV_KMEM_CACHE_CREATE("uvm_channel_t", UvmChannel);
uvm_channel_mgmt.c: g_uvmPushbufferCache = NV_KMEM_CACHE_CREATE("uvm_pushbuffer_t", UvmPushbuffer);
uvm_channel_mgmt.c: g_uvmTrackerCache = NV_KMEM_CACHE_CREATE("uvm_tracker_t", UvmTracker);
uvm_channel_mgmt.c: g_uvmTrackerItemCache = NV_KMEM_CACHE_CREATE("uvm_trackeritem_t", UvmTrackerItem);
uvm_full_ctx_mgmt.c: g_uvmClientChannelCache = NV_KMEM_CACHE_CREATE("uvm_channel_info", UvmClientChannel);
uvm_full_ctx_mgmt.c: g_uvmVaspaceCache = NV_KMEM_CACHE_CREATE("uvm_va_space", UvmVaspace);
uvm_full_ctx_mgmt.c: g_uvmRmMemoryCache = NV_KMEM_CACHE_CREATE("uvm_rm_memory", UvmRmMemory);
uvm_full_ctx_mgmt.c: g_uvmRmMemoryRegionCache = NV_KMEM_CACHE_CREATE("uvm_rm_memory_region", UvmRmMemoryRegion);
uvm_full_ctx_mgmt.c: g_uvmEngCtxCache = NV_KMEM_CACHE_CREATE("uvm_eng_ctx", UvmEngCtx);
uvm_full_ctx_mgmt.c: g_uvmMappingCache = NV_KMEM_CACHE_CREATE("uvm_mapping", struct address_space);
uvm_full_device_mgmt.c: g_uvmPendingFaultCache = NV_KMEM_CACHE_CREATE("uvm_gpu_pending_faults", UvmPendingFault);
uvm_full_fault_handler.c: g_uvmFaultCancelEntryCache = NV_KMEM_CACHE_CREATE("uvm_fault_cancel_info", UvmGpuCancelFaultInfo);
uvm_full_identity_map.c: g_uvmMapListNodeCache = NV_KMEM_CACHE_CREATE("uvm_mapListNode", mapList_node);
uvm_full_pa_mgmt.c: g_uvmPaManagerCache = NV_KMEM_CACHE_CREATE("uvm_pa_manager", UvmPaManager);
uvm_full_pa_mgmt.c: g_UvmPaDescCache = NV_KMEM_CACHE_CREATE("uvm_pa_desc", UvmPaDesc);
uvm_full_pa_mgmt.c: g_uvmPaToVaCache = NV_KMEM_CACHE_CREATE("uvm_pa_to_va", UvmPaToVa);
uvm_full_pagetbl_mgmt.c: g_uvm2MVaDescCache = NV_KMEM_CACHE_CREATE("uvm_2mvadesc", Uvm2MbVaDesc);
uvm_full_pagetbl_mgmt.c: g_uvmGpuPdeCache = NV_KMEM_CACHE_CREATE("uvm_gpupde", UvmGpuPde);
uvm_full_pagetbl_mgmt.c: g_uvmPbOpsCache = NV_KMEM_CACHE_CREATE("uvm_pbops", UvmPbOps);
uvm_full_va_trie.c: g_uvmVatL0Cache = NV_KMEM_CACHE_CREATE("uvm_vatL0Cache", UvmVatL0);
uvm_full_va_trie.c: g_uvmVatL1Cache = NV_KMEM_CACHE_CREATE("uvm_vatL1Cache", UvmVatL1);
uvm_full_va_trie.c: g_uvmVatL2Cache = NV_KMEM_CACHE_CREATE("uvm_vatL2Cache", UvmVatL2);
uvm_full_va_trie.c: g_uvmVatGpuHeaderCache = NV_KMEM_CACHE_CREATE("uvm_vatGpuHeaderCache", UvmVatLevelGpuHeader);
uvm_kernel_counters.c: g_UvmCounterContainerCache = NV_KMEM_CACHE_CREATE("uvm_counter_container_t", struct UvmCounterContainer_tag);
uvm_kernel_events.c: g_uvmEventContainerCache = NV_KMEM_CACHE_CREATE("uvm_event_container_t", struct UvmEventContainer_tag);
uvm_lite.c: g_uvmPrivateCache = NV_KMEM_CACHE_CREATE("uvm_private_t", struct DriverPrivate_tag);
uvm_lite.c: g_uvmCommitRecordCache = NV_KMEM_CACHE_CREATE("uvm_commit_record_t", struct UvmCommitRecord_tag);
uvm_lite.c: g_uvmMigTrackerCache = NV_KMEM_CACHE_CREATE("uvm_mig_tracker_t", struct UvmGpuMigrationTracking_tag);
uvm_lite.c: g_uvmStreamRecordCache = NV_KMEM_CACHE_CREATE("uvm_stream_record_t", struct UvmStreamRecord_tag);
uvm_lite.c: g_uvmMappingCache = NV_KMEM_CACHE_CREATE("uvm_mapping_t", struct address_space);
uvm_lite.c: g_uvmMpsServerCache = NV_KMEM_CACHE_CREATE("uvm_mps_server_t", struct UvmMpsServer_tag);
uvm_lite_prefetch.c: g_uvmLitePrefetchRegionAccessCache = NV_KMEM_CACHE_CREATE("UvmRegionAccess", UvmRegionAccess);
uvm_lite_region_tracking.c: g_uvmTrackingTreeCache = NV_KMEM_CACHE_CREATE("uvm_region_tracker_t", struct s_UvmRegionTracker);
uvm_lite_region_tracking.c: g_uvmTrackingTreeNodeCache = NV_KMEM_CACHE_CREATE("uvm_region_tracker_node_t", struct _tree_node);
uvm_page_cache.c: g_uvmPageTrackingCache = NV_KMEM_CACHE_CREATE("uvm_page_tracking_t", struct UvmPageTracking_tag);

Any chance you could tell me which ones need SLAB_USERCOPY as the third argument and which ones need a 0 or possibly provide a patch, similar to https://grsecurity.net/~paxguy1/nvidia- ... -pax.patch? Also, the second part of that patch to kernel/nvidia-uvm/uvm_common.c also has issues with the new NVIDIA driver. This looks like it can be fixed with something similar to this:

{
NV_STATUS status = NV_OK;

- g_exportedUvmOps.startDevice = uvm_gpu_event_start_device;
- g_exportedUvmOps.stopDevice = uvm_gpu_event_stop_device;
- if (uvmnext_activated())
- g_exportedUvmOps.isrTopHalf = uvmnext_isr_top_half;
- else if (uvmfull_activated())
- g_exportedUvmOps.isrTopHalf = uvmfull_isr_top_half;
- fi
+#ifdef NVIDIA_UVM_NEXT_ENABLED
+ static struct UvmOpsUvmEvents g_exportedUvmOps = {
+ .startDevice = uvm_gpu_event_start_device,
+ .stopDevice = uvm_gpu_event_stop_device,
+ .isrTopHalf = uvmnext_isr_top_half,
+ };
+#else
+ static struct UvmOpsUvmEvents g_exportedUvmOps = {
+ .startDevice = uvm_gpu_event_start_device,
+ .stopDevice = uvm_gpu_event_stop_device,
+ .isrTopHalf = uvmfull_isr_top_half,
+ };
+#endif //NVIDIA_UVM_NEXT_ENABLED

// call RM to exchange the function pointers.
status = nvUvmInterfaceRegisterUvmCallbacks(&g_exportedUvmOps);

Thanks for any help you can provide

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Sun Jan 10, 2016 10:36 pm
by PaX Team
my first cut is at https://grsecurity.net/~paxguy1/nvidia- ... -pax.patch that should compile with KERNEXEC/CONSTIFY but i have no idea yet if it works. for the slabs, you'll have to try the code as is and if you get usercopy violations, fix up the code to use the newly introduced NV_KMEM_CACHE_CREATE_USERCOPY macro. patches are welcome ;).

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Mon Jan 11, 2016 2:48 am
by x14sg1
Hello,

With a few changes to your patch (diff included), NVIDIA patches, builds and seems to work (tested with X, firefox and thunderbird)
The last patch in the diff was supplied by one of you a month or two ago.

Thank you.

$ diff ../nvidia-drivers-361.16-pax.patch.orig nvidia-drivers-361.16-pax.patch.new
4c4
< @@ -1330,9 +1330,13 @@ extern void *nvidia_stack_t_cache;
---
> @@ -1330,9 +1330,14 @@ extern void *nvidia_stack_t_cache;
12a13
> NULL)
15c16
< NULL)
---
> + NULL)
50a52,60
> @@ -32,6 +32,8 @@
> #include "nv_uvm_interface.h"
> #include "cla06f.h"
>
> +#include "linux/compiler.h"
> +
> // TODO Tweak this after we can run and benchmark real workloads. Likely also
> // using different number of channels for different pools.
> #define UVM_CHANNELS_PER_POOL 2
88a99,107
> @@ -29,6 +29,8 @@
> #define UVM_SEMAPHORE_PAGE_SIZE PAGE_SIZE
> #define UVM_SEMAPHORE_COUNT_PER_PAGE (PAGE_SIZE / UVM_SEMAPHORE_SIZE)
>
> +#include "linux/compiler.h"
> +
> struct uvm_gpu_semaphore_pool_struct
> {
> // The GPU owning the pool
150a170,193
> diff -urp kernel/nvidia-modeset/nvidia-modeset-linux.c kernel/nvidia-modeset/nvidia-modeset-linux.c
> --- kernel/nvidia-modeset/nvidia-modeset-linux.c 2015-12-30 00:44:45.000000000 -0500
> +++ kernel/nvidia-modeset/nvidia-modeset-linux.c 2016-01-05 18:49:30.000000000 -0500
> @@ -320,11 +320,20 @@ static void nvkms_resume(NvU32 gpuId)
> * so we can use a single nvidia_modeset_stack_ptr for calling RM.
> *************************************************************************/
>
> +#ifndef RANDSTRUCT_PLUGIN
> static nvidia_modeset_rm_ops_t __rm_ops = { 0 };
> +#else
> +static nvidia_modeset_rm_ops_t __rm_ops;
> +#endif
> static nvidia_modeset_stack_ptr nvkms_nvidia_stack = NULL;
> static nvidia_modeset_callbacks_t nvkms_rm_callbacks = {
> +#ifndef RANDSTRUCT_PLUGIN
> nvkms_suspend,
> nvkms_resume
> +#else
> + .suspend = nvkms_suspend,
> + .resume = nvkms_resume
> +#endif
> };
>
> static int nvkms_alloc_rm(void)

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Mon Jan 11, 2016 7:36 am
by PaX Team
can you repost it as an interdiff between the two patches instead? ;)

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Tue Jan 12, 2016 8:50 pm
by x14sg1
I can see why you wanted it this way ...

Code: Select all
diff -u NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h
--- NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h     2016-01-11 02:58:02.265211586 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h     2016-01-11 02:58:02.265211586 +0100
@@ -1335,6 +1335,7 @@
 #else
 #define NV_KMEM_CACHE_CREATE(name, type)    \
     kmem_cache_create(name, sizeof(type), 0, 0, NULL, \
+                      NULL)
 #define NV_KMEM_CACHE_CREATE_USERCOPY(name, type)    \
     kmem_cache_create(name, sizeof(type), 0, SLAB_USERCOPY, NULL, \
                       NULL)
diff -u NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c
--- NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c 2016-01-11 03:14:44.774335695 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c 2016-01-11 03:14:44.774335695 +0100
@@ -32,6 +32,8 @@
 #include "nv_uvm_interface.h"
 #include "cla06f.h"

+#include "linux/compiler.h"
+
 // TODO Tweak this after we can run and benchmark real workloads. Likely also
 // using different number of channels for different pools.
 #define UVM_CHANNELS_PER_POOL 2
diff -u NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c
--- NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c   2016-01-11 03:14:22.011553125 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c   2016-01-11 03:14:22.011553125 +0100
@@ -29,6 +29,8 @@
 #define UVM_SEMAPHORE_PAGE_SIZE PAGE_SIZE
 #define UVM_SEMAPHORE_COUNT_PER_PAGE (PAGE_SIZE / UVM_SEMAPHORE_SIZE)

+#include "linux/compiler.h"
+
 struct uvm_gpu_semaphore_pool_struct
 {
     // The GPU owning the pool
only in patch2:
unchanged:
--- kernel/nvidia-modeset/nvidia-modeset-linux.c        2015-12-30 00:44:45.000000000 -0500
+++ kernel/nvidia-modeset/nvidia-modeset-linux.c        2016-01-05 18:49:30.000000000 -0500
@@ -320,11 +320,20 @@ static void nvkms_resume(NvU32 gpuId)
  * so we can use a single nvidia_modeset_stack_ptr for calling RM.
  *************************************************************************/

+#ifndef RANDSTRUCT_PLUGIN
 static nvidia_modeset_rm_ops_t __rm_ops = { 0 };
+#else
+static nvidia_modeset_rm_ops_t __rm_ops;
+#endif
 static nvidia_modeset_stack_ptr nvkms_nvidia_stack = NULL;
 static nvidia_modeset_callbacks_t nvkms_rm_callbacks = {
+#ifndef RANDSTRUCT_PLUGIN
     nvkms_suspend,
     nvkms_resume
+#else
+    .suspend = nvkms_suspend,
+    .resume = nvkms_resume
+#endif
 };

 static int nvkms_alloc_rm(void)

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Fri Jan 15, 2016 11:34 pm
by x14sg1
I tried out the current patch you have for 361.18 and realized I forgot to remove the includes I added when I was getting the patch to work with a non-grsec kernel. However, as indicated below, another patch is needed to compile NVIDIA when using this compile command:


./NVIDIA-Linux-x86_64-361.18-no-compat32-custom.run --silent --no-network --force-tls=new --no-kernel-module-source --no-backup --no-nvidia-modprobe -n --no-check-for-alternate-installs --kernel-name 4.3.3-grsec --kernel-module-only --no-x-check


Code: Select all
diff -urp kernel/nvidia-modeset/nvidia-modeset-linux.c kernel/nvidia-modeset/nvidia-modeset-linux.c
--- kernel/nvidia-modeset/nvidia-modeset-linux.c        2015-12-30 00:44:45.000000000 -0500
+++ kernel/nvidia-modeset/nvidia-modeset-linux.c        2016-01-05 18:49:30.000000000 -0500
@@ -320,11 +320,11 @@ static void nvkms_resume(NvU32 gpuId)
  * so we can use a single nvidia_modeset_stack_ptr for calling RM.
  *************************************************************************/

-static nvidia_modeset_rm_ops_t __rm_ops = { 0 };
+static nvidia_modeset_rm_ops_t __rm_ops;
 static nvidia_modeset_stack_ptr nvkms_nvidia_stack = NULL;
 static nvidia_modeset_callbacks_t nvkms_rm_callbacks = {
-    nvkms_suspend,
-    nvkms_resume
+    .suspend = nvkms_suspend,
+    .resume = nvkms_resume
 };

 static int nvkms_alloc_rm(void)

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Sat Jan 16, 2016 7:34 am
by PaX Team
that hunk is for RANDSTRUCT needed under grsec only but i've included it in the latest patch along with some more constification. the biggest offender left now is some ops structure from nvidia's blob.

Re: NVIDIA-Linux-x86_64-361.16.run

PostPosted: Sat Jan 16, 2016 3:37 pm
by x14sg1
thanks