162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#define _GNU_SOURCE 462306a36Sopenharmony_ci#include <errno.h> 562306a36Sopenharmony_ci#include <fcntl.h> 662306a36Sopenharmony_ci#include <pthread.h> 762306a36Sopenharmony_ci#include <sched.h> 862306a36Sopenharmony_ci#include <stdbool.h> 962306a36Sopenharmony_ci#include <stdio.h> 1062306a36Sopenharmony_ci#include <stdlib.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci#include <sys/fsuid.h> 1362306a36Sopenharmony_ci#include <sys/ioctl.h> 1462306a36Sopenharmony_ci#include <sys/mount.h> 1562306a36Sopenharmony_ci#include <sys/socket.h> 1662306a36Sopenharmony_ci#include <sys/stat.h> 1762306a36Sopenharmony_ci#include <sys/sysinfo.h> 1862306a36Sopenharmony_ci#include <sys/types.h> 1962306a36Sopenharmony_ci#include <sys/wait.h> 2062306a36Sopenharmony_ci#include <unistd.h> 2162306a36Sopenharmony_ci#include <linux/android/binder.h> 2262306a36Sopenharmony_ci#include <linux/android/binderfs.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "../../kselftest_harness.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define DEFAULT_THREADS 4 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define PTR_TO_INT(p) ((int)((intptr_t)(p))) 2962306a36Sopenharmony_ci#define INT_TO_PTR(u) ((void *)((intptr_t)(u))) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define close_prot_errno_disarm(fd) \ 3262306a36Sopenharmony_ci if (fd >= 0) { \ 3362306a36Sopenharmony_ci int _e_ = errno; \ 3462306a36Sopenharmony_ci close(fd); \ 3562306a36Sopenharmony_ci errno = _e_; \ 3662306a36Sopenharmony_ci fd = -EBADF; \ 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic void change_mountns(struct __test_metadata *_metadata) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int ret; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci ret = unshare(CLONE_NEWNS); 4462306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 4562306a36Sopenharmony_ci TH_LOG("%s - Failed to unshare mount namespace", 4662306a36Sopenharmony_ci strerror(errno)); 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0); 5062306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 5162306a36Sopenharmony_ci TH_LOG("%s - Failed to mount / as private", 5262306a36Sopenharmony_ci strerror(errno)); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int __do_binderfs_test(struct __test_metadata *_metadata) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci int fd, ret, saved_errno, result = 1; 5962306a36Sopenharmony_ci size_t len; 6062306a36Sopenharmony_ci ssize_t wret; 6162306a36Sopenharmony_ci struct binderfs_device device = { 0 }; 6262306a36Sopenharmony_ci struct binder_version version = { 0 }; 6362306a36Sopenharmony_ci char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX", 6462306a36Sopenharmony_ci device_path[sizeof(P_tmpdir "/binderfs_XXXXXX/") + BINDERFS_MAX_NAME]; 6562306a36Sopenharmony_ci static const char * const binder_features[] = { 6662306a36Sopenharmony_ci "oneway_spam_detection", 6762306a36Sopenharmony_ci "extended_error", 6862306a36Sopenharmony_ci }; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci change_mountns(_metadata); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci EXPECT_NE(mkdtemp(binderfs_mntpt), NULL) { 7362306a36Sopenharmony_ci TH_LOG("%s - Failed to create binderfs mountpoint", 7462306a36Sopenharmony_ci strerror(errno)); 7562306a36Sopenharmony_ci goto out; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci ret = mount(NULL, binderfs_mntpt, "binder", 0, 0); 7962306a36Sopenharmony_ci EXPECT_EQ(ret, 0) { 8062306a36Sopenharmony_ci if (errno == ENODEV) 8162306a36Sopenharmony_ci SKIP(goto out, "binderfs missing"); 8262306a36Sopenharmony_ci TH_LOG("%s - Failed to mount binderfs", strerror(errno)); 8362306a36Sopenharmony_ci goto rmdir; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* success: binderfs mounted */ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci memcpy(device.name, "my-binder", strlen("my-binder")); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_mntpt); 9162306a36Sopenharmony_ci fd = open(device_path, O_RDONLY | O_CLOEXEC); 9262306a36Sopenharmony_ci EXPECT_GE(fd, 0) { 9362306a36Sopenharmony_ci TH_LOG("%s - Failed to open binder-control device", 9462306a36Sopenharmony_ci strerror(errno)); 9562306a36Sopenharmony_ci goto umount; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci ret = ioctl(fd, BINDER_CTL_ADD, &device); 9962306a36Sopenharmony_ci saved_errno = errno; 10062306a36Sopenharmony_ci close(fd); 10162306a36Sopenharmony_ci errno = saved_errno; 10262306a36Sopenharmony_ci EXPECT_GE(ret, 0) { 10362306a36Sopenharmony_ci TH_LOG("%s - Failed to allocate new binder device", 10462306a36Sopenharmony_ci strerror(errno)); 10562306a36Sopenharmony_ci goto umount; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci TH_LOG("Allocated new binder device with major %d, minor %d, and name %s", 10962306a36Sopenharmony_ci device.major, device.minor, device.name); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* success: binder device allocation */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), "%s/my-binder", binderfs_mntpt); 11462306a36Sopenharmony_ci fd = open(device_path, O_CLOEXEC | O_RDONLY); 11562306a36Sopenharmony_ci EXPECT_GE(fd, 0) { 11662306a36Sopenharmony_ci TH_LOG("%s - Failed to open my-binder device", 11762306a36Sopenharmony_ci strerror(errno)); 11862306a36Sopenharmony_ci goto umount; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci ret = ioctl(fd, BINDER_VERSION, &version); 12262306a36Sopenharmony_ci saved_errno = errno; 12362306a36Sopenharmony_ci close(fd); 12462306a36Sopenharmony_ci errno = saved_errno; 12562306a36Sopenharmony_ci EXPECT_GE(ret, 0) { 12662306a36Sopenharmony_ci TH_LOG("%s - Failed to open perform BINDER_VERSION request", 12762306a36Sopenharmony_ci strerror(errno)); 12862306a36Sopenharmony_ci goto umount; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci TH_LOG("Detected binder version: %d", version.protocol_version); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* success: binder transaction with binderfs binder device */ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci ret = unlink(device_path); 13662306a36Sopenharmony_ci EXPECT_EQ(ret, 0) { 13762306a36Sopenharmony_ci TH_LOG("%s - Failed to delete binder device", 13862306a36Sopenharmony_ci strerror(errno)); 13962306a36Sopenharmony_ci goto umount; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* success: binder device removal */ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_mntpt); 14562306a36Sopenharmony_ci ret = unlink(device_path); 14662306a36Sopenharmony_ci EXPECT_NE(ret, 0) { 14762306a36Sopenharmony_ci TH_LOG("Managed to delete binder-control device"); 14862306a36Sopenharmony_ci goto umount; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci EXPECT_EQ(errno, EPERM) { 15162306a36Sopenharmony_ci TH_LOG("%s - Failed to delete binder-control device but exited with unexpected error code", 15262306a36Sopenharmony_ci strerror(errno)); 15362306a36Sopenharmony_ci goto umount; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* success: binder-control device removal failed as expected */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(binder_features); i++) { 15962306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), "%s/features/%s", 16062306a36Sopenharmony_ci binderfs_mntpt, binder_features[i]); 16162306a36Sopenharmony_ci fd = open(device_path, O_CLOEXEC | O_RDONLY); 16262306a36Sopenharmony_ci EXPECT_GE(fd, 0) { 16362306a36Sopenharmony_ci TH_LOG("%s - Failed to open binder feature: %s", 16462306a36Sopenharmony_ci strerror(errno), binder_features[i]); 16562306a36Sopenharmony_ci goto umount; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci close(fd); 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* success: binder feature files found */ 17162306a36Sopenharmony_ci result = 0; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciumount: 17462306a36Sopenharmony_ci ret = umount2(binderfs_mntpt, MNT_DETACH); 17562306a36Sopenharmony_ci EXPECT_EQ(ret, 0) { 17662306a36Sopenharmony_ci TH_LOG("%s - Failed to unmount binderfs", strerror(errno)); 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_cirmdir: 17962306a36Sopenharmony_ci ret = rmdir(binderfs_mntpt); 18062306a36Sopenharmony_ci EXPECT_EQ(ret, 0) { 18162306a36Sopenharmony_ci TH_LOG("%s - Failed to rmdir binderfs mount", strerror(errno)); 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ciout: 18462306a36Sopenharmony_ci return result; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic int wait_for_pid(pid_t pid) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci int status, ret; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciagain: 19262306a36Sopenharmony_ci ret = waitpid(pid, &status, 0); 19362306a36Sopenharmony_ci if (ret == -1) { 19462306a36Sopenharmony_ci if (errno == EINTR) 19562306a36Sopenharmony_ci goto again; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return -1; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if (!WIFEXITED(status)) 20162306a36Sopenharmony_ci return -1; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci return WEXITSTATUS(status); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic int setid_userns_root(void) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci if (setuid(0)) 20962306a36Sopenharmony_ci return -1; 21062306a36Sopenharmony_ci if (setgid(0)) 21162306a36Sopenharmony_ci return -1; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci setfsuid(0); 21462306a36Sopenharmony_ci setfsgid(0); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cienum idmap_type { 22062306a36Sopenharmony_ci UID_MAP, 22162306a36Sopenharmony_ci GID_MAP, 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic ssize_t read_nointr(int fd, void *buf, size_t count) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci ssize_t ret; 22762306a36Sopenharmony_ciagain: 22862306a36Sopenharmony_ci ret = read(fd, buf, count); 22962306a36Sopenharmony_ci if (ret < 0 && errno == EINTR) 23062306a36Sopenharmony_ci goto again; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return ret; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic ssize_t write_nointr(int fd, const void *buf, size_t count) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci ssize_t ret; 23862306a36Sopenharmony_ciagain: 23962306a36Sopenharmony_ci ret = write(fd, buf, count); 24062306a36Sopenharmony_ci if (ret < 0 && errno == EINTR) 24162306a36Sopenharmony_ci goto again; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return ret; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic int write_id_mapping(enum idmap_type type, pid_t pid, const char *buf, 24762306a36Sopenharmony_ci size_t buf_size) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci int fd; 25062306a36Sopenharmony_ci int ret; 25162306a36Sopenharmony_ci char path[4096]; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (type == GID_MAP) { 25462306a36Sopenharmony_ci int setgroups_fd; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci snprintf(path, sizeof(path), "/proc/%d/setgroups", pid); 25762306a36Sopenharmony_ci setgroups_fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW); 25862306a36Sopenharmony_ci if (setgroups_fd < 0 && errno != ENOENT) 25962306a36Sopenharmony_ci return -1; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (setgroups_fd >= 0) { 26262306a36Sopenharmony_ci ret = write_nointr(setgroups_fd, "deny", sizeof("deny") - 1); 26362306a36Sopenharmony_ci close_prot_errno_disarm(setgroups_fd); 26462306a36Sopenharmony_ci if (ret != sizeof("deny") - 1) 26562306a36Sopenharmony_ci return -1; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci switch (type) { 27062306a36Sopenharmony_ci case UID_MAP: 27162306a36Sopenharmony_ci ret = snprintf(path, sizeof(path), "/proc/%d/uid_map", pid); 27262306a36Sopenharmony_ci break; 27362306a36Sopenharmony_ci case GID_MAP: 27462306a36Sopenharmony_ci ret = snprintf(path, sizeof(path), "/proc/%d/gid_map", pid); 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci default: 27762306a36Sopenharmony_ci return -1; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci if (ret < 0 || ret >= sizeof(path)) 28062306a36Sopenharmony_ci return -E2BIG; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW); 28362306a36Sopenharmony_ci if (fd < 0) 28462306a36Sopenharmony_ci return -1; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci ret = write_nointr(fd, buf, buf_size); 28762306a36Sopenharmony_ci close_prot_errno_disarm(fd); 28862306a36Sopenharmony_ci if (ret != buf_size) 28962306a36Sopenharmony_ci return -1; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic void change_userns(struct __test_metadata *_metadata, int syncfds[2]) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci int ret; 29762306a36Sopenharmony_ci char buf; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[1]); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci ret = unshare(CLONE_NEWUSER); 30262306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 30362306a36Sopenharmony_ci TH_LOG("%s - Failed to unshare user namespace", 30462306a36Sopenharmony_ci strerror(errno)); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci ret = write_nointr(syncfds[0], "1", 1); 30862306a36Sopenharmony_ci ASSERT_EQ(ret, 1) { 30962306a36Sopenharmony_ci TH_LOG("write_nointr() failed"); 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ret = read_nointr(syncfds[0], &buf, 1); 31362306a36Sopenharmony_ci ASSERT_EQ(ret, 1) { 31462306a36Sopenharmony_ci TH_LOG("read_nointr() failed"); 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[0]); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci ASSERT_EQ(setid_userns_root(), 0) { 32062306a36Sopenharmony_ci TH_LOG("setid_userns_root() failed"); 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic void change_idmaps(struct __test_metadata *_metadata, int syncfds[2], pid_t pid) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci int ret; 32762306a36Sopenharmony_ci char buf; 32862306a36Sopenharmony_ci char id_map[4096]; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[0]); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci ret = read_nointr(syncfds[1], &buf, 1); 33362306a36Sopenharmony_ci ASSERT_EQ(ret, 1) { 33462306a36Sopenharmony_ci TH_LOG("read_nointr() failed"); 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci snprintf(id_map, sizeof(id_map), "0 %d 1\n", getuid()); 33862306a36Sopenharmony_ci ret = write_id_mapping(UID_MAP, pid, id_map, strlen(id_map)); 33962306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 34062306a36Sopenharmony_ci TH_LOG("write_id_mapping(UID_MAP) failed"); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci snprintf(id_map, sizeof(id_map), "0 %d 1\n", getgid()); 34462306a36Sopenharmony_ci ret = write_id_mapping(GID_MAP, pid, id_map, strlen(id_map)); 34562306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 34662306a36Sopenharmony_ci TH_LOG("write_id_mapping(GID_MAP) failed"); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci ret = write_nointr(syncfds[1], "1", 1); 35062306a36Sopenharmony_ci ASSERT_EQ(ret, 1) { 35162306a36Sopenharmony_ci TH_LOG("write_nointr() failed"); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[1]); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistruct __test_metadata *_thread_metadata; 35862306a36Sopenharmony_cistatic void *binder_version_thread(void *data) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci struct __test_metadata *_metadata = _thread_metadata; 36162306a36Sopenharmony_ci int fd = PTR_TO_INT(data); 36262306a36Sopenharmony_ci struct binder_version version = { 0 }; 36362306a36Sopenharmony_ci int ret; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci ret = ioctl(fd, BINDER_VERSION, &version); 36662306a36Sopenharmony_ci if (ret < 0) 36762306a36Sopenharmony_ci TH_LOG("%s - Failed to open perform BINDER_VERSION request\n", 36862306a36Sopenharmony_ci strerror(errno)); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci pthread_exit(data); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci/* 37462306a36Sopenharmony_ci * Regression test: 37562306a36Sopenharmony_ci * 2669b8b0c798 ("binder: prevent UAF for binderfs devices") 37662306a36Sopenharmony_ci * f0fe2c0f050d ("binder: prevent UAF for binderfs devices II") 37762306a36Sopenharmony_ci * 211b64e4b5b6 ("binderfs: use refcount for binder control devices too") 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_ciTEST(binderfs_stress) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci int fds[1000]; 38262306a36Sopenharmony_ci int syncfds[2]; 38362306a36Sopenharmony_ci pid_t pid; 38462306a36Sopenharmony_ci int fd, ret; 38562306a36Sopenharmony_ci size_t len; 38662306a36Sopenharmony_ci struct binderfs_device device = { 0 }; 38762306a36Sopenharmony_ci char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX", 38862306a36Sopenharmony_ci device_path[sizeof(P_tmpdir "/binderfs_XXXXXX/") + BINDERFS_MAX_NAME]; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, syncfds); 39162306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 39262306a36Sopenharmony_ci TH_LOG("%s - Failed to create socket pair", strerror(errno)); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci pid = fork(); 39662306a36Sopenharmony_ci ASSERT_GE(pid, 0) { 39762306a36Sopenharmony_ci TH_LOG("%s - Failed to fork", strerror(errno)); 39862306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[0]); 39962306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[1]); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (pid == 0) { 40362306a36Sopenharmony_ci int i, j, k, nthreads; 40462306a36Sopenharmony_ci pthread_attr_t attr; 40562306a36Sopenharmony_ci pthread_t threads[DEFAULT_THREADS]; 40662306a36Sopenharmony_ci change_userns(_metadata, syncfds); 40762306a36Sopenharmony_ci change_mountns(_metadata); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ASSERT_NE(mkdtemp(binderfs_mntpt), NULL) { 41062306a36Sopenharmony_ci TH_LOG("%s - Failed to create binderfs mountpoint", 41162306a36Sopenharmony_ci strerror(errno)); 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = mount(NULL, binderfs_mntpt, "binder", 0, 0); 41562306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 41662306a36Sopenharmony_ci TH_LOG("%s - Failed to mount binderfs, check if CONFIG_ANDROID_BINDERFS is enabled in the running kernel", 41762306a36Sopenharmony_ci strerror(errno)); 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(fds); i++) { 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), 42362306a36Sopenharmony_ci "%s/binder-control", binderfs_mntpt); 42462306a36Sopenharmony_ci fd = open(device_path, O_RDONLY | O_CLOEXEC); 42562306a36Sopenharmony_ci ASSERT_GE(fd, 0) { 42662306a36Sopenharmony_ci TH_LOG("%s - Failed to open binder-control device", 42762306a36Sopenharmony_ci strerror(errno)); 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci memset(&device, 0, sizeof(device)); 43162306a36Sopenharmony_ci snprintf(device.name, sizeof(device.name), "%d", i); 43262306a36Sopenharmony_ci ret = ioctl(fd, BINDER_CTL_ADD, &device); 43362306a36Sopenharmony_ci close_prot_errno_disarm(fd); 43462306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 43562306a36Sopenharmony_ci TH_LOG("%s - Failed to allocate new binder device", 43662306a36Sopenharmony_ci strerror(errno)); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci snprintf(device_path, sizeof(device_path), "%s/%d", 44062306a36Sopenharmony_ci binderfs_mntpt, i); 44162306a36Sopenharmony_ci fds[i] = open(device_path, O_RDONLY | O_CLOEXEC); 44262306a36Sopenharmony_ci ASSERT_GE(fds[i], 0) { 44362306a36Sopenharmony_ci TH_LOG("%s - Failed to open binder device", strerror(errno)); 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci ret = umount2(binderfs_mntpt, MNT_DETACH); 44862306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 44962306a36Sopenharmony_ci TH_LOG("%s - Failed to unmount binderfs", strerror(errno)); 45062306a36Sopenharmony_ci rmdir(binderfs_mntpt); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci nthreads = get_nprocs_conf(); 45462306a36Sopenharmony_ci if (nthreads > DEFAULT_THREADS) 45562306a36Sopenharmony_ci nthreads = DEFAULT_THREADS; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci _thread_metadata = _metadata; 45862306a36Sopenharmony_ci pthread_attr_init(&attr); 45962306a36Sopenharmony_ci for (k = 0; k < ARRAY_SIZE(fds); k++) { 46062306a36Sopenharmony_ci for (i = 0; i < nthreads; i++) { 46162306a36Sopenharmony_ci ret = pthread_create(&threads[i], &attr, binder_version_thread, INT_TO_PTR(fds[k])); 46262306a36Sopenharmony_ci if (ret) { 46362306a36Sopenharmony_ci TH_LOG("%s - Failed to create thread %d", 46462306a36Sopenharmony_ci strerror(errno), i); 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci for (j = 0; j < i; j++) { 47062306a36Sopenharmony_ci void *fdptr = NULL; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci ret = pthread_join(threads[j], &fdptr); 47362306a36Sopenharmony_ci if (ret) 47462306a36Sopenharmony_ci TH_LOG("%s - Failed to join thread %d for fd %d", 47562306a36Sopenharmony_ci strerror(errno), j, PTR_TO_INT(fdptr)); 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci pthread_attr_destroy(&attr); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci for (k = 0; k < ARRAY_SIZE(fds); k++) 48162306a36Sopenharmony_ci close(fds[k]); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci exit(EXIT_SUCCESS); 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci change_idmaps(_metadata, syncfds, pid); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci ret = wait_for_pid(pid); 48962306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 49062306a36Sopenharmony_ci TH_LOG("wait_for_pid() failed"); 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ciTEST(binderfs_test_privileged) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci if (geteuid() != 0) 49762306a36Sopenharmony_ci SKIP(return, "Tests are not run as root. Skipping privileged tests"); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (__do_binderfs_test(_metadata)) 50062306a36Sopenharmony_ci SKIP(return, "The Android binderfs filesystem is not available"); 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ciTEST(binderfs_test_unprivileged) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci int ret; 50662306a36Sopenharmony_ci int syncfds[2]; 50762306a36Sopenharmony_ci pid_t pid; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, syncfds); 51062306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 51162306a36Sopenharmony_ci TH_LOG("%s - Failed to create socket pair", strerror(errno)); 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci pid = fork(); 51562306a36Sopenharmony_ci ASSERT_GE(pid, 0) { 51662306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[0]); 51762306a36Sopenharmony_ci close_prot_errno_disarm(syncfds[1]); 51862306a36Sopenharmony_ci TH_LOG("%s - Failed to fork", strerror(errno)); 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (pid == 0) { 52262306a36Sopenharmony_ci change_userns(_metadata, syncfds); 52362306a36Sopenharmony_ci if (__do_binderfs_test(_metadata)) 52462306a36Sopenharmony_ci exit(2); 52562306a36Sopenharmony_ci exit(EXIT_SUCCESS); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci change_idmaps(_metadata, syncfds, pid); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ret = wait_for_pid(pid); 53162306a36Sopenharmony_ci if (ret) { 53262306a36Sopenharmony_ci if (ret == 2) 53362306a36Sopenharmony_ci SKIP(return, "The Android binderfs filesystem is not available"); 53462306a36Sopenharmony_ci ASSERT_EQ(ret, 0) { 53562306a36Sopenharmony_ci TH_LOG("wait_for_pid() failed"); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ciTEST_HARNESS_MAIN 541