Import of kernel-6.12.0-211.31.1.el10_2

This commit is contained in:
almalinux-bot-kernel 2026-07-10 05:25:02 +00:00
parent 4fd067918e
commit 8a9da85e81
15 changed files with 207 additions and 145 deletions

View File

@ -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));

View File

@ -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(

View File

@ -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");
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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;
/*

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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
*/

View File

@ -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

View File

@ -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