minijail: Allow setting a cap_from_text(3)-compliant string to -c

This change allows callers of minijail0 use a human-friendly string as
argument to the -c flag. This avoids having to add comments explaining
what the cryptic hex constant means.

Bug: None
Test: # ./minijail0 -T static --ambient \
          -c 'cap_dac_read_search,cap_dac_override+e' -- \
          /bin/grep Cap /proc/self/status
      CapInh: 0000000000000006
      CapPrm: 0000000000000006
      CapEff: 0000000000000006
      CapBnd: 0000000000000006
      CapAmb: 0000000000000006
Test: # ./minijail0 -T static -- /bin/grep Cap /proc/self/status
      CapInh: 0000000000000000
      CapPrm: 0000003fffffffff
      CapEff: 0000003fffffffff
      CapBnd: 0000003fffffffff
      CapAmb: 0000000000000000

Change-Id: I2e352178ab479859d999d936bbc7eb3ed6f370ff
diff --git a/minijail0_cli.c b/minijail0_cli.c
index a1ee82b..ea66d7c 100644
--- a/minijail0_cli.c
+++ b/minijail0_cli.c
@@ -82,13 +82,37 @@
 
 static void use_caps(struct minijail *j, const char *arg)
 {
-	uint64_t caps;
-	char *end = NULL;
-	caps = strtoull(arg, &end, 16);
-	if (*end) {
-		fprintf(stderr, "Invalid cap set: '%s'\n", arg);
-		exit(1);
+	uint64_t caps = 0;
+	cap_t parsed_caps = cap_from_text(arg);
+
+	if (parsed_caps != NULL) {
+		unsigned int i;
+		const uint64_t one = 1;
+		cap_flag_value_t cap_value;
+		unsigned int last_valid_cap = get_last_valid_cap();
+
+		for (i = 0; i <= last_valid_cap; ++i) {
+			if (cap_get_flag(parsed_caps, i, CAP_EFFECTIVE,
+					 &cap_value)) {
+				fprintf(stderr,
+					"Could not get the value of "
+					"the %d-th capability: %m\n",
+					i);
+				exit(1);
+			}
+			if (cap_value == CAP_SET)
+				caps |= (one << i);
+		}
+		cap_free(parsed_caps);
+	} else {
+		char *end = NULL;
+		caps = strtoull(arg, &end, 16);
+		if (*end) {
+			fprintf(stderr, "Invalid cap set: '%s'\n", arg);
+			exit(1);
+		}
 	}
+
 	minijail_use_caps(j, caps);
 }