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