2016-11-28 1 views
0

Я хотел бы запустить программу под Linux SCHED_FIFO в режиме реального времени. Я предпочел бы сохранить жесткий лимит пользователя для RTPRIO, установленный в 0, и программно поднять жесткий предел только для одного процесса. В целом заявлено, что если я предоставил процесс CAP_SYS_RESOURCE, чтобы он мог поднять жесткий предел, например. , man setrlimit 2:Как повысить фиксированный лимит ulimit для приоритета в реальном времени программным способом с помощью setuid или возможности CAP_SYS_RESOURCE?

Мягкий предел - это значение, которое ядро ​​обеспечивает для соответствующего ресурса. Жесткий предел действует как потолок для мягкого предела: непривилегированный процесс может устанавливать только его мягкий предел до значения в диапазоне от 0 до жесткого предела и (необратимо) понижать его жесткий предел. Привилегированный процесс (в Linux: один с возможностью CAP_SYS_RESOURCE) может произвольно изменять либо предельное значение.

Однако, похоже, я не могу заставить это работать для меня. Вот тестовый код:

#include <stdio.h> 
#include <sched.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/resource.h> 

#define PRIORITY (50) 

int main(int argc, char **argv) { 
    struct sched_param param; 
    struct rlimit rl; 
    int e, min_fifo, max_fifo; 

    min_fifo = sched_get_priority_min(SCHED_FIFO); 
    max_fifo = sched_get_priority_max(SCHED_FIFO); 
    printf("For policy SCHED_FIFO min priority is %d, max is %d.\n", 
     min_fifo, max_fifo); 
    if ((min_fifo>PRIORITY)||(max_fifo<PRIORITY)) { 
    printf("Desired priority of %d is out of range.\n", PRIORITY); 
    return 1; 
    } 

    if (getrlimit(RLIMIT_RTPRIO, &rl) != 0) { 
    e = errno; 
    printf("Failed to getrlimit(): %s.\n", strerror(e)); 
    return 1; 
    } 
    printf("RTPRIO soft limit is %d, hard is %d.\n", 
     (int) rl.rlim_cur, (int) rl.rlim_max); 

    // Adjust hard limit if necessary 

    if (rl.rlim_max < PRIORITY) { 
    rl.rlim_max = PRIORITY; 
    if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) { 
     e = errno; 
     printf("Failed to raise hard limit for RTPRIO to %d: %s.\n", 
      (int) rl.rlim_max, strerror(e)); 
     return 1; 
    } 
    printf("Raised hard limit for RTPRIO to %d.\n", (int) rl.rlim_max); 
    } 

    // Adjust soft limit if necessary 

    if (rl.rlim_cur < PRIORITY) { 
    rl.rlim_cur = PRIORITY; 
    if (setrlimit(RLIMIT_RTPRIO, &rl) != 0) { 
     e = errno; 
     printf("Failed to raise soft limit for RTPRIO to %d: %s.\n", 
      (int) rl.rlim_cur, strerror(e)); 
     return 1; 
    } 
    printf("Raised soft limit for RTPRIO to %d.\n", (int) rl.rlim_cur); 
    } 

    // Set desired priority with class SCHED_FIFO 

    param.sched_priority = PRIORITY; 
    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) { 
    e = errno; 
    printf("Setting policy failed: %s.\n", strerror(e)); 
    return 1; 
    } else { 
    printf("Set policy SCHED_FIFO, priority %d.\n", param.sched_priority); 
    } 

    return 0; 
} 

Это работает, как ожидалось, без особых привилегий с жестким лимитом 99:

$ ./rtprio 
For policy SCHED_FIFO min priority is 1, max is 99. 
RTPRIO soft limit is 0, hard is 99. 
Raised soft limit for RTPRIO to 50. 
Set policy SCHED_FIFO, priority 50. 
$ 

Он работает, как ожидается, с жестким пределом 0, используя Sudo:

$ sudo ./rtprio 
For policy SCHED_FIFO min priority is 1, max is 99. 
RTPRIO soft limit is 0, hard is 0. 
Raised hard limit for RTPRIO to 50. 
Raised soft limit for RTPRIO to 50. 
Set policy SCHED_FIFO, priority 50. 
$ 

Однако он не работает должным образом, когда корень setuid:

$ sudo chown root ./rtprio 
$ sudo chgrp root ./rtprio 
$ sudo chmod ug+s ./rtprio 
$ ls -l ./rtprio 
-rwsrwsr-x 1 root root 8948 11月 28 12:04 ./rtprio 
$ ./rtprio 
For policy SCHED_FIFO min priority is 1, max is 99. 
RTPRIO soft limit is 0, hard is 0. 
Failed to raise hard limit for RTPRIO to 50: Operation not permitted. 

Он также неожиданно терпит неудачу с возможностью CAP_SYS_RESOURCE, а также с всех возможностей:

$ sudo setcap cap_sys_resource=eip ./rtprio 
$ getcap ./rtprio 
./rtprio = cap_sys_resource+eip 
$ ./rtprio 
For policy SCHED_FIFO min priority is 1, max is 99. 
RTPRIO soft limit is 0, hard is 0. 
Failed to raise hard limit for RTPRIO to 50: Operation not permitted. 

$ sudo setcap all=eip ./rtprio 
$ getcap ./rtprio 
./rtprio =eip 
$ ./rtprio 
For policy SCHED_FIFO min priority is 1, max is 99. 
RTPRIO soft limit is 0, hard is 0. 
Failed to raise hard limit for RTPRIO to 50: Operation not permitted. 

Что я здесь отсутствует?

$ uname -srv 
Linux 3.13.0-100-generiC#147-Ubuntu SMP Tue Oct 18 16:48:51 UTC 2016 
$ lsb_release -a 
No LSB modules are available. 
Distributor ID: Ubuntu 
Description: Ubuntu 14.04.5 LTS 
Release: 14.04 
Codename: trusty 
$ bash --version | head -1 
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu) 

ответ

0

Тот факт, что setuid root не работает это ключ.

Оказалось, что тестовая программа выше была в перегородке, установленной с nosuid, и, следовательно, биты setuid не влияют. Если вы не доверяете битам setuid в разделе, то вам, вероятно, также не следует доверять возможностям файла. И, действительно, оказывается, что при установке с nosuid возможности файла также игнорируются.

Кажется, что зашифрованные домашние каталоги luks имеют тенденцию к установке nosuid.

Я оставляю этот вопрос, потому что существует множество поисковых запросов для «возможностей linux nosuid», указывающих на то, что много времени было потрачено впустую на эту проблему (но, конечно, вы не знаете, это пока вы не выяснили).

Смежные вопросы