From owner-p4-projects@FreeBSD.ORG Thu Jun 11 12:01:07 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2453B10656CF; Thu, 11 Jun 2009 12:01:06 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5952C10656F1 for ; Thu, 11 Jun 2009 12:01:05 +0000 (UTC) (envelope-from jona@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 39AEC8FC2E for ; Thu, 11 Jun 2009 12:01:05 +0000 (UTC) (envelope-from jona@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5BC15tZ045658 for ; Thu, 11 Jun 2009 12:01:05 GMT (envelope-from jona@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5BC15Fe045656 for perforce@freebsd.org; Thu, 11 Jun 2009 12:01:05 GMT (envelope-from jona@FreeBSD.org) Date: Thu, 11 Jun 2009 12:01:05 GMT Message-Id: <200906111201.n5BC15Fe045656@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jona@FreeBSD.org using -f From: Jonathan Anderson To: Perforce Change Reviews Cc: Subject: PERFORCE change 164095 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jun 2009 12:01:15 -0000 http://perforce.freebsd.org/chv.cgi?CH=164095 Change 164095 by jona@jona-trustedbsd-belle-vm on 2009/06/11 12:00:09 user_angel can now handle requests for powerboxes (although the powerbox isn't actually implemented yet) Affected files ... .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdcomm.c#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#3 edit .. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/user_angel.c#3 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#3 (text+ko) ==== @@ -1,7 +1,7 @@ CFLAGS=-g -ggdb --std=c99 -Wall -Werror -pedantic-errors BIN=user_angel test_client -AGENT_OBJ = user_angel.o server.o cap.o protocol.o fdcomm.o +AGENT_OBJ = user_angel.o server.o cap.o protocol.o fdcomm.o powerbox.o CLIENT_OBJ = test_client.o protocol.o fdcomm.o @@ -16,7 +16,8 @@ cap.o: cap.c cap.h fdcomm.o: fdcomm.c fdcomm.h -protocol.o: protocol.c protocol.h +powerbox.o: powerbox.c powerbox.h +protocol.o: protocol.c protocol.h powerbox.h server.o: server.c protocol.h server.h user_angel.o: user_angel.c protocol.h server.h ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdcomm.c#3 (text+ko) ==== @@ -100,6 +100,7 @@ anc_data.hdr.cmsg_len = sizeof(struct fdhdr); anc_data.hdr.cmsg_level = SOL_SOCKET; anc_data.hdr.cmsg_type = SCM_RIGHTS; + anc_data.fd = -1; struct msghdr header; header.msg_name = NULL; ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#3 (text+ko) ==== @@ -33,32 +33,152 @@ #include +#include +#include +#include +#include + #include "protocol.h" -int get_int_from(int client, int *value) + +int cap_send_int(int client, int value) +{ + return send(client, &value, sizeof(int), 0); +} + +int cap_recv_int(int client, int *value) +{ + int bytes = -1; + while(bytes < 0) + { + bytes = recv(client, value, sizeof(int), 0); + + if((bytes < 0) && (errno == EAGAIN)) continue; + else break; + } + + return bytes; +} + + +int cap_send_string(int client, char *str, int len) { - return recv(client, value, sizeof(int), 0); + int total_bytes; + int bytes = cap_send_int(client, len); + if(bytes < 0) return bytes; + else total_bytes = bytes; + + if(len > 0) + { + bytes = send(client, str, len, 0); + if(bytes < 0) { perror("Error sending string"); return bytes; } + else total_bytes += bytes; + } + + return total_bytes; } -int get_string_from(int client, char *value, int maxlen) +int cap_recv_string(int client, char **value) { - int len; - int bytes = get_int_from(client, &len); - if(bytes <= 0) return bytes; + int len, total_bytes; + int bytes = cap_recv_int(client, &len); + if(bytes<= 0) return bytes; + else total_bytes = bytes; + + *value = (char*) malloc(len + 1); bytes = 0; while(bytes < len) { - int new_bytes = recv(client, value + bytes, maxlen - bytes, 0); + int new_bytes = recv(client, *value + bytes, len - bytes, 0); if(new_bytes < 0) return new_bytes; - bytes = bytes + new_bytes; + bytes += new_bytes; } - return bytes; + (*value)[len] = '\0'; + total_bytes += bytes; + + return total_bytes; +} + + +int cap_send_capbox_options(int client, struct capbox_options *options) +{ + int bytes, total_bytes = 0; + + bytes = cap_send_int(client, options->ui); + if(bytes <= 0) return bytes; + total_bytes += bytes; + + bytes = cap_send_int(client, options->operation); + if(bytes <= 0) return bytes; + total_bytes += bytes; + + bytes = cap_send_int(client, options->parent_window); + if(bytes <= 0) return bytes; + total_bytes += bytes; + + bytes = cap_send_string(client, options->start_path, options->pathlen); + if(bytes <= 0) return bytes; + total_bytes += bytes; +/* TODO: need to do a sendmsg with SCM_RIGHTS + bytes = cap_send_int(client, options->start_fd); + if(bytes <= 0) return bytes; + total_bytes += bytes; +*/ + bytes = cap_send_int(client, options->mult); + if(bytes <= 0) return bytes; + total_bytes += bytes; + + bytes = cap_send_string(client, options->filter, options->filterlen); + if(bytes <= 0) return bytes; + total_bytes += bytes; + + return total_bytes; } +int cap_recv_capbox_options(int client, struct capbox_options *options) +{ + int bytes, total_bytes = 0; + + bytes = cap_recv_int(client, (int*) &options->ui); + if(bytes <= 0) { perror("Error receiving UI option"); return bytes; } + total_bytes += bytes; + + bytes = cap_recv_int(client, (int*) &options->operation); + if(bytes <= 0) { perror("Error receiving operation"); return bytes; } + total_bytes += bytes; + + bytes = cap_recv_int(client, &options->parent_window); + if(bytes <= 0) { perror("Error receiving parent winid"); return bytes; } + total_bytes += bytes; + + bytes = cap_recv_string(client, &options->start_path); + if(bytes < 0) { perror("Error receiving start path"); return bytes; } + total_bytes += bytes; + + options->pathlen = bytes; +/* TODO: need to do a sendmsg with SCM_RIGHTS + bytes = cap_recv_int(client, &options->start_fd); + if(bytes <= 0) { perror("Error receiving path FD"); return bytes; } + total_bytes += bytes; +*/ + options->start_fd = -1; + + bytes = cap_recv_int(client, &options->mult); + if(bytes <= 0) { perror("Error receiving multiple option"); return bytes; } + total_bytes += bytes; + + bytes = cap_recv_string(client, &options->filter); + if(bytes <= 0) { perror("Error receiving filter"); return bytes; } + total_bytes += bytes; + + options->filterlen = bytes; + + return total_bytes; +} ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#3 (text+ko) ==== @@ -34,27 +34,24 @@ #include __FBSDID("$FreeBSD$"); +#include "powerbox.h" + /** Requests that clients can make */ -enum user_angel_request +enum capangel_req_t { FD_FROM_PATH, - FD_POWERBOX, - FD_POWERBOX_RELATIVE_PATH, - FD_POWERBOX_RELATIVE_FD + FD_POWERBOX }; -typedef int user_angel_powerbox_options; -#define POWERBOX_KDE 0x01 -#define POWERBOX_GNOME 0x02 /* currently no support */ +int cap_send_int(int client, int value); +int cap_recv_int(int client, int *value); +int cap_send_string(int client, char *value, int len); +int cap_recv_string(int client, char **value); - - - -int get_int_from(int client, int *value); -int get_string_from(int client, char *value, int maxlen); - +int cap_send_capbox_options(int client, struct capbox_options *options); +int cap_recv_capbox_options(int client, struct capbox_options *options); ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#3 (text+ko) ==== @@ -72,7 +72,7 @@ -int handle_request(int client, enum user_angel_request req); +int handle_request(int client, enum capangel_req_t req); int bind_to_path(const char *path); void accept_client(int fd_server); void service_clients(void); @@ -204,19 +204,25 @@ void service_clients(void) { - enum user_angel_request req; + enum capangel_req_t req; for(int i = 0; i < clientslen; i++) { int client = clients[i]; - int bytes = get_int_from(client, (int*) &req); + if(client == -1) continue; + + int bytes = cap_recv_int(client, (int*) &req); if(bytes > 0) { if(handle_request(client, req)) + { perror("Error handling client request"); + close(client); + clients[i] = -1; + } } - else if((bytes == 0) && (errno == EAGAIN)) continue; + else if(errno == EAGAIN) continue; else { if(shutting_down) return; @@ -229,7 +235,7 @@ -int handle_request(int client, enum user_angel_request req) +int handle_request(int client, enum capangel_req_t req) { printf("Client %i requests ", client); @@ -237,33 +243,57 @@ { case FD_FROM_PATH: ; - char path[256]; - int bytes = get_string_from(client, path, sizeof(path) - 1); + char *path; + int bytes = cap_recv_string(client, &path); if(bytes < 0) { perror("Error getting string from client"); return -1; } - path[bytes] = '\0'; printf("FD_FROM_PATH: %s\n", path); int cap = cap_open(path, O_RDONLY, CAP_SET_FILE_READ); if(fd_send(client, cap)) + { perror("Error sending file descriptor"); - - break; + return -1; + } + else return 0; case FD_POWERBOX: puts("FD_POWERBOX"); - break; + + struct capbox_options options; + if(cap_recv_capbox_options(client, &options) < 0) + { + perror("Error receiving capbox_options"); + return -1; + } + + // TODO: some more sophisticated per-client state (eg name) + options.window_title = (char*) malloc(80); + sprintf(options.window_title, + "Powerbox for user_angel client %i", client); + + int fd = capbox_display(&options); + if(fd < 0) + { + perror("Error in powerbox"); + cap_send_string(client, "error in powerbox", 17); + return 0; + } + + free(options.window_title); + free(options.start_path); - case FD_POWERBOX_RELATIVE_PATH: - puts("FD_POWERBOX_RELATIVE_PATH"); - break; + if(fd_send(client, cap)) + { + perror("Error sending file descriptor"); + return -1; + } + else return 0; - case FD_POWERBOX_RELATIVE_FD: - puts("FD_POWERBOX_RELATIVE_FD"); break; default: ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#3 (text+ko) ==== @@ -18,10 +18,13 @@ int connect_to_user_angel(void); -int -main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - int fd_control = connect_to_user_angel(); + int fd_angel = connect_to_user_angel(); + printf("angel FD: %i\n", fd_angel); + + fd_angel = cap_new(fd_angel, CAP_CONNECT | CAP_READ | CAP_WRITE); + printf("angel cap: %i\n", fd_angel); int proc; pid_t pid = pdfork(&proc); @@ -31,64 +34,69 @@ else if(pid == 0) return 0; // enter capability mode -// if(cap_enter()) err(EX_SOFTWARE, "Failed to enter capability mode"); -// else printf("Now operating in capability mode\n"); + if(cap_enter()) err(EX_SOFTWARE, "Failed to enter capability mode"); + else printf("Now operating in capability mode\n"); + // make sure that we are, in fact, sandboxed + char *path = "/etc/passwd"; + if(open(path, O_RDONLY) < 0) printf("Sandbox is working\n"); + else fprintf(stderr, "Was able to open %s directly\n", path); - enum user_angel_request req = FD_FROM_PATH; - char *path = "/etc/passwd"; - int len = strlen(path); - // make sure that we are, in fact, sandboxed - if(open(path, O_RDONLY) < 0) printf("Sandbox is working\n"); - else fprintf(stderr, "Was able to open %s directly\n", path); + enum capangel_req_t req = FD_FROM_PATH; +// char *path = "/etc/passwd"; + int len = strlen(path); // get the user angel to open the file for us - if(send(fd_control, &req, sizeof(int), 0) < 0) + if(cap_send_int(fd_angel, req) < 0) err(EX_IOERR, "Error sending request type %i", req); - if(send(fd_control, &len, sizeof(int), 0) < 0) - err(EX_IOERR, "Error sending path length %i", len); - - if(send(fd_control, path, len, 0) < 0) + if(cap_send_string(fd_angel, path, len) < 0) err(EX_IOERR, "Error sending path '%s'", path); // retrieve the file descriptor - int fd = fd_recv(fd_control); + int fd = fd_recv(fd_angel); if(fd >= 0) printf("Got file descriptor %i\n", fd); - else { fprintf(stderr, "Error receiving descriptor\n"); return 1; } + else err(EX_IOERR, "Error receiving file descriptor"); + // do some reading + char buf[40]; + read(fd, buf, 40); + printf("Data from %s: %s\n", path, buf); - - path = "/etc/group"; - // get the user angel to open the file for us - if(send(fd_control, &req, sizeof(int), 0) < 0) - err(EX_IOERR, "Error sending request type %i", req); - if(send(fd_control, &len, sizeof(int), 0) < 0) - err(EX_IOERR, "Error sending path length %i", len); + // now, let's try a powerbox! + req = FD_POWERBOX; - if(send(fd_control, path, len, 0) < 0) - err(EX_IOERR, "Error sending path '%s'", path); + struct capbox_options options; + options.ui = KDE; + options.operation = OPEN_FILE; + options.parent_window = 0; + options.start_path = NULL; + options.pathlen = 0; + options.start_fd = -1; + options.mult = 1; + options.filter = "*.c"; + options.filterlen = strlen(options.filter); + if(cap_send_int(fd_angel, req) < 0) + err(EX_IOERR, "Error sending powerbox request"); + int bytes = cap_send_capbox_options(fd_angel, &options); + if(bytes < 0) + err(EX_IOERR, "Error sending capbox_options"); - // retrieve the file descriptor - fd = fd_recv(fd_control); + fd = fd_recv(fd_angel); if(fd >= 0) printf("Got file descriptor %i\n", fd); - else { fprintf(stderr, "Error receiving descriptor\n"); return 1; } + else err(EX_IOERR, "Error receiving file descriptor"); - char buf[40]; - read(fd, buf, 40); - printf("Data from %s: %s\n", path, buf); - return 0; } @@ -109,10 +117,10 @@ addr.sun_family = AF_UNIX; strcpy(addr.sun_path, control_socket_name); - int fd_control = socket(AF_UNIX, SOCK_STREAM, 0); - if(connect(fd_control, (struct sockaddr*) &addr, sizeof(addr))) + int fd_angel = socket(AF_UNIX, SOCK_STREAM, 0); + if(connect(fd_angel, (struct sockaddr*) &addr, sizeof(addr))) err(EX_IOERR, "Error connecting to angel at '%s'", addr.sun_path); - return fd_control; + return fd_angel; } ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/user_angel.c#3 (text+ko) ==== @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "server.h" @@ -59,18 +60,22 @@ void sighandle(int sig) { - fprintf(stderr, "Caught signal %i\n", sig); - switch(sig) { case SIGINT: fprintf(stderr, "Caught SIGINT, shutting down...\n"); user_angel_server_shutdown(); - break; + exit(0); + + case SIGSEGV: + fprintf(stderr, "Caught SIGSEGV, shutting down...\n"); + user_angel_server_shutdown(); + exit(EX_SOFTWARE); default: fprintf(stderr, "Unexpected signal %i; panic!\n", sig); user_angel_server_shutdown(); + exit(EX_SOFTWARE); } } @@ -81,6 +86,7 @@ char *homedir = getenv("HOME"); signal(SIGINT, sighandle); + signal(SIGSEGV, sighandle); if(strlen(homedir) >= 80) {