[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHC9VhQ_hv1ri1csrgGP+9RssCuJBDuOLSDowZRD5xZcDD2mPA@mail.gmail.com>
Date: Mon, 20 Oct 2025 15:12:28 -0400
From: Paul Moore <paul@...l-moore.com>
To: Hongru Zhang <zhanghongru06@...il.com>
Cc: linux-kernel@...r.kernel.org, omosnace@...hat.com, selinux@...r.kernel.org,
stephen.smalley.work@...il.com, zhanghongru@...omi.com
Subject: Re: [PATCH v3 1/2] selinux: Make avc cache slot size configurable
during boot
On Fri, Oct 17, 2025 at 4:10 AM Hongru Zhang <zhanghongru06@...il.com> wrote:
> > On Sep 26, 2025 Hongru Zhang <zhanghongru06@...il.com> wrote:
...
> > I would expect the number of active AVC nodes, and AVC churn in general,
> > to be very policy dependent; some policies and use cases simply result in
> > more AVC nodes than others. With that in mind, I'm wondering if instead
> > of using a kernel command line parameter to specify the number of AVC
> > buckets, we should instead include an AVC size "hint" in the policy that
> > we can use to size the AVC when loading a new policy.
> >
> > Thoughts?
>
> I previously considered supporting dynamic adjustment of slot size during
> runtime, but this seems to introduce code complexity and overhead. Every
> time avc_lookup() or avc_insert() happens, we would need to check if the
> table exists. Adjusting slot size and accessing a specific slot might
> occur simultaneously, potentially requiring additional lock protection.
I would imagine that a very simple implementation would simply convert
the selinux_avc variable from an instance of selinux_avc to a RCU
protected selinux_avc pointer. As the AVC already uses RCU, I think
the number of changes should be relatively minimal:
* Ensure we wrap selinux_avc derefs with rcu_dereference(). This
should be the only real change needed for lookups and insertions as
every search through the AVC will start with deref'ing the selinux_avc
pointer.
* Update avc_init() to allocate the cache slots with a default value,
fail if unable to allocate the cache memory. If we ensure that the
selinux_avc pointer will always be valid, we can avoid having to check
it.
* Policy (re)loads which would change the number of AVC cache slots
would allocate and initialize a new selinux_avc then swap the global
selinux_avc pointer under spinlock. The old AVC cache could then be
free'd according to RCU rules. I haven't thought about it too much,
but I suspect we could do away with flushing the old AVC in these
cases, even if we can't, flushing the old AVC is easy enough.
> When increasing slot size, we could directly copy the contents from the
> old table. When decreasing slot size, nodes exceeding the new slot size
> would need to be re-hashed and attached to appropriate positions.
Changing the number of cache slots should happen infrequently enough
that I see no need to migrate the old entries to the new cache
instance. It's a cache, it will fill back up naturally.
> On my Android device, policies are fixed before system image release and
> don't change or load dynamically during system running. Using kernel
> parameters for adjustment ensures no additional locks or checks are needed
> during runtime table access, maintaining simplicity and efficiency of the
> lookup code.
If your system does not update its policy over the course of a single
boot, and presumably doesn't drastically change its behavior during
that time, there is another, simpler option that we should consider:
setting AVC_CACHE_SLOTS at compile time based on a Kconfig tunable.
The code change would essentially be one line:
#define AVC_CACHE_SLOTS (2 << CONFIG_SECURITY_SELINUX_AVC_HASH_BITS)
... with a corresponding entry in security/selinux/Kconfig. That
should be a very easy change, and if you set the default value such
that AVC_CACHE_SLOTS remains at 512, there should be no impact on
existing systems.
--
paul-moore.com
Powered by blists - more mailing lists