Import of kernel-6.12.0-211.31.1.el10_2
This commit is contained in:
parent
4fd067918e
commit
8a9da85e81
@ -182,6 +182,8 @@ static struct kmem_cache *pte_list_desc_cache;
|
||||
struct kmem_cache *mmu_page_header_cache;
|
||||
|
||||
static void mmu_spte_set(u64 *sptep, u64 spte);
|
||||
static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
|
||||
u64 *spte, struct list_head *invalid_list);
|
||||
|
||||
struct kvm_mmu_role_regs {
|
||||
const unsigned long cr0;
|
||||
@ -1283,19 +1285,6 @@ static void drop_spte(struct kvm *kvm, u64 *sptep)
|
||||
rmap_remove(kvm, sptep);
|
||||
}
|
||||
|
||||
static void drop_large_spte(struct kvm *kvm, u64 *sptep, bool flush)
|
||||
{
|
||||
struct kvm_mmu_page *sp;
|
||||
|
||||
sp = sptep_to_sp(sptep);
|
||||
WARN_ON_ONCE(sp->role.level == PG_LEVEL_4K);
|
||||
|
||||
drop_spte(kvm, sptep);
|
||||
|
||||
if (flush)
|
||||
kvm_flush_remote_tlbs_sptep(kvm, sptep);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write-protect on the specified @sptep, @pt_protect indicates whether
|
||||
* spte write-protection is caused by protecting shadow page table.
|
||||
@ -2460,12 +2449,15 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
|
||||
u64 *sptep, gfn_t gfn,
|
||||
bool direct, unsigned int access)
|
||||
{
|
||||
union kvm_mmu_page_role role;
|
||||
union kvm_mmu_page_role role = kvm_mmu_child_role(sptep, direct, access);
|
||||
|
||||
if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
|
||||
if (is_shadow_present_pte(*sptep) &&
|
||||
!is_large_pte(*sptep) &&
|
||||
spte_to_child_sp(*sptep) &&
|
||||
spte_to_child_sp(*sptep)->gfn == gfn &&
|
||||
spte_to_child_sp(*sptep)->role.word == role.word)
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
role = kvm_mmu_child_role(sptep, direct, access);
|
||||
return kvm_mmu_get_shadow_page(vcpu, gfn, role);
|
||||
}
|
||||
|
||||
@ -2540,13 +2532,16 @@ static void __link_shadow_page(struct kvm *kvm,
|
||||
|
||||
BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK);
|
||||
|
||||
/*
|
||||
* If an SPTE is present already, it must be a leaf and therefore
|
||||
* a large one. Drop it, and flush the TLB if needed, before
|
||||
* installing sp.
|
||||
*/
|
||||
if (is_shadow_present_pte(*sptep))
|
||||
drop_large_spte(kvm, sptep, flush);
|
||||
if (is_shadow_present_pte(*sptep)) {
|
||||
struct kvm_mmu_page *parent_sp;
|
||||
LIST_HEAD(invalid_list);
|
||||
|
||||
parent_sp = sptep_to_sp(sptep);
|
||||
WARN_ON_ONCE(parent_sp->role.level == PG_LEVEL_4K);
|
||||
|
||||
mmu_page_zap_pte(kvm, parent_sp, sptep, &invalid_list);
|
||||
kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, true);
|
||||
}
|
||||
|
||||
spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
|
||||
|
||||
|
||||
@ -12289,7 +12289,7 @@ static int tg3_get_link_ksettings(struct net_device *dev,
|
||||
ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
|
||||
advertising);
|
||||
|
||||
if (netif_running(dev) && tp->link_up) {
|
||||
if (netif_running(dev) && netif_carrier_ok(dev)) {
|
||||
cmd->base.speed = tp->link_config.active_speed;
|
||||
cmd->base.duplex = tp->link_config.active_duplex;
|
||||
ethtool_convert_legacy_u32_to_link_mode(
|
||||
|
||||
@ -1934,6 +1934,7 @@ remove_irq:
|
||||
mana_gd_remove_irqs(pdev);
|
||||
free_workqueue:
|
||||
destroy_workqueue(gc->service_wq);
|
||||
gc->service_wq = NULL;
|
||||
dev_err(&pdev->dev, "%s failed (error %d)\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
@ -1946,7 +1947,10 @@ static void mana_gd_cleanup(struct pci_dev *pdev)
|
||||
|
||||
mana_gd_remove_irqs(pdev);
|
||||
|
||||
destroy_workqueue(gc->service_wq);
|
||||
if (gc->service_wq) {
|
||||
destroy_workqueue(gc->service_wq);
|
||||
gc->service_wq = NULL;
|
||||
}
|
||||
dev_dbg(&pdev->dev, "mana gdma cleanup successful\n");
|
||||
}
|
||||
|
||||
|
||||
@ -3684,7 +3684,9 @@ void mana_rdma_remove(struct gdma_dev *gd)
|
||||
}
|
||||
|
||||
WRITE_ONCE(gd->rdma_teardown, true);
|
||||
flush_workqueue(gc->service_wq);
|
||||
|
||||
if (gc->service_wq)
|
||||
flush_workqueue(gc->service_wq);
|
||||
|
||||
if (gd->adev)
|
||||
remove_adev(gd);
|
||||
|
||||
238
fs/eventpoll.c
238
fs/eventpoll.c
@ -148,13 +148,6 @@ struct epitem {
|
||||
/* The file descriptor information this item refers to */
|
||||
struct epoll_filefd ffd;
|
||||
|
||||
/*
|
||||
* Protected by file->f_lock, true for to-be-released epitem already
|
||||
* removed from the "struct file" items list; together with
|
||||
* eventpoll->refcount orchestrates "struct eventpoll" disposal
|
||||
*/
|
||||
bool dying;
|
||||
|
||||
/* List containing poll wait queues */
|
||||
struct eppoll_entry *pwqlist;
|
||||
|
||||
@ -218,13 +211,14 @@ struct eventpoll {
|
||||
/* used to optimize loop detection check */
|
||||
u64 gen;
|
||||
struct hlist_head refs;
|
||||
u8 loop_check_depth;
|
||||
|
||||
/*
|
||||
* usage count, used together with epitem->dying to
|
||||
* orchestrate the disposal of this struct
|
||||
*/
|
||||
/* usage count, orchestrates "struct eventpoll" disposal */
|
||||
refcount_t refcount;
|
||||
|
||||
/* used to defer freeing past ep_get_upwards_depth_proc() RCU walk */
|
||||
struct rcu_head rcu;
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
/* used to track busy poll napi_id */
|
||||
unsigned int napi_id;
|
||||
@ -818,41 +812,61 @@ static void ep_free(struct eventpoll *ep)
|
||||
mutex_destroy(&ep->mtx);
|
||||
free_uid(ep->user);
|
||||
wakeup_source_unregister(ep->ws);
|
||||
kfree(ep);
|
||||
/* ep_get_upwards_depth_proc() may still hold epi->ep under RCU */
|
||||
kfree_rcu(ep, rcu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes a "struct epitem" from the eventpoll RB tree and deallocates
|
||||
* all the associated resources. Must be called with "mtx" held.
|
||||
* If the dying flag is set, do the removal only if force is true.
|
||||
* This prevents ep_clear_and_put() from dropping all the ep references
|
||||
* while running concurrently with eventpoll_release_file().
|
||||
* Returns true if the eventpoll can be disposed.
|
||||
* Pin @epi->ffd.file for operations that require both safe dereference
|
||||
* and exclusion from __fput().
|
||||
*
|
||||
* struct file uses SLAB_TYPESAFE_BY_RCU, so a freed slot can be
|
||||
* reassigned at any time. The bare load of epi->ffd.file is safe here
|
||||
* because the caller holds ep->mtx and eventpoll_release_file() blocks
|
||||
* on that mutex while tearing down the epi, so the backing file
|
||||
* allocation cannot be freed and reused under us. An rcu_read_lock()
|
||||
* is therefore unnecessary for the load.
|
||||
*
|
||||
* A successful file_ref_get() additionally blocks __fput() from
|
||||
* starting on this file: once the refcount has reached zero it cannot
|
||||
* come back. ep_remove() relies on that to touch file->f_lock and
|
||||
* file->f_ep without racing eventpoll_release_file() (see commit
|
||||
* a6dc643c6931). A NULL return means __fput() is already in flight;
|
||||
* the caller must bail without touching the file, and
|
||||
* eventpoll_release_file() will clean the epi up from its side.
|
||||
*/
|
||||
static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
|
||||
static struct file *epi_fget(const struct epitem *epi)
|
||||
{
|
||||
struct file *file = epi->ffd.file;
|
||||
struct epitems_head *to_free;
|
||||
struct file *file;
|
||||
|
||||
file = epi->ffd.file;
|
||||
if (!file_ref_get(&file->f_ref))
|
||||
file = NULL;
|
||||
return file;
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes &file->f_lock; returns with it released.
|
||||
*/
|
||||
static void ep_remove_file(struct eventpoll *ep, struct epitem *epi,
|
||||
struct file *file)
|
||||
{
|
||||
struct epitems_head *to_free = NULL;
|
||||
struct hlist_head *head;
|
||||
|
||||
lockdep_assert_irqs_enabled();
|
||||
lockdep_assert_held(&ep->mtx);
|
||||
|
||||
/*
|
||||
* Removes poll wait queue hooks.
|
||||
*/
|
||||
ep_unregister_pollwait(ep, epi);
|
||||
|
||||
/* Remove the current item from the list of epoll hooks */
|
||||
spin_lock(&file->f_lock);
|
||||
if (epi->dying && !force) {
|
||||
spin_unlock(&file->f_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
to_free = NULL;
|
||||
head = file->f_ep;
|
||||
if (head->first == &epi->fllink && !epi->fllink.next) {
|
||||
file->f_ep = NULL;
|
||||
if (hlist_is_singular_node(&epi->fllink, head)) {
|
||||
/*
|
||||
* Last watcher: publish NULL so the eventpoll_release()
|
||||
* fastpath in include/linux/eventpoll.h can skip the slow
|
||||
* path on a future __fput(). Safe because every f_ep writer
|
||||
* either holds a pin on @file via epi_fget() or is __fput()
|
||||
* itself -- see the comment in eventpoll_release().
|
||||
*/
|
||||
WRITE_ONCE(file->f_ep, NULL);
|
||||
if (!is_file_epoll(file)) {
|
||||
struct epitems_head *v;
|
||||
v = container_of(head, struct epitems_head, epitems);
|
||||
@ -863,6 +877,11 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
|
||||
hlist_del_rcu(&epi->fllink);
|
||||
spin_unlock(&file->f_lock);
|
||||
free_ephead(to_free);
|
||||
}
|
||||
|
||||
static void ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
|
||||
{
|
||||
lockdep_assert_held(&ep->mtx);
|
||||
|
||||
rb_erase_cached(&epi->rbn, &ep->rbr);
|
||||
|
||||
@ -882,16 +901,32 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
|
||||
kfree_rcu(epi, rcu);
|
||||
|
||||
percpu_counter_dec(&ep->user->epoll_watches);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* ep_remove variant for callers owing an additional reference to the ep
|
||||
*/
|
||||
static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
|
||||
static void ep_remove(struct eventpoll *ep, struct epitem *epi)
|
||||
{
|
||||
if (__ep_remove(ep, epi, false))
|
||||
WARN_ON_ONCE(ep_refcount_dec_and_test(ep));
|
||||
struct file *file __free(fput) = NULL;
|
||||
|
||||
lockdep_assert_irqs_enabled();
|
||||
lockdep_assert_held(&ep->mtx);
|
||||
|
||||
ep_unregister_pollwait(ep, epi);
|
||||
|
||||
/*
|
||||
* If we manage to grab a reference it means we're not in
|
||||
* eventpoll_release_file() and aren't going to be: once @file's
|
||||
* refcount has reached zero, file_ref_get() cannot bring it back.
|
||||
*/
|
||||
file = epi_fget(epi);
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
ep_remove_file(ep, epi, file);
|
||||
ep_remove_epi(ep, epi);
|
||||
WARN_ON_ONCE(ep_refcount_dec_and_test(ep));
|
||||
}
|
||||
|
||||
static void ep_clear_and_put(struct eventpoll *ep)
|
||||
@ -917,7 +952,7 @@ static void ep_clear_and_put(struct eventpoll *ep)
|
||||
|
||||
/*
|
||||
* Walks through the whole tree and try to free each "struct epitem".
|
||||
* Note that ep_remove_safe() will not remove the epitem in case of a
|
||||
* Note that ep_remove() will not remove the epitem in case of a
|
||||
* racing eventpoll_release_file(); the latter will do the removal.
|
||||
* At this point we are sure no poll callbacks will be lingering around.
|
||||
* Since we still own a reference to the eventpoll struct, the loop can't
|
||||
@ -926,7 +961,7 @@ static void ep_clear_and_put(struct eventpoll *ep)
|
||||
for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = next) {
|
||||
next = rb_next(rbp);
|
||||
epi = rb_entry(rbp, struct epitem, rbn);
|
||||
ep_remove_safe(ep, epi);
|
||||
ep_remove(ep, epi);
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
@ -1006,34 +1041,6 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ffd.file pointer may be in the process of being torn down due to
|
||||
* being closed, but we may not have finished eventpoll_release() yet.
|
||||
*
|
||||
* Normally, even with the atomic_long_inc_not_zero, the file may have
|
||||
* been free'd and then gotten re-allocated to something else (since
|
||||
* files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
|
||||
*
|
||||
* But for epoll, users hold the ep->mtx mutex, and as such any file in
|
||||
* the process of being free'd will block in eventpoll_release_file()
|
||||
* and thus the underlying file allocation will not be free'd, and the
|
||||
* file re-use cannot happen.
|
||||
*
|
||||
* For the same reason we can avoid a rcu_read_lock() around the
|
||||
* operation - 'ffd.file' cannot go away even if the refcount has
|
||||
* reached zero (but we must still not call out to ->poll() functions
|
||||
* etc).
|
||||
*/
|
||||
static struct file *epi_fget(const struct epitem *epi)
|
||||
{
|
||||
struct file *file;
|
||||
|
||||
file = epi->ffd.file;
|
||||
if (!file_ref_get(&file->f_ref))
|
||||
file = NULL;
|
||||
return file;
|
||||
}
|
||||
|
||||
/*
|
||||
* Differs from ep_eventpoll_poll() in that internal callers already have
|
||||
* the ep->mtx so we need to start from depth=1, such that mutex_lock_nested()
|
||||
@ -1111,18 +1118,17 @@ void eventpoll_release_file(struct file *file)
|
||||
{
|
||||
struct eventpoll *ep;
|
||||
struct epitem *epi;
|
||||
bool dispose;
|
||||
|
||||
/*
|
||||
* Use the 'dying' flag to prevent a concurrent ep_clear_and_put() from
|
||||
* touching the epitems list before eventpoll_release_file() can access
|
||||
* the ep->mtx.
|
||||
* A concurrent ep_remove() cannot outrace us: it pins @file via
|
||||
* epi_fget(), which fails once __fput() has dropped the refcount
|
||||
* to zero -- the path we're on. So any racing ep_remove() bails
|
||||
* and leaves the epi for us to clean up here.
|
||||
*/
|
||||
again:
|
||||
spin_lock(&file->f_lock);
|
||||
if (file->f_ep && file->f_ep->first) {
|
||||
epi = hlist_entry(file->f_ep->first, struct epitem, fllink);
|
||||
epi->dying = true;
|
||||
spin_unlock(&file->f_lock);
|
||||
|
||||
/*
|
||||
@ -1131,10 +1137,15 @@ again:
|
||||
*/
|
||||
ep = epi->ep;
|
||||
mutex_lock(&ep->mtx);
|
||||
dispose = __ep_remove(ep, epi, true);
|
||||
|
||||
ep_unregister_pollwait(ep, epi);
|
||||
|
||||
ep_remove_file(ep, epi, file);
|
||||
ep_remove_epi(ep, epi);
|
||||
|
||||
mutex_unlock(&ep->mtx);
|
||||
|
||||
if (dispose && ep_refcount_dec_and_test(ep))
|
||||
if (ep_refcount_dec_and_test(ep))
|
||||
ep_free(ep);
|
||||
goto again;
|
||||
}
|
||||
@ -1630,7 +1641,8 @@ allocate:
|
||||
spin_unlock(&file->f_lock);
|
||||
goto allocate;
|
||||
}
|
||||
file->f_ep = head;
|
||||
/* See eventpoll_release() for details. */
|
||||
WRITE_ONCE(file->f_ep, head);
|
||||
to_free = NULL;
|
||||
}
|
||||
hlist_add_head_rcu(&epi->fllink, file->f_ep);
|
||||
@ -1696,21 +1708,21 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
|
||||
mutex_unlock(&tep->mtx);
|
||||
|
||||
/*
|
||||
* ep_remove_safe() calls in the later error paths can't lead to
|
||||
* ep_remove() calls in the later error paths can't lead to
|
||||
* ep_free() as the ep file itself still holds an ep reference.
|
||||
*/
|
||||
ep_get(ep);
|
||||
|
||||
/* now check if we've created too many backpaths */
|
||||
if (unlikely(full_check && reverse_path_check())) {
|
||||
ep_remove_safe(ep, epi);
|
||||
ep_remove(ep, epi);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (epi->event.events & EPOLLWAKEUP) {
|
||||
error = ep_create_wakeup_source(epi);
|
||||
if (error) {
|
||||
ep_remove_safe(ep, epi);
|
||||
ep_remove(ep, epi);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -1734,7 +1746,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
|
||||
* high memory pressure.
|
||||
*/
|
||||
if (unlikely(!epq.epi)) {
|
||||
ep_remove_safe(ep, epi);
|
||||
ep_remove(ep, epi);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -2118,23 +2130,25 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
|
||||
}
|
||||
|
||||
/**
|
||||
* ep_loop_check_proc - verify that adding an epoll file inside another
|
||||
* epoll structure does not violate the constraints, in
|
||||
* terms of closed loops, or too deep chains (which can
|
||||
* result in excessive stack usage).
|
||||
* ep_loop_check_proc - verify that adding an epoll file @ep inside another
|
||||
* epoll file does not create closed loops, and
|
||||
* determine the depth of the subtree starting at @ep
|
||||
*
|
||||
* @ep: the &struct eventpoll to be currently checked.
|
||||
* @depth: Current depth of the path being checked.
|
||||
*
|
||||
* Return: %zero if adding the epoll @file inside current epoll
|
||||
* structure @ep does not violate the constraints, or %-1 otherwise.
|
||||
* Return: depth of the subtree, or a value bigger than EP_MAX_NESTS if we found
|
||||
* a loop or went too deep.
|
||||
*/
|
||||
static int ep_loop_check_proc(struct eventpoll *ep, int depth)
|
||||
{
|
||||
int error = 0;
|
||||
int result = 0;
|
||||
struct rb_node *rbp;
|
||||
struct epitem *epi;
|
||||
|
||||
if (ep->gen == loop_check_gen)
|
||||
return ep->loop_check_depth;
|
||||
|
||||
mutex_lock_nested(&ep->mtx, depth + 1);
|
||||
ep->gen = loop_check_gen;
|
||||
for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
|
||||
@ -2142,13 +2156,11 @@ static int ep_loop_check_proc(struct eventpoll *ep, int depth)
|
||||
if (unlikely(is_file_epoll(epi->ffd.file))) {
|
||||
struct eventpoll *ep_tovisit;
|
||||
ep_tovisit = epi->ffd.file->private_data;
|
||||
if (ep_tovisit->gen == loop_check_gen)
|
||||
continue;
|
||||
if (ep_tovisit == inserting_into || depth > EP_MAX_NESTS)
|
||||
error = -1;
|
||||
result = EP_MAX_NESTS+1;
|
||||
else
|
||||
error = ep_loop_check_proc(ep_tovisit, depth + 1);
|
||||
if (error != 0)
|
||||
result = max(result, ep_loop_check_proc(ep_tovisit, depth + 1) + 1);
|
||||
if (result > EP_MAX_NESTS)
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
@ -2162,9 +2174,27 @@ static int ep_loop_check_proc(struct eventpoll *ep, int depth)
|
||||
list_file(epi->ffd.file);
|
||||
}
|
||||
}
|
||||
ep->loop_check_depth = result;
|
||||
mutex_unlock(&ep->mtx);
|
||||
|
||||
return error;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ep_get_upwards_depth_proc - determine depth of @ep when traversed upwards
|
||||
*/
|
||||
static int ep_get_upwards_depth_proc(struct eventpoll *ep, int depth)
|
||||
{
|
||||
int result = 0;
|
||||
struct epitem *epi;
|
||||
|
||||
if (ep->gen == loop_check_gen)
|
||||
return ep->loop_check_depth;
|
||||
hlist_for_each_entry_rcu(epi, &ep->refs, fllink)
|
||||
result = max(result, ep_get_upwards_depth_proc(epi->ep, depth + 1) + 1);
|
||||
ep->gen = loop_check_gen;
|
||||
ep->loop_check_depth = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2180,8 +2210,22 @@ static int ep_loop_check_proc(struct eventpoll *ep, int depth)
|
||||
*/
|
||||
static int ep_loop_check(struct eventpoll *ep, struct eventpoll *to)
|
||||
{
|
||||
int depth, upwards_depth;
|
||||
|
||||
inserting_into = ep;
|
||||
return ep_loop_check_proc(to, 0);
|
||||
/*
|
||||
* Check how deep down we can get from @to, and whether it is possible
|
||||
* to loop up to @ep.
|
||||
*/
|
||||
depth = ep_loop_check_proc(to, 0);
|
||||
if (depth > EP_MAX_NESTS)
|
||||
return -1;
|
||||
/* Check how far up we can go from @ep. */
|
||||
rcu_read_lock();
|
||||
upwards_depth = ep_get_upwards_depth_proc(ep, 0);
|
||||
rcu_read_unlock();
|
||||
|
||||
return (depth+1+upwards_depth > EP_MAX_NESTS) ? -1 : 0;
|
||||
}
|
||||
|
||||
static void clear_tfile_check_list(void)
|
||||
@ -2397,7 +2441,7 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
|
||||
* The eventpoll itself is still alive: the refcount
|
||||
* can't go to zero here.
|
||||
*/
|
||||
ep_remove_safe(ep, epi);
|
||||
ep_remove(ep, epi);
|
||||
error = 0;
|
||||
} else {
|
||||
error = -ENOENT;
|
||||
|
||||
@ -531,7 +531,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
||||
}
|
||||
|
||||
sid = task_session_nr_ns(task, ns);
|
||||
ppid = task_tgid_nr_ns(task->real_parent, ns);
|
||||
ppid = task_ppid_nr_ns(task, ns);
|
||||
pgid = task_pgrp_nr_ns(task, ns);
|
||||
|
||||
unlock_task_sighand(task, &flags);
|
||||
|
||||
@ -111,7 +111,7 @@ static int check_wsl_eas(struct kvec *rsp_iov)
|
||||
u32 outlen, next;
|
||||
u16 vlen;
|
||||
u8 nlen;
|
||||
u8 *end;
|
||||
u8 *ea_end, *iov_end;
|
||||
|
||||
outlen = le32_to_cpu(rsp->OutputBufferLength);
|
||||
if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE ||
|
||||
@ -120,15 +120,19 @@ static int check_wsl_eas(struct kvec *rsp_iov)
|
||||
|
||||
ea = (void *)((u8 *)rsp_iov->iov_base +
|
||||
le16_to_cpu(rsp->OutputBufferOffset));
|
||||
end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
|
||||
ea_end = (u8 *)ea + outlen;
|
||||
iov_end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
|
||||
if (ea_end > iov_end)
|
||||
return -EINVAL;
|
||||
|
||||
for (;;) {
|
||||
if ((u8 *)ea > end - sizeof(*ea))
|
||||
if ((u8 *)ea > ea_end - sizeof(*ea))
|
||||
return -EINVAL;
|
||||
|
||||
nlen = ea->ea_name_length;
|
||||
vlen = le16_to_cpu(ea->ea_value_length);
|
||||
if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
|
||||
(u8 *)ea + nlen + 1 + vlen > end)
|
||||
(u8 *)ea->ea_data + nlen + 1 + vlen > ea_end)
|
||||
return -EINVAL;
|
||||
|
||||
switch (vlen) {
|
||||
|
||||
@ -35,14 +35,18 @@ static inline void eventpoll_release(struct file *file)
|
||||
{
|
||||
|
||||
/*
|
||||
* Fast check to avoid the get/release of the semaphore. Since
|
||||
* we're doing this outside the semaphore lock, it might return
|
||||
* false negatives, but we don't care. It'll help in 99.99% of cases
|
||||
* to avoid the semaphore lock. False positives simply cannot happen
|
||||
* because the file in on the way to be removed and nobody ( but
|
||||
* eventpoll ) has still a reference to this file.
|
||||
* Fast check to skip the slow path in the common case where the
|
||||
* file was never attached to an epoll. Safe without file->f_lock
|
||||
* because every f_ep writer excludes a concurrent __fput() on
|
||||
* @file:
|
||||
* - ep_insert() requires the file alive (refcount > 0);
|
||||
* - ep_remove() holds @file pinned via epi_fget() across the
|
||||
* write;
|
||||
* - eventpoll_release_file() runs from __fput() itself.
|
||||
* We are in __fput() here, so none of those can race us: a NULL
|
||||
* observation truly means no epoll path has work left on @file.
|
||||
*/
|
||||
if (likely(!file->f_ep))
|
||||
if (likely(!READ_ONCE(file->f_ep)))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,6.12.0-211.30.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,6.12.0-211.31.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
@ -347,6 +347,18 @@ void xdp_do_check_flushed(struct napi_struct *napi);
|
||||
static inline void xdp_do_check_flushed(struct napi_struct *napi) { }
|
||||
#endif
|
||||
|
||||
/* Best effort check that NAPI is not idle (can't be scheduled to run) */
|
||||
static inline void napi_assert_will_not_race(const struct napi_struct *napi)
|
||||
{
|
||||
/* uninitialized instance, can't race */
|
||||
if (!napi->poll_list.next)
|
||||
return;
|
||||
|
||||
/* SCHED bit is set on disabled instances */
|
||||
WARN_ON(!test_bit(NAPI_STATE_SCHED, &napi->state));
|
||||
WARN_ON(READ_ONCE(napi->list_owner) != -1);
|
||||
}
|
||||
|
||||
void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu);
|
||||
|
||||
#define XMIT_RECURSION_LIMIT 8
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
#include <trace/events/page_pool.h>
|
||||
|
||||
#include RH_KABI_HIDE_INCLUDE("dev.h")
|
||||
#include "mp_dmabuf_devmem.h"
|
||||
#include "netmem_priv.h"
|
||||
#include "page_pool_priv.h"
|
||||
@ -1196,11 +1197,7 @@ void page_pool_disable_direct_recycling(struct page_pool *pool)
|
||||
if (!pool->p.napi)
|
||||
return;
|
||||
|
||||
/* To avoid races with recycling and additional barriers make sure
|
||||
* pool and NAPI are unlinked when NAPI is disabled.
|
||||
*/
|
||||
WARN_ON(!test_bit(NAPI_STATE_SCHED, &pool->p.napi->state));
|
||||
WARN_ON(READ_ONCE(pool->p.napi->list_owner) != -1);
|
||||
napi_assert_will_not_race(pool->p.napi);
|
||||
|
||||
mutex_lock(&page_pools_lock);
|
||||
WRITE_ONCE(pool->p.napi, NULL);
|
||||
|
||||
@ -698,7 +698,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
struct ioam6_namespace *ns,
|
||||
struct ioam6_trace_hdr *trace,
|
||||
struct ioam6_schema *sc,
|
||||
u8 sclen, bool is_input)
|
||||
unsigned int sclen, bool is_input)
|
||||
{
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
struct timespec64 ts;
|
||||
@ -929,7 +929,7 @@ void ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
bool is_input)
|
||||
{
|
||||
struct ioam6_schema *sc;
|
||||
u8 sclen = 0;
|
||||
unsigned int sclen = 0;
|
||||
|
||||
/* Skip if Overflow flag is set
|
||||
*/
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-211.30.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-211.31.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
2
uki.sbat
2
uki.sbat
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-211.30.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-211.31.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
Loading…
Reference in New Issue
Block a user