All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ondrej Mosnacek <omosnace@redhat.com>
To: "Christian Göttsche" <cgzones@googlemail.com>
Cc: SElinux list <selinux@vger.kernel.org>
Subject: Re: [PATCH userspace v2 0/6] Parallel setfiles/restorecon
Date: Tue, 19 Oct 2021 14:29:01 +0200	[thread overview]
Message-ID: <CAFqZXNt2V21x7bAYGVQ_U818ZfShAYiyzzdU8D2L9uBZrsea1g@mail.gmail.com> (raw)
In-Reply-To: <CAFqZXNuL-jb=QptF2ZuQ8208j9g1-xJXTAkfPia7MwYZmfEbWA@mail.gmail.com>

On Mon, Oct 18, 2021 at 10:56 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> On Fri, Oct 15, 2021 at 3:25 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> > On Fri, Oct 15, 2021 at 2:37 PM Christian Göttsche
> > <cgzones@googlemail.com> wrote:
> > > On Thu, 14 Oct 2021 at 16:53, Ondrej Mosnacek <omosnace@redhat.com> wrote:
> > > >
> > > > This series adds basic support for parallel relabeling to the libselinux
> > > > API and the setfiles/restorecon CLI tools. It turns out that doing the
> > > > relabeling in parallel can significantly reduce the time even with a
> > > > relatively simple approach.
> > > >
> > > > The first patch is a small cleanup that was found along the way and can
> > > > be applied independently. Patches 2-4 are small incremental changes that
> > > > make the internal selinux_restorecon functions more thread-safe (I kept
> > > > them separate for ease of of review, but maybe they should be rather
> > > > folded into the netx patch...). Patch 5 then completes the parallel
> > > > relabeling implementation at libselinux level and adds a new function
> > > > to the API that allows to make use of it. Finally, patch 6 adds parallel
> > > > relabeling support to he setfiles/restorecon tools.
> > > >
> > > > The relevant man pages are also updated to reflect the new
> > > > functionality.
> > > >
> > > > The patch descriptions contain more details, namely the last patch has
> > > > also some benchmark numbers.
> > > >
> > > > Changes v1->v2:
> > > > - make selinux_log() synchronized instead of introducing selinux_log_sync()
> > > > - fix -Wcomma warning
> > > > - update the swig files as well
> > > > - bump new symbol version to LIBSELINUX_3.3 (this may need further update
> > > >   depending on when this gets merged)
> > > >
> > > > Ondrej Mosnacek (6):
> > > >   selinux_restorecon: simplify fl_head allocation by using calloc()
> > > >   selinux_restorecon: protect file_spec list with a mutex
> > > >   libselinux: make selinux_log() thread-safe
> > > >   selinux_restorecon: add a global mutex to synchronize progress output
> > > >   selinux_restorecon: introduce selinux_restorecon_parallel(3)
> > > >   setfiles/restorecon: support parallel relabeling
> > > >
> > > >  libselinux/include/selinux/restorecon.h       |  14 +
> > > >  libselinux/man/man3/selinux_restorecon.3      |  29 ++
> > > >  .../man/man3/selinux_restorecon_parallel.3    |   1 +
> > > >  libselinux/src/callbacks.c                    |   8 +-
> > > >  libselinux/src/callbacks.h                    |  13 +-
> > > >  libselinux/src/libselinux.map                 |   5 +
> > > >  libselinux/src/selinux_internal.h             |  14 +
> > > >  libselinux/src/selinux_restorecon.c           | 466 ++++++++++++------
> > > >  libselinux/src/selinuxswig_python.i           |   6 +-
> > > >  libselinux/src/selinuxswig_python_exception.i |   8 +
> > > >  policycoreutils/setfiles/Makefile             |   2 +-
> > > >  policycoreutils/setfiles/restore.c            |   7 +-
> > > >  policycoreutils/setfiles/restore.h            |   2 +-
> > > >  policycoreutils/setfiles/restorecon.8         |   9 +
> > > >  policycoreutils/setfiles/setfiles.8           |   9 +
> > > >  policycoreutils/setfiles/setfiles.c           |  28 +-
> > > >  16 files changed, 444 insertions(+), 177 deletions(-)
> > > >  create mode 100644 libselinux/man/man3/selinux_restorecon_parallel.3
> > > >
> > > > --
> > > > 2.31.1
> > > >
> > >
> > >
> > > Running under ThreadSanitizer shows multiple instances of the following issue:
> > >
> > > ==================
> > > WARNING: ThreadSanitizer: data race (pid=16933)
> > >   Read of size 4 at 0x7f8790d636f4 by thread T2:
> > >     #0 lookup_all ./libselinux/src/label_file.c:954 (libselinux.so.1+0x14d1b)
> > >     #1 lookup_common ./libselinux/src/label_file.c:997 (libselinux.so.1+0x14f62)
> > >     #2 lookup ./libselinux/src/label_file.c:1095 (libselinux.so.1+0x14fff)
> > >     #3 selabel_lookup_common ./libselinux/src/label.c:167
> > > (libselinux.so.1+0x12291)
> > >     #4 selabel_lookup_raw ./libselinux/src/label.c:256 (libselinux.so.1+0x126ca)
> > >     #5 restorecon_sb ./libselinux/src/selinux_restorecon.c:638
> > > (libselinux.so.1+0x20c76)
> > >     #6 selinux_restorecon_thread
> > > ./libselinux/src/selinux_restorecon.c:947 (libselinux.so.1+0x21e99)
> > >
> > >   Previous write of size 4 at 0x7f8790d636f4 by thread T1:
> > >     #0 lookup_all ./libselinux/src/label_file.c:954 (libselinux.so.1+0x14d29)
> > >     #1 lookup_common ./libselinux/src/label_file.c:997 (libselinux.so.1+0x14f62)
> > >     #2 lookup ./libselinux/src/label_file.c:1095 (libselinux.so.1+0x14fff)
> > >     #3 selabel_lookup_common ./libselinux/src/label.c:167
> > > (libselinux.so.1+0x12291)
> > >     #4 selabel_lookup_raw ./libselinux/src/label.c:256 (libselinux.so.1+0x126ca)
> > >     #5 restorecon_sb ./libselinux/src/selinux_restorecon.c:638
> > > (libselinux.so.1+0x20c76)
> > >     #6 selinux_restorecon_thread
> > > ./libselinux/src/selinux_restorecon.c:947 (libselinux.so.1+0x21e99)
> > >
> > >   Location is heap block of size 267120 at 0x7f8790d45000 allocated by
> > > main thread:
> > >     #0 malloc ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:655
> > > (libtsan.so.0+0x31799)
> > >     #1 sort_specs ./libselinux/src/label_file.h:207 (libselinux.so.1+0x17bd9)
> > >     #2 init ./libselinux/src/label_file.c:795 (libselinux.so.1+0x17bd9)
> > >     #3 selabel_file_init ./libselinux/src/label_file.c:1293
> > > (libselinux.so.1+0x1835b)
> > >     #4 selabel_open ./libselinux/src/label.c:228 (libselinux.so.1+0x125d8)
> > >     #5 restore_init ./policycoreutils/setfiles/restore.c:30 (setfiles+0x3886)
> > >     #6 main ./policycoreutils/setfiles/setfiles.c:434 (setfiles+0x344e)
> > >
> > >   Thread T2 (tid=16940, running) created by main thread at:
> > >     #0 pthread_create
> > > ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969
> > > (libtsan.so.0+0x5ad75)
> > >     #1 selinux_restorecon_common
> > > ./libselinux/src/selinux_restorecon.c:1197 (libselinux.so.1+0x2341c)
> > >     #2 selinux_restorecon_parallel
> > > ./libselinux/src/selinux_restorecon.c:1306 (libselinux.so.1+0x23985)
> > >     #3 process_glob ./policycoreutils/setfiles/restore.c:94 (setfiles+0x3ba4)
> > >     #4 main ./policycoreutils/setfiles/setfiles.c:463 (setfiles+0x362a)
> > >
> > >   Thread T1 (tid=16939, running) created by main thread at:
> > >     #0 pthread_create
> > > ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969
> > > (libtsan.so.0+0x5ad75)
> > >     #1 selinux_restorecon_common
> > > ./libselinux/src/selinux_restorecon.c:1197 (libselinux.so.1+0x2341c)
> > >     #2 selinux_restorecon_parallel
> > > ./libselinux/src/selinux_restorecon.c:1306 (libselinux.so.1+0x23985)
> > >     #3 process_glob ./policycoreutils/setfiles/restore.c:94 (setfiles+0x3ba4)
> > >     #4 main ./policycoreutils/setfiles/setfiles.c:463 (setfiles+0x362a)
> > >
> > > SUMMARY: ThreadSanitizer: data race ./libselinux/src/label_file.c:954
> > > in lookup_all
> > > ==================
> >
> > Good catch, although this one seems to be pre-existing w.r.t. thread
> > safety of selinux_restorecon(3) (which seems to be implied by the
> > existence of struct spec::regex_lock). I spotted some existing usage
> > of GCC atomic builtins, so I'll try to fix it using those.
> >
> > > Also some thread joins seems to be missing:
> > >
> > > ==================
> > > WARNING: ThreadSanitizer: thread leak (pid=16933)
> > >   Thread T1 (tid=16939, finished) created by main thread at:
> > >     #0 pthread_create
> > > ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969
> > > (libtsan.so.0+0x5ad75)
> > >     #1 selinux_restorecon_common
> > > ./libselinux/src/selinux_restorecon.c:1197 (libselinux.so.1+0x2341c)
> > >     #2 selinux_restorecon_parallel
> > > ./libselinux/src/selinux_restorecon.c:1306 (libselinux.so.1+0x23985)
> > >     #3 process_glob ./policycoreutils/setfiles/restore.c:94 (setfiles+0x3ba4)
> > >     #4 main ./policycoreutils/setfiles/setfiles.c:463 (setfiles+0x362a)
> > >
> > >   And 2 more similar thread leaks.
> > >
> > > SUMMARY: ThreadSanitizer: thread leak
> > > ./libselinux/src/selinux_restorecon.c:1197 in
> > > selinux_restorecon_common
> > > ==================
> >
> > Hm... My intention was to avoid the need for joins by synchronizing
> > via other means and just letting the threads exit on their own, but I
> > guess that doesn't fly with the sanitizer. Guess I'll have to allocate
> > an array for the handles and join the threads at the end after all...
>
> So I was able to get ThreadSanitizer to detect the race (by using only
> two threads and a very small number of files), but then the program
> just runs forever and I never get to see the thread leaks... Any hints
> on how you ran/compiled it to see the thread leaks? Or how long you
> had to wait for the program to finish? BTW, I only managed to get
> thread sanitizer to work with GCC. With CLang I always got some linker
> error...

Seems it was getting stuck because of the lack of joins. Once I
rewrote selinux_restorecon_common() to wait for the threads via
pthread_join(), setfiles built with -fsanitize=thread exited quickly
and without warnings.

-- 
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.


      reply	other threads:[~2021-10-19 12:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-14 14:53 [PATCH userspace v2 0/6] Parallel setfiles/restorecon Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 1/6] selinux_restorecon: simplify fl_head allocation by using calloc() Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 2/6] selinux_restorecon: protect file_spec list with a mutex Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 3/6] libselinux: make selinux_log() thread-safe Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 4/6] selinux_restorecon: add a global mutex to synchronize progress output Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 5/6] selinux_restorecon: introduce selinux_restorecon_parallel(3) Ondrej Mosnacek
2021-10-14 14:53 ` [PATCH userspace v2 6/6] setfiles/restorecon: support parallel relabeling Ondrej Mosnacek
2021-10-15 12:37 ` [PATCH userspace v2 0/6] Parallel setfiles/restorecon Christian Göttsche
2021-10-15 13:25   ` Ondrej Mosnacek
2021-10-18  8:56     ` Ondrej Mosnacek
2021-10-19 12:29       ` Ondrej Mosnacek [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAFqZXNt2V21x7bAYGVQ_U818ZfShAYiyzzdU8D2L9uBZrsea1g@mail.gmail.com \
    --to=omosnace@redhat.com \
    --cc=cgzones@googlemail.com \
    --cc=selinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.