minijail: Add support for building constants through masks

This change adds support for building numeric constants through
bitmasks. Things like "O_WRONLY|O_CREAT" are now valid constants.

Since this change works at the atom level, there can be no spaces around
the "|" character.

BUG=chromium:516701
TEST=syscall_filter_unittest passes.

Change-Id: Ia74957f4c5661c9dff7df072684cc6d725c83c10
Reviewed-on: https://chromium-review.googlesource.com/290468
Tested-by: Luis Hector Chavez <lhchavez@google.com>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Queue: Luis Hector Chavez <lhchavez@google.com>
diff --git a/util.c b/util.c
index 6b16a23..90ac9f0 100644
--- a/util.c
+++ b/util.c
@@ -40,6 +40,8 @@
 
 const size_t log_syscalls_len = sizeof(log_syscalls)/sizeof(log_syscalls[0]);
 
+long int parse_single_constant(char *constant_str, char **endptr);
+
 int lookup_syscall(const char *name)
 {
 	const struct syscall_entry *entry = syscall_table;
@@ -60,6 +62,36 @@
 
 long int parse_constant(char *constant_str, char **endptr)
 {
+	long int value = 0;
+	char *group, *lastpos = constant_str;
+	char *original_constant_str = constant_str;
+
+	/*
+	 * Try to parse constants separated by pipes.  Note that since
+	 * |constant_str| is an atom, there can be no spaces between the
+	 * constant and the pipe.  Constants can be either a named constant
+	 * defined in libconstants.gen.c or a number parsed with strtol.
+	 *
+	 * If there is an error parsing any of the constants, the whole process
+	 * fails.
+	 */
+	while ((group = tokenize(&constant_str, "|")) != NULL) {
+		char *end = group;
+		value |= parse_single_constant(group, &end);
+		if (end == group) {
+			lastpos = original_constant_str;
+			value = 0;
+			break;
+		}
+		lastpos = end;
+	}
+	if (endptr)
+		*endptr = lastpos;
+	return value;
+}
+
+long int parse_single_constant(char *constant_str, char **endptr)
+{
 	const struct constant_entry *entry = constant_table;
 	for (; entry->name; ++entry) {
 		if (!strcmp(entry->name, constant_str)) {