Re: [PATCH v6] libselinux: use kernel status page by default

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Di., 11. Aug. 2020 um 14:14 Uhr schrieb Stephen Smalley
<stephen.smalley.work@xxxxxxxxx>:
>
> On Thu, Aug 6, 2020 at 8:05 AM Stephen Smalley
> <stephen.smalley.work@xxxxxxxxx> wrote:
> >
> > On 8/5/20 3:43 PM, Mike Palmiotto wrote:
> >
> > > Commit bc2a8f418e3b ("libselinux: add selinux_status_* interfaces for
> > > /selinux/status") introduced the sestatus mechanism, which allows for
> > > mmap()'ing of the kernel status page as a replacement for avc_netlink.
> > >
> > > The mechanism was initially intended for userspace object managers that
> > > were calculating access decisions within their application and did not
> > > rely on the libselinux AVC implementation. In order to properly make use
> > > of sestatus within avc_has_perm(), the status mechanism needs to
> > > properly set avc internals during status events; else, avc_enforcing is
> > > never updated upon sestatus changes.
> > >
> > > This commit gets rid of the default avc_netlink_open() in
> > > avc_init_internal(), replacing it with selinux_status_open(). In the
> > > event that the kernel status page cannot be mapped, the netlink fallback
> > > will be used. By default, avc_has_perm_noaudit() and
> > > selinux_check_access() will now attempt to read the kernel status page,
> > > which removes a system call from two critical code paths.
> > >
> > > Since the AVC thread create/stop callbacks were intended to avoid a
> > > system call in the critical code path, they no longer need to be created
> > > by default. In the event that the kernel status page is successfully
> > > mapped, threads will not be created. Threads will still be
> > > created/stopped for the sestatus fallback codepaths.
> > >
> > > Userspace object managers that still need a netlink socket can call
> > > avc_netlink_acquire_fd() to open and/or obtain one.
> > >
> > > Update the manpage to reflect the new avc_netlink_acquire_fd()
> > > functionality.
> > >
> > > Signed-off-by: Mike Palmiotto <mike.palmiotto@xxxxxxxxxxxxxxx>
> >
> > Acked-by: Stephen Smalley <stephen.smalley.work@xxxxxxxxx>
>
> Applied.

I think in `libselinux/src/sestatus.c` the static variable
`last_policyload` does not get updated during `selinux_status_open()`.

This leads to policyload-callbacks getting called if the first change
to the status page is an enforcing change.

Reproducible with trailed test binary:
Running the binary and during its runtime changing the enforcing
status via setenforce 0/1 triggers the policyload callback:

> ./test_selinux_status &
[1] 4091
selinux_status_updated returned 0
selinux_status_updated returned 0
> setenforce 0
selinux_status_updated returned 0
uavc:  received setenforce notice (enforcing=0)
setenforce_cb(0)
uavc:  received policyload notice (seqno=4)
policyload_cb(4)
selinux_status_updated returned 1
selinux_status_updated returned 0
> setenforce 1
selinux_status_updated returned 0
uavc:  received setenforce notice (enforcing=1)
setenforce_cb(1)
selinux_status_updated returned 1
selinux_status_updated returned 0
selinux_status_updated returned 0
selinux_status_updated returned 0
[1]+  Done                    ./test_selinux_status


<<<< test binary >>>>
#include <stdio.h>
#include <unistd.h>

#include <selinux/avc.h>

int policyload_cb(int seqno) {
        printf("policyload_cb(%d)\n", seqno);

        return 0;
}

int setenforce_cb(int enforcing) {
        printf("setenforce_cb(%d)\n", enforcing);

        return 0;
}

int main(void) {
        int r;

        r = selinux_status_open(0);
        if (r < 0) {
                fprintf(stderr, "Failed to open SELinux status page: %m\n");
                return EXIT_FAILURE;
        }

        selinux_set_callback(SELINUX_CB_POLICYLOAD, (union
selinux_callback) policyload_cb);
        selinux_set_callback(SELINUX_CB_SETENFORCE, (union
selinux_callback) setenforce_cb);

        for (int i = 0; i < 10; ++i) {
                sleep(1);

                r = selinux_status_updated();
                printf("selinux_status_updated returned %d\n", r);
        }

        selinux_status_close();

        return EXIT_SUCCESS;
}



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux