From: lakostis@altlinux.org
To: devel-kernel@lists.altlinux.org
Subject: [d-kernel] [PATCH 1/4] binder: turn into module
Date: Fri, 23 Oct 2026 09:42:37 +0200
Message-ID: <20261023074559.941014-2-lakostis@altlinux.org> (raw)
In-Reply-To: <20261023074559.941014-1-lakostis@altlinux.org>
From: Christian Brauner <christian@brauner.io>
The Android binder driver needs to become a module for the sake of shipping
Anbox. To do this we need to export the following functions since binder is
currently still using them:
- security_binder_set_context_mgr()
- security_binder_transaction()
- security_binder_transfer_binder()
- security_binder_transfer_file()
- can_nice()
- __close_fd_get_file()
- mmput_async()
- task_work_add()
- map_kernel_range_noflush()
- get_vm_area()
- zap_vma_range()
- put_ipc_ns()
- get_ipc_ns_exported()
- show_init_ipc_ns()
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
[ saf: fix additional reference to init_ipc_ns from 5.0-rc6 ]
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
[ arighi: fix EXPORT_SYMBOL vs EXPORT_SYMBOL_GPL change from 6.0-rc5 ]
[ arighi: zap_page_range() has been dropped, export zap_page_range_single() in 6.3 ]
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
[ ppisati: export list_lru_add, list_lru_del, lock_vma_under_rcu]
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
[ tjaalton: selftests got converted to KUnit ]
[ tjaalton: 7.1: rename zap_page_range_simple to zap_vma_range]
Signed-off-by: Timo Aaltonen <timo.aaltonen@canonical.com>
Signed-off-by: Alexandre Frade <kernel@xanmod.org>
Signed-off-by: Konstantin A. Lepikhov <lakostis@altlinux.ru>
---
drivers/android/Kconfig | 6 +++---
drivers/android/Makefile | 9 +++++----
drivers/android/binder.c | 15 ++++++++++++++-
drivers/android/binder_alloc.h | 1 +
drivers/android/binder_internal.h | 5 +++--
drivers/android/binderfs.c | 6 +++---
fs/file.c | 1 +
include/linux/ipc_namespace.h | 3 +++
ipc/namespace.c | 17 +++++++++++++++++
kernel/sched/syscalls.c | 1 +
kernel/task_work.c | 1 +
mm/list_lru.c | 1 +
mm/memory.c | 1 +
mm/mmap_lock.c | 1 +
mm/vmalloc.c | 1 +
security/security.c | 4 ++++
16 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 606a9d07f774..b5feebbead21 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -2,7 +2,7 @@
menu "Android"
config ANDROID_BINDER_IPC
- bool "Android Binder IPC Driver"
+ tristate "Android Binder IPC Driver"
depends on MMU
depends on NET
default n
@@ -28,8 +28,8 @@ config ANDROID_BINDER_IPC_RUST
between said processes.
config ANDROID_BINDERFS
- bool "Android Binderfs filesystem"
- depends on ANDROID_BINDER_IPC
+ tristate "Android Binderfs filesystem"
+ depends on (ANDROID_BINDER_IPC=y) || (ANDROID_BINDER_IPC=m && m)
default n
help
Binderfs is a pseudo-filesystem for the Android Binder IPC driver
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index e0c650d3898e..81ac0681fa1b 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
ccflags-y += -I$(src) # needed for trace events
-obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
-obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o binder_netlink.o
-obj-$(CONFIG_ANDROID_BINDER_ALLOC_KUNIT_TEST) += tests/
-obj-$(CONFIG_ANDROID_BINDER_IPC_RUST) += binder/
+binder_linux-y := binder.o binder_alloc.o binder_netlink.o
+obj-$(CONFIG_ANDROID_BINDER_IPC) += binder_linux.o
+binder_linux-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
+binder_linux-$(CONFIG_ANDROID_BINDER_ALLOC_KUNIT_TEST) += binder_alloc_selftest.o
+binder_linux-$(CONFIG_ANDROID_BINDER_IPC_RUST) += binder/
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index bc8bc9ee43a5..9422030f170b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -7181,7 +7181,20 @@ static int __init binder_init(void)
return ret;
}
-device_initcall(binder_init);
+module_init(binder_init);
+/*
+ * binder will have no exit function since binderfs instances can be mounted
+ * multiple times and also in user namespaces finding and destroying them all
+ * is not feasible without introducing insane locking. Just ignoring existing
+ * instances on module unload also wouldn't work since we would loose track of
+ * what major numer was dynamically allocated and also what minor numbers are
+ * already given out. So this would get us into all kinds of issues with device
+ * number reuse. So simply don't allow unloading unless we are forced to do so.
+ */
+
+MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Driver for Android binder device");
+MODULE_LICENSE("GPL v2");
#define CREATE_TRACE_POINTS
#include "binder_trace.h"
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index d6f1f6f2d00e..7edae3eb50f5 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -6,6 +6,7 @@
#ifndef _LINUX_BINDER_ALLOC_H
#define _LINUX_BINDER_ALLOC_H
+#include <linux/kconfig.h>
#include <linux/rbtree.h>
#include <linux/list.h>
#include <linux/mm.h>
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 342574bfd28a..a723f845bd6a 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -4,6 +4,7 @@
#define _LINUX_BINDER_INTERNAL_H
#include <linux/fs.h>
+#include <linux/kconfig.h>
#include <linux/list.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
@@ -76,7 +77,7 @@ extern const struct file_operations binder_fops;
extern char *binder_devices_param;
-#ifdef CONFIG_ANDROID_BINDERFS
+#if IS_ENABLED(CONFIG_ANDROID_BINDERFS)
extern bool is_binderfs_device(const struct inode *inode);
extern struct dentry *binderfs_create_file(struct dentry *dir, const char *name,
const struct file_operations *fops,
@@ -95,7 +96,7 @@ static inline struct dentry *binderfs_create_file(struct dentry *dir,
}
#endif
-#ifdef CONFIG_ANDROID_BINDERFS
+#if IS_ENABLED(CONFIG_ANDROID_BINDERFS)
extern int __init init_binderfs(void);
#else
static inline int __init init_binderfs(void)
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
index 1ca31b9a0583..748e96cddc59 100644
--- a/drivers/android/binderfs.c
+++ b/drivers/android/binderfs.c
@@ -123,7 +123,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
struct super_block *sb = ref_inode->i_sb;
struct binderfs_info *info = sb->s_fs_info;
#if defined(CONFIG_IPC_NS)
- bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+ bool use_reserve = (info->ipc_ns == show_init_ipc_ns());
#else
bool use_reserve = true;
#endif
@@ -390,7 +390,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
struct dentry *root = sb->s_root;
struct binderfs_info *info = sb->s_fs_info;
#if defined(CONFIG_IPC_NS)
- bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+ bool use_reserve = (info->ipc_ns == show_init_ipc_ns());
#else
bool use_reserve = true;
#endif
@@ -642,7 +642,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc)
return -ENOMEM;
info = sb->s_fs_info;
- info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+ info->ipc_ns = get_ipc_ns_exported(current->nsproxy->ipc_ns);
info->root_gid = make_kgid(sb->s_user_ns, 0);
if (!gid_valid(info->root_gid))
diff --git a/fs/file.c b/fs/file.c
index 628ca07dc4b1..d18a19c2e6af 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -886,6 +886,7 @@ struct file *file_close_fd(unsigned int fd)
return file;
}
+EXPORT_SYMBOL(close_fd_get_file);
void do_close_on_exec(struct files_struct *files)
{
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 12faca29bbb9..5bf174df249e 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -128,6 +128,9 @@ extern int mq_init_ns(struct ipc_namespace *ns);
static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }
#endif
+extern struct ipc_namespace *get_ipc_ns_exported(struct ipc_namespace *ns);
+extern struct ipc_namespace *show_init_ipc_ns(void);
+
#if defined(CONFIG_IPC_NS)
static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns)
{
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 75aa7b469348..3559938a6ba0 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -210,6 +210,23 @@ void put_ipc_ns(struct ipc_namespace *ns)
schedule_work(&free_ipc_work);
}
}
+EXPORT_SYMBOL(put_ipc_ns);
+
+struct ipc_namespace *get_ipc_ns_exported(struct ipc_namespace *ns)
+{
+ return get_ipc_ns(ns);
+}
+EXPORT_SYMBOL(get_ipc_ns_exported);
+
+struct ipc_namespace *show_init_ipc_ns(void)
+{
+#if defined(CONFIG_IPC_NS)
+ return &init_ipc_ns;
+#else
+ return NULL;
+#endif
+}
+EXPORT_SYMBOL(show_init_ipc_ns);
static struct ns_common *ipcns_get(struct task_struct *task)
{
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index b215b0ead9a6..a9fc5414292c 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -119,6 +119,7 @@ int can_nice(const struct task_struct *p, const int nice)
{
return is_nice_reduction(p, nice) || capable(CAP_SYS_NICE);
}
+EXPORT_SYMBOL(can_nice);
#ifdef __ARCH_WANT_SYS_NICE
diff --git a/kernel/task_work.c b/kernel/task_work.c
index 0f7519f8e7c9..08eb29abaea6 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()
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 36662d02ff96..b7ea86ae6d66 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -273,6 +273,7 @@ bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
list_lru_unlock(l);
return ret;
}
+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 8b0c2c735d3d..f07c56290222 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2378,6 +2378,7 @@ void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
zap_vma_range_batched(&tlb, vma, address, size, NULL);
tlb_finish_mmu(&tlb);
}
+EXPORT_SYMBOL(zap_vma_range);
/**
* zap_special_vma_range - zap all page table entries in a special vma range
diff --git a/mm/mmap_lock.c b/mm/mmap_lock.c
index 898c2ef1e958..4f5e3badb8ea 100644
--- a/mm/mmap_lock.c
+++ b/mm/mmap_lock.c
@@ -340,6 +340,7 @@ struct vm_area_struct *lock_vma_under_rcu(struct mm_struct *mm,
count_vm_vma_lock_event(VMA_LOCK_ABORT);
return NULL;
}
+EXPORT_SYMBOL_GPL(lock_vma_under_rcu);
static struct vm_area_struct *lock_next_vma_under_mmap_lock(struct mm_struct *mm,
struct vma_iterator *vmi,
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index bea9f76ed7e7..4b51fbc83040 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3292,6 +3292,7 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
NUMA_NO_NODE, GFP_KERNEL,
__builtin_return_address(0));
}
+EXPORT_SYMBOL(get_vm_area);
struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
const void *caller)
diff --git a/security/security.c b/security/security.c
index 2ee276ab15c5..bad282ef9154 100644
--- a/security/security.c
+++ b/security/security.c
@@ -514,6 +514,7 @@ int security_binder_set_context_mgr(const struct cred *mgr)
{
return call_int_hook(binder_set_context_mgr, mgr);
}
+EXPORT_SYMBOL(security_binder_set_context_mgr);
/**
* security_binder_transaction() - Check if a binder transaction is allowed
@@ -529,6 +530,7 @@ int security_binder_transaction(const struct cred *from,
{
return call_int_hook(binder_transaction, from, to);
}
+EXPORT_SYMBOL(security_binder_transaction);
/**
* security_binder_transfer_binder() - Check if a binder transfer is allowed
@@ -544,6 +546,7 @@ int security_binder_transfer_binder(const struct cred *from,
{
return call_int_hook(binder_transfer_binder, from, to);
}
+EXPORT_SYMBOL(security_binder_transfer_binder);
/**
* security_binder_transfer_file() - Check if a binder file xfer is allowed
@@ -560,6 +563,7 @@ int security_binder_transfer_file(const struct cred *from,
{
return call_int_hook(binder_transfer_file, from, to, file);
}
+EXPORT_SYMBOL(security_binder_transfer_file);
/**
* security_ptrace_access_check() - Check if tracing is allowed
--
2.50.1
next prev parent reply other threads:[~2026-10-23 7:42 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 7:42 [d-kernel] [7.3] " lakostis
2026-10-23 7:42 ` lakostis [this message]
2026-10-23 7:42 ` [d-kernel] [PATCH 2/4] binder: give binder_alloc its own debug mask file lakostis
2026-10-23 7:42 ` [d-kernel] [PATCH 3/4] wait: allow to use __wake_up_pollfree() from GPL modules lakostis
2026-10-23 7:42 ` [d-kernel] [PATCH 4/4] file: export file_close_fd() instead of close_fd_get_file() lakostis
2026-10-23 9:05 ` [d-kernel] [7.3] binder: turn into module Ivan A. Melnikov
2026-10-23 11:35 ` Konstantin Lepikhov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261023074559.941014-2-lakostis@altlinux.org \
--to=lakostis@altlinux.org \
--cc=devel-kernel@lists.altlinux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
ALT Linux kernel packages development
This inbox may be cloned and mirrored by anyone:
git clone --mirror http://lore.altlinux.org/devel-kernel/0 devel-kernel/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 devel-kernel devel-kernel/ http://lore.altlinux.org/devel-kernel \
devel-kernel@altlinux.org devel-kernel@altlinux.ru devel-kernel@altlinux.com
public-inbox-index devel-kernel
Example config snippet for mirrors.
Newsgroup available over NNTP:
nntp://lore.altlinux.org/org.altlinux.lists.devel-kernel
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git