[VDPAU] [PATCH] Save the result from secure_getenv

Zach Angold zangold at nvidia.com
Tue Feb 16 22:18:14 UTC 2016


The return value from secure_getenv is not guaranteed to be kept after
another call to secure_getenv, so we replace it with safe_secure_getenv,
which places the result of secure_getenv in a specified buffer.
---
 src/mesa_dri2.c     | 10 +++++++++-
 src/util.h          | 28 ++++++++++++++++++++++++++++
 src/vdpau_wrapper.c | 29 ++++++++++++++++++++++++++---
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/src/mesa_dri2.c b/src/mesa_dri2.c
index 420ccee..d591a97 100644
--- a/src/mesa_dri2.c
+++ b/src/mesa_dri2.c
@@ -38,6 +38,7 @@
 #endif
 
 #define NEED_REPLIES
+#include <stdio.h>
 #include <X11/Xlibint.h>
 #include <X11/extensions/Xext.h>
 #include <X11/extensions/extutil.h>
@@ -135,7 +136,14 @@ _vdp_DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName
    req->driverType = DRI2DriverVDPAU;
 #ifdef DRI2DriverPrimeShift
    {
-      char *prime = secure_getenv("DRI_PRIME");
+      char primebuf[256];
+      const char *prime;
+      if (!safe_secure_getenv(&prime, "DRI_PRIME", primebuf, sizeof(primebuf))) {
+         fprintf(stderr, "Could not get DRI_PRIME: variable too long\n");
+         UnlockDisplay(dpy);
+         SyncHandle();
+         return False;
+      }
       if (prime) {
          unsigned int primeid;
          errno = 0;
diff --git a/src/util.h b/src/util.h
index 39227ea..1d46d70 100644
--- a/src/util.h
+++ b/src/util.h
@@ -46,3 +46,31 @@ static inline char * getenv_wrapper(const char *name)
 #    define secure_getenv getenv_wrapper
 #  endif
 #endif
+
+/*
+ * Copies the result of secure_getenv() to a buffer.
+ * (*result) will be equal to buf if secure_getenv succeeds, or NULL if
+ * there is no match or secure execution is required (see man page for getenv).
+ * Returns zero if the result of secure_getenv() does not fit in buf and buf,
+ * nonzero otherwise.
+ */
+static inline int safe_secure_getenv(const char **result,
+                                     const char *name,
+                                     char *buf,
+                                     size_t buflen)
+{
+    const char * env = secure_getenv(name);
+    if (env == NULL) {
+        (*result) = NULL;
+        return 1;
+    }
+
+    if (buf == NULL) {
+        return 1;
+    }
+
+    (*result) = buf;
+    strncpy(buf, env, buflen);
+
+    return strlen(env) < buflen;
+}
diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c
index 79dcb94..325ea09 100644
--- a/src/vdpau_wrapper.c
+++ b/src/vdpau_wrapper.c
@@ -112,13 +112,22 @@ static VdpStatus _vdp_open_driver(
     int                   screen)
 {
     char const * vdpau_driver;
+    char         vdpau_driver_copy[PATH_MAX];
     char * vdpau_driver_dri2 = NULL;
     const char * vdpau_driver_path = NULL;
+    char         vdpau_driver_path_copy[PATH_MAX];
     char         vdpau_driver_lib[PATH_MAX];
     char const * vdpau_trace;
+    char         vdpau_trace_copy[PATH_MAX];
     char const * func_name;
 
-    vdpau_driver = secure_getenv("VDPAU_DRIVER");
+    if (!safe_secure_getenv(&vdpau_driver, "VDPAU_DRIVER", vdpau_driver_copy,
+                            sizeof(vdpau_driver_copy))) {
+        fprintf(stderr, "Failed to save VDPAU driver name: name too long\n");
+        _VDP_ERROR_BREAKPOINT();
+        return VDP_STATUS_NO_IMPLEMENTATION;
+    }
+
     if (vdpau_driver) {
         if (strchr(vdpau_driver, '/')) {
             vdpau_driver = NULL;
@@ -133,7 +142,16 @@ static VdpStatus _vdp_open_driver(
     }
 
     /* Don't allow setuid apps to use VDPAU_DRIVER_PATH */
-    vdpau_driver_path = secure_getenv("VDPAU_DRIVER_PATH");
+    if (!safe_secure_getenv(&vdpau_driver_path, "VDPAU_DRIVER_PATH",
+                           vdpau_driver_path_copy, sizeof(vdpau_driver_path_copy))) {
+        fprintf(stderr, "Failed to save VDPAU driver path: path too long\n");
+        if (vdpau_driver_dri2) {
+            XFree(vdpau_driver_dri2);
+            vdpau_driver_dri2 = NULL;
+        }
+        _VDP_ERROR_BREAKPOINT();
+        return VDP_STATUS_NO_IMPLEMENTATION;
+    }
     if (vdpau_driver_path &&
         snprintf(vdpau_driver_lib, sizeof(vdpau_driver_lib),
                  DRIVER_LIB_FORMAT, vdpau_driver_path, vdpau_driver) <
@@ -181,7 +199,12 @@ static VdpStatus _vdp_open_driver(
 
     _vdp_backend_dll = _vdp_driver_dll;
 
-    vdpau_trace = secure_getenv("VDPAU_TRACE");
+    if (!safe_secure_getenv(&vdpau_trace, "VDPAU_TRACE", vdpau_trace_copy,
+                            sizeof(vdpau_trace_copy))) {
+        fprintf(stderr, "Failed to save VDPAU_TRACE: result too long\n");
+        _VDP_ERROR_BREAKPOINT();
+        return VDP_STATUS_NO_IMPLEMENTATION;
+    }
     if (vdpau_trace && atoi(vdpau_trace)) {
         SetDllHandle * set_dll_handle;
 
-- 
2.1.4



More information about the VDPAU mailing list