Glynn,

We ended up patching the source as you recommended.

We were a little surprised to discover that tightening the umask or mode prior to socket creation did not prevent others from connecting to Xvfb. So our second approach was to compare the EUID of the Xvfb process with the EUID of the client attempting to connect, and only allow connections when they match, effectively limiting users only to the Xvfb instances that they started themselves. This doesn't fix the issue of two users wanting to use the same DISPLAY number, but telling users to "export DISPLAY=:$$" seemed to generally take care of that problem for us. This code isn't enough to be included in X right now, but if there is enough interest in this feature that it might be included, maybe I can make it a configuration option.

I've attached our patch, applied to Xtranssock.c in the xtrans-1.2.7 source code (don't mind my bad indentation). From what we've tested, it appears to work for us. I thought I'd post our solution anyway, in case I've overlooked something.

Thanks,

Billy Wilson

On 01/16/2015 08:22 PM, Glynn Clements wrote:

Billy Wilson wrote:

Is there a way to secure Xvfb during an installation from source, such
as during ./configure?
I don't think that you're going to get the behaviour you desire
without patching the source.


--- Xtranssock.c.orig	2015-01-23 16:13:06.288288000 -0700
+++ Xtranssock.c	2015-01-23 16:16:46.543003000 -0700
@@ -1249,6 +1249,8 @@
     XtransConnInfo	newciptr;
     struct sockaddr_in	sockname;
     SOCKLEN_T		namelen = sizeof(sockname);
+    struct ucred cr;
+    int cl=sizeof(cr);
 
     prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd);
 
@@ -1271,6 +1273,24 @@
 	return NULL;
     }
 
+    if (getsockopt(newciptr->fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0) {
+	prmsg (1, "SocketINETAccept: failed to get uid\n");
+    close (newciptr->fd);
+	free (newciptr);
+	*status = TRANS_ACCEPT_FAILED;
+	return NULL;
+    
+    }
+
+    if (cr.uid != geteuid())
+    {
+    prmsg (1, "SocketINETAccept: euid mismatch, permission denied\n");
+    close (newciptr->fd);
+    free (newciptr);
+    *status = TRANS_ACCEPT_FAILED;
+    return NULL;
+    }
+
 #ifdef TCP_NODELAY
     {
 	/*
@@ -1325,6 +1345,8 @@
     XtransConnInfo	newciptr;
     struct sockaddr_un	sockname;
     SOCKLEN_T 		namelen = sizeof sockname;
+    struct ucred cr;
+    int cl=sizeof(cr);
 
     prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd);
 
@@ -1344,6 +1366,24 @@
 	return NULL;
     }
 
+    if (getsockopt(newciptr->fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) != 0) {
+    prmsg (1, "SocketUNIXAccept: failed to get uid\n");
+    close (newciptr->fd);
+    free (newciptr);
+    *status = TRANS_ACCEPT_FAILED;
+    return NULL;
+
+    }
+
+    if (cr.uid != geteuid())
+    {
+    prmsg (1, "SocketUNIXAccept: euid mismatch, permission denied\n");
+    close (newciptr->fd);
+    free (newciptr);
+    *status = TRANS_ACCEPT_FAILED;
+    return NULL;
+    }
+
 	ciptr->addrlen = namelen;
     /*
      * Get the socket name and the peer name from the listener socket,

_______________________________________________
xorg@lists.x.org: X.Org support
Archives: http://lists.freedesktop.org/archives/xorg
Info: http://lists.x.org/mailman/listinfo/xorg
Your subscription address: %(user_address)s

Reply via email to