gallium: fix surface->destroy use-after-free
demo: tested on radeonsi && nouveau
I think its small security issue
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// g++ egl.cpp -lEGL -lGLESv2 && ./a.out
#include <EGL/egl.h>
#include <GLES2/gl2.h>
void fatalEGL(const char *msg) {
printf("EGL: %s %d\n", msg, eglGetError());
exit(-1);
}
#define ENSURE(condition) \
if (!(condition)) \
fatalEGL(#condition);
int main(void) {
EGLDisplay display;
EGLint eglMaj, eglMin;
EGLContext ctx1, ctx2;
ENSURE((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) != EGL_NO_DISPLAY);
ENSURE(eglInitialize(display, &eglMaj, &eglMin));
ENSURE(eglBindAPI(EGL_OPENGL_ES_API));
// sleep(5);
// Get an EGL config.
const EGLint attribs[] = {EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES3_BIT,
EGL_BLUE_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_RED_SIZE,
8,
EGL_DEPTH_SIZE,
16,
EGL_NONE};
EGLint numConfig = 0;
EGLConfig eglConfig;
ENSURE(eglChooseConfig(display, attribs, &eglConfig, 1, &numConfig) &&
numConfig > 0);
// Create a context.
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
ENSURE((ctx2 = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT,
contextAttribs)) != EGL_NO_CONTEXT);
ENSURE((ctx1 = eglCreateContext(display, eglConfig, ctx2, contextAttribs)) !=
EGL_NO_CONTEXT);
ENSURE(eglMakeCurrent(display, 0, 0, ctx1));
GLuint fb = 0;
glGenFramebuffers(1, &fb);
GLuint rbDepthStencil, rbColor;
glGenRenderbuffers(1, &rbDepthStencil);
glGenRenderbuffers(1, &rbColor);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glBindRenderbuffer(GL_RENDERBUFFER, rbDepthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, 0x88F0, 64, 64);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, rbColor);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 64, 64);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rbDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, rbDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, rbColor);
ENSURE(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ENSURE(eglMakeCurrent(display, 0, 0, ctx2));
glBindFramebuffer(GL_FRAMEBUFFER, fb);
ENSURE(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ENSURE(eglMakeCurrent(display, 0, 0, 0));
ENSURE(eglDestroyContext(display, ctx1));
printf("BUG\n");
ENSURE((ctx1 = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT,
contextAttribs)) != EGL_NO_CONTEXT);
ENSURE(eglDestroyContext(display, ctx2)); // 这里的zsbuf已经是use-after-free了
return 0;
}