Merge "call abort() on sigsys"
diff --git a/Android.mk b/Android.mk
index 5cd0499..013ee3b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -162,6 +162,23 @@
 include $(BUILD_NATIVE_TEST)
 
 
+# test_minijail executable for brillo_Minijail test.
+# =========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libminijail_test
+ifdef BRILLO
+  LOCAL_MODULE_TAGS := eng
+endif
+
+LOCAL_CFLAGS := $(minijailCommonCFlags)
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := \
+	test/libminijail_test.cpp
+
+LOCAL_SHARED_LIBRARIES := libbase libminijail
+include $(BUILD_EXECUTABLE)
+
+
 # libminijail usage example.
 # =========================================================
 include $(CLEAR_VARS)
diff --git a/examples/drop_privs.cpp b/examples/drop_privs.cpp
index 26d1659..d2b0e17 100644
--- a/examples/drop_privs.cpp
+++ b/examples/drop_privs.cpp
@@ -48,6 +48,7 @@
     for (size_t i = 0; i < (size_t)nsupp_groups; i++) {
         LOG(INFO) << "supp gid " << i + 1 << " " << list[i];
     }
+    free(list);
 }
 
 int main(void) {
diff --git a/test/libminijail_test.cpp b/test/libminijail_test.cpp
new file mode 100644
index 0000000..c8b26c4
--- /dev/null
+++ b/test/libminijail_test.cpp
@@ -0,0 +1,102 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <sys/types.h>
+#include <sys/capability.h>
+#include <unistd.h>
+
+#include <libminijail.h>
+
+#include <android-base/logging.h>
+
+const uid_t kSystemUid = 1000U;
+
+gid_t groups[] = { kSystemUid + 1, kSystemUid + 2 };
+
+size_t getgroups_with_alloc(gid_t **plist) {
+    *plist = NULL;
+
+    int nsupp_groups = getgroups(0, NULL);
+    if (nsupp_groups < 0) {
+        PLOG(ERROR) << "getgroups(0)";
+        return 0;
+    }
+    if (nsupp_groups == 0) {
+        LOG(INFO) << "no supplemental groups";
+        return 0;
+    }
+
+    *plist = (gid_t*)calloc((size_t)nsupp_groups, sizeof(gid_t));
+    nsupp_groups = getgroups(nsupp_groups, *plist);
+    if (nsupp_groups < 0) {
+        PLOG(ERROR) << "getgroups(nsupp_groups)";
+        free(*plist);
+        return 0;
+    }
+    return nsupp_groups;
+}
+
+bool check_ugid(uid_t expected_id) {
+    bool success = true;
+    uid_t ruid = getuid();
+    if (ruid != expected_id) {
+        LOG(ERROR) << "rUID << " << ruid << " is not " << expected_id;
+        success = false;
+    }
+    gid_t rgid = getgid();
+    if (rgid != expected_id) {
+        LOG(ERROR) << "rGID << " << ruid << " is not " << expected_id;
+        success = false;
+    }
+    return success;
+}
+
+void log_resugid() {
+    uid_t ruid, euid, suid;
+    gid_t rgid, egid, sgid;
+    getresuid(&ruid, &euid, &suid);
+    getresgid(&rgid, &egid, &sgid);
+
+    LOG(INFO) << "ruid " << ruid << " euid " << euid << " suid " << suid;
+    LOG(INFO) << "rgid " << rgid << " egid " << egid << " sgid " << sgid;
+
+    gid_t *list;
+    size_t nsupp_groups = getgroups_with_alloc(&list);
+    for (size_t i = 0; i < (size_t)nsupp_groups; i++) {
+        LOG(INFO) << "supp gid " << i + 1 << " " << list[i];
+    }
+    free(list);
+}
+
+int main(void) {
+    log_resugid();
+    minijail *j = minijail_new();
+    minijail_change_user(j, "system");
+    minijail_change_group(j, "system");
+    minijail_set_supplementary_gids(j, sizeof(groups) / sizeof(groups[0]), groups);
+    minijail_use_caps(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
+    minijail_enter(j);
+
+    check_ugid(kSystemUid);
+
+    minijail_destroy(j);
+    minijail *j2 = minijail_new();
+    minijail_change_uid(j2, 5 * kSystemUid);
+    minijail_change_gid(j2, 5 * kSystemUid);
+    minijail_enter(j2);
+
+    check_ugid(5 * kSystemUid);
+
+    return 0;
+}