mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge android11-5.4.281 (d62984a) into msm-5.4
* remotes/origin/tmp-d62984a:
ANDROID: delete tool added by mistake
ANDROID: fix ENOMEM check of binder_proc_ext
ANDROID: binder: fix KMI issues due to frozen notification
BACKPORT: FROMGIT: binder: frozen notification binder_features flag
BACKPORT: FROMGIT: binder: frozen notification
BACKPORT: selftests/binderfs: add test for feature files
UPSTREAM: docs: binderfs: add section about feature files
BACKPORT: binderfs: add support for feature files
FROMLIST: binder: fix memory leaks of spam and pending work
FROMGIT: Binder: add TF_UPDATE_TXN to replace outdated txn
BACKPORT: binder: tell userspace to dump current backtrace when detected oneway spamming
UPSTREAM: net: sched: sch_multiq: fix possible OOB write in multiq_tune()
FROMLIST: binder: fix UAF caused by offsets overwrite
Revert "net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD()"
Linux 5.4.281
tap: add missing verification for short frame
tun: add missing verification for short frame
filelock: Fix fcntl/close race recovery compat path
ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
jfs: don't walk off the end of ealist
ocfs2: add bounds checking to ocfs2_check_dir_entry()
net: relax socket state check at accept time.
drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq()
ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
ARM: 9324/1: fix get_user() broken with veneer
hfsplus: fix uninit-value in copy_name
selftests/vDSO: fix clang build errors and warnings
spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
fs: better handle deep ancestor chains in is_subdir()
Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
scsi: libsas: Fix exp-attached device scan after probe failure scanned in again after probe failed
powerpc/eeh: avoid possible crash when edev->pdev changes
powerpc/pseries: Whitelist dtl slub object for copying to userspace
net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD()
net: usb: qmi_wwan: add Telit FN912 compositions
ALSA: dmaengine_pcm: terminate dmaengine before synchronize
s390/sclp: Fix sclp_init() cleanup on failure
can: kvaser_usb: fix return value for hif_usb_send_regout
ASoC: ti: omap-hdmi: Fix too long driver name
ASoC: ti: davinci-mcasp: Set min period size using FIFO config
bytcr_rt5640 : inverse jack detect for Archos 101 cesium
Input: elantech - fix touchpad state on resume for Lenovo N24
mips: fix compat_sys_lseek syscall
ALSA: hda/realtek: Add more codec ID to no shutup pins list
KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
mei: demote client disconnect warning on suspend to debug
fs/file: fix the check in find_next_fd()
kconfig: remove wrong expr_trans_bool()
kconfig: gconf: give a proper initial state to the Save button
ila: block BH in ila_output()
Input: silead - Always support 10 fingers
wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
ACPI: EC: Avoid returning AE_OK on errors in address space handler
ACPI: EC: Abort address space access upon error
scsi: qedf: Set qed_slowpath_params to zero before use
filelock: Remove locks reliably when fcntl/close race is detected
gcc-plugins: Rename last_stmt() for GCC 14+
ANDROID: GKI: refresh ABI to include kimage_vaddr
ANDROID: preserve CRC for struct tcp_sock
Linux 5.4.280
i2c: rcar: bring hardware to known state when probing
nilfs2: fix kernel bug on rename operation of broken directory
tcp: avoid too many retransmit packets
tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
net: tcp: fix unexcepted socket die when snd_wnd is 0
tcp: refactor tcp_retransmit_timer()
SUNRPC: Fix RPC client cleaned up the freed pipefs dentries
libceph: fix race between delayed_work() and ceph_monc_stop()
ALSA: hda/realtek: Limit mic boost on VAIO PRO PX
nvmem: meson-efuse: Fix return value of nvmem callbacks
hpet: Support 32-bit userspace
USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor
usb: gadget: configfs: Prevent OOB read/write in usb_string_copy()
USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k
USB: serial: option: add Rolling RW350-GL variants
USB: serial: option: add Netprisma LCUK54 series modules
USB: serial: option: add support for Foxconn T99W651
USB: serial: option: add Fibocom FM350-GL
USB: serial: option: add Telit FN912 rmnet compositions
USB: serial: option: add Telit generic core-dump composition
octeontx2-af: fix detection of IP layer
ARM: davinci: Convert comma to semicolon
s390: Mark psw in __load_psw_mask() as __unitialized
udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port().
ppp: reject claimed-as-LCP but actually malformed packets
net: ethernet: lantiq_etop: fix double free in detach
net: lantiq_etop: add blank line after declaration
octeontx2-af: Fix incorrect value output on error path in rvu_check_rsrc_availability()
tcp: fix incorrect undo caused by DSACK of TLP retransmit
tcp: add TCP_INFO status for failed client TFO
vfs: don't mod negative dentry count when on shrinker list
fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading
filelock: fix potential use-after-free in posix_lock_inode
nilfs2: fix incorrect inode allocation from reserved inodes
nvme-multipath: find NUMA path only for online numa-node
ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897
i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr
media: dw2102: fix a potential buffer overflow
bnx2x: Fix multiple UBSAN array-index-out-of-bounds
drm/amdgpu/atomfirmware: silence UBSAN warning
drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes
Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again"
fsnotify: Do not generate events for O_PATH file descriptors
can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct
mm: optimize the redundant loop of mm_update_owner_next()
nilfs2: add missing check for inode numbers on directory entries
nilfs2: fix inode number range checks
inet_diag: Initialize pad field in struct inet_diag_req_v2
selftests: make order checking verbose in msg_zerocopy selftest
selftests: fix OOM in msg_zerocopy selftest
bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set()
wifi: wilc1000: fix ies_len type in connect path
tcp_metrics: validate source addr length
UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open()
net: tcp better handling of reordering then loss cases
tcp: add ece_ack flag to reno sack functions
tcp: tcp_mark_head_lost is only valid for sack-tcp
s390/pkey: Wipe sensitive data on failure
jffs2: Fix potential illegal address access in jffs2_free_inode
powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#"
orangefs: fix out-of-bounds fsid access
powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n
i2c: i801: Annotate apanel_addr as __ro_after_init
media: dvb-frontends: tda10048: Fix integer overflow
media: s2255: Use refcount_t instead of atomic_t for num_channels
media: dvb-frontends: tda18271c2dd: Remove casting during div
net: dsa: mv88e6xxx: Correct check for empty list
Input: ff-core - prefer struct_size over open coded arithmetic
firmware: dmi: Stop decoding on broken entry
sctp: prefer struct_size over open coded arithmetic
media: dw2102: Don't translate i2c read into write
drm/amd/display: Skip finding free audio for unknown engine_id
drm/amdgpu: Initialize timestamp for some legacy SOCs
scsi: qedf: Make qedf_execute_tmf() non-preemptible
IB/core: Implement a limit on UMAD receive List
media: dvb-usb: dib0700_devices: Add missing release_firmware()
media: dvb: as102-fe: Fix as10x_register_addr packing
drm/lima: fix shared irq handling on driver remove
Compiler Attributes: Add __uninitialized macro
Linux 5.4.279
arm64: dts: rockchip: Add sound-dai-cells for RK3368
ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node
tcp: Fix data races around icsk->icsk_af_ops.
ipv6: Fix data races around sk->sk_prot.
ipv6: annotate some data-races around sk->sk_prot
nfs: Leave pages in the pagecache if readpage failed
pwm: stm32: Refuse too small period requests
mtd: spinand: macronix: Add support for serial NAND flash
ftruncate: pass a signed offset
ata: libata-core: Fix double free on error
batman-adv: Don't accept TT entries for out-of-spec VIDs
drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes
drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes
hexagon: fix fadvise64_64 calling conventions
csky, hexagon: fix broken sys_sync_file_range
net: can: j1939: enhanced error handling for tightly received RTS messages in xtp_rx_rts_session_new
net: can: j1939: recover socket queue on CAN bus error during BAM transmission
net: can: j1939: Initialize unused data in j1939_send_one()
tty: mcf: MCF54418 has 10 UARTS
usb: atm: cxacru: fix endpoint checking in cxacru_bind()
usb: musb: da8xx: fix a resource leak in probe()
usb: gadget: printer: SS+ support
net: usb: ax88179_178a: improve link status logs
iio: chemical: bme680: Fix sensor data read operation
iio: chemical: bme680: Fix overflows in compensate() functions
iio: chemical: bme680: Fix calibration data variable
iio: chemical: bme680: Fix pressure value output
iio: adc: ad7266: Fix variable checking bug
mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro()
mmc: sdhci: Do not invert write-protect twice
mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos
x86: stop playing stack games in profile_pc()
gpio: davinci: Validate the obtained number of IRQs
nvme: fixup comment for nvme RDMA Provider Type
soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message
media: dvbdev: Initialize sbuf
ALSA: emux: improve patch ioctl data validation
net/dpaa2: Avoid explicit cpumask var allocation on stack
net/iucv: Avoid explicit cpumask var allocation on stack
mtd: partitions: redboot: Added conversion of operands to a larger type
drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
parisc: use correct compat recv/recvfrom syscalls
sparc: fix old compat_sys_select()
net: phy: micrel: add Microchip KSZ 9477 to the device table
net: phy: mchp: Add support for LAN8814 QUAD PHY
net: dsa: microchip: fix initial port flush problem
ASoC: fsl-asoc-card: set priv->pdev before using it
netfilter: nf_tables: validate family when identifying table via handle
drm/amdgpu: fix UBSAN warning in kv_dpm.c
pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set
pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins
pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins
pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER
iio: dac: ad5592r: fix temperature channel scaling value
iio: dac: ad5592r: un-indent code-block for scale read
iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
x86/amd_nb: Check for invalid SMN reads
PCI: Add PCI_ERROR_RESPONSE and related definitions
perf/core: Fix missing wakeup when waiting for context reference
kheaders: explicitly define file modes for archived headers
Revert "kheaders: substituting --sort in archive creation"
tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test
arm64: dts: qcom: qcs404: fix bluetooth device address
ARM: dts: samsung: smdk4412: fix keypad no-autorepeat
ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat
ARM: dts: samsung: smdkv310: fix keypad no-autorepeat
i2c: ocores: set IACK bit after core is enabled
gcov: add support for GCC 14
drm/radeon: fix UBSAN warning in kv_dpm.c
ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is fine."
dmaengine: ioatdma: Fix missing kmem_cache_destroy()
regulator: core: Fix modpost error "regulator_get_regmap" undefined
net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings
netfilter: ipset: Fix suspicious rcu_dereference_protected()
virtio_net: checksum offloading handling fix
net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()
net/sched: act_api: rely on rcu in tcf_idr_check_alloc
netns: Make get_net_ns() handle zero refcount net
xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
ipv6: prevent possible NULL dereference in rt6_probe()
ipv6: prevent possible NULL deref in fib6_nh_init()
netrom: Fix a memory leak in nr_heartbeat_expiry()
cipso: fix total option length computation
mips: bmips: BCM6358: make sure CBR is correctly set
MIPS: Routerboard 532: Fix vendor retry check code
MIPS: Octeon: Add PCIe link status check
PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports
udf: udftime: prevent overflow in udf_disk_stamp_to_time()
usb: misc: uss720: check for incompatible versions of the Belkin F5U002
powerpc/io: Avoid clang null pointer arithmetic warnings
powerpc/pseries: Enforce hcall result buffer validity and size
Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl
scsi: qedi: Fix crash while reading debugfs attribute
drop_monitor: replace spin_lock by raw_spin_lock
batman-adv: bypass empty buckets in batadv_purge_orig_ref()
selftests/bpf: Prevent client connect before server bind in test_tc_tunnel.sh
rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment
i2c: at91: Fix the functionality flags of the slave-only interface
usb-storage: alauda: Check whether the media is initialized
greybus: Fix use-after-free bug in gb_interface_release due to race condition.
netfilter: nftables: exthdr: fix 4-byte stack OOB write
hugetlb_encode.h: fix undefined behaviour (34 << 26)
hv_utils: drain the timesync packets on onchannelcallback
tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()
nilfs2: fix potential kernel bug due to lack of writeback flag waiting
intel_th: pci: Add Lunar Lake support
intel_th: pci: Add Meteor Lake-S support
intel_th: pci: Add Sapphire Rapids SOC support
intel_th: pci: Add Granite Rapids SOC support
intel_th: pci: Add Granite Rapids support
dmaengine: axi-dmac: fix possible race in remove()
PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
ocfs2: fix races between hole punching and AIO+DIO
ocfs2: use coarse time for new created files
fs/proc: fix softlockup in __read_vmcore
vmci: prevent speculation leaks by sanitizing event in event_deliver()
tracing/selftests: Fix kprobe event name test for .isra. functions
drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
drm/exynos/vidi: fix memory leak in .get_modes()
drivers: core: synchronize really_probe() and dev_uevent()
ionic: fix use after netif_napi_del()
net/ipv6: Fix the RT cache flush via sysctl using a previous delay
netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets
tcp: fix race in tcp_v6_syn_recv_sock()
drm/bridge/panel: Fix runtime warning on panel bridge release
drm/komeda: check for error-valued pointer
liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
iommu: Return right value in iommu_sva_bind_device()
iommu/amd: Fix sysfs leak in iommu init
HID: core: remove unnecessary WARN_ON() in implement()
gpio: tqmx86: fix typo in Kconfig label
SUNRPC: return proper error from gss_wrap_req_priv
Input: try trimming too long modalias strings
scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
xhci: Apply broken streams quirk to Etron EJ188 xHCI host
xhci: Apply reset resume quirk to Etron EJ188 xHCI host
xhci: Set correct transferred length for cancelled bulk transfers
jfs: xattr: fix buffer overflow for invalid xattr
mei: me: release irq in mei_me_pci_resume error path
USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
nilfs2: return the mapped address from nilfs_get_page()
nilfs2: Remove check for PageError
selftests/mm: compaction_test: fix bogus test success on Aarch64
selftests/mm: conform test to TAP format output
selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
drm/amd/display: Handle Y carry-over in VCP X.Y calculation
ASoC: ti: davinci-mcasp: Fix race condition during probe
ASoC: ti: davinci-mcasp: Handle missing required DT properties
ASoC: ti: davinci-mcasp: Simplify the configuration parameter handling
ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
ASoC: ti: davinci-mcasp: remove always zero of davinci_mcasp_get_dt_params
ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
ipv6: fix possible race in __fib6_drop_pcpu_from()
af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll().
af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
ptp: Fix error message on failed pin verification
net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
net/mlx5: Stop waiting for PCI if pci channel is offline
tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
vxlan: Fix regression when dropping packets due to invalid src addresses
net: sched: sch_multiq: fix possible OOB write in multiq_tune()
ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
wifi: iwlwifi: mvm: don't read past the mfuart notifcation
wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
wifi: cfg80211: pmsr: use correct nla_get_uX functions
wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
Conflicts:
kernel/gen_kheaders.sh
Change-Id: I4a0de5504b5e61a23b78a1a8f06aceaac810f3c7
Signed-off-by: kamasali Satyanarayan <[email protected]>
This commit is contained in:
commit
222ee0825f
274 changed files with 4165 additions and 2349 deletions
|
|
@ -1439,6 +1439,7 @@ static void binder_free_ref(struct binder_ref *ref)
|
|||
if (ref->node)
|
||||
binder_free_node(ref->node);
|
||||
kfree(ref->death);
|
||||
kfree(ref->freeze);
|
||||
kfree(ref);
|
||||
}
|
||||
|
||||
|
|
@ -2814,6 +2815,56 @@ static int binder_fixup_parent(struct list_head *pf_head,
|
|||
return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_can_update_transaction() - Can a txn be superseded by an updated one?
|
||||
* @t1: the pending async txn in the frozen process
|
||||
* @t2: the new async txn to supersede the outdated pending one
|
||||
*
|
||||
* Return: true if t2 can supersede t1
|
||||
* false if t2 can not supersede t1
|
||||
*/
|
||||
static bool binder_can_update_transaction(struct binder_transaction *t1,
|
||||
struct binder_transaction *t2)
|
||||
{
|
||||
if ((t1->flags & t2->flags & (TF_ONE_WAY | TF_UPDATE_TXN)) !=
|
||||
(TF_ONE_WAY | TF_UPDATE_TXN) || !t1->to_proc || !t2->to_proc)
|
||||
return false;
|
||||
if (t1->to_proc->tsk == t2->to_proc->tsk && t1->code == t2->code &&
|
||||
t1->flags == t2->flags && t1->buffer->pid == t2->buffer->pid &&
|
||||
t1->buffer->target_node->ptr == t2->buffer->target_node->ptr &&
|
||||
t1->buffer->target_node->cookie == t2->buffer->target_node->cookie)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_find_outdated_transaction_ilocked() - Find the outdated transaction
|
||||
* @t: new async transaction
|
||||
* @target_list: list to find outdated transaction
|
||||
*
|
||||
* Return: the outdated transaction if found
|
||||
* NULL if no outdated transacton can be found
|
||||
*
|
||||
* Requires the proc->inner_lock to be held.
|
||||
*/
|
||||
static struct binder_transaction *
|
||||
binder_find_outdated_transaction_ilocked(struct binder_transaction *t,
|
||||
struct list_head *target_list)
|
||||
{
|
||||
struct binder_work *w;
|
||||
|
||||
list_for_each_entry(w, target_list, entry) {
|
||||
struct binder_transaction *t_queued;
|
||||
|
||||
if (w->type != BINDER_WORK_TRANSACTION)
|
||||
continue;
|
||||
t_queued = container_of(w, struct binder_transaction, work);
|
||||
if (binder_can_update_transaction(t_queued, t))
|
||||
return t_queued;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_proc_transaction() - sends a transaction to a process and wakes it up
|
||||
* @t: transaction to send
|
||||
|
|
@ -2839,6 +2890,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||
struct binder_node *node = t->buffer->target_node;
|
||||
bool oneway = !!(t->flags & TF_ONE_WAY);
|
||||
bool pending_async = false;
|
||||
struct binder_transaction *t_outdated = NULL;
|
||||
|
||||
BUG_ON(!node);
|
||||
binder_node_lock(node);
|
||||
|
|
@ -2874,6 +2926,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||
} else if (!pending_async) {
|
||||
binder_enqueue_work_ilocked(&t->work, &proc->todo);
|
||||
} else {
|
||||
if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) {
|
||||
t_outdated = binder_find_outdated_transaction_ilocked(t,
|
||||
&node->async_todo);
|
||||
if (t_outdated) {
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"txn %d supersedes %d\n",
|
||||
t->debug_id, t_outdated->debug_id);
|
||||
list_del_init(&t_outdated->work.entry);
|
||||
proc->outstanding_txns--;
|
||||
}
|
||||
}
|
||||
binder_enqueue_work_ilocked(&t->work, &node->async_todo);
|
||||
}
|
||||
|
||||
|
|
@ -2884,6 +2947,22 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(node);
|
||||
|
||||
/*
|
||||
* To reduce potential contention, free the outdated transaction and
|
||||
* buffer after releasing the locks.
|
||||
*/
|
||||
if (t_outdated) {
|
||||
struct binder_buffer *buffer = t_outdated->buffer;
|
||||
|
||||
t_outdated->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
trace_binder_transaction_update_buffer_release(buffer);
|
||||
binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
|
||||
binder_alloc_free_buf(&proc->alloc, buffer);
|
||||
kfree(t_outdated);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3342,6 +3421,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
*/
|
||||
copy_size = object_offset - user_offset;
|
||||
if (copy_size && (user_offset > object_offset ||
|
||||
object_offset > tr->data_size ||
|
||||
binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, user_offset,
|
||||
|
|
@ -3585,7 +3665,10 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
|
||||
if (t->buffer->oneway_spam_suspect)
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
|
||||
else
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
|
||||
t->work.type = BINDER_WORK_TRANSACTION;
|
||||
|
||||
if (reply) {
|
||||
|
|
@ -3734,6 +3817,154 @@ err_invalid_target_handle:
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
binder_request_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
bool is_frozen;
|
||||
|
||||
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
|
||||
if (!freeze)
|
||||
return -ENOMEM;
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (ref->freeze || !ref->node->proc) {
|
||||
binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
|
||||
proc->pid, thread->pid,
|
||||
ref->freeze ? "already set" : "dead node");
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_inner_proc_lock(ref->node->proc);
|
||||
is_frozen = ref->node->proc->is_frozen;
|
||||
binder_inner_proc_unlock(ref->node->proc);
|
||||
|
||||
INIT_LIST_HEAD(&freeze->work.entry);
|
||||
freeze->cookie = handle_cookie->cookie;
|
||||
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
freeze->is_frozen = is_frozen;
|
||||
|
||||
ref->freeze = freeze;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_clear_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (!ref->freeze) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n",
|
||||
proc->pid, thread->pid);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
freeze = ref->freeze;
|
||||
binder_inner_proc_lock(proc);
|
||||
if (freeze->cookie != handle_cookie->cookie) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch %016llx != %016llx\n",
|
||||
proc->pid, thread->pid, (u64)freeze->cookie,
|
||||
(u64)handle_cookie->cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
ref->freeze = NULL;
|
||||
/*
|
||||
* Take the existing freeze object and overwrite its work type. There are three cases here:
|
||||
* 1. No pending notification. In this case just add the work to the queue.
|
||||
* 2. A notification was sent and is pending an ack from userspace. Once an ack arrives, we
|
||||
* should resend with the new work type.
|
||||
* 3. A notification is pending to be sent. Since the work is already in the queue, nothing
|
||||
* needs to be done here.
|
||||
*/
|
||||
freeze->work.type = BINDER_WORK_CLEAR_FREEZE_NOTIFICATION;
|
||||
if (list_empty(&freeze->work.entry)) {
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
} else if (freeze->sent) {
|
||||
freeze->resend = true;
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_freeze_notification_done(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
binder_uintptr_t cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze = NULL;
|
||||
struct binder_work *w;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
list_for_each_entry(w, &proc_wrapper(proc)->delivered_freeze, entry) {
|
||||
struct binder_ref_freeze *tmp_freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
|
||||
if (tmp_freeze->cookie == cookie) {
|
||||
freeze = tmp_freeze;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!freeze) {
|
||||
binder_user_error("%d:%d BC_FREEZE_NOTIFICATION_DONE %016llx not found\n",
|
||||
proc->pid, thread->pid, (u64)cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_dequeue_work_ilocked(&freeze->work);
|
||||
freeze->sent = false;
|
||||
if (freeze->resend) {
|
||||
freeze->resend = false;
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_free_buf() - free the specified buffer
|
||||
* @proc: binder proc that owns buffer
|
||||
|
|
@ -4209,6 +4440,44 @@ static int binder_thread_write(struct binder_proc *proc,
|
|||
binder_inner_proc_unlock(proc);
|
||||
} break;
|
||||
|
||||
case BC_REQUEST_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_request_freeze_notification(proc, thread,
|
||||
&handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_clear_freeze_notification(proc, thread, &handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_FREEZE_NOTIFICATION_DONE: {
|
||||
binder_uintptr_t cookie;
|
||||
int error;
|
||||
|
||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
|
||||
ptr += sizeof(cookie);
|
||||
error = binder_freeze_notification_done(proc, thread, cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
default:
|
||||
pr_err("%d:%d unknown command %d\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
|
|
@ -4462,9 +4731,14 @@ retry:
|
|||
|
||||
binder_stat_br(proc, thread, cmd);
|
||||
} break;
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE:
|
||||
case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
|
||||
if (proc->oneway_spam_detection_enabled &&
|
||||
w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
|
||||
cmd = BR_ONEWAY_SPAM_SUSPECT;
|
||||
else
|
||||
cmd = BR_TRANSACTION_COMPLETE;
|
||||
binder_inner_proc_unlock(proc);
|
||||
cmd = BR_TRANSACTION_COMPLETE;
|
||||
kfree(w);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
||||
|
|
@ -4604,6 +4878,45 @@ retry:
|
|||
if (cmd == BR_DEAD_BINDER)
|
||||
goto done; /* DEAD_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_FROZEN_BINDER: {
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_frozen_state_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
freeze = container_of(w, struct binder_ref_freeze, work);
|
||||
info.is_frozen = freeze->is_frozen;
|
||||
info.cookie = freeze->cookie;
|
||||
freeze->sent = true;
|
||||
binder_enqueue_work_ilocked(w, &proc_wrapper(proc)->delivered_freeze);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
if (put_user(BR_FROZEN_BINDER, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (copy_to_user(ptr, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(info);
|
||||
binder_stat_br(proc, thread, BR_FROZEN_BINDER);
|
||||
goto done; /* BR_FROZEN_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_ref_freeze *freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
binder_uintptr_t cookie = freeze->cookie;
|
||||
|
||||
binder_inner_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
if (put_user(BR_CLEAR_FREEZE_NOTIFICATION_DONE, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (put_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(binder_uintptr_t);
|
||||
binder_stat_br(proc, thread, BR_CLEAR_FREEZE_NOTIFICATION_DONE);
|
||||
} break;
|
||||
|
||||
default:
|
||||
binder_inner_proc_unlock(proc);
|
||||
pr_err("%d:%d: bad work type %d\n",
|
||||
|
|
@ -4791,6 +5104,7 @@ static void binder_release_work(struct binder_proc *proc,
|
|||
"undelivered TRANSACTION_ERROR: %u\n",
|
||||
e->cmd);
|
||||
} break;
|
||||
case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT:
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
||||
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
|
||||
"undelivered TRANSACTION_COMPLETE\n");
|
||||
|
|
@ -5220,6 +5534,48 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
|
||||
{
|
||||
struct rb_node *n;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||
struct binder_node *node;
|
||||
|
||||
node = rb_entry(n, struct binder_node, rb_node);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_lock(node);
|
||||
hlist_for_each_entry(ref, &node->refs, node_entry) {
|
||||
/*
|
||||
* Need the node lock to synchronize
|
||||
* with new notification requests and the
|
||||
* inner lock to synchronize with queued
|
||||
* freeze notifications.
|
||||
*/
|
||||
binder_inner_proc_lock(ref->proc);
|
||||
if (!ref->freeze) {
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
continue;
|
||||
}
|
||||
ref->freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
if (list_empty(&ref->freeze->work.entry)) {
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &ref->proc->todo);
|
||||
binder_wakeup_proc_ilocked(ref->proc);
|
||||
} else {
|
||||
if (ref->freeze->sent && ref->freeze->is_frozen != is_frozen)
|
||||
ref->freeze->resend = true;
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
}
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
}
|
||||
binder_node_unlock(node);
|
||||
binder_inner_proc_lock(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
}
|
||||
|
||||
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
struct binder_proc *target_proc)
|
||||
{
|
||||
|
|
@ -5231,6 +5587,7 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
|||
target_proc->async_recv = false;
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
binder_add_freeze_work(target_proc, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5263,6 +5620,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
|||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
} else {
|
||||
binder_add_freeze_work(target_proc, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -5494,6 +5853,18 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: {
|
||||
uint32_t enable;
|
||||
|
||||
if (copy_from_user(&enable, ubuf, sizeof(enable))) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
binder_inner_proc_lock(proc);
|
||||
proc->oneway_spam_detection_enabled = (bool)enable;
|
||||
binder_inner_proc_unlock(proc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
|
|
@ -5594,9 +5965,9 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||
current->group_leader->pid, current->pid);
|
||||
|
||||
eproc = kzalloc(sizeof(*eproc), GFP_KERNEL);
|
||||
proc = &eproc->proc;
|
||||
if (proc == NULL)
|
||||
if (eproc == NULL)
|
||||
return -ENOMEM;
|
||||
proc = &eproc->proc;
|
||||
spin_lock_init(&proc->inner_lock);
|
||||
spin_lock_init(&proc->outer_lock);
|
||||
get_task_struct(current->group_leader);
|
||||
|
|
@ -5628,6 +5999,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||
binder_stats_created(BINDER_STAT_PROC);
|
||||
proc->pid = current->group_leader->pid;
|
||||
INIT_LIST_HEAD(&proc->delivered_death);
|
||||
INIT_LIST_HEAD(&proc_wrapper(proc)->delivered_freeze);
|
||||
INIT_LIST_HEAD(&proc->waiting_threads);
|
||||
filp->private_data = proc;
|
||||
|
||||
|
|
@ -6180,6 +6552,7 @@ static const char * const binder_return_strings[] = {
|
|||
"BR_CLEAR_DEATH_NOTIFICATION_DONE",
|
||||
"BR_FAILED_REPLY",
|
||||
"BR_FROZEN_REPLY",
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
};
|
||||
|
||||
static const char * const binder_command_strings[] = {
|
||||
|
|
@ -6211,7 +6584,7 @@ static const char * const binder_objstat_strings[] = {
|
|||
"ref",
|
||||
"death",
|
||||
"transaction",
|
||||
"transaction_complete"
|
||||
"transaction_complete",
|
||||
};
|
||||
|
||||
static void print_binder_stats(struct seq_file *m, const char *prefix,
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma(
|
|||
return vma;
|
||||
}
|
||||
|
||||
static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
||||
static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
||||
{
|
||||
/*
|
||||
* Find the amount and size of buffers allocated by the current caller;
|
||||
|
|
@ -367,13 +367,19 @@ static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
|||
|
||||
/*
|
||||
* Warn if this pid has more than 50 transactions, or more than 50% of
|
||||
* async space (which is 25% of total buffer size).
|
||||
* async space (which is 25% of total buffer size). Oneway spam is only
|
||||
* detected when the threshold is exceeded.
|
||||
*/
|
||||
if (num_buffers > 50 || total_alloc_size > alloc->buffer_size / 4) {
|
||||
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
|
||||
"%d: pid %d spamming oneway? %zd buffers allocated for a total size of %zd\n",
|
||||
alloc->pid, pid, num_buffers, total_alloc_size);
|
||||
if (!alloc->oneway_spam_detected) {
|
||||
alloc->oneway_spam_detected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct binder_buffer *binder_alloc_new_buf_locked(
|
||||
|
|
@ -526,6 +532,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
|
|||
buffer->async_transaction = is_async;
|
||||
buffer->extra_buffers_size = extra_buffers_size;
|
||||
buffer->pid = pid;
|
||||
buffer->oneway_spam_suspect = false;
|
||||
if (is_async) {
|
||||
alloc->free_async_space -= size;
|
||||
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
|
||||
|
|
@ -537,7 +544,9 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
|
|||
* of async space left (which is less than 10% of total
|
||||
* buffer size).
|
||||
*/
|
||||
debug_low_async_space_locked(alloc, pid);
|
||||
buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc, pid);
|
||||
} else {
|
||||
alloc->oneway_spam_detected = false;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ struct binder_transaction;
|
|||
* @clear_on_free: %true if buffer must be zeroed after use
|
||||
* @allow_user_free: %true if user is allowed to free buffer
|
||||
* @async_transaction: %true if buffer is in use for an async txn
|
||||
* @oneway_spam_suspect: %true if total async allocate size just exceed
|
||||
* spamming detect threshold
|
||||
* @debug_id: unique ID for debugging
|
||||
* @transaction: pointer to associated struct binder_transaction
|
||||
* @target_node: struct binder_node associated with this buffer
|
||||
|
|
@ -45,7 +47,8 @@ struct binder_buffer {
|
|||
unsigned clear_on_free:1;
|
||||
unsigned allow_user_free:1;
|
||||
unsigned async_transaction:1;
|
||||
unsigned debug_id:28;
|
||||
unsigned oneway_spam_suspect:1;
|
||||
unsigned debug_id:27;
|
||||
|
||||
struct binder_transaction *transaction;
|
||||
|
||||
|
|
@ -87,6 +90,8 @@ struct binder_lru_page {
|
|||
* @buffer_size: size of address space specified via mmap
|
||||
* @pid: pid for associated binder_proc (invariant after init)
|
||||
* @pages_high: high watermark of offset in @pages
|
||||
* @oneway_spam_detected: %true if oneway spam detection fired, clear that
|
||||
* flag once the async buffer has returned to a healthy state
|
||||
*
|
||||
* Bookkeeping structure for per-proc address space management for binder
|
||||
* buffers. It is normally initialized during binder_init() and binder_mmap()
|
||||
|
|
@ -107,6 +112,7 @@ struct binder_alloc {
|
|||
uint32_t buffer_free;
|
||||
int pid;
|
||||
size_t pages_high;
|
||||
bool oneway_spam_detected;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ enum binder_stat_types {
|
|||
};
|
||||
|
||||
struct binder_stats {
|
||||
atomic_t br[_IOC_NR(BR_FROZEN_REPLY) + 1];
|
||||
atomic_t br[_IOC_NR(BR_ONEWAY_SPAM_SUSPECT) + 1];
|
||||
atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
|
||||
atomic_t obj_created[BINDER_STAT_COUNT];
|
||||
atomic_t obj_deleted[BINDER_STAT_COUNT];
|
||||
|
|
@ -174,11 +174,16 @@ struct binder_work {
|
|||
enum binder_work_type {
|
||||
BINDER_WORK_TRANSACTION = 1,
|
||||
BINDER_WORK_TRANSACTION_COMPLETE,
|
||||
BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT,
|
||||
BINDER_WORK_RETURN_ERROR,
|
||||
BINDER_WORK_NODE,
|
||||
BINDER_WORK_DEAD_BINDER,
|
||||
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
|
||||
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
|
||||
#ifndef __GENKSYMS__
|
||||
BINDER_WORK_FROZEN_BINDER,
|
||||
BINDER_WORK_CLEAR_FREEZE_NOTIFICATION,
|
||||
#endif
|
||||
} type;
|
||||
};
|
||||
|
||||
|
|
@ -300,6 +305,14 @@ struct binder_ref_death {
|
|||
binder_uintptr_t cookie;
|
||||
};
|
||||
|
||||
struct binder_ref_freeze {
|
||||
struct binder_work work;
|
||||
binder_uintptr_t cookie;
|
||||
bool is_frozen:1;
|
||||
bool sent:1;
|
||||
bool resend:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct binder_ref_data - binder_ref counts and id
|
||||
* @debug_id: unique ID for the ref
|
||||
|
|
@ -332,6 +345,8 @@ struct binder_ref_data {
|
|||
* @node indicates the node must be freed
|
||||
* @death: pointer to death notification (ref_death) if requested
|
||||
* (protected by @node->lock)
|
||||
* @freeze: pointer to freeze notification (ref_freeze) if requested
|
||||
* (protected by @node->lock)
|
||||
*
|
||||
* Structure to track references from procA to target node (on procB). This
|
||||
* structure is unsafe to access without holding @proc->outer_lock.
|
||||
|
|
@ -348,6 +363,7 @@ struct binder_ref {
|
|||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
struct binder_ref_death *death;
|
||||
struct binder_ref_freeze *freeze;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -438,6 +454,8 @@ enum binder_prio_state {
|
|||
* @outer_lock: no nesting under innor or node lock
|
||||
* Lock order: 1) outer, 2) node, 3) inner
|
||||
* @binderfs_entry: process-specific binderfs log file
|
||||
* @oneway_spam_detection_enabled: process enabled oneway spam detection
|
||||
* or not
|
||||
*
|
||||
* Bookkeeping structure for binder processes
|
||||
*/
|
||||
|
|
@ -473,6 +491,7 @@ struct binder_proc {
|
|||
spinlock_t inner_lock;
|
||||
spinlock_t outer_lock;
|
||||
struct dentry *binderfs_entry;
|
||||
bool oneway_spam_detection_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -481,6 +500,8 @@ struct binder_proc {
|
|||
* @cred struct cred associated with the `struct file`
|
||||
* in binder_open()
|
||||
* (invariant after initialized)
|
||||
* @delivered_freeze: list of delivered freeze notification
|
||||
* (protected by @inner_lock)
|
||||
*
|
||||
* Extended binder_proc -- needed to add the "cred" field without
|
||||
* changing the KMI for binder_proc.
|
||||
|
|
@ -488,6 +509,7 @@ struct binder_proc {
|
|||
struct binder_proc_ext {
|
||||
struct binder_proc proc;
|
||||
const struct cred *cred;
|
||||
struct list_head delivered_freeze;
|
||||
};
|
||||
|
||||
static inline const struct cred *binder_get_cred(struct binder_proc *proc)
|
||||
|
|
@ -498,6 +520,12 @@ static inline const struct cred *binder_get_cred(struct binder_proc *proc)
|
|||
return eproc->cred;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct binder_proc_ext *proc_wrapper(struct binder_proc *proc)
|
||||
{
|
||||
return container_of(proc, struct binder_proc_ext, proc);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct binder_thread - binder thread bookkeeping
|
||||
* @proc: binder process for this thread
|
||||
|
|
|
|||
|
|
@ -306,6 +306,10 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
|
|||
TP_PROTO(struct binder_buffer *buffer),
|
||||
TP_ARGS(buffer));
|
||||
|
||||
DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release,
|
||||
TP_PROTO(struct binder_buffer *buffer),
|
||||
TP_ARGS(buffer));
|
||||
|
||||
TRACE_EVENT(binder_update_page_range,
|
||||
TP_PROTO(struct binder_alloc *alloc, bool allocate,
|
||||
void __user *start, void __user *end),
|
||||
|
|
|
|||
|
|
@ -59,12 +59,22 @@ enum binderfs_stats_mode {
|
|||
STATS_GLOBAL,
|
||||
};
|
||||
|
||||
struct binder_features {
|
||||
bool oneway_spam_detection;
|
||||
bool freeze_notification;
|
||||
};
|
||||
|
||||
static const match_table_t tokens = {
|
||||
{ Opt_max, "max=%d" },
|
||||
{ Opt_stats_mode, "stats=%s" },
|
||||
{ Opt_err, NULL }
|
||||
};
|
||||
|
||||
static struct binder_features binder_features = {
|
||||
.oneway_spam_detection = true,
|
||||
.freeze_notification = true,
|
||||
};
|
||||
|
||||
static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
|
||||
{
|
||||
return inode->i_sb->s_fs_info;
|
||||
|
|
@ -589,6 +599,39 @@ out:
|
|||
return dentry;
|
||||
}
|
||||
|
||||
static int binder_features_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
bool *feature = m->private;
|
||||
|
||||
seq_printf(m, "%d\n", *feature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_features);
|
||||
|
||||
static int init_binder_features(struct super_block *sb)
|
||||
{
|
||||
struct dentry *dentry, *dir;
|
||||
|
||||
dir = binderfs_create_dir(sb->s_root, "features");
|
||||
if (IS_ERR(dir))
|
||||
return PTR_ERR(dir);
|
||||
|
||||
dentry = binderfs_create_file(dir, "oneway_spam_detection",
|
||||
&binder_features_fops,
|
||||
&binder_features.oneway_spam_detection);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
dentry = binderfs_create_file(dir, "freeze_notification",
|
||||
&binder_features_fops,
|
||||
&binder_features.freeze_notification);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_binder_logs(struct super_block *sb)
|
||||
{
|
||||
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
|
||||
|
|
@ -730,6 +773,10 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
name++;
|
||||
}
|
||||
|
||||
ret = init_binder_features(sb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (info->mount_opts.stats_mode == STATS_GLOBAL)
|
||||
return init_binder_logs(sb);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue