binderfs_test.c 12 KB

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