This exports the functionality needed by Binder to close file descriptors. When you send a fd over Binder, what happens is this: 1. The sending process turns the fd into a struct file and stores it in the transaction object. 2. When the receiving process gets the message, the fd is installed as a fd into the current process. 3. When the receiving process is done handling the message, it tells Binder to clean up the transaction. As part of this, fds embedded in the transaction are closed. Note that it was not always implemented like this. Previously the sending process would install the fd directly into the receiving proc in step 1, but as discussed previously [1] this is not ideal and has since been changed so that fd install happens during receive. The functions being exported here are for closing the fd in step 3. They are required because closing a fd from an ioctl is in general not safe. This is to meet the requirements for using fdget(), which is used by the ioctl framework code before calling into the driver's implementation of the ioctl. Binder works around this with this sequence of operations: 1. file_close_fd() 2. get_file() 3. filp_close() 4. task_work_add(current, TWA_RESUME) 5. 6. fput() This ensures that when fput() is called in the task work, the fdget() that the ioctl framework code uses has already been fdput(), so if the fd being closed happens to be the same fd, then the fd is not closed in violation of the fdget() rules. Link: https://lore.kernel.org/all/20180730203633.GC12962@bombadil.infradead.org/ [1] Signed-off-by: Alice Ryhl --- fs/file.c | 1 + kernel/task_work.c | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/file.c b/fs/file.c index 0a4f3bdb2dec6284a0c7b9687213137f2eecb250..0046d0034bf16270cdea7e30a86866ebea3a5a81 100644 --- a/fs/file.c +++ b/fs/file.c @@ -881,6 +881,7 @@ struct file *file_close_fd(unsigned int fd) return file; } +EXPORT_SYMBOL(file_close_fd); void do_close_on_exec(struct files_struct *files) { diff --git a/kernel/task_work.c b/kernel/task_work.c index 0f7519f8e7c93f9a4536c26a341255799c320432..08eb29abaea6b98cc443d1087ddb1d0f1a38c9ae 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -102,6 +102,7 @@ int task_work_add(struct task_struct *task, struct callback_head *work, return 0; } +EXPORT_SYMBOL(task_work_add); /** * task_work_cancel_match - cancel a pending work added by task_work_add() -- 2.53.0.rc2.204.g2597b5adb4-goog To enable building Binder as a module, export these symbols. Signed-off-by: Alice Ryhl --- security/security.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/security/security.c b/security/security.c index 31a688650601b62df1e536bbe4407817edbd6707..b4776f0e25b33df95379a08a7659c0e5f767237b 100644 --- a/security/security.c +++ b/security/security.c @@ -488,6 +488,7 @@ int security_binder_set_context_mgr(const struct cred *mgr) { return call_int_hook(binder_set_context_mgr, mgr); } +EXPORT_SYMBOL_GPL(security_binder_set_context_mgr); /** * security_binder_transaction() - Check if a binder transaction is allowed @@ -503,6 +504,7 @@ int security_binder_transaction(const struct cred *from, { return call_int_hook(binder_transaction, from, to); } +EXPORT_SYMBOL_GPL(security_binder_transaction); /** * security_binder_transfer_binder() - Check if a binder transfer is allowed @@ -518,6 +520,7 @@ int security_binder_transfer_binder(const struct cred *from, { return call_int_hook(binder_transfer_binder, from, to); } +EXPORT_SYMBOL_GPL(security_binder_transfer_binder); /** * security_binder_transfer_file() - Check if a binder file xfer is allowed @@ -534,6 +537,7 @@ int security_binder_transfer_file(const struct cred *from, { return call_int_hook(binder_transfer_file, from, to, file); } +EXPORT_SYMBOL_GPL(security_binder_transfer_file); /** * security_ptrace_access_check() - Check if tracing is allowed -- 2.53.0.rc2.204.g2597b5adb4-goog These are the functions needed by Binder's shrinker. Binder uses zap_page_range_single in the shrinker path to remove an unused page from the mmap'd region. Note that pages are only removed from the mmap'd region lazily when shrinker asks for it. Binder uses list_lru_add/del to keep track of the shrinker lru list, and it can't use _obj because the list head is not stored inline in the page actually being lru freed, so page_to_nid(virt_to_page(item)) on the list head computes the nid of the wrong page. Signed-off-by: Alice Ryhl --- mm/list_lru.c | 2 ++ mm/memory.c | 1 + 2 files changed, 3 insertions(+) diff --git a/mm/list_lru.c b/mm/list_lru.c index ec48b5dadf519a5296ac14cda035c067f9e448f8..bf95d73c9815548a19db6345f856cee9baad22e3 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -179,6 +179,7 @@ bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid, unlock_list_lru(l, false); return false; } +EXPORT_SYMBOL_GPL(list_lru_add); bool list_lru_add_obj(struct list_lru *lru, struct list_head *item) { @@ -216,6 +217,7 @@ bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid, unlock_list_lru(l, false); return false; } +EXPORT_SYMBOL_GPL(list_lru_del); bool list_lru_del_obj(struct list_lru *lru, struct list_head *item) { diff --git a/mm/memory.c b/mm/memory.c index da360a6eb8a48e29293430d0c577fb4b6ec58099..64083ace239a2caf58e1645dd5d91a41d61492c4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2168,6 +2168,7 @@ void zap_page_range_single(struct vm_area_struct *vma, unsigned long address, zap_page_range_single_batched(&tlb, vma, address, size, details); tlb_finish_mmu(&tlb); } +EXPORT_SYMBOL(zap_page_range_single); /** * zap_vma_ptes - remove ptes mapping the vma -- 2.53.0.rc2.204.g2597b5adb4-goog These symbols are used by binderfs as part of the info stored with the file system. Signed-off-by: Alice Ryhl --- ipc/msgutil.c | 1 + ipc/namespace.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ipc/msgutil.c b/ipc/msgutil.c index e28f0cecb2ec942a4f6ee93df8384716bd026011..024faedd07c333b23f1e8733833b84ecf5aed9a7 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -30,6 +30,7 @@ struct ipc_namespace init_ipc_ns = { .ns = NS_COMMON_INIT(init_ipc_ns), .user_ns = &init_user_ns, }; +EXPORT_SYMBOL(init_ipc_ns); struct msg_msgseg { struct msg_msgseg *next; diff --git a/ipc/namespace.c b/ipc/namespace.c index 535f16ea40e187a9152a03a7345e00b6c5611dbe..c6355020641a74c3be7737b9da15022b961d8f2a 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -210,6 +210,7 @@ void put_ipc_ns(struct ipc_namespace *ns) schedule_work(&free_ipc_work); } } +EXPORT_SYMBOL(put_ipc_ns); static struct ns_common *ipcns_get(struct task_struct *task) { -- 2.53.0.rc2.204.g2597b5adb4-goog Currently Binder only builds as built-in module, but in downstream Android branches we update the build system to make Rust Binder buildable as a module. The same situation applies to distros, as there are many distros that enable Binder for support of apps such as waydroid, which would benefit from the ability to build Binder as a module. Note that although the situation in Android may be temporary - once we no longer have a C implementation, it makes sense for Rust Binder to be built-in. But that will both take a while, and in any case, distros enabling Binder will benefit from it being a module even if Android goes back to built-in. This doesn't mark C Binder buildable as a module. That would require more intrusive Makefile changes as it's built from multiple objects, and I'm not sure there's any way to produce a file called 'binder.ko' containing all of those objects linked together without renaming 'binder.c', as right now there will be naming conflicts between the object built from binder.c, and the object that results from linking binder.o,binderfs.o,binder_alloc.o and so on together. (As an aside, this issue is why the Rust Binder entry-point is called rust_binder_main.rs instead of just rust_binder.rs) Signed-off-by: Alice Ryhl --- drivers/android/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig index e2e402c9d1759c81591473ad02ab7ad011bc61d0..3c1755e53195b0160d0ed244f078eed96e16272c 100644 --- a/drivers/android/Kconfig +++ b/drivers/android/Kconfig @@ -15,7 +15,7 @@ config ANDROID_BINDER_IPC between said processes. config ANDROID_BINDER_IPC_RUST - bool "Rust version of Android Binder IPC Driver" + tristate "Rust version of Android Binder IPC Driver" depends on RUST && MMU && !ANDROID_BINDER_IPC help This enables the Rust implementation of the Binder driver. -- 2.53.0.rc2.204.g2597b5adb4-goog