In order to avoid DLL preloading attacks, we should be careful about where we
load DLLs from. These packages load graphics DLLs, which may be provided by the
OS, by a graphics vendor, or even by individual applications. As such, we can't
restrict loading them to just system32-provided paths. Instead, we invoke
LoadLibraryEx [0] with the LOAD_LIBRARY_SEARCH_DEFAULT_DIRS path, which will search
system32, application-defined paths, and the path of the primary application
executable. This mode ignores the system %PATH% variable, which dramatically
reduces the attack surface of malicious or unintended DLLs.
Applications may add custom paths to the search list by calling the standard
windows AddDllDirectory function [1] prior to attempting to initialize GL.
Thanks to Mohsen Mirzakhani and Utkarsh Satya Prakash for bringing this to
our attention.
[0] https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa
[1] https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
---
internal/egl/egl_windows.go | 74 +++++----
internal/gl/gl_windows.go | 296 +++++++++++++++++++++++++-----------
2 files changed, 255 insertions(+), 115 deletions(-)
diff --git a/internal/egl/egl_windows.go b/internal/egl/egl_windows.go
index 4433dd79..284f765e 100644
--- a/internal/egl/egl_windows.go
+++ b/internal/egl/egl_windows.go
@@ -9,8 +9,6 @@ import (
"unsafe"
syscall "golang.org/x/sys/windows"
-
- "gioui.org/internal/gl"
)
type (
@@ -24,23 +22,23 @@ type (
)
var (
- libEGL = syscall.NewLazyDLL("libEGL.dll")
- _eglChooseConfig = libEGL.NewProc("eglChooseConfig")
- _eglCreateContext = libEGL.NewProc("eglCreateContext")
- _eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
- _eglDestroyContext = libEGL.NewProc("eglDestroyContext")
- _eglDestroySurface = libEGL.NewProc("eglDestroySurface")
- _eglGetConfigAttrib = libEGL.NewProc("eglGetConfigAttrib")
- _eglGetDisplay = libEGL.NewProc("eglGetDisplay")
- _eglGetError = libEGL.NewProc("eglGetError")
- _eglInitialize = libEGL.NewProc("eglInitialize")
- _eglMakeCurrent = libEGL.NewProc("eglMakeCurrent")
- _eglReleaseThread = libEGL.NewProc("eglReleaseThread")
- _eglSwapInterval = libEGL.NewProc("eglSwapInterval")
- _eglSwapBuffers = libEGL.NewProc("eglSwapBuffers")
- _eglTerminate = libEGL.NewProc("eglTerminate")
- _eglQueryString = libEGL.NewProc("eglQueryString")
- _eglWaitClient = libEGL.NewProc("eglWaitClient")
+ libEGL = syscall.DLL{}
+ _eglChooseConfig *syscall.Proc
+ _eglCreateContext *syscall.Proc
+ _eglCreateWindowSurface *syscall.Proc
+ _eglDestroyContext *syscall.Proc
+ _eglDestroySurface *syscall.Proc
+ _eglGetConfigAttrib *syscall.Proc
+ _eglGetDisplay *syscall.Proc
+ _eglGetError *syscall.Proc
+ _eglInitialize *syscall.Proc
+ _eglMakeCurrent *syscall.Proc
+ _eglReleaseThread *syscall.Proc
+ _eglSwapInterval *syscall.Proc
+ _eglSwapBuffers *syscall.Proc
+ _eglTerminate *syscall.Proc
+ _eglQueryString *syscall.Proc
+ _eglWaitClient *syscall.Proc
)
var loadOnce sync.Once
@@ -54,21 +52,45 @@ func loadEGL() error {
}
func loadDLLs() error {
- if err := loadDLL(libEGL, "libEGL.dll"); err != nil {
+ if err := loadDLL(&libEGL, "libEGL.dll"); err != nil {
return err
}
- if err := loadDLL(gl.LibGLESv2, "libGLESv2.dll"); err != nil {
- return err
+
+ procs := map[string]**syscall.Proc{
+ "eglChooseConfig": &_eglChooseConfig,
+ "eglCreateContext": &_eglCreateContext,
+ "eglCreateWindowSurface": &_eglCreateWindowSurface,
+ "eglDestroyContext": &_eglDestroyContext,
+ "eglDestroySurface": &_eglDestroySurface,
+ "eglGetConfigAttrib": &_eglGetConfigAttrib,
+ "eglGetDisplay": &_eglGetDisplay,
+ "eglGetError": &_eglGetError,
+ "eglInitialize": &_eglInitialize,
+ "eglMakeCurrent": &_eglMakeCurrent,
+ "eglReleaseThread": &_eglReleaseThread,
+ "eglSwapInterval": &_eglSwapInterval,
+ "eglSwapBuffers": &_eglSwapBuffers,
+ "eglTerminate": &_eglTerminate,
+ "eglQueryString": &_eglQueryString,
+ "eglWaitClient": &_eglWaitClient,
}
- // d3dcompiler_47.dll is needed internally for shader compilation to function.
- return loadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
+ for name, proc := range procs {
+ p, err := libEGL.FindProc(name)
+ if err != nil {
+ return fmt.Errorf("failed to locate %s in %s: %w", name, libEGL.Name, err)
+ }
+ *proc = p
+ }
+ return nil
}
-func loadDLL(dll *syscall.LazyDLL, name string) error {
- err := dll.Load()
+func loadDLL(dll *syscall.DLL, name string) error {
+ handle, err := syscall.LoadLibraryEx(name, 0, syscall.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)
if err != nil {
return fmt.Errorf("egl: failed to load %s: %v", name, err)
}
+ dll.Handle = handle
+ dll.Name = name
return nil
}
diff --git a/internal/gl/gl_windows.go b/internal/gl/gl_windows.go
index a30457fd..b4422e7e 100644
--- a/internal/gl/gl_windows.go
+++ b/internal/gl/gl_windows.go
@@ -3,103 +3,217 @@
package gl
import (
+ "fmt"
"math"
"runtime"
+ "sync"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
+func loadGLESv2Procs() error {
+ dllName := "libGLESv2.dll"
+ handle, err := windows.LoadLibraryEx(dllName, 0, windows.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)
+ if err != nil {
+ return fmt.Errorf("gl: failed to load %s: %v", dllName, err)
+ }
+ gles := windows.DLL{Handle: handle, Name: dllName}
+ // d3dcompiler_47.dll is needed internally for shader compilation to function.
+ dllName = "d3dcompiler_47.dll"
+ _, err = windows.LoadLibraryEx(dllName, 0, windows.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)
+ if err != nil {
+ return fmt.Errorf("gl: failed to load %s: %v", dllName, err)
+ }
+ procs := map[string]**windows.Proc{
+ "glActiveTexture": &_glActiveTexture,
+ "glAttachShader": &_glAttachShader,
+ "glBeginQuery": &_glBeginQuery,
+ "glBindAttribLocation": &_glBindAttribLocation,
+ "glBindBuffer": &_glBindBuffer,
+ "glBindBufferBase": &_glBindBufferBase,
+ "glBindFramebuffer": &_glBindFramebuffer,
+ "glBindRenderbuffer": &_glBindRenderbuffer,
+ "glBindTexture": &_glBindTexture,
+ "glBindVertexArray": &_glBindVertexArray,
+ "glBlendEquation": &_glBlendEquation,
+ "glBlendFuncSeparate": &_glBlendFuncSeparate,
+ "glBufferData": &_glBufferData,
+ "glBufferSubData": &_glBufferSubData,
+ "glCheckFramebufferStatus": &_glCheckFramebufferStatus,
+ "glClear": &_glClear,
+ "glClearColor": &_glClearColor,
+ "glClearDepthf": &_glClearDepthf,
+ "glDeleteQueries": &_glDeleteQueries,
+ "glDeleteVertexArrays": &_glDeleteVertexArrays,
+ "glCompileShader": &_glCompileShader,
+ "glCopyTexSubImage2D": &_glCopyTexSubImage2D,
+ "glGenerateMipmap": &_glGenerateMipmap,
+ "glGenBuffers": &_glGenBuffers,
+ "glGenFramebuffers": &_glGenFramebuffers,
+ "glGenVertexArrays": &_glGenVertexArrays,
+ "glGetUniformBlockIndex": &_glGetUniformBlockIndex,
+ "glCreateProgram": &_glCreateProgram,
+ "glGenRenderbuffers": &_glGenRenderbuffers,
+ "glCreateShader": &_glCreateShader,
+ "glGenTextures": &_glGenTextures,
+ "glDeleteBuffers": &_glDeleteBuffers,
+ "glDeleteFramebuffers": &_glDeleteFramebuffers,
+ "glDeleteProgram": &_glDeleteProgram,
+ "glDeleteShader": &_glDeleteShader,
+ "glDeleteRenderbuffers": &_glDeleteRenderbuffers,
+ "glDeleteTextures": &_glDeleteTextures,
+ "glDepthFunc": &_glDepthFunc,
+ "glDepthMask": &_glDepthMask,
+ "glDisableVertexAttribArray": &_glDisableVertexAttribArray,
+ "glDisable": &_glDisable,
+ "glDrawArrays": &_glDrawArrays,
+ "glDrawElements": &_glDrawElements,
+ "glEnable": &_glEnable,
+ "glEnableVertexAttribArray": &_glEnableVertexAttribArray,
+ "glEndQuery": &_glEndQuery,
+ "glFinish": &_glFinish,
+ "glFlush": &_glFlush,
+ "glFramebufferRenderbuffer": &_glFramebufferRenderbuffer,
+ "glFramebufferTexture2D": &_glFramebufferTexture2D,
+ "glGenQueries": &_glGenQueries,
+ "glGetError": &_glGetError,
+ "glGetRenderbufferParameteriv": &_glGetRenderbufferParameteriv,
+ "glGetFloatv": &_glGetFloatv,
+ "glGetFramebufferAttachmentParameteriv": &_glGetFramebufferAttachmentParameteriv,
+ "glGetIntegerv": &_glGetIntegerv,
+ "glGetIntegeri_v": &_glGetIntegeri_v,
+ "glGetProgramiv": &_glGetProgramiv,
+ "glGetProgramInfoLog": &_glGetProgramInfoLog,
+ "glGetQueryObjectuiv": &_glGetQueryObjectuiv,
+ "glGetShaderiv": &_glGetShaderiv,
+ "glGetShaderInfoLog": &_glGetShaderInfoLog,
+ "glGetString": &_glGetString,
+ "glGetUniformLocation": &_glGetUniformLocation,
+ "glGetVertexAttribiv": &_glGetVertexAttribiv,
+ "glGetVertexAttribPointerv": &_glGetVertexAttribPointerv,
+ "glInvalidateFramebuffer": &_glInvalidateFramebuffer,
+ "glIsEnabled": &_glIsEnabled,
+ "glLinkProgram": &_glLinkProgram,
+ "glPixelStorei": &_glPixelStorei,
+ "glReadPixels": &_glReadPixels,
+ "glRenderbufferStorage": &_glRenderbufferStorage,
+ "glScissor": &_glScissor,
+ "glShaderSource": &_glShaderSource,
+ "glTexImage2D": &_glTexImage2D,
+ "glTexStorage2D": &_glTexStorage2D,
+ "glTexSubImage2D": &_glTexSubImage2D,
+ "glTexParameteri": &_glTexParameteri,
+ "glUniformBlockBinding": &_glUniformBlockBinding,
+ "glUniform1f": &_glUniform1f,
+ "glUniform1i": &_glUniform1i,
+ "glUniform2f": &_glUniform2f,
+ "glUniform3f": &_glUniform3f,
+ "glUniform4f": &_glUniform4f,
+ "glUseProgram": &_glUseProgram,
+ "glVertexAttribPointer": &_glVertexAttribPointer,
+ "glViewport": &_glViewport,
+ }
+ for name, proc := range procs {
+ p, err := gles.FindProc(name)
+ if err != nil {
+ return fmt.Errorf("failed to locate %s in %s: %w", name, gles.Name, err)
+ }
+ *proc = p
+ }
+ return nil
+}
+
var (
- LibGLESv2 = windows.NewLazyDLL("libGLESv2.dll")
- _glActiveTexture = LibGLESv2.NewProc("glActiveTexture")
- _glAttachShader = LibGLESv2.NewProc("glAttachShader")
- _glBeginQuery = LibGLESv2.NewProc("glBeginQuery")
- _glBindAttribLocation = LibGLESv2.NewProc("glBindAttribLocation")
- _glBindBuffer = LibGLESv2.NewProc("glBindBuffer")
- _glBindBufferBase = LibGLESv2.NewProc("glBindBufferBase")
- _glBindFramebuffer = LibGLESv2.NewProc("glBindFramebuffer")
- _glBindRenderbuffer = LibGLESv2.NewProc("glBindRenderbuffer")
- _glBindTexture = LibGLESv2.NewProc("glBindTexture")
- _glBindVertexArray = LibGLESv2.NewProc("glBindVertexArray")
- _glBlendEquation = LibGLESv2.NewProc("glBlendEquation")
- _glBlendFuncSeparate = LibGLESv2.NewProc("glBlendFuncSeparate")
- _glBufferData = LibGLESv2.NewProc("glBufferData")
- _glBufferSubData = LibGLESv2.NewProc("glBufferSubData")
- _glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus")
- _glClear = LibGLESv2.NewProc("glClear")
- _glClearColor = LibGLESv2.NewProc("glClearColor")
- _glClearDepthf = LibGLESv2.NewProc("glClearDepthf")
- _glDeleteQueries = LibGLESv2.NewProc("glDeleteQueries")
- _glDeleteVertexArrays = LibGLESv2.NewProc("glDeleteVertexArrays")
- _glCompileShader = LibGLESv2.NewProc("glCompileShader")
- _glCopyTexSubImage2D = LibGLESv2.NewProc("glCopyTexSubImage2D")
- _glGenerateMipmap = LibGLESv2.NewProc("glGenerateMipmap")
- _glGenBuffers = LibGLESv2.NewProc("glGenBuffers")
- _glGenFramebuffers = LibGLESv2.NewProc("glGenFramebuffers")
- _glGenVertexArrays = LibGLESv2.NewProc("glGenVertexArrays")
- _glGetUniformBlockIndex = LibGLESv2.NewProc("glGetUniformBlockIndex")
- _glCreateProgram = LibGLESv2.NewProc("glCreateProgram")
- _glGenRenderbuffers = LibGLESv2.NewProc("glGenRenderbuffers")
- _glCreateShader = LibGLESv2.NewProc("glCreateShader")
- _glGenTextures = LibGLESv2.NewProc("glGenTextures")
- _glDeleteBuffers = LibGLESv2.NewProc("glDeleteBuffers")
- _glDeleteFramebuffers = LibGLESv2.NewProc("glDeleteFramebuffers")
- _glDeleteProgram = LibGLESv2.NewProc("glDeleteProgram")
- _glDeleteShader = LibGLESv2.NewProc("glDeleteShader")
- _glDeleteRenderbuffers = LibGLESv2.NewProc("glDeleteRenderbuffers")
- _glDeleteTextures = LibGLESv2.NewProc("glDeleteTextures")
- _glDepthFunc = LibGLESv2.NewProc("glDepthFunc")
- _glDepthMask = LibGLESv2.NewProc("glDepthMask")
- _glDisableVertexAttribArray = LibGLESv2.NewProc("glDisableVertexAttribArray")
- _glDisable = LibGLESv2.NewProc("glDisable")
- _glDrawArrays = LibGLESv2.NewProc("glDrawArrays")
- _glDrawElements = LibGLESv2.NewProc("glDrawElements")
- _glEnable = LibGLESv2.NewProc("glEnable")
- _glEnableVertexAttribArray = LibGLESv2.NewProc("glEnableVertexAttribArray")
- _glEndQuery = LibGLESv2.NewProc("glEndQuery")
- _glFinish = LibGLESv2.NewProc("glFinish")
- _glFlush = LibGLESv2.NewProc("glFlush")
- _glFramebufferRenderbuffer = LibGLESv2.NewProc("glFramebufferRenderbuffer")
- _glFramebufferTexture2D = LibGLESv2.NewProc("glFramebufferTexture2D")
- _glGenQueries = LibGLESv2.NewProc("glGenQueries")
- _glGetError = LibGLESv2.NewProc("glGetError")
- _glGetRenderbufferParameteriv = LibGLESv2.NewProc("glGetRenderbufferParameteriv")
- _glGetFloatv = LibGLESv2.NewProc("glGetFloatv")
- _glGetFramebufferAttachmentParameteriv = LibGLESv2.NewProc("glGetFramebufferAttachmentParameteriv")
- _glGetIntegerv = LibGLESv2.NewProc("glGetIntegerv")
- _glGetIntegeri_v = LibGLESv2.NewProc("glGetIntegeri_v")
- _glGetProgramiv = LibGLESv2.NewProc("glGetProgramiv")
- _glGetProgramInfoLog = LibGLESv2.NewProc("glGetProgramInfoLog")
- _glGetQueryObjectuiv = LibGLESv2.NewProc("glGetQueryObjectuiv")
- _glGetShaderiv = LibGLESv2.NewProc("glGetShaderiv")
- _glGetShaderInfoLog = LibGLESv2.NewProc("glGetShaderInfoLog")
- _glGetString = LibGLESv2.NewProc("glGetString")
- _glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation")
- _glGetVertexAttribiv = LibGLESv2.NewProc("glGetVertexAttribiv")
- _glGetVertexAttribPointerv = LibGLESv2.NewProc("glGetVertexAttribPointerv")
- _glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer")
- _glIsEnabled = LibGLESv2.NewProc("glIsEnabled")
- _glLinkProgram = LibGLESv2.NewProc("glLinkProgram")
- _glPixelStorei = LibGLESv2.NewProc("glPixelStorei")
- _glReadPixels = LibGLESv2.NewProc("glReadPixels")
- _glRenderbufferStorage = LibGLESv2.NewProc("glRenderbufferStorage")
- _glScissor = LibGLESv2.NewProc("glScissor")
- _glShaderSource = LibGLESv2.NewProc("glShaderSource")
- _glTexImage2D = LibGLESv2.NewProc("glTexImage2D")
- _glTexStorage2D = LibGLESv2.NewProc("glTexStorage2D")
- _glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D")
- _glTexParameteri = LibGLESv2.NewProc("glTexParameteri")
- _glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding")
- _glUniform1f = LibGLESv2.NewProc("glUniform1f")
- _glUniform1i = LibGLESv2.NewProc("glUniform1i")
- _glUniform2f = LibGLESv2.NewProc("glUniform2f")
- _glUniform3f = LibGLESv2.NewProc("glUniform3f")
- _glUniform4f = LibGLESv2.NewProc("glUniform4f")
- _glUseProgram = LibGLESv2.NewProc("glUseProgram")
- _glVertexAttribPointer = LibGLESv2.NewProc("glVertexAttribPointer")
- _glViewport = LibGLESv2.NewProc("glViewport")
+ glInitOnce sync.Once
+ _glActiveTexture *windows.Proc
+ _glAttachShader *windows.Proc
+ _glBeginQuery *windows.Proc
+ _glBindAttribLocation *windows.Proc
+ _glBindBuffer *windows.Proc
+ _glBindBufferBase *windows.Proc
+ _glBindFramebuffer *windows.Proc
+ _glBindRenderbuffer *windows.Proc
+ _glBindTexture *windows.Proc
+ _glBindVertexArray *windows.Proc
+ _glBlendEquation *windows.Proc
+ _glBlendFuncSeparate *windows.Proc
+ _glBufferData *windows.Proc
+ _glBufferSubData *windows.Proc
+ _glCheckFramebufferStatus *windows.Proc
+ _glClear *windows.Proc
+ _glClearColor *windows.Proc
+ _glClearDepthf *windows.Proc
+ _glDeleteQueries *windows.Proc
+ _glDeleteVertexArrays *windows.Proc
+ _glCompileShader *windows.Proc
+ _glCopyTexSubImage2D *windows.Proc
+ _glGenerateMipmap *windows.Proc
+ _glGenBuffers *windows.Proc
+ _glGenFramebuffers *windows.Proc
+ _glGenVertexArrays *windows.Proc
+ _glGetUniformBlockIndex *windows.Proc
+ _glCreateProgram *windows.Proc
+ _glGenRenderbuffers *windows.Proc
+ _glCreateShader *windows.Proc
+ _glGenTextures *windows.Proc
+ _glDeleteBuffers *windows.Proc
+ _glDeleteFramebuffers *windows.Proc
+ _glDeleteProgram *windows.Proc
+ _glDeleteShader *windows.Proc
+ _glDeleteRenderbuffers *windows.Proc
+ _glDeleteTextures *windows.Proc
+ _glDepthFunc *windows.Proc
+ _glDepthMask *windows.Proc
+ _glDisableVertexAttribArray *windows.Proc
+ _glDisable *windows.Proc
+ _glDrawArrays *windows.Proc
+ _glDrawElements *windows.Proc
+ _glEnable *windows.Proc
+ _glEnableVertexAttribArray *windows.Proc
+ _glEndQuery *windows.Proc
+ _glFinish *windows.Proc
+ _glFlush *windows.Proc
+ _glFramebufferRenderbuffer *windows.Proc
+ _glFramebufferTexture2D *windows.Proc
+ _glGenQueries *windows.Proc
+ _glGetError *windows.Proc
+ _glGetRenderbufferParameteriv *windows.Proc
+ _glGetFloatv *windows.Proc
+ _glGetFramebufferAttachmentParameteriv *windows.Proc
+ _glGetIntegerv *windows.Proc
+ _glGetIntegeri_v *windows.Proc
+ _glGetProgramiv *windows.Proc
+ _glGetProgramInfoLog *windows.Proc
+ _glGetQueryObjectuiv *windows.Proc
+ _glGetShaderiv *windows.Proc
+ _glGetShaderInfoLog *windows.Proc
+ _glGetString *windows.Proc
+ _glGetUniformLocation *windows.Proc
+ _glGetVertexAttribiv *windows.Proc
+ _glGetVertexAttribPointerv *windows.Proc
+ _glInvalidateFramebuffer *windows.Proc
+ _glIsEnabled *windows.Proc
+ _glLinkProgram *windows.Proc
+ _glPixelStorei *windows.Proc
+ _glReadPixels *windows.Proc
+ _glRenderbufferStorage *windows.Proc
+ _glScissor *windows.Proc
+ _glShaderSource *windows.Proc
+ _glTexImage2D *windows.Proc
+ _glTexStorage2D *windows.Proc
+ _glTexSubImage2D *windows.Proc
+ _glTexParameteri *windows.Proc
+ _glUniformBlockBinding *windows.Proc
+ _glUniform1f *windows.Proc
+ _glUniform1i *windows.Proc
+ _glUniform2f *windows.Proc
+ _glUniform3f *windows.Proc
+ _glUniform4f *windows.Proc
+ _glUseProgram *windows.Proc
+ _glVertexAttribPointer *windows.Proc
+ _glViewport *windows.Proc
)
type Functions struct {
@@ -115,7 +229,11 @@ func NewFunctions(ctx Context, forceES bool) (*Functions, error) {
if ctx != nil {
panic("non-nil context")
}
- return new(Functions), nil
+ var err error
+ glInitOnce.Do(func() {
+ err = loadGLESv2Procs()
+ })
+ return new(Functions), err
}
func (c *Functions) ActiveTexture(t Enum) {
--
2.47.1