Commit 4bb1f7e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc driver fixes from Greg KH:
 "Here are some small char/misc/android driver fixes for 6.18-rc3 for
  reported issues. Included in here are:

   - rust binder fixes for reported issues

   - mei device id addition

   - mei driver fixes

   - comedi bugfix

   - most usb driver bugfixes

   - fastrpc memory leak fix

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  most: usb: hdm_probe: Fix calling put_device() before device initialization
  most: usb: Fix use-after-free in hdm_disconnect
  binder: remove "invalid inc weak" check
  mei: txe: fix initialization order
  comedi: fix divide-by-zero in comedi_buf_munge()
  mei: late_bind: Fix -Wincompatible-function-pointer-types-strict
  misc: fastrpc: Fix dma_buf object leak in fastrpc_map_lookup
  mei: me: add wildcat lake P DID
  misc: amd-sbi: Clarify that this is a BMC driver
  nvmem: rcar-efuse: add missing MODULE_DEVICE_TABLE
  binder: Fix missing kernel-doc entries in binder.c
  rust_binder: report freeze notification only when fully frozen
  rust_binder: don't delete FreezeListener if there are pending duplicates
  rust_binder: freeze_notif_done should resend if wrong state
  rust_binder: remove warning about orphan mappings
  rust_binder: clean `clippy::mem_replace_with_default` warning
parents 40282418 a8cc9e5f
Loading
Loading
Loading
Loading
+15 −23
Original line number Diff line number Diff line
@@ -851,18 +851,9 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong,
	} else {
		if (!internal)
			node->local_weak_refs++;
		if (!node->has_weak_ref && list_empty(&node->work.entry)) {
			if (target_list == NULL) {
				pr_err("invalid inc weak node for %d\n",
					node->debug_id);
				return -EINVAL;
			}
			/*
			 * See comment above
			 */
		if (!node->has_weak_ref && target_list && list_empty(&node->work.entry))
			binder_enqueue_work_ilocked(&node->work, target_list);
	}
	}
	return 0;
}

@@ -2418,10 +2409,10 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,

/**
 * struct binder_ptr_fixup - data to be fixed-up in target buffer
 * @offset	offset in target buffer to fixup
 * @skip_size	bytes to skip in copy (fixup will be written later)
 * @fixup_data	data to write at fixup offset
 * @node	list node
 * @offset:      offset in target buffer to fixup
 * @skip_size:   bytes to skip in copy (fixup will be written later)
 * @fixup_data:  data to write at fixup offset
 * @node:        list node
 *
 * This is used for the pointer fixup list (pf) which is created and consumed
 * during binder_transaction() and is only accessed locally. No
@@ -2438,10 +2429,10 @@ struct binder_ptr_fixup {

/**
 * struct binder_sg_copy - scatter-gather data to be copied
 * @offset		offset in target buffer
 * @sender_uaddr	user address in source buffer
 * @length		bytes to copy
 * @node		list node
 * @offset:        offset in target buffer
 * @sender_uaddr:  user address in source buffer
 * @length:        bytes to copy
 * @node:          list node
 *
 * This is used for the sg copy list (sgc) which is created and consumed
 * during binder_transaction() and is only accessed locally. No
@@ -4064,13 +4055,14 @@ binder_freeze_notification_done(struct binder_proc *proc,
/**
 * binder_free_buf() - free the specified buffer
 * @proc:       binder proc that owns buffer
 * @thread:     binder thread performing the buffer release
 * @buffer:     buffer to be freed
 * @is_failure: failed to send transaction
 *
 * If buffer for an async transaction, enqueue the next async
 * If the buffer is for an async transaction, enqueue the next async
 * transaction from the node.
 *
 * Cleanup buffer and free it.
 * Cleanup the buffer and free it.
 */
static void
binder_free_buf(struct binder_proc *proc,
+14 −4
Original line number Diff line number Diff line
@@ -106,13 +106,22 @@ fn do_work(
            return Ok(true);
        }
        if freeze.is_clearing {
            kernel::warn_on!(freeze.num_cleared_duplicates != 0);
            if freeze.num_pending_duplicates > 0 {
                // The primary freeze listener was deleted, so convert a pending duplicate back
                // into the primary one.
                freeze.num_pending_duplicates -= 1;
                freeze.is_pending = true;
                freeze.is_clearing = true;
            } else {
                _removed_listener = freeze_entry.remove_node();
            }
            drop(node_refs);
            writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?;
            writer.write_payload(&self.cookie.0)?;
            Ok(true)
        } else {
            let is_frozen = freeze.node.owner.inner.lock().is_frozen;
            let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
            if freeze.last_is_frozen == Some(is_frozen) {
                return Ok(true);
            }
@@ -245,8 +254,9 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
                );
                return Err(EINVAL);
            }
            if freeze.is_clearing {
                // Immediately send another FreezeMessage for BR_CLEAR_FREEZE_NOTIFICATION_DONE.
            let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
            if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) {
                // Immediately send another FreezeMessage.
                clear_msg = Some(FreezeMessage::init(alloc, cookie));
            }
            freeze.is_pending = false;
+1 −1
Original line number Diff line number Diff line
@@ -687,7 +687,7 @@ pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
            );
        }
        if inner.freeze_list.is_empty() {
            _unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new());
            _unused_capacity = mem::take(&mut inner.freeze_list);
        }
    }

+37 −13
Original line number Diff line number Diff line
@@ -72,6 +72,33 @@ fn new(address: usize, size: usize) -> Self {
const PROC_DEFER_FLUSH: u8 = 1;
const PROC_DEFER_RELEASE: u8 = 2;

#[derive(Copy, Clone)]
pub(crate) enum IsFrozen {
    Yes,
    No,
    InProgress,
}

impl IsFrozen {
    /// Whether incoming transactions should be rejected due to freeze.
    pub(crate) fn is_frozen(self) -> bool {
        match self {
            IsFrozen::Yes => true,
            IsFrozen::No => false,
            IsFrozen::InProgress => true,
        }
    }

    /// Whether freeze notifications consider this process frozen.
    pub(crate) fn is_fully_frozen(self) -> bool {
        match self {
            IsFrozen::Yes => true,
            IsFrozen::No => false,
            IsFrozen::InProgress => false,
        }
    }
}

/// The fields of `Process` protected by the spinlock.
pub(crate) struct ProcessInner {
    is_manager: bool,
@@ -98,7 +125,7 @@ pub(crate) struct ProcessInner {
    /// are woken up.
    outstanding_txns: u32,
    /// Process is frozen and unable to service binder transactions.
    pub(crate) is_frozen: bool,
    pub(crate) is_frozen: IsFrozen,
    /// Process received sync transactions since last frozen.
    pub(crate) sync_recv: bool,
    /// Process received async transactions since last frozen.
@@ -124,7 +151,7 @@ fn new() -> Self {
            started_thread_count: 0,
            defer_work: 0,
            outstanding_txns: 0,
            is_frozen: false,
            is_frozen: IsFrozen::No,
            sync_recv: false,
            async_recv: false,
            binderfs_file: None,
@@ -1260,7 +1287,7 @@ fn deferred_release(self: Arc<Self>) {
        let is_manager = {
            let mut inner = self.inner.lock();
            inner.is_dead = true;
            inner.is_frozen = false;
            inner.is_frozen = IsFrozen::No;
            inner.sync_recv = false;
            inner.async_recv = false;
            inner.is_manager
@@ -1346,10 +1373,6 @@ fn deferred_release(self: Arc<Self>) {
                .alloc
                .take_for_each(|offset, size, debug_id, odata| {
                    let ptr = offset + address;
                    pr_warn!(
                        "{}: removing orphan mapping {offset}:{size}\n",
                        self.pid_in_current_ns()
                    );
                    let mut alloc =
                        Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
                    if let Some(data) = odata {
@@ -1371,7 +1394,7 @@ pub(crate) fn drop_outstanding_txn(&self) {
                return;
            }
            inner.outstanding_txns -= 1;
            inner.is_frozen && inner.outstanding_txns == 0
            inner.is_frozen.is_frozen() && inner.outstanding_txns == 0
        };

        if wake {
@@ -1385,7 +1408,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
            let mut inner = self.inner.lock();
            inner.sync_recv = false;
            inner.async_recv = false;
            inner.is_frozen = false;
            inner.is_frozen = IsFrozen::No;
            drop(inner);
            msgs.send_messages();
            return Ok(());
@@ -1394,7 +1417,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
        let mut inner = self.inner.lock();
        inner.sync_recv = false;
        inner.async_recv = false;
        inner.is_frozen = true;
        inner.is_frozen = IsFrozen::InProgress;

        if info.timeout_ms > 0 {
            let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
@@ -1408,7 +1431,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
                    .wait_interruptible_timeout(&mut inner, jiffies)
                {
                    CondVarTimeoutResult::Signal { .. } => {
                        inner.is_frozen = false;
                        inner.is_frozen = IsFrozen::No;
                        return Err(ERESTARTSYS);
                    }
                    CondVarTimeoutResult::Woken { jiffies: remaining } => {
@@ -1422,17 +1445,18 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
        }

        if inner.txns_pending_locked() {
            inner.is_frozen = false;
            inner.is_frozen = IsFrozen::No;
            Err(EAGAIN)
        } else {
            drop(inner);
            match self.prepare_freeze_messages() {
                Ok(batch) => {
                    self.inner.lock().is_frozen = IsFrozen::Yes;
                    batch.send_messages();
                    Ok(())
                }
                Err(kernel::alloc::AllocError) => {
                    self.inner.lock().is_frozen = false;
                    self.inner.lock().is_frozen = IsFrozen::No;
                    Err(ENOMEM)
                }
            }
+3 −3
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {

        if oneway {
            if let Some(target_node) = self.target_node.clone() {
                if process_inner.is_frozen {
                if process_inner.is_frozen.is_frozen() {
                    process_inner.async_recv = true;
                    if self.flags & TF_UPDATE_TXN != 0 {
                        if let Some(t_outdated) =
@@ -270,7 +270,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
                    }
                }

                if process_inner.is_frozen {
                if process_inner.is_frozen.is_frozen() {
                    return Err(BinderError::new_frozen_oneway());
                } else {
                    return Ok(());
@@ -280,7 +280,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
            }
        }

        if process_inner.is_frozen {
        if process_inner.is_frozen.is_frozen() {
            process_inner.sync_recv = true;
            return Err(BinderError::new_frozen());
        }
Loading