VirtualBox

Ignore:
Timestamp:
Jul 14, 2016 11:19:31 AM (8 years ago)
Author:
vboxsync
Message:

bugref:8087: Additions/x11: support non-root X server: further improve preventing loading of OpenGL libraries by the X server, by detecting when libEGL.so is being loaded by the X server using the same method that Mesa uses, and just refusing to work in a normal sort of way without trickery. Also switch from IPRT primitives to pthreads ones to avoid a dependency on IPRT in the X server in this case.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/crOpenGL/egl.c

    r62201 r62242  
    2121*******************************************************************************/
    2222#include <iprt/cdefs.h>
    23 #include <iprt/initterm.h>
    24 #include <iprt/mem.h>
    25 #include <iprt/once.h>
    26 #include <iprt/thread.h>
     23#include <iprt/types.h>
    2724
    2825#include <EGL/egl.h>
     
    3027#include <X11/Xlib.h>
    3128
     29#include <dlfcn.h>
     30#include <pthread.h>
     31#include <stdio.h>
    3232#include <stdlib.h>
     33
     34#define EGL_ASSERT(expr) \
     35    if (!(expr)) { printf("Assertion failed: %s\n", #expr); exit(1); }
    3336
    3437/*******************************************************************************
     
    7275*******************************************************************************/
    7376
    74 static RTTLS    g_tls = NIL_RTTLS;
    75 static RTONCE   g_tlsOnce = RTONCE_INITIALIZER;
    76 static Display *g_pDefaultDisplay = NULL;
    77 static RTONCE   g_defaultDisplayOnce = RTONCE_INITIALIZER;
    78 
    79 static DECLCALLBACK(int32_t) tlsInitOnce(void *pv)
    80 {
    81     NOREF(pv);
    82     g_tls = RTTlsAlloc();
    83     return VINF_SUCCESS;
     77static pthread_key_t  g_tls;
     78static pthread_once_t g_tlsOnce = PTHREAD_ONCE_INIT;
     79static Display       *g_pDefaultDisplay = NULL;
     80static pthread_once_t g_defaultDisplayOnce = PTHREAD_ONCE_INIT;
     81
     82static void tlsInitOnce(void)
     83{
     84    pthread_key_create(&g_tls, NULL);
    8485}
    8586
     
    8889    struct VBEGLTLS *pTls;
    8990
    90     RTOnce(&g_tlsOnce, tlsInitOnce, NULL);
    91     pTls = (struct VBEGLTLS *)RTTlsGet(g_tls);
     91    pthread_once(&g_tlsOnce, tlsInitOnce);
     92    pTls = (struct VBEGLTLS *)pthread_getspecific(g_tls);
    9293    if (RT_LIKELY(pTls))
    9394        return pTls;
    94     pTls = (struct VBEGLTLS *)RTMemAlloc(sizeof(*pTls));
     95    pTls = (struct VBEGLTLS *)malloc(sizeof(*pTls));
    9596    if (!VALID_PTR(pTls))
    9697        return NULL;
     
    101102    pTls->hCurrentDraw = EGL_NO_SURFACE;
    102103    pTls->hCurrentRead = EGL_NO_SURFACE;
    103     RTTlsSet(g_tls, pTls);
    104     return pTls;
    105 }
    106 
    107 static DECLCALLBACK(int32_t) defaultDisplayInitOnce(void *pv)
    108 {
    109     NOREF(pv);
     104    if (pthread_setspecific(g_tls, pTls) == 0)
     105        return pTls;
     106    free(pTls);
     107    return NULL;
     108}
     109
     110static void defaultDisplayInitOnce(void)
     111{
    110112    g_pDefaultDisplay = XOpenDisplay(NULL);
    111     return VINF_SUCCESS;
    112113}
    113114
     
    131132}
    132133
     134static EGLBoolean testValidDisplay(EGLNativeDisplayType hDisplay)
     135{
     136    if (hDisplay == EGL_DEFAULT_DISPLAY)
     137        return EGL_TRUE;
     138    if ((void *)hDisplay == NULL)
     139        return EGL_FALSE;
     140    /* This is the test that Mesa uses to see if this is a GBM "display".  Not
     141     * very pretty, but since no one can afford to break Mesa it should be
     142     * safe. Obviously we can't support GBM for now. */
     143    if (*(void **)hDisplay == dlsym(NULL, "gbm_create_device"))
     144        return EGL_FALSE;
     145    return EGL_TRUE;
     146}
     147
    133148DECLEXPORT(EGLDisplay) eglGetDisplay(EGLNativeDisplayType hDisplay)
    134149{
    135150    Display *pDisplay;
    136151    int rc, cError, cEvent, cMajor, cMinor;
    137     /* Prevent working from inside the X server by requiring a valid DISPLAY. */
    138     char *pszDisplay = getenv("DISPLAY");
    139    
    140     if (!pszDisplay || !*pszDisplay)
    141         return EGL_NO_DISPLAY;
    142     rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
    143     if (RT_FAILURE(rc))
     152
     153    if (!testValidDisplay(hDisplay))
    144154        return EGL_NO_DISPLAY;
    145155    if (!clearEGLError())  /* Set up our tls. */
     
    149159    else
    150160    {
    151         RTOnce(&g_defaultDisplayOnce, defaultDisplayInitOnce, NULL);
     161        pthread_once(&g_defaultDisplayOnce, defaultDisplayInitOnce);
    152162        pDisplay = g_pDefaultDisplay;
    153163    }
     
    170180DECLEXPORT(EGLBoolean) eglInitialize (EGLDisplay hDisplay, EGLint *pcMajor, EGLint *pcMinor)
    171181{
    172     /* Prevent working from inside the X server by requiring a valid DISPLAY. */
    173     char *pszDisplay = getenv("DISPLAY");
    174    
    175     if (!pszDisplay || !*pszDisplay)
     182    if (hDisplay == EGL_NO_DISPLAY)
    176183        return EGL_FALSE;
    177184    if (!VALID_PTR(hDisplay))
     
    222229        return setEGLError(EGL_BAD_PARAMETER);
    223230    paFBConfigs = glXGetFBConfigs(pDisplay, DefaultScreen(pDisplay), &caFBConfigs);
    224     AssertPtrReturn(paFBConfigs, setEGLError(EGL_BAD_PARAMETER));
     231    if (!VALID_PTR(paFBConfigs))
     232        return setEGLError(EGL_BAD_PARAMETER);
    225233    if (caFBConfigs > caConfigs)
    226234        caFBConfigs = caConfigs;
     
    426434    {
    427435        aAttribList[cAttribs] = None;
    428         AssertRelease(cAttribs < RT_ELEMENTS(aAttribList));
     436        EGL_ASSERT(cAttribs < RT_ELEMENTS(aAttribList));
    429437        if (!(cRenderableType & EGL_OPENGL_BIT))
    430438            return setEGLError(EGL_BAD_ACCESS);
     
    559567        return EGL_NO_SURFACE;
    560568    }
    561     AssertRelease(hGLXWindow < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
     569    EGL_ASSERT(hGLXWindow < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
    562570    clearEGLError();
    563571    return (EGLSurface)(hGLXWindow | VBEGL_WINDOW_SURFACE);
     
    627635            paAttributes += 2;
    628636        }
    629     AssertRelease(cIndex < RT_ELEMENTS(aAttributes) - 1);
     637    EGL_ASSERT(cIndex < RT_ELEMENTS(aAttributes) - 1);
    630638    aAttributes[cIndex + 1] = None;
    631639    hPbuffer = glXCreatePbuffer(pDisplay, (GLXFBConfig)config, aAttributes);
     
    635643        return EGL_NO_SURFACE;
    636644    }
    637     AssertRelease(hPbuffer < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
     645    EGL_ASSERT(hPbuffer < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
    638646    clearEGLError();
    639647    return (EGLSurface)(hPbuffer | VBEGL_PBUFFER_SURFACE);
     
    671679        return EGL_NO_SURFACE;
    672680    }
    673     AssertRelease(hGLXPixmap < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
     681    EGL_ASSERT(hGLXPixmap < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
    674682    clearEGLError();
    675683    return (EGLSurface)(hGLXPixmap | VBEGL_PIXMAP_SURFACE);
     
    741749DECLEXPORT(EGLBoolean) eglBindAPI(EGLenum enmApi)
    742750{
    743     /* Prevent working from inside the X server by requiring a valid DISPLAY. */
    744     char *pszDisplay = getenv("DISPLAY");
    745    
    746     if (!pszDisplay || !*pszDisplay)
    747         return EGL_FALSE;
    748751    return enmApi == EGL_OPENGL_API ? clearEGLError() : setEGLError(EGL_BAD_PARAMETER);
    749752}
     
    842845DECLEXPORT(EGLDisplay) eglGetCurrentDisplay(void)
    843846{
    844     struct VBEGLTLS *pTls = getTls();
    845 
     847    struct VBEGLTLS *pTls;
     848
     849    pTls = getTls();
    846850    if (!VALID_PTR(pTls))
    847851        return EGL_NO_DISPLAY;
     
    947951    if (!(pTls))
    948952        return EGL_TRUE;
    949     RTMemFree(pTls);
    950     RTTlsSet(g_tls, NULL);
     953    free(pTls);
     954    /* Can this fail with ENOMEM? */
     955    pthread_setspecific(g_tls, NULL);
    951956    return EGL_TRUE;
    952957}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette