On Fri, Oct 25, 2024 at 12:51:02AM -0700, Li Li wrote: > From: Li Li <dualli@xxxxxxxxxx> > > Frozen tasks can't process binder transactions, so sync binder > transactions will fail with BR_FROZEN_REPLY and async binder > transactions will be queued in the kernel async binder buffer. > As these queued async transactions accumulates over time, the async > buffer will eventually be running out, denying all new transactions > after that with BR_FAILED_REPLY. > > In addition to the above cases, different kinds of binder error codes > might be returned to the sender. However, the core Linux, or Android, > system administration process never knows what's actually happening. > > This patch introduces the Linux generic netlink messages into the binder "Introduce generic netlink messages ..." > driver so that the Linux/Android system administration process can > listen to important events and take corresponding actions, like stopping > a broken app from attacking the OS by sending huge amount of spamming > binder transactions. > <snipped>... > diff --git a/Documentation/admin-guide/binder_genl.rst b/Documentation/admin-guide/binder_genl.rst > new file mode 100644 > index 000000000000..ecbf62f662a6 > --- /dev/null > +++ b/Documentation/admin-guide/binder_genl.rst > @@ -0,0 +1,93 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +=========================================================== > +Generic Netlink for the Android Binder Driver (Binder Genl) > +=========================================================== > + > +The Generic Netlink subsystem in the Linux kernel provides a generic way for > +the Linux kernel to communicate to the user space applications via binder > +driver. It is used to report various kinds of binder transactions to user > +space administration process. The driver allows multiple binder devices and > +their corresponding binder contexts. Each context has an independent Generic > +Netlink for security reason. To prevent untrusted user applications from > +accessing the netlink data, the kernel driver uses unicast mode instead of > +multicast. > + > +Basically, the user space code uses the "set" command to request what kinds "what kind of ..." > +of binder transactions reported by the kernel binder driver. The driver then > +uses "reply" command to acknowledge the request. The "set" command also > +registers the current user space process to receive the reports. When the > +user space process exits, the previous request will be reset to prevent any > +potential leaks. > + > +Currently the driver can report binder trasnactiosn that "failed" to reach "transactions" > +the target process, or that are "delayed" due to the target process being > +frozen by cgroup freezer, or that are considered "spam" according to existing > +logic in binder_alloc.c. > + > +When the specified binder transactions happen, the driver uses the "report" > +command to send a generic netlink message to the registered process, > +containing the payload struct binder_report. > + > +More details about the flags, attributes and operations can be found at the > +the doc sections in Documentations/netlink/specs/binder_genl.yaml and the > +kernel-doc comments of the new source code in binder.{h|c}. > + > +Using Binder Genl > +----------------- > + > +The Binder Genl can be used in the same way as any other generic netlink > +drivers. Userspace application uses a raw netlink socket to send commands > +to and receive packets from the kernel driver. > + > +.. note:: > + If the user application that talks to the Binder Genl driver exits, the "If the userspace application that talks to the driver ..." > + kernel driver will automatically reset the configuration to the default > + and stop sending more reports to prevent leaking memory. > + > +Usage example (user space pseudo code): > + > +:: > + > + // open netlink socket > + int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); > + > + // bind netlink socket > + bind(fd, struct socketaddr); > + > + // get the family id of the binder genl > + send(fd, CTRL_CMD_GETFAMILY, CTRL_ATTR_FAMILY_NAME, "binder"); > + void *data = recv(CTRL_CMD_NEWFAMILY); > + __u16 id = nla(data)[CTRL_ATTR_FAMILY_ID]; > + > + // enable per-context binder report > + send(fd, id, BINDER_GENL_CMD_SET, 0, BINDER_GENL_FLAG_FAILED | > + BINDER_GENL_FLAG_DELAYED); > + > + // confirm the per-context configuration > + void *data = recv(fd, BINDER_GENL_CMD_REPLY); > + __u32 pid = nla(data)[BINDER_GENL_ATTR_PID]; > + __u32 flags = nla(data)[BINDER_GENL_ATTR_FLAGS]; > + > + // set optional per-process report, overriding the per-context one > + send(fd, id, BINDER_GENL_CMD_SET, getpid(), > + BINDER_GENL_FLAG_SPAM | BINDER_REPORT_OVERRIDE); > + > + // confirm the optional per-process configuration > + void *data = recv(fd, BINDER_GENL_CMD_REPLY); > + __u32 pid = nla(data)[BINDER_GENL_A_ATTR_PID]; > + __u32 flags = nla(data)[BINDER_GENL_A_ATTR_FLAGS]; > + > + // wait and read all binder reports > + while (running) { > + void *data = recv(fd, BINDER_GENL_CMD_REPORT); > + struct binder_report report = nla(data)[BINDER_GENL_A_ATTR_REPORT]; > + > + // process struct binder_report > + do_something(&report); > + } > + > + // clean up > + send(fd, id, BINDER_GENL_CMD_SET, 0, 0); > + send(fd, id, BINDER_GENL_CMD_SET, getpid(), 0); > + close(fd); Thanks. -- An old man doll... just what I always wanted! - Clara
Attachment:
signature.asc
Description: PGP signature