PERFORCE change 164095 for review

Jonathan Anderson jona at FreeBSD.org
Thu Jun 11 12:01:15 UTC 2009


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

Change 164095 by jona at 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 <sys/socket.h>
 
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #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 <sys/cdefs.h>
 __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 <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sysexits.h>
 #include <unistd.h>
 
 #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)
 	{


More information about the p4-projects mailing list