1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 #include <errno.h> 5 #include <fcntl.h> 6 #include <pthread.h> 7 #include <sched.h> 8 #include <stdbool.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/fsuid.h> 13 #include <sys/ioctl.h> 14 #include <sys/mount.h> 15 #include <sys/socket.h> 16 #include <sys/stat.h> 17 #include <sys/sysinfo.h> 18 #include <sys/types.h> 19 #include <sys/wait.h> 20 #include <unistd.h> 21 #include <linux/android/binder.h> 22 #include <linux/android/binderfs.h> 23 24 #include "../../kselftest.h" 25 #include "../../kselftest_harness.h" 26 27 #define DEFAULT_THREADS 4 28 29 #define PTR_TO_INT(p) ((int)((intptr_t)(p))) 30 #define INT_TO_PTR(u) ((void *)((intptr_t)(u))) 31 32 #define close_prot_errno_disarm(fd) \ 33 if (fd >= 0) { \ 34 int _e_ = errno; \ 35 close(fd); \ 36 errno = _e_; \ 37 fd = -EBADF; \ 38 } 39 40 #define log_exit(format, ...) \ 41 ({ \ 42 fprintf(stderr, format "\n", ##__VA_ARGS__); \ 43 exit(EXIT_FAILURE); \ 44 }) 45 46 static void change_mountns(void) 47 { 48 int ret; 49 50 ret = unshare(CLONE_NEWNS); 51 if (ret < 0) 52 ksft_exit_fail_msg("%s - Failed to unshare mount namespace\n", 53 strerror(errno)); 54 55 ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0); 56 if (ret < 0) 57 ksft_exit_fail_msg("%s - Failed to mount / as private\n", 58 strerror(errno)); 59 } 60 61 static void rmdir_protect_errno(const char *dir) 62 { 63 int saved_errno = errno; 64 (void)rmdir(dir); 65 errno = saved_errno; 66 } 67 68 static int __do_binderfs_test(void) 69 { 70 int fd, ret, saved_errno; 71 size_t len; 72 ssize_t wret; 73 struct binderfs_device device = { 0 }; 74 struct binder_version version = { 0 }; 75 char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX", 76 device_path[sizeof(P_tmpdir "/binderfs_XXXXXX/") + BINDERFS_MAX_NAME]; 77 78 change_mountns(); 79 80 if (!mkdtemp(binderfs_mntpt)) 81 ksft_exit_fail_msg( 82 "%s - Failed to create binderfs mountpoint\n", 83 strerror(errno)); 84 85 ret = mount(NULL, binderfs_mntpt, "binder", 0, 0); 86 if (ret < 0) { 87 if (errno != ENODEV) 88 ksft_exit_fail_msg("%s - Failed to mount binderfs\n", 89 strerror(errno)); 90 91 rmdir_protect_errno(binderfs_mntpt); 92 return 1; 93 } 94 95 /* binderfs mount test passed */ 96 ksft_inc_pass_cnt(); 97 98 memcpy(device.name, "my-binder", strlen("my-binder")); 99 100 snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_mntpt); 101 fd = open(device_path, O_RDONLY | O_CLOEXEC); 102 if (fd < 0) 103 ksft_exit_fail_msg( 104 "%s - Failed to open binder-control device\n", 105 strerror(errno)); 106 107 ret = ioctl(fd, BINDER_CTL_ADD, &device); 108 saved_errno = errno; 109 close(fd); 110 errno = saved_errno; 111 if (ret < 0) { 112 rmdir_protect_errno(binderfs_mntpt); 113 ksft_exit_fail_msg( 114 "%s - Failed to allocate new binder device\n", 115 strerror(errno)); 116 } 117 118 ksft_print_msg( 119 "Allocated new binder device with major %d, minor %d, and name %s\n", 120 device.major, device.minor, device.name); 121 122 /* binder device allocation test passed */ 123 ksft_inc_pass_cnt(); 124 125 snprintf(device_path, sizeof(device_path), "%s/my-binder", binderfs_mntpt); 126 fd = open(device_path, O_CLOEXEC | O_RDONLY); 127 if (fd < 0) { 128 rmdir_protect_errno(binderfs_mntpt); 129 ksft_exit_fail_msg("%s - Failed to open my-binder device\n", 130 strerror(errno)); 131 } 132 133 ret = ioctl(fd, BINDER_VERSION, &version); 134 saved_errno = errno; 135 close(fd); 136 errno = saved_errno; 137 if (ret < 0) { 138 rmdir_protect_errno(binderfs_mntpt); 139 ksft_exit_fail_msg( 140 "%s - Failed to open perform BINDER_VERSION request\n", 141 strerror(errno)); 142 } 143 144 ksft_print_msg("Detected binder version: %d\n", 145 version.protocol_version); 146 147 /* binder transaction with binderfs binder device passed */ 148 ksft_inc_pass_cnt(); 149 150 ret = unlink(device_path); 151 if (ret < 0) { 152 rmdir_protect_errno(binderfs_mntpt); 153 ksft_exit_fail_msg("%s - Failed to delete binder device\n", 154 strerror(errno)); 155 } 156 157 /* binder device removal passed */ 158 ksft_inc_pass_cnt(); 159 160 snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_mntpt); 161 ret = unlink(device_path); 162 if (!ret) { 163 rmdir_protect_errno(binderfs_mntpt); 164 ksft_exit_fail_msg("Managed to delete binder-control device\n"); 165 } else if (errno != EPERM) { 166 rmdir_protect_errno(binderfs_mntpt); 167 ksft_exit_fail_msg( 168 "%s - Failed to delete binder-control device but exited with unexpected error code\n", 169 strerror(errno)); 170 } 171 172 /* binder-control device removal failed as expected */ 173 ksft_inc_xfail_cnt(); 174 175 on_error: 176 ret = umount2(binderfs_mntpt, MNT_DETACH); 177 rmdir_protect_errno(binderfs_mntpt); 178 if (ret < 0) 179 ksft_exit_fail_msg("%s - Failed to unmount binderfs\n", 180 strerror(errno)); 181 182 /* binderfs unmount test passed */ 183 ksft_inc_pass_cnt(); 184 return 0; 185 } 186 187 static int wait_for_pid(pid_t pid) 188 { 189 int status, ret; 190 191 again: 192 ret = waitpid(pid, &status, 0); 193 if (ret == -1) { 194 if (errno == EINTR) 195 goto again; 196 197 return -1; 198 } 199 200 if (!WIFEXITED(status)) 201 return -1; 202 203 return WEXITSTATUS(status); 204 } 205 206 static int setid_userns_root(void) 207 { 208 if (setuid(0)) 209 return -1; 210 if (setgid(0)) 211 return -1; 212 213 setfsuid(0); 214 setfsgid(0); 215 216 return 0; 217 } 218 219 enum idmap_type { 220 UID_MAP, 221 GID_MAP, 222 }; 223 224 static ssize_t read_nointr(int fd, void *buf, size_t count) 225 { 226 ssize_t ret; 227 again: 228 ret = read(fd, buf, count); 229 if (ret < 0 && errno == EINTR) 230 goto again; 231 232 return ret; 233 } 234 235 static ssize_t write_nointr(int fd, const void *buf, size_t count) 236 { 237 ssize_t ret; 238 again: 239 ret = write(fd, buf, count); 240 if (ret < 0 && errno == EINTR) 241 goto again; 242 243 return ret; 244 } 245 246 static int write_id_mapping(enum idmap_type type, pid_t pid, const char *buf, 247 size_t buf_size) 248 { 249 int fd; 250 int ret; 251 char path[4096]; 252 253 if (type == GID_MAP) { 254 int setgroups_fd; 255 256 snprintf(path, sizeof(path), "/proc/%d/setgroups", pid); 257 setgroups_fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW); 258 if (setgroups_fd < 0 && errno != ENOENT) 259 return -1; 260 261 if (setgroups_fd >= 0) { 262 ret = write_nointr(setgroups_fd, "deny", sizeof("deny") - 1); 263 close_prot_errno_disarm(setgroups_fd); 264 if (ret != sizeof("deny") - 1) 265 return -1; 266 } 267 } 268 269 switch (type) { 270 case UID_MAP: 271 ret = snprintf(path, sizeof(path), "/proc/%d/uid_map", pid); 272 break; 273 case GID_MAP: 274 ret = snprintf(path, sizeof(path), "/proc/%d/gid_map", pid); 275 break; 276 default: 277 return -1; 278 } 279 if (ret < 0 || ret >= sizeof(path)) 280 return -E2BIG; 281 282 fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW); 283 if (fd < 0) 284 return -1; 285 286 ret = write_nointr(fd, buf, buf_size); 287 close_prot_errno_disarm(fd); 288 if (ret != buf_size) 289 return -1; 290 291 return 0; 292 } 293 294 static void change_userns(int syncfds[2]) 295 { 296 int ret; 297 char buf; 298 299 close_prot_errno_disarm(syncfds[1]); 300 301 ret = unshare(CLONE_NEWUSER); 302 if (ret < 0) 303 ksft_exit_fail_msg("%s - Failed to unshare user namespace\n", 304 strerror(errno)); 305 306 ret = write_nointr(syncfds[0], "1", 1); 307 if (ret != 1) 308 ksft_exit_fail_msg("write_nointr() failed\n"); 309 310 ret = read_nointr(syncfds[0], &buf, 1); 311 if (ret != 1) 312 ksft_exit_fail_msg("read_nointr() failed\n"); 313 314 close_prot_errno_disarm(syncfds[0]); 315 316 if (setid_userns_root()) 317 ksft_exit_fail_msg("setid_userns_root() failed"); 318 } 319 320 static void change_idmaps(int syncfds[2], pid_t pid) 321 { 322 int ret; 323 char buf; 324 char id_map[4096]; 325 326 close_prot_errno_disarm(syncfds[0]); 327 328 ret = read_nointr(syncfds[1], &buf, 1); 329 if (ret != 1) 330 ksft_exit_fail_msg("read_nointr() failed\n"); 331 332 snprintf(id_map, sizeof(id_map), "0 %d 1\n", getuid()); 333 ret = write_id_mapping(UID_MAP, pid, id_map, strlen(id_map)); 334 if (ret) 335 ksft_exit_fail_msg("write_id_mapping(UID_MAP) failed"); 336 337 snprintf(id_map, sizeof(id_map), "0 %d 1\n", getgid()); 338 ret = write_id_mapping(GID_MAP, pid, id_map, strlen(id_map)); 339 if (ret) 340 ksft_exit_fail_msg("write_id_mapping(GID_MAP) failed"); 341 342 ret = write_nointr(syncfds[1], "1", 1); 343 if (ret != 1) 344 ksft_exit_fail_msg("write_nointr() failed"); 345 346 close_prot_errno_disarm(syncfds[1]); 347 } 348 349 static void *binder_version_thread(void *data) 350 { 351 int fd = PTR_TO_INT(data); 352 struct binder_version version = { 0 }; 353 int ret; 354 355 ret = ioctl(fd, BINDER_VERSION, &version); 356 if (ret < 0) 357 ksft_print_msg("%s - Failed to open perform BINDER_VERSION request\n", strerror(errno)); 358 359 pthread_exit(data); 360 } 361 362 /* 363 * Regression test: 364 * 2669b8b0c798 ("binder: prevent UAF for binderfs devices") 365 * f0fe2c0f050d ("binder: prevent UAF for binderfs devices II") 366 * 211b64e4b5b6 ("binderfs: use refcount for binder control devices too") 367 */ 368 TEST(binderfs_stress) 369 { 370 int fds[1000]; 371 int syncfds[2]; 372 pid_t pid; 373 int fd, ret; 374 size_t len; 375 struct binderfs_device device = { 0 }; 376 char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX", 377 device_path[sizeof(P_tmpdir "/binderfs_XXXXXX/") + BINDERFS_MAX_NAME]; 378 379 ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, syncfds); 380 if (ret < 0) 381 ksft_exit_fail_msg("%s - Failed to create socket pair", strerror(errno)); 382 383 pid = fork(); 384 if (pid < 0) { 385 close_prot_errno_disarm(syncfds[0]); 386 close_prot_errno_disarm(syncfds[1]); 387 ksft_exit_fail_msg("%s - Failed to fork", strerror(errno)); 388 } 389 390 if (pid == 0) { 391 int i, j, k, nthreads; 392 pthread_attr_t attr; 393 pthread_t threads[DEFAULT_THREADS]; 394 change_userns(syncfds); 395 change_mountns(); 396 397 if (!mkdtemp(binderfs_mntpt)) 398 log_exit("%s - Failed to create binderfs mountpoint\n", 399 strerror(errno)); 400 401 ret = mount(NULL, binderfs_mntpt, "binder", 0, 0); 402 if (ret < 0) 403 log_exit("%s - Failed to mount binderfs\n", strerror(errno)); 404 405 for (int i = 0; i < ARRAY_SIZE(fds); i++) { 406 407 snprintf(device_path, sizeof(device_path), 408 "%s/binder-control", binderfs_mntpt); 409 fd = open(device_path, O_RDONLY | O_CLOEXEC); 410 if (fd < 0) 411 log_exit("%s - Failed to open binder-control device\n", strerror(errno)); 412 413 memset(&device, 0, sizeof(device)); 414 snprintf(device.name, sizeof(device.name), "%d", i); 415 ret = ioctl(fd, BINDER_CTL_ADD, &device); 416 close_prot_errno_disarm(fd); 417 if (ret < 0) 418 log_exit("%s - Failed to allocate new binder device\n", strerror(errno)); 419 420 snprintf(device_path, sizeof(device_path), "%s/%d", 421 binderfs_mntpt, i); 422 fds[i] = open(device_path, O_RDONLY | O_CLOEXEC); 423 if (fds[i] < 0) 424 log_exit("%s - Failed to open binder device\n", strerror(errno)); 425 } 426 427 ret = umount2(binderfs_mntpt, MNT_DETACH); 428 rmdir_protect_errno(binderfs_mntpt); 429 if (ret < 0) 430 log_exit("%s - Failed to unmount binderfs\n", strerror(errno)); 431 432 nthreads = get_nprocs_conf(); 433 if (nthreads > DEFAULT_THREADS) 434 nthreads = DEFAULT_THREADS; 435 436 pthread_attr_init(&attr); 437 for (k = 0; k < ARRAY_SIZE(fds); k++) { 438 for (i = 0; i < nthreads; i++) { 439 ret = pthread_create(&threads[i], &attr, binder_version_thread, INT_TO_PTR(fds[k])); 440 if (ret) { 441 ksft_print_msg("%s - Failed to create thread %d\n", strerror(errno), i); 442 break; 443 } 444 } 445 446 for (j = 0; j < i; j++) { 447 void *fdptr = NULL; 448 449 ret = pthread_join(threads[j], &fdptr); 450 if (ret) 451 ksft_print_msg("%s - Failed to join thread %d for fd %d\n", strerror(errno), j, PTR_TO_INT(fdptr)); 452 } 453 } 454 pthread_attr_destroy(&attr); 455 456 for (k = 0; k < ARRAY_SIZE(fds); k++) 457 close(fds[k]); 458 459 exit(EXIT_SUCCESS); 460 } 461 462 change_idmaps(syncfds, pid); 463 464 ret = wait_for_pid(pid); 465 if (ret) 466 ksft_exit_fail_msg("wait_for_pid() failed"); 467 } 468 469 TEST(binderfs_test_privileged) 470 { 471 if (geteuid() != 0) 472 XFAIL(return, "Tests are not run as root. Skipping privileged tests"); 473 474 if (__do_binderfs_test() == 1) 475 XFAIL(return, "The Android binderfs filesystem is not available"); 476 } 477 478 TEST(binderfs_test_unprivileged) 479 { 480 int ret; 481 int syncfds[2]; 482 pid_t pid; 483 484 ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, syncfds); 485 if (ret < 0) 486 ksft_exit_fail_msg("%s - Failed to create socket pair", strerror(errno)); 487 488 pid = fork(); 489 if (pid < 0) { 490 close_prot_errno_disarm(syncfds[0]); 491 close_prot_errno_disarm(syncfds[1]); 492 ksft_exit_fail_msg("%s - Failed to fork", strerror(errno)); 493 } 494 495 if (pid == 0) { 496 change_userns(syncfds); 497 if (__do_binderfs_test() == 1) 498 exit(2); 499 exit(EXIT_SUCCESS); 500 } 501 502 change_idmaps(syncfds, pid); 503 504 ret = wait_for_pid(pid); 505 if (ret) { 506 if (ret == 2) 507 XFAIL(return, "The Android binderfs filesystem is not available"); 508 else 509 ksft_exit_fail_msg("wait_for_pid() failed"); 510 } 511 } 512 513 TEST_HARNESS_MAIN 514