From nobody Thu Apr 2 15:41:19 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79D9B337BA4 for ; Tue, 10 Feb 2026 23:30:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770766223; cv=none; b=buecxsR87mOY1UQnRoNA94XIt+4a3TUVISkkd6uWo0OnNv6VOGaYNyBwXpTTOqPXN30TTff3n8HGVsMQgdFKIg+vkoBI5xUpr9zHkgL7g519QtLEwBubc/zm1OoXAUUPB7UHz9tNQh6zJ3x9mDaLVg6UoP06W+7HB6X9zuwt3wo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770766223; c=relaxed/simple; bh=7Pa7vSAHTHgeNPV7lnCcMA0KjCpXbLVVkJL+cwa0SSA=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=K+adggSiklnVNNRKdCQ70+sSPLOJNNe7VSgs5wA0bxt7YHhunSMQG34DbRRz45GgVE3Jt4fZXI30INeWkC8xoQXDOmbfhQqlPATb1VfMPrrMTehw6UmSCzc7tYV/Tvg8NWmHcTWQlNw/U0NsjJlpM44udwVvwu+hBhC6FatXD4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--cmllamas.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eoTsNhOw; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--cmllamas.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eoTsNhOw" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-124a95d580cso44422111c88.1 for ; Tue, 10 Feb 2026 15:30:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770766215; x=1771371015; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=lj0RKcz76JMrswthVhhC2aRGx+N/zrzPWxqncCabNxk=; b=eoTsNhOw0aUkf3EWeJf9zAHvaEjxsawLRqtMQDupJzY2racsqPulP3pwTlOIeV/gul nuT5eX4FOXsWPpEz0IlB7wqcUsAnILPfia8p8klBJ3r/lk3gffHizixNrPq2y4Af2P73 e9jUXF2WcilwkPm8rqXngrvjWNvNp2NcHV7NBah7q8xs5p8TtsHtOCWw3/qxM8YU+3Uk Nz99hlWv35qfoyzXuIz/Dj5DPWV+jBOCG3iyjMTkO1+uR7Gu4BlZwuDr/sITsTctZxk/ h5ycMATOkangjBvKarRGVTZXXOzCOiftaZ0Jz6m2CvB9ODuCXeVZarK10iuIxqqHTl2b kmqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770766215; x=1771371015; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=lj0RKcz76JMrswthVhhC2aRGx+N/zrzPWxqncCabNxk=; b=BHS6LjZwR/UuuTs14ppgB6b+ZE0BwF/pYbY3/afdwU0GrGeI8xO2+dI4GtOZd+ZR7b 3klq3pd0qqjAoNNjce0fETfBlF6y5QY2ToNdsdBi8nx9sfCB2OK7z8aK5HTTYsCVDPwx /SKh4bYrfQAzPc/LxQpfDkKtb1ojyv5ib0kUk60xg6neGpU7IL2Up8wKizLk+SO4q9uW gddkD53PE3xWv67UtJAqadIRqZjcNubMKh6aD7Flc1CDuzR/u0EhFE9mPHzufl8kJKBN /L0KnTXJ4yiSsaeOIVUDHzeI+Lsk3uifcSnoY8WW7jCFsBbHt61HohJQ22pZwm5p7eFG WvMA== X-Forwarded-Encrypted: i=1; AJvYcCVkZ0OrAoJBITaXKfdD/nWGkxQmBP8PbhJEMKXL9nF6ODaPL8SWcGvci7XB8aC7lxfSP9JHkwz4ejcM1As=@vger.kernel.org X-Gm-Message-State: AOJu0YyEHSZ5H5pLZc37xENuwzF3MUNTQte5uucilvC264aMOkmRYEK+ aVFizGQ1YEzbZXJmWu0JQyufKRG49oRRLvUcn+TC/N6ciSwDgRTdAoTP/l0N0KB3D5rGsPjd0ga 142jYqwX5Q98uJg== X-Received: from dlbeg13.prod.google.com ([2002:a05:7022:f8d:b0:124:a511:1ddf]) (user=cmllamas job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:4581:b0:119:e569:fb9b with SMTP id a92af1059eb24-1270411bf1cmr8087419c88.10.1770766215449; Tue, 10 Feb 2026 15:30:15 -0800 (PST) Date: Tue, 10 Feb 2026 23:28:20 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260210232949.3770644-1-cmllamas@google.com> Subject: [PATCH] rust_binder: fix oneway spam detection From: Carlos Llamas To: Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Christian Brauner , Carlos Llamas , Alice Ryhl , Wedson Almeida Filho , Matt Gilbride , Paul Moore , Vitaly Wool , Miguel Ojeda Cc: kernel-team@android.com, linux-kernel@vger.kernel.org, Tiffany Yang , stable@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The spam detection logic in TreeRange was executed before the current request was inserted into the tree. So the new request was not being factored in the spam calculation. Fix this by moving the logic after the new range has been inserted. Also, the detection logic for ArrayRange was missing altogether which meant large spamming transactions could get away without being detected. Fix this by implementing an equivalent low_oneway_space() in ArrayRange. Note that I looked into centralizing this logic in RangeAllocator but iterating through 'state' and 'size' got a bit too complicated (for me) and I abandoned this effort. Cc: stable@vger.kernel.org Cc: Alice Ryhl Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver") Signed-off-by: Carlos Llamas Reviewed-by: Alice Ryhl --- drivers/android/binder/range_alloc/array.rs | 35 +++++++++++++++++++-- drivers/android/binder/range_alloc/mod.rs | 4 +-- drivers/android/binder/range_alloc/tree.rs | 18 +++++------ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/android/binder/range_alloc/array.rs b/drivers/android/= binder/range_alloc/array.rs index 07e1dec2ce63..ada1d1b4302e 100644 --- a/drivers/android/binder/range_alloc/array.rs +++ b/drivers/android/binder/range_alloc/array.rs @@ -118,7 +118,7 @@ pub(crate) fn reserve_new( size: usize, is_oneway: bool, pid: Pid, - ) -> Result { + ) -> Result<(usize, bool)> { // Compute new value of free_oneway_space, which is set only on su= ccess. let new_oneway_space =3D if is_oneway { match self.free_oneway_space.checked_sub(size) { @@ -146,7 +146,38 @@ pub(crate) fn reserve_new( .ok() .unwrap(); =20 - Ok(insert_at_offset) + // Start detecting spammers once we have less than 20% + // of async space left (which is less than 10% of total + // buffer size). + // + // (This will short-circuit, so `low_oneway_space` is + // only called when necessary.) + let oneway_spam_detected =3D + is_oneway && new_oneway_space < self.size / 10 && self.low_one= way_space(pid); + + Ok((insert_at_offset, oneway_spam_detected)) + } + + /// Find the amount and size of buffers allocated by the current calle= r. + /// + /// The idea is that once we cross the threshold, whoever is responsib= le + /// for the low async space is likely to try to send another async tra= nsaction, + /// and at some point we'll catch them in the act. This is more effic= ient + /// than keeping a map per pid. + fn low_oneway_space(&self, calling_pid: Pid) -> bool { + let mut total_alloc_size =3D 0; + let mut num_buffers =3D 0; + + // Warn if this pid has more than 50 transactions, or more than 50= % of + // async space (which is 25% of total buffer size). Oneway spam is= only + // detected when the threshold is exceeded. + for range in &self.ranges { + if range.state.is_oneway() && range.state.pid() =3D=3D calling= _pid { + total_alloc_size +=3D range.size; + num_buffers +=3D 1; + } + } + num_buffers > 50 || total_alloc_size > self.size / 4 } =20 pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result { diff --git a/drivers/android/binder/range_alloc/mod.rs b/drivers/android/bi= nder/range_alloc/mod.rs index 2301e2bc1a1f..1f4734468ff1 100644 --- a/drivers/android/binder/range_alloc/mod.rs +++ b/drivers/android/binder/range_alloc/mod.rs @@ -188,11 +188,11 @@ pub(crate) fn reserve_new(&mut self, mut args: Reserv= eNewArgs) -> Result { - let offset =3D + let (offset, oneway_spam_detected) =3D array.reserve_new(args.debug_id, args.size, args.is_on= eway, args.pid)?; Ok(ReserveNew::Success(ReserveNewSuccess { offset, - oneway_spam_detected: false, + oneway_spam_detected, _empty_array_alloc: args.empty_array_alloc, _new_tree_alloc: args.new_tree_alloc, _tree_alloc: args.tree_alloc, diff --git a/drivers/android/binder/range_alloc/tree.rs b/drivers/android/b= inder/range_alloc/tree.rs index 838fdd2b47ea..48796fcdb362 100644 --- a/drivers/android/binder/range_alloc/tree.rs +++ b/drivers/android/binder/range_alloc/tree.rs @@ -164,15 +164,6 @@ pub(crate) fn reserve_new( self.free_oneway_space }; =20 - // Start detecting spammers once we have less than 20% - // of async space left (which is less than 10% of total - // buffer size). - // - // (This will short-circut, so `low_oneway_space` is - // only called when necessary.) - let oneway_spam_detected =3D - is_oneway && new_oneway_space < self.size / 10 && self.low_one= way_space(pid); - let (found_size, found_off, tree_node, free_tree_node) =3D match s= elf.find_best_match(size) { None =3D> { pr_warn!("ENOSPC from range_alloc.reserve_new - size: {}",= size); @@ -203,6 +194,15 @@ pub(crate) fn reserve_new( self.free_tree.insert(free_tree_node); } =20 + // Start detecting spammers once we have less than 20% + // of async space left (which is less than 10% of total + // buffer size). + // + // (This will short-circuit, so `low_oneway_space` is + // only called when necessary.) + let oneway_spam_detected =3D + is_oneway && new_oneway_space < self.size / 10 && self.low_one= way_space(pid); + Ok((found_off, oneway_spam_detected)) } =20 --=20 2.53.0.239.g8d8fc8a987-goog