reproducible hard lock with lxrt + sys_setresuid -- does it happen in current RTAI?

Jeff Epler <[email protected]> Wed, 19 Apr 2017 20:51:13 -0500
Newsgroups gmane.linux.real-time.rtai
Message-ID <[email protected]>
In at least some older versions of rtai lxrt, calling seteuid() while a RT
task exists in the same process causes a hard lock.  This is reproducible on
a kernel and rtai version shipped by linuxcnc.org, but I don't know about
current ones.

Can someone tell me if this is still reproducing with current RTAI
and kernel trees so I know whether to continue barking up this tree,
or whether it's specific to versions so old that only linuxcnc uses
them anymore?

Compile the below code with e.g.,
    $ g++ -std=c++14 threadtest.cc -I /usr/include/rtai -pthread -llxrt
If you don't want to hard-lock your system, you will need to
-DNO_KABOOM, which just skips the calls to seteuid().

Remember to manually insert (insmod / modprobe / whatever) the
necessary modules, such as rtai_hal and rtai_sched, dependent on
your setup.

Then, run with
    $ sudo ./a.out
The program calls sync() first thing so hopefully you won't lose much data
if it succeeds in hard locking you.

If it hard locks your computer, yay, you've reproduced my bug report.

If the 'final value' is 0 then the RT code never ran at all (non
root, or modules not loaded?).

If it's large (say, a few million) then probably the task ran but
didn't enter real-time periodic mode (not root, or modules not
loaded?)

If it's around 10,000 then congratulations: you may not have the bug!

tested (and fails consistently) on
3.18.0-1-rtai-amd64 #1 SMP PREEMPT Debian 3.18.20-1linuxcnc (2016-06-22) x86_64 GNU/Linux
with rtai 5.0~test2.2016.05.12.37.g1d358aa from seb's git except we
rebased it or something so that ref doesn't seem to exist anymore :(
It's probably similar to our ref a844a0751b11f.

Kconfig file at
https://emergent.unpythonic.net/files/sandbox/config-3.18.0-1-rtai-amd64

rtai tree including build system in debian/ at
https://github.com/SebKuzminsky/rtai (see branch vulcano-debs;
debian/rules.in shows configure flags)

My unsubstantiated theory is that sys_setresuid (which is what glibc
seteuid calls) probably has to do something for each task in the
process to make it take the new credentials, but this can deadlock
when the other task is hard realtime.

Jeff

//- cut here for the reproducer program "threadtest.cc" ----------------
#include <atomic>
#include <iterator>
#include <pthread.h>
#include <stdio.h>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
#pragma GCC diagnostic ignored "-Wvla"
#include <rtai_lxrt.h>
#pragma GCC diagnostic pop

namespace
{

constexpr long period = 100'000; // 100us
constexpr int policy = SCHED_FIFO;
int prio = sched_get_priority_max(policy);
std::atomic<bool> stop;
std::atomic<int> count;
pthread_t thr;

void *wrapper(__attribute__((unused)) void *arg) {
    int nprocs = sysconf( _SC_NPROCESSORS_ONLN );
    auto rt_task = rt_task_init_schmod(1, 0, 0, 0, SCHED_FIFO,
        1u << (nprocs - 1));
    rt_set_periodic_mode();

    rt_make_hard_real_time();
    rt_task_make_periodic_relative_ns(rt_task, period, period);

    while(!stop) { count++; rt_task_wait_period(); }

    return nullptr;
}
}

int main() {
    sync();
    printf("initial value: %d\n", count.load());
    if(pthread_create(&thr, nullptr, &wrapper, nullptr) < 0) {
        perror("pthred_create");
        abort();
    }

    for(int i=0; i<1000; i++) {
        usleep(1000);
#ifndef NO_KABOOM
        seteuid(1000);
        seteuid(0);
#endif
    }

    stop = true;

    pthread_join(thr, nullptr);

    printf("final value: %d\n", count.load());
}

_______________________________________________
Rtai mailing list
[email protected]
https://mail.rtai.org/cgi-bin/mailman/listinfo/rtai