kwo pushed a commit to branch master.

http://git.enlightenment.org/legacy/imlib2.git/commit/?id=ca17031280fddf1ba14a5f9d8d89507301d0db26

commit ca17031280fddf1ba14a5f9d8d89507301d0db26
Author: Alexander Volkov <[email protected]>
Date:   Tue Feb 6 16:04:20 2018 +0100

    Add support for MIT-SHM FD-passing
    
    Summary:
    This is more secure way of using shared memory because
    it's visible only to the X server and the application.
    
    Reviewers: kwo
    
    Reviewed By: kwo
    
    Differential Revision: https://phab.enlightenment.org/D5788
---
 configure.ac        |  24 ++++++++
 src/lib/Makefile.am |   2 +-
 src/lib/ximage.c    | 164 +++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 148 insertions(+), 42 deletions(-)

diff --git a/configure.ac b/configure.ac
index bc5a8d0..15ab954 100644
--- a/configure.ac
+++ b/configure.ac
@@ -99,8 +99,31 @@ fi
 
 if test "x$have_x" = "xyes"; then
   AC_DEFINE(BUILD_X11, 1, [enabling X11 support])
+  AC_MSG_CHECKING(whether to enable X11 MIT-SHM FD-passing support)
+  AC_ARG_WITH([x-shm-fd],
+    [AS_HELP_STRING([--without-x-shm-fd], [Disable X11 MIT-SHM FD-passing 
support])],
+    [
+     if test "$withval" = no ; then
+       x_shm_fd=no
+     else
+       x_shm_fd=yes
+     fi
+    ],
+    [ x_shm_fd=auto ]
+  )
+  AC_MSG_RESULT($x_shm_fd)
+
+  if test "$x_shm_fd" != no ; then
+    PKG_CHECK_MODULES(X_SHM_FD, x11-xcb xcb xcb-shm >= 1.9, [ x_shm_fd="yes" 
], [ x_shm_fd="no"])
+  else
+    x_shm_fd="no"
+  fi
+  if test "$x_shm_fd" = yes ; then
+    AC_DEFINE(HAVE_X11_SHM_FD, 1, [enabling X11 MIT-SHM FD-passing support])
+  fi
 else
   have_x="no"
+  x_shm_fd="no"
 fi
 AM_CONDITIONAL(BUILD_X11, test "x$have_x" = "xyes")
 
@@ -443,6 +466,7 @@ echo "Use X86 MMX for speed.....: $mmx"
 echo "Use AMD64 for speed.......: $amd64"
 echo
 echo "Use visibility hiding.....: $enable_visibility_hiding"
+echo "Use X MIT-SHM FD-passing..: $x_shm_fd"
 echo
 echo
 echo "Installation Path.........: $prefix"
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 83c734f..4f48310 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -87,7 +87,7 @@ EXTRA_DIST = $(MMX_SRCS) $(AMD64_SRCS) asm_loadimmq.S
 
 MY_LIBS = $(FREETYPE_LIBS) $(DLOPEN_LIBS) -lm
 if BUILD_X11
-MY_LIBS += -lXext -lX11
+MY_LIBS += -lXext -lX11 @X_SHM_FD_LIBS@
 endif
 
 if BUILD_MMX
diff --git a/src/lib/ximage.c b/src/lib/ximage.c
index 96327f1..14c145c 100644
--- a/src/lib/ximage.c
+++ b/src/lib/ximage.c
@@ -3,6 +3,11 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/XShm.h>
 #include <X11/Xutil.h>
+#ifdef HAVE_X11_SHM_FD
+#include <X11/Xlib-xcb.h>
+#include <xcb/shm.h>
+#include <sys/mman.h>
+#endif
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
@@ -10,6 +15,9 @@
 
 /* global flags */
 static signed char  x_does_shm = -1;
+#ifdef HAVE_X11_SHM_FD
+static signed char  x_does_shm_fd = 0;
+#endif
 
 /* static private variables */
 static int          list_num = 0;
@@ -37,10 +45,24 @@ ShmCheck(Display * d)
 {
    /* if its there set x_does_shm flag */
    if (XShmQueryExtension(d))
-      x_does_shm = 2;           /* 2: __imlib_ShmGetXImage tests first 
XShmAttach */
+     {
+#ifdef HAVE_X11_SHM_FD
+        int major, minor;
+        Bool pixmaps;
+#endif
+        x_does_shm = 2;           /* 2: __imlib_ShmGetXImage tests first 
XShmAttach */
+#ifdef HAVE_X11_SHM_FD
+        if (XShmQueryVersion(d, &major, &minor, &pixmaps))
+          {
+             x_does_shm_fd = (major == 1 && minor >= 2) || major > 1;
+          }
+#endif
+     }
    /* clear the flag - no shm at all */
    else
-      x_does_shm = 0;
+     {
+        x_does_shm = 0;
+     }
 }
 
 XImage             *
@@ -60,55 +82,106 @@ __imlib_ShmGetXImage(Display * d, Visual * v, Drawable 
draw, int depth,
    if (!xim)
       return NULL;
 
-   /* get an shm id of this image */
-   si->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
-                      IPC_CREAT | 0666);
-   /* if the get succeeds */
-   if (si->shmid != -1)
+#ifdef HAVE_X11_SHM_FD
+   if (x_does_shm_fd)
      {
-        /* set the params for the shm segment */
+        xcb_generic_error_t *error = NULL;
+        xcb_shm_create_segment_cookie_t cookie;
+        xcb_shm_create_segment_reply_t *reply;
+        size_t segment_size = xim->bytes_per_line * xim->height;
+
+        xcb_connection_t *c = XGetXCBConnection(d);
+        si->shmaddr = NULL;
+        si->shmseg = xcb_generate_id(c);
         si->readOnly = False;
-        si->shmaddr = xim->data = shmat(si->shmid, 0, 0);
-        /* get the shm addr for this data chunk */
-        if (xim->data != (char *)-1)
-          {
-             XErrorHandler       ph = NULL;
 
-             if (x_does_shm == 2)
+        cookie = xcb_shm_create_segment(c, si->shmseg, segment_size, 
si->readOnly);
+        reply = xcb_shm_create_segment_reply(c, cookie, &error);
+        if (reply)
+          {
+             int *fds = reply->nfd == 1 ? xcb_shm_create_segment_reply_fds(c, 
reply) : NULL;
+             if (fds)
                {
-                  /* setup a temporary error handler */
-                  _x_err = 0;
-                  XSync(d, False);
-                  ph = XSetErrorHandler(TmpXError);
+                  si->shmaddr = mmap(0, segment_size, PROT_READ|PROT_WRITE,
+                                     MAP_SHARED, fds[0], 0);
+                  close(fds[0]);
+                  if (si->shmaddr == MAP_FAILED)
+                      si->shmaddr = NULL;
                }
-             /* ask X to attach to the shared mem segment */
-             XShmAttach(d, si);
-             if (draw != None)
-                XShmGetImage(d, draw, xim, x, y, 0xffffffff);
-             if (x_does_shm == 2)
+             if (si->shmaddr == NULL)
                {
-                  /* wait for X to reply and do this */
-                  XSync(d, False);
-                  /* reset the error handler */
-                  XSetErrorHandler(ph);
-                  x_does_shm = 1;
+                  xcb_shm_detach(c, si->shmseg);
                }
+             free(reply);
+          }
+        free(error);
 
-             /* if we attached without an error we're set */
-             if (_x_err == 0)
-                return xim;
+        if (si->shmaddr)
+          {
+             xim->data = si->shmaddr;
+             if (draw != None)
+                XShmGetImage(d, draw, xim, x, y, 0xffffffff);
 
-             /* attach by X failed... must be remote client */
-             /* flag shm forever to not work - remote */
+             return xim;
+          }
+        else
+          {
              x_does_shm = 0;
-
-             /* detach */
-             shmdt(si->shmaddr);
           }
+     }
+   else
+#endif
+     {
+        /* get an shm id of this image */
+        si->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
+                           IPC_CREAT | 0666);
+        /* if the get succeeds */
+        if (si->shmid != -1)
+          {
+             /* set the params for the shm segment */
+             si->readOnly = False;
+             si->shmaddr = xim->data = shmat(si->shmid, 0, 0);
+             /* get the shm addr for this data chunk */
+             if (xim->data != (char *)-1)
+               {
+                  XErrorHandler       ph = NULL;
 
-        /* get failed - out of shm id's or shm segment too big ? */
-        /* remove the shm id we created */
-        shmctl(si->shmid, IPC_RMID, 0);
+                  if (x_does_shm == 2)
+                    {
+                       /* setup a temporary error handler */
+                       _x_err = 0;
+                       XSync(d, False);
+                       ph = XSetErrorHandler(TmpXError);
+                    }
+                  /* ask X to attach to the shared mem segment */
+                  XShmAttach(d, si);
+                  if (draw != None)
+                     XShmGetImage(d, draw, xim, x, y, 0xffffffff);
+                  if (x_does_shm == 2)
+                    {
+                       /* wait for X to reply and do this */
+                       XSync(d, False);
+                       /* reset the error handler */
+                       XSetErrorHandler(ph);
+                       x_does_shm = 1;
+                    }
+
+                  /* if we attached without an error we're set */
+                  if (_x_err == 0)
+                     return xim;
+
+                  /* attach by X failed... must be remote client */
+                  /* flag shm forever to not work - remote */
+                  x_does_shm = 0;
+
+                  /* detach */
+                  shmdt(si->shmaddr);
+               }
+
+             /* get failed - out of shm id's or shm segment too big ? */
+             /* remove the shm id we created */
+             shmctl(si->shmid, IPC_RMID, 0);
+          }
      }
 
    /* couldnt create SHM image ? */
@@ -123,8 +196,17 @@ __imlib_ShmDestroyXImage(Display * d, XImage * xim, 
XShmSegmentInfo * si)
 {
    XSync(d, False);
    XShmDetach(d, si);
-   shmdt(si->shmaddr);
-   shmctl(si->shmid, IPC_RMID, 0);
+#ifdef HAVE_X11_SHM_FD
+   if (x_does_shm_fd)
+     {
+        munmap(si->shmaddr, xim->bytes_per_line * xim->height);
+     }
+   else
+#endif
+     {
+        shmdt(si->shmaddr);
+        shmctl(si->shmid, IPC_RMID, 0);
+     }
    XDestroyImage(xim);
 }
 

-- 


Reply via email to