Date: Tue, 14 Jul 2009 06:50:00 GMT From: Jonathan Anderson <jona@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 166064 for review Message-ID: <200907140650.n6E6o0wN033930@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166064 Change 166064 by jona@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907140650.n6E6o0wN033930>