From: Linus Torvalds Date: Thu, 18 Jan 2024 00:47:17 +0000 (-0800) Subject: Merge tag 'char-misc-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh... X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=296455ade1fdcf5f8f8c033201633b60946c589a;p=people%2Faperard%2Flinux.git Merge tag 'char-misc-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc and other driver updates from Greg KH: "Here is the big set of char/misc and other driver subsystem changes for 6.8-rc1. Other than lots of binder driver changes (as you can see by the merge conflicts) included in here are: - lots of iio driver updates and additions - spmi driver updates - eeprom driver updates - firmware driver updates - ocxl driver updates - mhi driver updates - w1 driver updates - nvmem driver updates - coresight driver updates - platform driver remove callback api changes - tags.sh script updates - bus_type constant marking cleanups - lots of other small driver updates All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (341 commits) android: removed duplicate linux/errno uio: Fix use-after-free in uio_open drivers: soc: xilinx: add check for platform firmware: xilinx: Export function to use in other module scripts/tags.sh: remove find_sources scripts/tags.sh: use -n to test archinclude scripts/tags.sh: add local annotation scripts/tags.sh: use more portable -path instead of -wholename scripts/tags.sh: Update comment (addition of gtags) firmware: zynqmp: Convert to platform remove callback returning void firmware: turris-mox-rwtm: Convert to platform remove callback returning void firmware: stratix10-svc: Convert to platform remove callback returning void firmware: stratix10-rsu: Convert to platform remove callback returning void firmware: raspberrypi: Convert to platform remove callback returning void firmware: qemu_fw_cfg: Convert to platform remove callback returning void firmware: mtk-adsp-ipc: Convert to platform remove callback returning void firmware: imx-dsp: Convert to platform remove callback returning void firmware: coreboot_table: Convert to platform remove callback returning void firmware: arm_scpi: Convert to platform remove callback returning void firmware: arm_scmi: Convert to platform remove callback returning void ... --- 296455ade1fdcf5f8f8c033201633b60946c589a diff --cc drivers/android/binder_alloc.c index f69d30c9f50fa,a4a4dc87ba53a..e0e4dc38b6920 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@@ -178,55 -175,110 +175,110 @@@ struct binder_buffer *binder_alloc_prep return buffer; } - static int binder_update_page_range(struct binder_alloc *alloc, int allocate, - void __user *start, void __user *end) + static inline void + binder_set_installed_page(struct binder_lru_page *lru_page, + struct page *page) + { + /* Pairs with acquire in binder_get_installed_page() */ + smp_store_release(&lru_page->page_ptr, page); + } + + static inline struct page * + binder_get_installed_page(struct binder_lru_page *lru_page) + { + /* Pairs with release in binder_set_installed_page() */ + return smp_load_acquire(&lru_page->page_ptr); + } + + static void binder_lru_freelist_add(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { - void __user *page_addr; - unsigned long user_page_addr; struct binder_lru_page *page; - struct vm_area_struct *vma = NULL; - struct mm_struct *mm = NULL; - bool need_mm = false; + unsigned long page_addr; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %pK-%pK\n", alloc->pid, - allocate ? "allocate" : "free", start, end); + trace_binder_update_page_range(alloc, false, start, end); - if (end <= start) - return 0; + for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { + size_t index; + int ret; - trace_binder_update_page_range(alloc, allocate, start, end); + index = (page_addr - alloc->buffer) / PAGE_SIZE; + page = &alloc->pages[index]; - if (allocate == 0) - goto free_range; + if (!binder_get_installed_page(page)) + continue; - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; - if (!page->page_ptr) { - need_mm = true; - break; - } + trace_binder_free_lru_start(alloc, index); + - ret = list_lru_add(&binder_freelist, &page->lru); ++ ret = list_lru_add_obj(&binder_freelist, &page->lru); + WARN_ON(!ret); + + trace_binder_free_lru_end(alloc, index); } + } + + static int binder_install_single_page(struct binder_alloc *alloc, + struct binder_lru_page *lru_page, + unsigned long addr) + { + struct page *page; + int ret = 0; - if (need_mm && mmget_not_zero(alloc->mm)) - mm = alloc->mm; + if (!mmget_not_zero(alloc->mm)) + return -ESRCH; - if (mm) { - mmap_write_lock(mm); - vma = alloc->vma; + /* + * Protected with mmap_sem in write mode as multiple tasks + * might race to install the same page. + */ + mmap_write_lock(alloc->mm); + if (binder_get_installed_page(lru_page)) + goto out; + + if (!alloc->vma) { + pr_err("%d: %s failed, no vma\n", alloc->pid, __func__); + ret = -ESRCH; + goto out; } - if (!vma && need_mm) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d: binder_alloc_buf failed to map pages in userspace, no vma\n", - alloc->pid); - goto err_no_vma; + page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (!page) { + pr_err("%d: failed to allocate page\n", alloc->pid); + ret = -ENOMEM; + goto out; } - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { + ret = vm_insert_page(alloc->vma, addr, page); + if (ret) { + pr_err("%d: %s failed to insert page at offset %lx with %d\n", + alloc->pid, __func__, addr - alloc->buffer, ret); + __free_page(page); + ret = -ENOMEM; + goto out; + } + + /* Mark page installation complete and safe to use */ + binder_set_installed_page(lru_page, page); + out: + mmap_write_unlock(alloc->mm); + mmput_async(alloc->mm); + return ret; + } + + static int binder_install_buffer_pages(struct binder_alloc *alloc, + struct binder_buffer *buffer, + size_t size) + { + struct binder_lru_page *page; + unsigned long start, final; + unsigned long page_addr; + + start = buffer->user_data & PAGE_MASK; + final = PAGE_ALIGN(buffer->user_data + size); + + for (page_addr = start; page_addr < final; page_addr += PAGE_SIZE) { + unsigned long index; int ret; - bool on_lru; - size_t index; index = (page_addr - alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; @@@ -283,30 -314,19 +314,19 @@@ static void binder_lru_freelist_del(str index = (page_addr - alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; - trace_binder_free_lru_start(alloc, index); + if (page->page_ptr) { + trace_binder_alloc_lru_start(alloc, index); - ret = list_lru_add_obj(&binder_alloc_lru, &page->lru); - WARN_ON(!ret); - on_lru = list_lru_del(&binder_freelist, &page->lru); ++ on_lru = list_lru_del_obj(&binder_freelist, &page->lru); + WARN_ON(!on_lru); - trace_binder_free_lru_end(alloc, index); - if (page_addr == start) - break; - continue; - - err_vm_insert_page_failed: - __free_page(page->page_ptr); - page->page_ptr = NULL; - err_alloc_page_failed: - err_page_ptr_cleared: - if (page_addr == start) - break; - } - err_no_vma: - if (mm) { - mmap_write_unlock(mm); - mmput(mm); + trace_binder_alloc_lru_end(alloc, index); + continue; + } + + if (index + 1 > alloc->pages_high) + alloc->pages_high = index + 1; } - return vma ? -ENOMEM : -ESRCH; } static inline void binder_alloc_set_vma(struct binder_alloc *alloc, @@@ -848,12 -931,12 +931,12 @@@ void binder_alloc_deferred_release(stru if (!alloc->pages[i].page_ptr) continue; - on_lru = list_lru_del_obj(&binder_alloc_lru, - on_lru = list_lru_del(&binder_freelist, -- &alloc->pages[i].lru); ++ on_lru = list_lru_del_obj(&binder_freelist, ++ &alloc->pages[i].lru); page_addr = alloc->buffer + i * PAGE_SIZE; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %pK %s\n", - __func__, alloc->pid, i, page_addr, + "%s: %d: page %d %s\n", + __func__, alloc->pid, i, on_lru ? "on lru" : "active"); __free_page(alloc->pages[i].page_ptr); page_count++; diff --cc drivers/misc/vmw_vmci/vmci_handle_array.h index b0e6b19560140,e386c5732727d..27a38b97e8a85 --- a/drivers/misc/vmw_vmci/vmci_handle_array.h +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h @@@ -17,17 -17,11 +17,11 @@@ struct vmci_handle_arr u32 max_capacity; u32 size; u32 pad; - struct vmci_handle entries[]; + struct vmci_handle entries[] __counted_by(capacity); }; - #define VMCI_HANDLE_ARRAY_HEADER_SIZE \ - offsetof(struct vmci_handle_arr, entries) /* Select a default capacity that results in a 64 byte sized array */ #define VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY 6 - /* Make sure that the max array size can be expressed by a u32 */ - #define VMCI_HANDLE_ARRAY_MAX_CAPACITY \ - ((U32_MAX - VMCI_HANDLE_ARRAY_HEADER_SIZE - 1) / \ - sizeof(struct vmci_handle)) struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity); void vmci_handle_arr_destroy(struct vmci_handle_arr *array);