PERFORCE change 166064 for review

Jonathan Anderson jona at FreeBSD.org
Tue Jul 14 06:50:01 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166064

Change 166064 by jona at jona-trustedbsd-belle-vmware on 2009/07/14 06:48:59

	X in the sandbox works (but not Qt, yet)

Affected files ...

.. //depot/projects/trustedbsd/capabilities/src/tools/cap/sandbox_qt/sandbox_qt.cpp#2 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/sandbox_qt/sandbox_qt.pro#2 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/sandbox_qt/xcb_auth.c#1 add

Differences ...

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/sandbox_qt/sandbox_qt.cpp#2 (text+ko) ====

@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Robert N. M. Watson
+ * Copyright (c) 2009 Jonathan Anderson
  * All rights reserved.
  *
  * WARNING: THIS IS EXPERIMENTAL SECURITY SOFTWARE THAT MUST NOT BE RELIED
@@ -34,70 +34,90 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
+#include <sys/capability.h>
+#include <sys/types.h>
+#include <sys/procdesc.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <libcapability.h>
+#include <libuserangel.h>
 
-extern "C"
-{
-	#include <sys/procdesc.h>
-	#include <sys/types.h>
-	#include <sys/uio.h>
+#include <QApplication>
+#include <QFile>
+#include <QMessageBox>
 
-	#include <err.h>
-	#include <errno.h>
-	#include <fcntl.h>
-	#include <libcapability.h>
-	#include <libuserangel.h>
-	#include <stdio.h>
-	#include <stdlib.h>
-	#include <string.h>
-	#include <sysexits.h>
-	#include <unistd.h>
-}
+#include <X11/Xlib.h>
+#include <X11/Xauth.h>
+#include <xcb/xcb.h>
 
 #include <iostream>
 using namespace std;
 
 
+extern "C" int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display);
+
+
 struct lc_library find_library(const char *name)
 {
 	struct lc_library lib;
 	lib.lcl_libname = name;
+	lib.lcl_fd = -1;
+
+	char path[strlen(name) + 32];
+	cap_rights_t rights = CAP_MASK_VALID ^ CAP_ACCEPT;
 
-	char path[128];
-	lib.lcl_fd = -1;
+	const char *libdirs[] =
+	{
+		"/lib",
+		"/usr/lib",
+		"/usr/local/lib",
+		"/usr/local/lib/qt4",
+		NULL
+	};
 
-	sprintf(path, "/lib/%s", name);
-	lib.lcl_fd = open(path, O_RDONLY);
-	if(lib.lcl_fd >= 0) return lib;
+	for(int i = 0; libdirs[i]; i++)
+	{
+		sprintf(path, "%s/%s", libdirs[i], name);
+		lib.lcl_fd = ua_ropen(path, O_RDONLY, rights);
+		// TODO: this is a kludge because mmap() fails in the child proc
+		lib.lcl_fd = open(path, O_RDONLY);
+		if(lib.lcl_fd >= 0) return lib;
 
-	sprintf(path, "/usr/lib/%s", name);
-	lib.lcl_fd = open(path, O_RDONLY);
-	if(lib.lcl_fd >= 0) return lib;
+		printf("errno: %i\n", errno);
+	}
 
-	sprintf(path, "/usr/local/lib/%s", name);
-	lib.lcl_fd = open(path, O_RDONLY);
-	if(lib.lcl_fd >= 0) return lib;
+	err(-1, "Error opening %s with rights 0x%016llx\n", name, rights);
+}
 
-	sprintf(path, "/usr/local/lib/qt4/%s", name);
-	lib.lcl_fd = open(path, O_RDONLY);
-	if(lib.lcl_fd >= 0) return lib;
 
-	fprintf(stderr, "Couldn't find library %s\n", name);
+int connect_to_X(int*, xcb_auth_info_t*);
 
-	return lib;
-}
 
 
 int main(int argc, char *argv[])
 {
-	cout << "Host app" << endl;
-	cout << "In sandbox: " << ld_insandbox() << endl;
+	cout << "host:\t\tIn sandbox: " << ld_insandbox() << endl;
 
-	QCoreApplication app(argc, argv);
+	QApplication app(argc, argv);
 
-
-	cout << "Reading from /etc/passwd using normal (non-UA) means..." << endl;
+	cout << "host:\t\tReading from /etc/passwd using normal open()..." << endl;
 	QFile passwd("/etc/passwd");
 	if(!passwd.open(QIODevice::ReadOnly | QIODevice::Text))
 		err(EX_IOERR, "Error opening /etc/passwd");
@@ -109,6 +129,7 @@
 	struct lc_sandbox *sandbox;
 	struct lc_library libs[] =
 	{
+		// QtCore libraries
 		find_library("libQtCore.so.4"),
 		find_library("libuserangel.so.1"),
 		find_library("libz.so.4"),
@@ -121,24 +142,42 @@
 		find_library("libthr.so.3"),
 		find_library("libintl.so.8"),
 		find_library("libpcre.so.0"),
+
+		//QtGui Libraries
+		find_library("libQtGui.so.4"),
+		find_library("libpng.so.5"),
+		find_library("libSM.so.6"),
+		find_library("libICE.so.6"),
+		find_library("libXi.so.6"),
+		find_library("libXrender.so.1"),
+		find_library("libXrandr.so.2"),
+		find_library("libfreetype.so.9"),
+		find_library("libfontconfig.so.1"),
+		find_library("libXext.so.6"),
+		find_library("libX11.so.6"),
+		find_library("libxcb.so.2"),
+		find_library("libXau.so.6"),
+		find_library("libXdmcp.so.6"),
+		find_library("librpcsvc.so.4"),
+		find_library("libexpat.so.6"),
+
 		{ NULL, NULL, -1 }
 	};
+//	sleep(120);
 	int libcount = 0;
 	while(libs[libcount].lcl_fd >= 0) libcount++;
 
+
 	int ret = lch_startfd_libs(my_fd, "sandbox_qt", sargv,
 	                           LCH_PERMIT_STDOUT | LCH_PERMIT_STDERR,
 	                           libs, libcount, &sandbox);
-	if(ret < 0)
-	{
-		cerr << "Error starting sandbox: " << errno << " ("
-		     << strerror(errno) << ")" << endl;
-		return -1;
-	}
+
+	if(ret < 0) err(EX_SOFTWARE, "Error starting sandbox");
 
 
 	int32_t angel = ua_find();
 	if(angel < 0) err(EX_SOFTWARE, "Couldn't find user angel");
+	else cout << "host:\t\tUser angel at FD " << angel << endl;
 
 	int sandsock = -1;
 	if(lch_getsock(sandbox, &sandsock)) err(EX_SOFTWARE, "Couldn't getsock");
@@ -151,30 +190,90 @@
 		return -1;
 	}
 
-	sleep(1);
+	cout << "host:\t\tSent user angel FD (" << angel << ") to sandbox" << endl;
+
+	int Xfd;
+	xcb_auth_info_t xauth;
+
+	if(connect_to_X(&Xfd, &xauth))
+		err(EX_SOFTWARE, "Error connecting to X server");
+
+	cout << "host:\t\tConnected to X at FD " << Xfd << endl;
+	cout
+		<< "host:\t\tauth info: " << endl
+		<< "     \t\t\tname: ";
+
+	for(int i = 0; i < xauth.namelen; i++) cout << xauth.name[i];
+	cout
+		<< endl
+		<< "     \t\t\tdata: ";
+
+	for(int i = 0; i < xauth.datalen; i++)
+		printf("%02x ", xauth.data[i] & 0xff);
+	cout << endl;
+
+
+	struct ua_datum *d = ua_marshall_string("DISPLAY", 10);
+	if(ua_send(sandsock, d, &Xfd, 1) < 0)
+	{
+		cerr << "Error sending X FD: " << errno << " ("
+		     << strerror(errno) << ")" << endl;
+		return -1;
+	}
+	cout << "host:\t\tSent X FD (" << angel << ") to sandbox" << endl;
+
+	d = ua_marshall_string(xauth.name, xauth.namelen);
+	if(ua_send(sandsock, d, NULL, 0) < 0)
+	{
+		cerr << "Error sending Xauth name: " << errno << " ("
+		     << strerror(errno) << ")" << endl;
+		return -1;
+	}
+	cout << "host:\t\tSent Xauth name to sandbox" << endl;
+
+	d = ua_marshall_string(xauth.data, xauth.datalen);
+	if(ua_send(sandsock, d, NULL, 0) < 0)
+	{
+		cerr << "Error sending Xauth data: " << errno << " ("
+		     << strerror(errno) << ")" << endl;
+		return -1;
+	}
+	cout << "host:\t\tSent Xauth data to sandbox" << endl;
+
+	QMessageBox::information(NULL, "Host", "This is on the host");
 
 	return 0;
 }
 
 
+void raw_x_tests();
+
+
 extern "C" int cap_main(int argc, char *argv[])
 {
-	puts("Sandboxed app");
-	printf("In sandbox: %i\n", ld_insandbox());
+	printf("sandbox:\tIn sandbox: %i\n", ld_insandbox());
+	fflush(stdout);
 
-	QCoreApplication app(argc, argv);
 
 	struct lc_host *lchpp;
 	if(lcs_get(&lchpp) < 0) err(EX_IOERR, "Error getting lc_host");
 
 	int host;
 	if(lcs_getsock(lchpp, &host) < 0) err(EX_IOERR, "Error in lcs_getsock()");
+	printf("sandbox:\tHost at FD %i\n", host);
+	fflush(stdout);
 
 
 	int32_t angel = -1;
 	uint32_t angellen = 1;
 	struct ua_datum *d = ua_recv(host, &angel, &angellen);
 
+	if(!d)
+	{
+		fprintf(stderr, "Received NULL datum\n");
+		return -1;
+	}
+
 	if(angellen != 1)
 	{
 		fprintf(stderr, "Received %i FDs, not 1\n", angellen);
@@ -184,9 +283,92 @@
 	ua_set(angel);
 
 
+
+	// first test X stuff (inc. starting the QApplication)
+	int32_t Xfd = -1;
+	uint32_t Xfdlen = 1;
+	d = ua_recv(host, &Xfd, &Xfdlen);
+
+	if(!d)
+	{
+		fprintf(stderr, "Received NULL datum\n");
+		return -1;
+	}
+
+	if(Xfdlen != 1)
+	{
+		fprintf(stderr, "Received %i FDs, not 1\n", Xfdlen);
+		return -1;
+	}
+
+	printf("sandbox:\tX at FD %i\n", Xfd);
+	fflush(stdout);
+
+	d = ua_recv(host, NULL, 0);
+	if(!d)
+	{
+		fprintf(stderr, "Received NULL datum\n");
+		return -1;
+	}
+
+	unsigned int xauthnamelen = 50;
+	char xauthname[xauthnamelen];
+	if(ua_unmarshall_string(d, xauthname, &xauthnamelen) < 0)
+		err(EX_IOERR, "Error unmarshalling Xauth name");
+
+	printf("sandbox:\tXauth name: %s\n", xauthname);
+	fflush(stdout);
+
+	d = ua_recv(host, NULL, 0);
+	if(!d)
+	{
+		fprintf(stderr, "Received NULL datum\n");
+		return -1;
+	}
+
+	unsigned int xauthdatalen = 50;
+	char xauthdata[xauthdatalen];
+	if(ua_unmarshall_string(d, xauthdata, &xauthdatalen) < 0)
+		err(EX_IOERR, "Error unmarshalling Xauth data");
+
+	printf("sandbox:\tXauth data: ");
+	for(unsigned int i = 0; i < xauthdatalen; i++) printf("%02x ", xauthdata[i] & 0xff);
+	printf("\n");
+	fflush(stdout);
+
+
+	xcb_auth_info_t xauthinfo;
+	xauthinfo.namelen = xauthnamelen;
+	xauthinfo.name = xauthname;
+	xauthinfo.datalen = xauthdatalen;
+	xauthinfo.data = xauthdata;
+
+
+	xcb_auth_cache(&xauthinfo);
+
+
+	char display[20];
+	sprintf(display, "fd://cap:%i", Xfd);
+	setenv("DISPLAY", display, 1);
+	printf("sandbox:\tset DISPLAY to %s\n", getenv("DISPLAY"));
+	fflush(stdout);
+
+	raw_x_tests();
+
+	printf("sandbox:\tCreating QApplication...\n");
+	fflush(stdout);
+	QApplication app(argc, argv);
+	printf("sandbox:\tQApplication started, displaying message box...\n");
+	fflush(stdout);
+	QMessageBox::information(NULL, "Sandbox", "This is sandboxed");
+	printf("sandbox:\tMessage box closed\n");
+	fflush(stdout);
+
+
+
+	// now test file opening
 	int fd = ua_open("/etc/passwd", O_RDONLY);
-	if(fd < 0)
-		err(EX_IOERR, "Error opening passwd via angel: %s", ua_protocol_error());
+	if(fd < 0) err(EX_IOERR, "Error opening passwd via angel");
 
 	char buf[80];
 	bzero(buf, 80);
@@ -197,8 +379,7 @@
 	fflush(stdout);
 
 	FILE *f = ua_fopen("/etc/passwd", "r");
-	if(!f)
-		err(EX_IOERR, "Error opening passwd via angel: %s", ua_protocol_error());
+	if(!f) err(EX_IOERR, "Error opening passwd via angel");
 
 	bzero(buf, 80);
 	if(!fgets(buf, 55, f) < 0) perror("Error reading /etc/passwd");
@@ -220,3 +401,151 @@
 
 	return 0;
 }
+
+
+
+void raw_x_tests()
+{
+	printf("sandbox:\traw_x_tests()\n");
+	fflush(stdout);
+
+  xcb_connection_t    *c;
+  xcb_screen_t        *s;
+  xcb_window_t         w;
+  xcb_gcontext_t       g;
+  xcb_generic_event_t *e;
+  uint32_t             mask;
+  uint32_t             values[2];
+  int                  done = 0;
+  xcb_rectangle_t      r = { 20, 20, 60, 60 };
+ 
+                        /* open connection with the server */
+  int screenp;
+  printf("sandbox:\tConnecting...\n");
+  fflush(stdout);
+  c = xcb_connect_to_display_with_auth_info(NULL, NULL/*xauth*/, &screenp);
+  printf("sandbox:\tConnection: %x\n", (unsigned int) c);
+  fflush(stdout);
+  if (xcb_connection_has_error(c)) {
+    printf("Cannot open display\n");
+    fflush(stdout);
+    return;
+  }
+                        /* get the first screen */
+  s = xcb_setup_roots_iterator( xcb_get_setup(c) ).data;
+ 
+                       /* create black graphics context */
+  g = xcb_generate_id(c);
+  w = s->root;
+  mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
+  values[0] = s->black_pixel;
+  values[1] = 0;
+  xcb_create_gc(c, g, w, mask, values);
+ 
+                       /* create window */
+  w = xcb_generate_id(c);
+  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+  values[0] = s->white_pixel;
+  values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
+  xcb_create_window(c, s->root_depth, w, s->root,
+                    10, 10, 100, 100, 1,
+                    XCB_WINDOW_CLASS_INPUT_OUTPUT, s->root_visual,
+                    mask, values);
+ 
+                        /* map (show) the window */
+  xcb_map_window(c, w);
+ 
+  xcb_flush(c);
+ 
+                        /* event loop */
+  while (!done && (e = xcb_wait_for_event(c))) {
+    switch (e->response_type & ~0x80) {
+    case XCB_EXPOSE:    /* draw or redraw the window */
+      xcb_poly_fill_rectangle(c, w, g,  1, &r);
+      xcb_flush(c);
+      break;
+    case XCB_KEY_PRESS:  /* exit on key press */
+      done = 1;
+      break;
+    }
+    free(e);
+  }
+                        /* close connection to server */
+  xcb_disconnect(c);
+}
+
+
+int connect_to_X(int *Xfd, xcb_auth_info_t *auth)
+{
+	char *host;
+	int display;
+	int screen;
+
+	if(xcb_parse_display(NULL, &host, &display, &screen) < 0) return -1;
+
+	if(host)
+	{
+		*Xfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+		if(*Xfd < 0) return -1;
+
+		int on = 1;
+		setsockopt(*Xfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+
+		struct addrinfo hints, *results, *addr;
+		bzero(&hints, sizeof(hints));
+		hints.ai_family = AF_UNSPEC;
+		hints.ai_socktype = SOCK_STREAM;
+
+		char service[6];
+		int port = 6000 + display;
+
+		snprintf(service, sizeof(service), "%hu", port);
+		if(getaddrinfo(host, service, &hints, &results)) return -1;
+
+		for(addr = results; addr; addr = addr->ai_next)
+		{
+			*Xfd = socket(addr->ai_family, addr->ai_socktype,
+			             addr->ai_protocol);
+
+			if(*Xfd < 0)
+			{
+				close(*Xfd);
+				*Xfd = -1;
+				continue;
+			}
+
+			
+
+           		int on = 1;
+         		setsockopt(*Xfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+
+            		if(connect(*Xfd, addr->ai_addr, addr->ai_addrlen) >= 0)
+			{
+				_xcb_get_auth_info(*Xfd, auth, display);
+				break;
+			}
+		}
+		freeaddrinfo(results);
+
+		return 0;
+	}
+	else
+	{
+		*Xfd = socket(AF_UNIX, SOCK_STREAM, 0);
+		if(*Xfd == -1) return -1;
+
+		char sockname[30];
+		if(snprintf(sockname, sizeof(sockname), "/tmp/.X11-unix/X%i",
+		            display) < 0)
+			return -1;
+
+		struct sockaddr_un addr;
+		strcpy(addr.sun_path, sockname);
+		addr.sun_family = AF_UNIX;
+
+		if(connect(*Xfd, (struct sockaddr*) &addr, sizeof(addr))) return -1;
+
+		return 0;
+	}
+}
+

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/sandbox_qt/sandbox_qt.pro#2 (text+ko) ====

@@ -3,13 +3,11 @@
 DEPENDPATH += .
 INCLUDEPATH += .
 
-QT = core
-
 LIBS += -lcapability -luserangel -lsbuf
 QMAKE_CFLAGS += -g -ggdb
 QMAKE_CXXFLAGS += -g -ggdb
 QMAKE_LFLAGS += -rdynamic
 
 # Input
-SOURCES += sandbox_qt.cpp
+SOURCES += sandbox_qt.cpp xcb_auth.c
 


More information about the p4-projects mailing list