<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-dev/security/selinux/ss/sidtab.c, branch linus/master</title>
<subtitle>Linux kernel development work - see feature branches</subtitle>
<id>https://git.zx2c4.com/linux-dev/atom/security/selinux/ss/sidtab.c?h=linus%2Fmaster</id>
<link rel='self' href='https://git.zx2c4.com/linux-dev/atom/security/selinux/ss/sidtab.c?h=linus%2Fmaster'/>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/'/>
<updated>2022-01-26T20:13:58Z</updated>
<entry>
<title>selinux: enclose macro arguments in parenthesis</title>
<updated>2022-01-26T20:13:58Z</updated>
<author>
<name>Christian Göttsche</name>
<email>cgzones@googlemail.com</email>
</author>
<published>2022-01-25T14:14:14Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=9e2fe574c02bde46307255467a5e4291f65227fe'/>
<id>urn:sha1:9e2fe574c02bde46307255467a5e4291f65227fe</id>
<content type='text'>
Enclose the macro arguments in parenthesis to avoid potential evaluation
order issues.

Note the xperm and ebitmap macros are still not side-effect safe due to
double evaluation.

Reported by clang-tidy [bugprone-macro-parentheses]

Signed-off-by: Christian Göttsche &lt;cgzones@googlemail.com&gt;
Reviewed-by: Nick Desaulniers &lt;ndesaulniers@google.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: Use struct_size() helper in kmalloc()</title>
<updated>2021-12-06T02:58:32Z</updated>
<author>
<name>Xiu Jianfeng</name>
<email>xiujianfeng@huawei.com</email>
</author>
<published>2021-12-02T07:35:33Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=5fe375728983b3fca6b958434a2e3f547bbbb2aa'/>
<id>urn:sha1:5fe375728983b3fca6b958434a2e3f547bbbb2aa</id>
<content type='text'>
Make use of struct_size() helper instead of an open-coded calculation.

Link: https://github.com/KSPP/linux/issues/160
Signed-off-by: Xiu Jianfeng &lt;xiujianfeng@huawei.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: fix race between old and new sidtab</title>
<updated>2021-04-08T00:42:56Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2021-04-07T07:24:43Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=9ad6e9cb39c66366bf7b9aece114aca277981a1f'/>
<id>urn:sha1:9ad6e9cb39c66366bf7b9aece114aca277981a1f</id>
<content type='text'>
Since commit 1b8b31a2e612 ("selinux: convert policy read-write lock to
RCU"), there is a small window during policy load where the new policy
pointer has already been installed, but some threads may still be
holding the old policy pointer in their read-side RCU critical sections.
This means that there may be conflicting attempts to add a new SID entry
to both tables via sidtab_context_to_sid().

See also (and the rest of the thread):
https://lore.kernel.org/selinux/CAFqZXNvfux46_f8gnvVvRYMKoes24nwm2n3sPbMjrB8vKTW00g@mail.gmail.com/

Fix this by installing the new policy pointer under the old sidtab's
spinlock along with marking the old sidtab as "frozen". Then, if an
attempt to add new entry to a "frozen" sidtab is detected, make
sidtab_context_to_sid() return -ESTALE to indicate that a new policy
has been installed and that the caller will have to abort the policy
transaction and try again after re-taking the policy pointer (which is
guaranteed to be a newer policy). This requires adding a retry-on-ESTALE
logic to all callers of sidtab_context_to_sid(), but fortunately these
are easy to determine and aren't that many.

This seems to be the simplest solution for this problem, even if it
looks somewhat ugly. Note that other places in the kernel (e.g.
do_mknodat() in fs/namei.c) use similar stale-retry patterns, so I think
it's reasonable.

Cc: stable@vger.kernel.org
Fixes: 1b8b31a2e612 ("selinux: convert policy read-write lock to RCU")
Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: move policy commit after updating selinuxfs</title>
<updated>2020-08-18T00:50:22Z</updated>
<author>
<name>Stephen Smalley</name>
<email>stephen.smalley.work@gmail.com</email>
</author>
<published>2020-08-07T13:29:34Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=02a52c5c8c3b8cbad0f12009cde9f36dbefb6972'/>
<id>urn:sha1:02a52c5c8c3b8cbad0f12009cde9f36dbefb6972</id>
<content type='text'>
With the refactoring of the policy load logic in the security
server from the previous change, it is now possible to split out
the committing of the new policy from security_load_policy() and
perform it only after successful updating of selinuxfs.  Change
security_load_policy() to return the newly populated policy
data structures to the caller, export selinux_policy_commit()
for external callers, and introduce selinux_policy_cancel() to
provide a way to cancel the policy load in the event of an error
during updating of the selinuxfs directory tree.  Further, rework
the interfaces used by selinuxfs to get information from the policy
when creating the new directory tree to take and act upon the
new policy data structure rather than the current/active policy.
Update selinuxfs to use these updated and new interfaces.  While
we are here, stop re-creating the policy_capabilities directory
on each policy load since it does not depend on the policy, and
stop trying to create the booleans and classes directories during
the initial creation of selinuxfs since no information is available
until first policy load.

After this change, a failure while updating the booleans and class
directories will cause the entire policy load to be canceled, leaving
the original policy intact, and policy load notifications to userspace
will only happen after a successful completion of updating those
directories.  This does not (yet) provide full atomicity with respect
to the updating of the directory trees themselves.

Signed-off-by: Stephen Smalley &lt;stephen.smalley.work@gmail.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: move context hashing under sidtab</title>
<updated>2020-04-17T20:04:38Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2020-04-17T08:11:57Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=225621c9348d2a759db141024d5986d48e8c50dc'/>
<id>urn:sha1:225621c9348d2a759db141024d5986d48e8c50dc</id>
<content type='text'>
Now that context hash computation no longer depends on policydb, we can
simplify things by moving the context hashing completely under sidtab.
The hash is still cached in sidtab entries, but not for the in-flight
context structures.

Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: drop unnecessary smp_load_acquire() call</title>
<updated>2020-04-15T22:27:35Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2020-04-08T09:08:08Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=433e3aa37773e8a36858b9417c3e345eff79a079'/>
<id>urn:sha1:433e3aa37773e8a36858b9417c3e345eff79a079</id>
<content type='text'>
In commit 66f8e2f03c02 ("selinux: sidtab reverse lookup hash table") the
corresponding load is moved under the spin lock, so there is no race
possible and we can read the count directly. The smp_store_release() is
still needed to avoid racing with the lock-free readers.

Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: fix sidtab string cache locking</title>
<updated>2020-02-05T23:31:10Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2020-02-03T08:50:23Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=39a706fbcf2694bfb651bed9041d44c3f4fa8078'/>
<id>urn:sha1:39a706fbcf2694bfb651bed9041d44c3f4fa8078</id>
<content type='text'>
Avoiding taking a lock in an IRQ context is not enough to prevent
deadlocks, as discovered by syzbot:

===
WARNING: SOFTIRQ-safe -&gt; SOFTIRQ-unsafe lock order detected
5.5.0-syzkaller #0 Not tainted
-----------------------------------------------------
syz-executor.0/8927 [HC0[0]:SC0[2]:HE1:SE0] is trying to acquire:
ffff888027c94098 (&amp;(&amp;s-&gt;cache_lock)-&gt;rlock){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline]
ffff888027c94098 (&amp;(&amp;s-&gt;cache_lock)-&gt;rlock){+.+.}, at: sidtab_sid2str_put.part.0+0x36/0x880 security/selinux/ss/sidtab.c:533

and this task is already holding:
ffffffff898639b0 (&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock){+.-.}, at: spin_lock include/linux/spinlock.h:338 [inline]
ffffffff898639b0 (&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock){+.-.}, at: nf_conntrack_lock+0x17/0x70 net/netfilter/nf_conntrack_core.c:91
which would create a new lock dependency:
 (&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock){+.-.} -&gt; (&amp;(&amp;s-&gt;cache_lock)-&gt;rlock){+.+.}

but this new dependency connects a SOFTIRQ-irq-safe lock:
 (&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock){+.-.}

[...]

other info that might help us debug this:

 Possible interrupt unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&amp;(&amp;s-&gt;cache_lock)-&gt;rlock);
                               local_irq_disable();
                               lock(&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock);
                               lock(&amp;(&amp;s-&gt;cache_lock)-&gt;rlock);
  &lt;Interrupt&gt;
    lock(&amp;(&amp;nf_conntrack_locks[i])-&gt;rlock);

 *** DEADLOCK ***
[...]
===

Fix this by simply locking with irqsave/irqrestore and stop giving up on
!in_task(). It makes the locking a bit slower, but it shouldn't make a
big difference in real workloads. Under the scenario from [1] (only
cache hits) it only increased the runtime overhead from the
security_secid_to_secctx() function from ~2% to ~3% (it was ~5-65%
before introducing the cache).

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1733259

Fixes: d97bd23c2d7d ("selinux: cache the SID -&gt; context string translation")
Reported-by: syzbot+61cba5033e2072d61806@syzkaller.appspotmail.com
Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Acked-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: cache the SID -&gt; context string translation</title>
<updated>2019-12-09T21:14:51Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2019-11-26T13:57:00Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=d97bd23c2d7d866e99eb3a927c742715c85a90ef'/>
<id>urn:sha1:d97bd23c2d7d866e99eb3a927c742715c85a90ef</id>
<content type='text'>
Translating a context struct to string can be quite slow, especially if
the context has a lot of category bits set. This can cause quite
noticeable performance impact in situations where the translation needs
to be done repeatedly. A common example is a UNIX datagram socket with
the SO_PASSSEC option enabled, which is used e.g. by systemd-journald
when receiving log messages via datagram socket. This scenario can be
reproduced with:

    cat /dev/urandom | base64 | logger &amp;
    timeout 30s perf record -p $(pidof systemd-journald) -a -g
    kill %1
    perf report -g none --pretty raw | grep security_secid_to_secctx

Before the caching introduced by this patch, computing the context
string (security_secid_to_secctx() function) takes up ~65% of
systemd-journald's CPU time (assuming a context with 1024 categories
set and Fedora x86_64 release kernel configs). After this patch
(assuming near-perfect cache hit ratio) this overhead is reduced to just
~2%.

This patch addresses the issue by caching a certain number (compile-time
configurable) of recently used context strings to speed up repeated
translations of the same context, while using only a small amount of
memory.

The cache is integrated into the existing sidtab table by adding a field
to each entry, which when not NULL contains an RCU-protected pointer to
a cache entry containing the cached string. The cache entries are kept
in a linked list sorted according to how recently they were used. On a
cache miss when the cache is full, the least recently used entry is
removed to make space for the new entry.

The patch migrates security_sid_to_context_core() to use the cache (also
a few other functions where it was possible without too much fuss, but
these mostly use the translation for logging in case of error, which is
rare).

Link: https://bugzilla.redhat.com/show_bug.cgi?id=1733259
Cc: Michal Sekletar &lt;msekleta@redhat.com&gt;
Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Reviewed-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
Tested-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
Reviewed-by: Paul E. McKenney &lt;paulmck@kernel.org&gt;
[PM: lots of merge fixups due to collisions with other sidtab patches]
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: sidtab reverse lookup hash table</title>
<updated>2019-12-09T21:14:51Z</updated>
<author>
<name>Jeff Vander Stoep</name>
<email>jeffv@google.com</email>
</author>
<published>2019-11-22T09:33:06Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=66f8e2f03c02e812002f8e9e465681cc62edda5b'/>
<id>urn:sha1:66f8e2f03c02e812002f8e9e465681cc62edda5b</id>
<content type='text'>
This replaces the reverse table lookup and reverse cache with a
hashtable which improves cache-miss reverse-lookup times from
O(n) to O(1)* and maintains the same performance as a reverse
cache hit.

This reduces the time needed to add a new sidtab entry from ~500us
to 5us on a Pixel 3 when there are ~10,000 sidtab entries.

The implementation uses the kernel's generic hashtable API,
It uses the context's string represtation as the hash source,
and the kernels generic string hashing algorithm full_name_hash()
to reduce the string to a 32 bit value.

This change also maintains the improvement introduced in
commit ee1a84fdfeed ("selinux: overhaul sidtab to fix bug and improve
performance") which removed the need to keep the current sidtab
locked during policy reload. It does however introduce periodic
locking of the target sidtab while converting the hashtable. Sidtab
entries are never modified or removed, so the context struct stored
in the sid_to_context tree can also be used for the context_to_sid
hashtable to reduce memory usage.

This bug was reported by:
- On the selinux bug tracker.
  BUG: kernel softlockup due to too many SIDs/contexts #37
  https://github.com/SELinuxProject/selinux-kernel/issues/37
- Jovana Knezevic on Android's bugtracker.
  Bug: 140252993
  "During multi-user performance testing, we create and remove users
  many times. selinux_android_restorecon_pkgdir goes from 1ms to over
  20ms after about 200 user creations and removals. Accumulated over
  ~280 packages, that adds a significant time to user creation,
  making perf benchmarks unreliable."

* Hashtable lookup is only O(1) when n &lt; the number of buckets.

Signed-off-by: Jeff Vander Stoep &lt;jeffv@google.com&gt;
Reported-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
Reported-by: Jovana Knezevic &lt;jovanak@google.com&gt;
Reviewed-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
Tested-by: Stephen Smalley &lt;sds@tycho.nsa.gov&gt;
[PM: subj tweak, removed changelog from patch description]
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
<entry>
<title>selinux: avoid atomic_t usage in sidtab</title>
<updated>2019-08-27T17:26:13Z</updated>
<author>
<name>Ondrej Mosnacek</name>
<email>omosnace@redhat.com</email>
</author>
<published>2019-08-14T13:33:20Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/linux-dev/commit/?id=116f21bb967fcef1fa360fe591a2947481788020'/>
<id>urn:sha1:116f21bb967fcef1fa360fe591a2947481788020</id>
<content type='text'>
As noted in Documentation/atomic_t.txt, if we don't need the RMW atomic
operations, we should only use READ_ONCE()/WRITE_ONCE() +
smp_rmb()/smp_wmb() where necessary (or the combined variants
smp_load_acquire()/smp_store_release()).

This patch converts the sidtab code to use regular u32 for the counter
and reverse lookup cache and use the appropriate operations instead of
atomic_get()/atomic_set(). Note that when reading/updating the reverse
lookup cache we don't need memory barriers as it doesn't need to be
consistent or accurate. We can now also replace some atomic ops with
regular loads (when under spinlock) and stores (for conversion target
fields that are always accessed under the master table's spinlock).

We can now also bump SIDTAB_MAX to U32_MAX as we can use the full u32
range again.

Suggested-by: Jann Horn &lt;jannh@google.com&gt;
Signed-off-by: Ondrej Mosnacek &lt;omosnace@redhat.com&gt;
Reviewed-by: Jann Horn &lt;jannh@google.com&gt;
Signed-off-by: Paul Moore &lt;paul@paul-moore.com&gt;
</content>
</entry>
</feed>
