1 // SPDX-License-Identifier: GPL-2.0
12 #include <sys/fsuid.h>
13 #include <sys/ioctl.h>
14 #include <sys/mount.h>
15 #include <sys/socket.h>
17 #include <sys/sysinfo.h>
18 #include <sys/types.h>
21 #include <linux/android/binder.h>
22 #include <linux/android/binderfs.h>
24 #include "../../kselftest_harness.h"
26 #define DEFAULT_THREADS 4
28 #define PTR_TO_INT(p) ((int)((intptr_t)(p)))
29 #define INT_TO_PTR(u) ((void *)((intptr_t)(u)))
31 #define close_prot_errno_disarm(fd) \
39 static void change_mountns(struct __test_metadata
*_metadata
)
43 ret
= unshare(CLONE_NEWNS
);
45 TH_LOG("%s - Failed to unshare mount namespace",
49 ret
= mount(NULL
, "/", NULL
, MS_REC
| MS_PRIVATE
, 0);
51 TH_LOG("%s - Failed to mount / as private",
56 static int __do_binderfs_test(struct __test_metadata
*_metadata
)
58 int fd
, ret
, saved_errno
, result
= 1;
61 struct binderfs_device device
= { 0 };
62 struct binder_version version
= { 0 };
63 char binderfs_mntpt
[] = P_tmpdir
"/binderfs_XXXXXX",
64 device_path
[sizeof(P_tmpdir
"/binderfs_XXXXXX/") + BINDERFS_MAX_NAME
];
66 change_mountns(_metadata
);
68 EXPECT_NE(mkdtemp(binderfs_mntpt
), NULL
) {
69 TH_LOG("%s - Failed to create binderfs mountpoint",
74 ret
= mount(NULL
, binderfs_mntpt
, "binder", 0, 0);
77 SKIP(goto out
, "binderfs missing");
78 TH_LOG("%s - Failed to mount binderfs", strerror(errno
));
82 /* success: binderfs mounted */
84 memcpy(device
.name
, "my-binder", strlen("my-binder"));
86 snprintf(device_path
, sizeof(device_path
), "%s/binder-control", binderfs_mntpt
);
87 fd
= open(device_path
, O_RDONLY
| O_CLOEXEC
);
89 TH_LOG("%s - Failed to open binder-control device",
94 ret
= ioctl(fd
, BINDER_CTL_ADD
, &device
);
99 TH_LOG("%s - Failed to allocate new binder device",
104 TH_LOG("Allocated new binder device with major %d, minor %d, and name %s",
105 device
.major
, device
.minor
, device
.name
);
107 /* success: binder device allocation */
109 snprintf(device_path
, sizeof(device_path
), "%s/my-binder", binderfs_mntpt
);
110 fd
= open(device_path
, O_CLOEXEC
| O_RDONLY
);
112 TH_LOG("%s - Failed to open my-binder device",
117 ret
= ioctl(fd
, BINDER_VERSION
, &version
);
122 TH_LOG("%s - Failed to open perform BINDER_VERSION request",
127 TH_LOG("Detected binder version: %d", version
.protocol_version
);
129 /* success: binder transaction with binderfs binder device */
131 ret
= unlink(device_path
);
133 TH_LOG("%s - Failed to delete binder device",
138 /* success: binder device removal */
140 snprintf(device_path
, sizeof(device_path
), "%s/binder-control", binderfs_mntpt
);
141 ret
= unlink(device_path
);
143 TH_LOG("Managed to delete binder-control device");
146 EXPECT_EQ(errno
, EPERM
) {
147 TH_LOG("%s - Failed to delete binder-control device but exited with unexpected error code",
152 /* success: binder-control device removal failed as expected */
156 ret
= umount2(binderfs_mntpt
, MNT_DETACH
);
158 TH_LOG("%s - Failed to unmount binderfs", strerror(errno
));
161 ret
= rmdir(binderfs_mntpt
);
163 TH_LOG("%s - Failed to rmdir binderfs mount", strerror(errno
));
169 static int wait_for_pid(pid_t pid
)
174 ret
= waitpid(pid
, &status
, 0);
182 if (!WIFEXITED(status
))
185 return WEXITSTATUS(status
);
188 static int setid_userns_root(void)
206 static ssize_t
read_nointr(int fd
, void *buf
, size_t count
)
210 ret
= read(fd
, buf
, count
);
211 if (ret
< 0 && errno
== EINTR
)
217 static ssize_t
write_nointr(int fd
, const void *buf
, size_t count
)
221 ret
= write(fd
, buf
, count
);
222 if (ret
< 0 && errno
== EINTR
)
228 static int write_id_mapping(enum idmap_type type
, pid_t pid
, const char *buf
,
235 if (type
== GID_MAP
) {
238 snprintf(path
, sizeof(path
), "/proc/%d/setgroups", pid
);
239 setgroups_fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
240 if (setgroups_fd
< 0 && errno
!= ENOENT
)
243 if (setgroups_fd
>= 0) {
244 ret
= write_nointr(setgroups_fd
, "deny", sizeof("deny") - 1);
245 close_prot_errno_disarm(setgroups_fd
);
246 if (ret
!= sizeof("deny") - 1)
253 ret
= snprintf(path
, sizeof(path
), "/proc/%d/uid_map", pid
);
256 ret
= snprintf(path
, sizeof(path
), "/proc/%d/gid_map", pid
);
261 if (ret
< 0 || ret
>= sizeof(path
))
264 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
268 ret
= write_nointr(fd
, buf
, buf_size
);
269 close_prot_errno_disarm(fd
);
276 static void change_userns(struct __test_metadata
*_metadata
, int syncfds
[2])
281 close_prot_errno_disarm(syncfds
[1]);
283 ret
= unshare(CLONE_NEWUSER
);
285 TH_LOG("%s - Failed to unshare user namespace",
289 ret
= write_nointr(syncfds
[0], "1", 1);
291 TH_LOG("write_nointr() failed");
294 ret
= read_nointr(syncfds
[0], &buf
, 1);
296 TH_LOG("read_nointr() failed");
299 close_prot_errno_disarm(syncfds
[0]);
301 ASSERT_EQ(setid_userns_root(), 0) {
302 TH_LOG("setid_userns_root() failed");
306 static void change_idmaps(struct __test_metadata
*_metadata
, int syncfds
[2], pid_t pid
)
312 close_prot_errno_disarm(syncfds
[0]);
314 ret
= read_nointr(syncfds
[1], &buf
, 1);
316 TH_LOG("read_nointr() failed");
319 snprintf(id_map
, sizeof(id_map
), "0 %d 1\n", getuid());
320 ret
= write_id_mapping(UID_MAP
, pid
, id_map
, strlen(id_map
));
322 TH_LOG("write_id_mapping(UID_MAP) failed");
325 snprintf(id_map
, sizeof(id_map
), "0 %d 1\n", getgid());
326 ret
= write_id_mapping(GID_MAP
, pid
, id_map
, strlen(id_map
));
328 TH_LOG("write_id_mapping(GID_MAP) failed");
331 ret
= write_nointr(syncfds
[1], "1", 1);
333 TH_LOG("write_nointr() failed");
336 close_prot_errno_disarm(syncfds
[1]);
339 struct __test_metadata
*_thread_metadata
;
340 static void *binder_version_thread(void *data
)
342 struct __test_metadata
*_metadata
= _thread_metadata
;
343 int fd
= PTR_TO_INT(data
);
344 struct binder_version version
= { 0 };
347 ret
= ioctl(fd
, BINDER_VERSION
, &version
);
349 TH_LOG("%s - Failed to open perform BINDER_VERSION request\n",
357 * 2669b8b0c798 ("binder: prevent UAF for binderfs devices")
358 * f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
359 * 211b64e4b5b6 ("binderfs: use refcount for binder control devices too")
361 TEST(binderfs_stress
)
368 struct binderfs_device device
= { 0 };
369 char binderfs_mntpt
[] = P_tmpdir
"/binderfs_XXXXXX",
370 device_path
[sizeof(P_tmpdir
"/binderfs_XXXXXX/") + BINDERFS_MAX_NAME
];
372 ret
= socketpair(PF_LOCAL
, SOCK_STREAM
| SOCK_CLOEXEC
, 0, syncfds
);
374 TH_LOG("%s - Failed to create socket pair", strerror(errno
));
379 TH_LOG("%s - Failed to fork", strerror(errno
));
380 close_prot_errno_disarm(syncfds
[0]);
381 close_prot_errno_disarm(syncfds
[1]);
385 int i
, j
, k
, nthreads
;
387 pthread_t threads
[DEFAULT_THREADS
];
388 change_userns(_metadata
, syncfds
);
389 change_mountns(_metadata
);
391 ASSERT_NE(mkdtemp(binderfs_mntpt
), NULL
) {
392 TH_LOG("%s - Failed to create binderfs mountpoint",
396 ret
= mount(NULL
, binderfs_mntpt
, "binder", 0, 0);
398 TH_LOG("%s - Failed to mount binderfs", strerror(errno
));
401 for (int i
= 0; i
< ARRAY_SIZE(fds
); i
++) {
403 snprintf(device_path
, sizeof(device_path
),
404 "%s/binder-control", binderfs_mntpt
);
405 fd
= open(device_path
, O_RDONLY
| O_CLOEXEC
);
407 TH_LOG("%s - Failed to open binder-control device",
411 memset(&device
, 0, sizeof(device
));
412 snprintf(device
.name
, sizeof(device
.name
), "%d", i
);
413 ret
= ioctl(fd
, BINDER_CTL_ADD
, &device
);
414 close_prot_errno_disarm(fd
);
416 TH_LOG("%s - Failed to allocate new binder device",
420 snprintf(device_path
, sizeof(device_path
), "%s/%d",
422 fds
[i
] = open(device_path
, O_RDONLY
| O_CLOEXEC
);
423 ASSERT_GE(fds
[i
], 0) {
424 TH_LOG("%s - Failed to open binder device", strerror(errno
));
428 ret
= umount2(binderfs_mntpt
, MNT_DETACH
);
430 TH_LOG("%s - Failed to unmount binderfs", strerror(errno
));
431 rmdir(binderfs_mntpt
);
434 nthreads
= get_nprocs_conf();
435 if (nthreads
> DEFAULT_THREADS
)
436 nthreads
= DEFAULT_THREADS
;
438 _thread_metadata
= _metadata
;
439 pthread_attr_init(&attr
);
440 for (k
= 0; k
< ARRAY_SIZE(fds
); k
++) {
441 for (i
= 0; i
< nthreads
; i
++) {
442 ret
= pthread_create(&threads
[i
], &attr
, binder_version_thread
, INT_TO_PTR(fds
[k
]));
444 TH_LOG("%s - Failed to create thread %d",
450 for (j
= 0; j
< i
; j
++) {
453 ret
= pthread_join(threads
[j
], &fdptr
);
455 TH_LOG("%s - Failed to join thread %d for fd %d",
456 strerror(errno
), j
, PTR_TO_INT(fdptr
));
459 pthread_attr_destroy(&attr
);
461 for (k
= 0; k
< ARRAY_SIZE(fds
); k
++)
467 change_idmaps(_metadata
, syncfds
, pid
);
469 ret
= wait_for_pid(pid
);
471 TH_LOG("wait_for_pid() failed");
475 TEST(binderfs_test_privileged
)
478 SKIP(return, "Tests are not run as root. Skipping privileged tests");
480 if (__do_binderfs_test(_metadata
))
481 SKIP(return, "The Android binderfs filesystem is not available");
484 TEST(binderfs_test_unprivileged
)
490 ret
= socketpair(PF_LOCAL
, SOCK_STREAM
| SOCK_CLOEXEC
, 0, syncfds
);
492 TH_LOG("%s - Failed to create socket pair", strerror(errno
));
497 close_prot_errno_disarm(syncfds
[0]);
498 close_prot_errno_disarm(syncfds
[1]);
499 TH_LOG("%s - Failed to fork", strerror(errno
));
503 change_userns(_metadata
, syncfds
);
504 if (__do_binderfs_test(_metadata
))
509 change_idmaps(_metadata
, syncfds
, pid
);
511 ret
= wait_for_pid(pid
);
514 SKIP(return, "The Android binderfs filesystem is not available");
516 TH_LOG("wait_for_pid() failed");