PERFORCE change 164664 for review

Jonathan Anderson jona at FreeBSD.org
Thu Jun 18 13:02:33 UTC 2009


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

Change 164664 by jona at jona-trustedbsd-kentvm on 2009/06/18 13:01:59

	Error message passing and handling

Affected files ...

.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#6 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.h#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#11 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#10 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#7 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#8 edit

Differences ...

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#6 (text+ko) ====

@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
@@ -41,21 +41,27 @@
 #include "cap.h"
 
 
+char errstr[512];
+const char *cap_error() { return errstr; }
+
+
 int cap_open(const char *path, int flags, cap_rights_t rights)
 {
 	int fd = open(path, flags);
 	if(fd < 0)
 	{
-		char error[80 + strlen(path)];
-		sprintf(error, "failed to open() path '%s'", path);
-		perror(error);
+		if(strlen(path) > 256) path = "<very long path>";
+		sprintf(errstr, "Failed to open() path '%s': %i (%s)",
+		                 path, errno, strerror(errno));
 		return -1;
 	}
 
 	int cap = cap_new(fd, rights);
 	if(cap < 0)
 	{
-		perror("Failed to create new capability");
+		if(strlen(path) > 256) path = "<very long path>";
+		sprintf(errstr, "Failed to create new capability: %i (%s)",
+		                 errno, strerror(errno));
 		return -1;
 	}
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.h#3 (text+ko) ====

@@ -41,6 +41,9 @@
 #define CAP_SET_FILE_RW		(CAP_SET_FILE_READ | CAP_SET_FILE_WRITE)
 
 
+/** The last capability-related error */
+const char *cap_error();
+
 
 /** Open a file in capability mode with specified rights */
 int cap_open(const char *path, int flags, cap_rights_t rights);

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#11 (text+ko) ====

@@ -44,9 +44,30 @@
 #include "protocol.h"
 
 
+char errmsg[256];
+const char* cap_protocol_error(void) { return errmsg; }
+
+typedef struct cap_wire_datum wire_datum;
 
 
 
+void handle_error(const wire_datum *d)
+{
+	int32_t errnum;
+	char msg[200];
+	int msglen = 200;
+
+	if(cap_unmarshall_error(d, &errnum, msg, &msglen) < 0)
+	{
+		sprintf(errmsg, "Error unmarshalling error message\n");
+		return;
+	}
+
+	sprintf(errmsg, "user_angel error: %s (%i: %s)",
+	                msg, errnum, strerror(errnum));
+}
+
+
 void print_datum(const struct cap_wire_datum *d)
 {
 	printf("Datum @ 0x%8x:\n", (unsigned int) d);
@@ -65,14 +86,6 @@
 
 
 
-
-typedef struct cap_wire_datum wire_datum;
-
-
-char errmsg[256];
-const char* cap_error(void) { return errmsg; }
-
-
 wire_datum* cap_marshall_int(int32_t value)
 {
 	int size = sizeof(wire_datum) + sizeof(int32_t);
@@ -99,8 +112,9 @@
 
 	if(!(datum->type & INTEGER))
 	{
-		sprintf(errmsg, "Datum's type is %i, not INTEGER (%i)",
-		        datum->type, INTEGER);
+		if(datum->type & ERROR) handle_error(datum);
+		else sprintf(errmsg, "Datum's type is %i, not INTEGER (%i)",
+		             datum->type, INTEGER);
 		return -1;
 	}
 
@@ -138,8 +152,9 @@
 	}
 	else if(datum->type != STRING)
 	{
-		sprintf(errmsg, "Datum's type is %i, not STRING (%i)",
-		        datum->type, STRING);
+		if(datum->type & ERROR) handle_error(datum);
+		else sprintf(errmsg, "Datum's type is %i, not STRING (%i)",
+		                     datum->type, STRING);
 	}
 	else if(datum->length < 0)
 	{
@@ -163,40 +178,25 @@
 
 
 
-wire_datum* cap_marshall_error(int errno, const char *msg, int msglen)
+wire_datum* cap_marshall_error(int errnum, const char *msg, int msglen)
 {
-	wire_datum *data[2];
-	data[0] = cap_marshall_int(errno);
-	data[1] = cap_marshall_string(msg, msglen);
-
-	int total_size = 0;
-	for(int i = 0; i < 2; i++)
-		if(data[i] == NULL)
-		{
-			sprintf(errmsg, "Error datum %i is NULL", i);
-			return NULL;
-		}
-		else total_size += (sizeof(wire_datum) + data[i]->length);
-
-	wire_datum *d = (wire_datum*) malloc(sizeof(wire_datum) + total_size);
+	int size = sizeof(wire_datum) + sizeof(int32_t) + msglen;
+	wire_datum *d = (wire_datum*) malloc(size);
+	
 	d->type = ERROR;
-	d->length = total_size;
+	d->length = sizeof(int32_t) + msglen;
 
-	char *buffer = ((char*) d) + sizeof(wire_datum);
-	char *head = buffer;
-	for(int i = 0; i < 2; i++)
-	{
-		memcpy(head, data[i], sizeof(wire_datum) + data[i]->length);
-		head += sizeof(wire_datum) + data[i]->length;
+	char *address = ((char*) d) + sizeof(wire_datum);
+	*((int32_t*) address) = errnum;
 
-		free(data[i]);
-	}
+	address += sizeof(int32_t);
+	memcpy((char*) address, msg, msglen);
 
 	return d;
 }
 
 
-int cap_unmarshall_error(const wire_datum *d, int *errno, const char *msg, int *msglen)
+int cap_unmarshall_error(const wire_datum *datum, int *errnum, char *msg, int *msglen)
 {
 	if(datum == NULL)
 	{
@@ -214,30 +214,22 @@
 		                datum->length);
 		return -1;
 	}
-
-	int32_t tmp_int;
-	wire_datum *d = (wire_datum*) (((char*) datum) + sizeof(wire_datum));
-
-	if(cap_unmarshall_int(d, &tmp_int) < 0)
+	else if(datum->length >= (*msglen - sizeof(int32_t)))
 	{
-		char error[128];
-		sprintf(error, "Error unmarshalling errno: %s", cap_error());
-		strcpy(errmsg, error);
+		sprintf(errmsg, "Message is too long (%iB) to fit in buffer (%iB)",
+		        datum->length - sizeof(int32_t), *msglen);
 		return -1;
 	}
-	*errno = tmp_int;
-	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
 
+	char *address = ((char*) datum) + sizeof(wire_datum);
+	*errnum = *((int32_t*) address);
+	address += sizeof(int32_t);
 
-	if(cap_unmarshall_string(d, msg, msglen) < 0)
-	{
-		char error[128];
-		sprintf(error, "Error unmarshalling path: %s", cap_error());
-		strcpy(errmsg, error);
-		return -1;
-	}
+	*msglen = datum->length - sizeof(int32_t);
+	memcpy(msg, address, *msglen);
+	msg[*msglen] = '\0';
 
-	return sizeof(wire_datum) + datum->length;
+	return datum->length;
 }
 
 
@@ -290,8 +282,10 @@
 	}
 	else if(datum->type != CAPBOX_OPTIONS)
 	{
-		sprintf(errmsg, "Datum's type is %i, not CAPBOX_OPTIONS (%i)",
-		        datum->type, CAPBOX_OPTIONS);
+		if(datum->type & ERROR) handle_error(datum);
+		else sprintf(errmsg, "Datum's type is %i, not CAPBOX_OPTIONS (%i)",
+		                     datum->type, CAPBOX_OPTIONS);
+		return -1;
 	}
 	else if(datum->length < 0)
 	{
@@ -306,7 +300,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling UI type: %s", cap_error());
+		sprintf(error, "Error unmarshalling UI type: %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -316,7 +310,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling operation: %s", cap_error());
+		sprintf(error, "Error unmarshalling operation: %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -330,7 +324,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling parent: %s", cap_error());
+		sprintf(error, "Error unmarshalling parent: %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -342,7 +336,7 @@
 	if(cap_unmarshall_string(d, (char*) options->start_path, &options->pathlen) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling path: %s", cap_error());
+		sprintf(error, "Error unmarshalling path: %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -356,7 +350,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling 'mult': %s", cap_error());
+		sprintf(error, "Error unmarshalling 'mult': %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -368,7 +362,7 @@
 	if(cap_unmarshall_string(d, (char*) options->filter, &options->filterlen) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling filter: %s", cap_error());
+		sprintf(error, "Error unmarshalling filter: %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -377,7 +371,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling 'flags': %s", cap_error());
+		sprintf(error, "Error unmarshalling 'flags': %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}
@@ -387,7 +381,7 @@
 	if(cap_unmarshall_int(d, &tmp_int) < 0)
 	{
 		char error[128];
-		sprintf(error, "Error unmarshalling 'rights': %s", cap_error());
+		sprintf(error, "Error unmarshalling 'rights': %s", cap_protocol_error());
 		strcpy(errmsg, error);
 		return -1;
 	}

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#10 (text+ko) ====

@@ -46,7 +46,7 @@
 
 
 /** The last protocol error */
-const char* cap_error(void);
+const char* cap_protocol_error(void);
 
 
 
@@ -76,14 +76,14 @@
 /* Unmarshalling functions; calling programs should free the result */
 struct cap_wire_datum* cap_marshall_int(int32_t value);
 struct cap_wire_datum* cap_marshall_string(const char *value, int len);
-struct cap_wire_datum* cap_marshall_error(int errno, const char *msg, int msglen);
+struct cap_wire_datum* cap_marshall_error(int errnum, const char *msg, int msglen);
 struct cap_wire_datum* cap_marshall_capbox(const struct capbox_options *options);
 
 
 /* Unmarshalling functions; return the number of bytes unmarshalled (or -1) */
 int cap_unmarshall_int(const struct cap_wire_datum *d, int32_t *value);
 int cap_unmarshall_string(const struct cap_wire_datum *d, char *value, int *len);
-int cap_unmarshall_error(const struct cap_wire_datum *d, int *errno, const char *msg, int *msglen);
+int cap_unmarshall_error(const struct cap_wire_datum *d, int *errnum, char *msg, int *msglen);
 int cap_unmarshall_capbox(const struct cap_wire_datum *d, struct capbox_options *options);
 
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#7 (text+ko) ====

@@ -53,6 +53,8 @@
 int shutting_down = 0;
 char control_socket_name[256] = "";
 
+char current_error[512];
+
 struct fd_set clients;
 int highest_fd;
 
@@ -76,7 +78,7 @@
 int	handle_request(int client, enum capangel_req_t req);
 int	handle_path_request(int client);
 int	handle_powerbox_request(int client);
-void	client_closed(int client);
+void	close_client(int client, int errnum, const char *msg);
 
 
 
@@ -242,7 +244,7 @@
 	if(!d)
 	{
 		if((errno == ENOENT) || (errno == ECONNRESET))
-			client_closed(client);
+			close_client(client, errno, "Client socket closed");
 
 		else perror("Error receiving from client");
 
@@ -256,20 +258,20 @@
 
 	else
 	{
-		fprintf(stderr, "enum size is %iB\n", sizeof(enum capangel_req_t));
+		sprintf(current_error, "enum size is %iB",
+		                       sizeof(enum capangel_req_t));
 		return -1;
 	}
 
 	if(bytes < 0)
 	{
-		fprintf(stderr, "Error unmarshalling request: %s\n", cap_error());
+		strcpy(current_error, cap_protocol_error());
 		return -1;
 	}
 
 	if(handle_request(client, req))
 	{
-		perror("Error handling client request");
-		client_closed(client);
+		close_client(client, errno, current_error);
 		return 0;
 	}
 
@@ -292,7 +294,7 @@
 			return handle_powerbox_request(client);
 
 		default:
-			fprintf(stderr, "Unknown request %i\n", req);
+			sprintf(current_error, "Unknown request %i", req);
 			return -1;
 	}
 
@@ -303,37 +305,48 @@
 int handle_path_request(int client)
 {
 	int fdlen = 0;
+	char path[256] = "";
+	int pathlen = 256;
+
 	struct cap_wire_datum *d = cap_recv_fds(client, NULL, &fdlen);
+	if(cap_unmarshall_string(d, path, &pathlen) < 0)
+	{
+		strcpy(current_error, cap_protocol_error());
+		return -1;
+	}
+	free(d);
 
-	if(!d)
+	int32_t flags, rights;
+	if(cap_unmarshall_int(cap_recv(client), &flags) < 0)
 	{
-		perror("Error receiving path from client");
+		fprintf(stderr, "Error unmarshalling flags: %s\n", cap_protocol_error());
 		return -1;
 	}
 
-	char path[256] = "";
-	int pathlen = 256;
-
-	if(cap_unmarshall_string(d, path, &pathlen) < 0)
+	if(cap_unmarshall_int(cap_recv(client), &rights) < 0)
 	{
-		fprintf(stderr, "Error unmarshalling path: %s\n", cap_error());
+		fprintf(stderr, "Error unmarshalling rights: %s\n", cap_protocol_error());
 		return -1;
 	}
-	free(d);
 
 
-	int cap = cap_open(path, O_RDONLY, CAP_SET_FILE_READ);
+	int cap = cap_open(path, flags, rights);
+	if(cap < 0)
+	{
+		strcpy(current_error, cap_error());
+		return -1;
+	}
 
 	d = cap_marshall_int(1);
 	if(!d)
 	{
-		fprintf(stderr, "Error marshalling FD count: %s\n", cap_error());
+		strcpy(current_error, cap_protocol_error());
 		return -1;
 	}
 
 	if(cap_send(client, d) < 0)
 	{
-		perror("Error sending FD count");
+		sprintf(current_error, "Error sending FD count: %s", strerror(errno));
 		return -1;
 	}
 	free(d);
@@ -341,7 +354,7 @@
 	d = cap_marshall_string(path, pathlen);
 	if(!d)
 	{
-		fprintf(stderr, "Error marshalling FD path: %s\n", cap_error());
+		strcpy(current_error, cap_protocol_error());
 		return -1;
 	}
 
@@ -371,8 +384,7 @@
 
 	if(cap_unmarshall_capbox(d, &options) < 0)
 	{
-		fprintf(stderr, "Error unmarshalling powerbox options: %s",
-		        cap_error());
+		strcpy(current_error, cap_protocol_error());
 		return -1;
 	}
 
@@ -388,8 +400,8 @@
 	int len = 32;
 	if(capbox_display(&options, fds, names, &len))
 	{
-		fprintf(stderr, "Error in powerbox\n");
-		return 0;
+		strcpy(current_error, "Unknown error in powerbox");
+		return -1;
 	}
 
 	free(options.window_title);
@@ -419,9 +431,13 @@
 }
 
 
-void client_closed(int client)
+void close_client(int client, int errnum, const char *reason)
 {
-	printf("Client %4i: Closed\n", client);
+	printf("Client %4i: Closing (errno: %i/'%s', reason: '%s')\n",
+	       client, errnum, strerror(errnum), reason);
+
+	cap_send(client, cap_marshall_error(errnum, reason, strlen(reason)));
+
 	close(client);
 	FD_CLR(client, &clients);
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#8 (text+ko) ====

@@ -15,7 +15,7 @@
 
 
 int connect_to_user_angel(void);
-void open_file(int fd_angel, const char *path);
+void open_file(int fd_angel, const char *path, int flags, cap_rights_t rights);
 void open_powerbox(int fd_angel, const char *path, const char *filter, int parent);
 void test_fd(int fd, char *name);
 
@@ -61,8 +61,8 @@
 
 
 
-	open_file(fd_angel, "/etc/group");
-	open_file(fd_angel, "/etc/passwd");
+	open_file(fd_angel, "/etc/group", O_RDONLY, CAP_FSTAT | CAP_READ | CAP_SEEK);
+	open_file(fd_angel, "/etc/passwd", O_RDONLY, CAP_FSTAT | CAP_READ | CAP_WRITE | CAP_SEEK);
 	open_powerbox(fd_angel, "~/Desktop/", "*.gz", 0x2a00003);
 
 	return 0;
@@ -94,19 +94,23 @@
 
 
 
-void open_file(int fd_angel, const char *path)
+void open_file(int fd_angel, const char *path, int flags, cap_rights_t rights)
 {
 	// get the user angel to open the file for us
-	struct cap_wire_datum *data[2];
+	struct cap_wire_datum *data[4];
 	data[0] = cap_marshall_int(FD_FROM_PATH);
 	data[1] = cap_marshall_string(path, strlen(path));
+	data[2] = cap_marshall_int(flags);
+	data[3] = cap_marshall_int(rights);
 
 
-	if(cap_send_message(fd_angel, data, 2) < 0)
+	if(cap_send_message(fd_angel, data, 4) < 0)
 		err(EX_IOERR, "Error sending request message");
 
 	free(data[0]);
 	free(data[1]);
+	free(data[2]);
+	free(data[3]);
 
 
 
@@ -116,7 +120,10 @@
 
 	int fdcount;
 	if(cap_unmarshall_int(fdcountd, &fdcount) < 0)
-		err(EX_SOFTWARE, "Error unmarshalling FD count");
+	{
+		fprintf(stderr, "Error unmarshalling FD count: %s\n", cap_protocol_error());
+		return;
+	}
 
 	for(int i = 0; i < fdcount; i++)
 	{


More information about the p4-projects mailing list