从setuid根程序运行“ systemctl restart ___”,而无需输入root密码?

时间:2019-12-05 18:14:36

标签: systemctl suid

我正在为运行Linux(CentOS 8)的网络设备开发,并为在VGA控制台上进行一些非常基本的配置,我们设置了一个锁定的用户帐户。我们提供了几个suid根程序,这些程序可以进行诸如设置IP地址和配置NTP之类的操作。 (所有其他设置都是通过Apache和某些网页完成的。)

我们需要从这些程序中执行的一些操作是重新启动NetworkManager.service,重新启动chronyd.service,关闭电源并重新启动。关机和重新启动都可以很好地工作,但是重新启动服务却不能。相反,我们得到以下信息:

Restarting ntp service
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to restart 'chronyd.service'.
Authenticating as: root
Password: 

我猜想systemctl试图对身份验证保持精明,并且能够检测从其运行的用户不是root用户,即使它具有root特权。有什么方法可以更改用户ID,以便systemctl调用它的是根用户?

作为参考,我将完整的源代码附加到下面的suid根程序之一。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void print_usage()
{
    printf("Usage: safeguard <option>\n");
    printf("Options:\n");
    printf("  poweroff\n");
    printf("  reboot\n");
    printf("  ntp       [restarts NTP service]\n");
    printf("  net       [restarts NetworkManager service]\n");
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        print_usage();
        return 0;
    }

    if (0==strcmp(argv[1], "poweroff")) {
        printf("Executing poweroff\n");
        system("poweroff");
        return 0;
    } else if (0==strcmp(argv[1], "reboot")) {
        printf("Executing reboot\n");
        system("reboot");
        return 0;
    } else if (0==strcmp(argv[1], "ntp")) {
        printf("Restarting ntp service\n");
        system("systemctl restart chronyd.service");
        return 0;
    } else if (0==strcmp(argv[1], "net")) {
        printf("Restarting NetworkManager service\n");
        system("systemctl restart NetworkManager.service");
        return 0;
    }

    print_usage();
    return 0;
}

1 个答案:

答案 0 :(得分:0)

我知道了。我必须添加以下代码,才能将“真实用户ID”更改为与“有效用户ID”相同。

uid_t uid, euid, suid;
getresuid(&uid, &euid, &suid);
setresuid(euid, euid, suid);