Fix marshaling for supplementary gid list.

We were not marshaling the supplementary gid list at all.
While in there, make unmarshaling seccomp filters more robust.

Bug: 25870500
Change-Id: I8b7d832ae62eaa3d859863b3fdd7f9772732239f
diff --git a/libminijail.c b/libminijail.c
index 8b8100e..a29ebdf 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -600,7 +600,7 @@
 }
 
 void marshal_append(struct marshal_state *state,
-		    char *src, size_t length)
+		    void *src, size_t length)
 {
 	size_t copy_len = MIN(state->available, length);
 
@@ -621,6 +621,10 @@
 	marshal_append(state, (char *)j, sizeof(*j));
 	if (j->user)
 		marshal_append(state, j->user, strlen(j->user) + 1);
+	if (j->suppl_gid_list) {
+		marshal_append(state, j->suppl_gid_list,
+			       j->suppl_gid_count * sizeof(gid_t));
+	}
 	if (j->chrootdir)
 		marshal_append(state, j->chrootdir, strlen(j->chrootdir) + 1);
 	if (j->alt_syscall_table) {
@@ -716,6 +720,23 @@
 			goto clear_pointers;
 	}
 
+	if (j->suppl_gid_list) {	/* stale pointer */
+		if (j->suppl_gid_count > NGROUPS_MAX) {
+			goto bad_gid_list;
+		}
+		size_t gid_list_size = j->suppl_gid_count * sizeof(gid_t);
+		void *gid_list_bytes =
+		    consumebytes(gid_list_size, &serialized, &length);
+		if (!gid_list_bytes)
+			goto bad_gid_list;
+
+		j->suppl_gid_list = calloc(j->suppl_gid_count, sizeof(gid_t));
+		if (!j->suppl_gid_list)
+			goto bad_gid_list;
+
+		memcpy(j->suppl_gid_list, gid_list_bytes, gid_list_size);
+	}
+
 	if (j->chrootdir) {	/* stale pointer */
 		char *chrootdir = consumestr(&serialized, &length);
 		if (!chrootdir)
@@ -746,8 +767,14 @@
 			goto bad_filters;
 
 		j->filter_prog = malloc(sizeof(struct sock_fprog));
+		if (!j->filter_prog)
+			goto bad_filters;
+
 		j->filter_prog->len = ninstrs;
 		j->filter_prog->filter = malloc(program_len);
+		if (!j->filter_prog->filter)
+			goto bad_filter_prog_instrs;
+
 		memcpy(j->filter_prog->filter, program, program_len);
 	}
 
@@ -780,6 +807,9 @@
 		free(j->filter_prog->filter);
 		free(j->filter_prog);
 	}
+bad_filter_prog_instrs:
+	if (j->filter_prog)
+		free(j->filter_prog);
 bad_filters:
 	if (j->alt_syscall_table)
 		free(j->alt_syscall_table);
@@ -787,10 +817,14 @@
 	if (j->chrootdir)
 		free(j->chrootdir);
 bad_chrootdir:
+	if (j->suppl_gid_list)
+		free(j->suppl_gid_list);
+bad_gid_list:
 	if (j->user)
 		free(j->user);
 clear_pointers:
 	j->user = NULL;
+	j->suppl_gid_list = NULL;
 	j->chrootdir = NULL;
 	j->alt_syscall_table = NULL;
 out: