diff --git a/src/Mem.h b/src/Mem.h
index 21616a405..9e39e963c 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -61,6 +61,7 @@ public:
     static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);
 
     static void *allocateExecutableMemory(size_t size);
+    static void protectExecutableMemory(void *p, size_t size);
     static void flushInstructionCache(void *p, size_t size);
 
     static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp
index a30d9f720..833c200c1 100644
--- a/src/Mem_unix.cpp
+++ b/src/Mem_unix.cpp
@@ -100,6 +100,12 @@ void *Mem::allocateExecutableMemory(size_t size)
 }
 
 
+void Mem::protectExecutableMemory(void *p, size_t size)
+{
+    mprotect(p, size, PROT_READ | PROT_EXEC);
+}
+
+
 void Mem::flushInstructionCache(void *p, size_t size)
 {
 #   ifndef __FreeBSD__
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index c43b2ce46..27c1348b0 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -191,6 +191,13 @@ void *Mem::allocateExecutableMemory(size_t size)
 }
 
 
+void Mem::protectExecutableMemory(void *p, size_t size)
+{
+    DWORD oldProtect;
+    VirtualProtect(p, size, PAGE_EXECUTE_READ, &oldProtect);
+}
+
+
 void Mem::flushInstructionCache(void *p, size_t size)
 {
     ::FlushInstructionCache(GetCurrentProcess(), p, size);
diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp
index 082effe2d..db02bda7a 100644
--- a/src/workers/CpuThread.cpp
+++ b/src/workers/CpuThread.cpp
@@ -118,6 +118,7 @@ void xmrig::CpuThread::patchAsmVariants()
     patchCode(cn_half_mainloop_bulldozer_asm,           cnv2_mainloop_bulldozer_asm,            xmrig::CRYPTONIGHT_HALF_ITER,   xmrig::CRYPTONIGHT_MASK);
     patchCode(cn_half_double_mainloop_sandybridge_asm,  cnv2_double_mainloop_sandybridge_asm,   xmrig::CRYPTONIGHT_HALF_ITER,   xmrig::CRYPTONIGHT_MASK);
 
+    Mem::protectExecutableMemory(base, allocation_size);
     Mem::flushInstructionCache(base, allocation_size);
 }
 #endif