Setuid-bit и apt-get странное поведение

У меня странное поведение на моем raspberry pi.

Я написал небольшую C-программу для обновления RPi. Он просто вызывает через system() «apt-get update && apt-get dist-upgrade && apt-get upgrade && rpi-update && reboot»

С битом setuid программа будет работать как root.

Почему программа на Си? Потому что бит setuid не работает со сценариями bash.

Для суперпользователя проблем нет.

Если я запускаю программу как обычный пользователь, я получаю эту ошибку после "apt-get update" (извините за немецкую версию):

 E: Unable to write to /var/cache/apt/               
E: The package lists or status file could not be parsed or opened.

Бит setuid установлен, и владельцем исполняемого файла является root. Так почему у меня другое поведение?

Вот код:

основной.с:

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

int main () {
        int status = 0;

        if (status == 0) {
                status = system("apt-get -y update");        }

        if (status == 0) {
                status = system("apt-get -y dist-upgrade");
}
        if (status == 0) {
                status = system("apt-get -y upgrade");
        }

        if (status == 0) {
                status = system("rpi-update");
        }

        if (status == 0) {
                status = system("reboot");
        }
        return status;
}

Makefile:

CC=gcc
TARGET=update-system
PREFIX=/usr/bin

all: main.o
        ${CC} -o ${TARGET} main.c
        make clean

main.o: main.c
        ${CC} -c main.c

.PHONY: clean
clean:
        rm ./*.o 
install:
        chown root ${TARGET} 
        chgrp root ${TARGET} 
        chmod +s ${TARGET}
        mv ${TARGET} ${PREFIX}

person Peter C. Glade    schedule 29.10.2015    source источник
comment
Возможно, вам следует сначала проверить, не запущен ли ваш менеджер пакетов. У вашего пользователя есть привилегии? В любом случае вы должны использовать sudo там.   -  person Michi    schedule 29.10.2015
comment
Но почему я должен использовать sudo, если программа работает с привилегиями root (из бита setuid)? Я думал, что это то же самое, как если бы вы работали как root?   -  person Peter C. Glade    schedule 29.10.2015
comment
Никогда не используйте root, вместо этого используйте sudo из соображений безопасности.   -  person Michi    schedule 29.10.2015
comment
Так есть ли разница запускать что-то как root или с помощью sudo?   -  person Peter C. Glade    schedule 29.10.2015
comment
@PeterC.Glade Есть огромная разница. Размещенный вами код можно использовать, чтобы позволить любому пользователю, вызвавшему его, получить полный root-доступ. Для начала см. en.wikipedia.org/wiki/Setuid#Security.   -  person Andrew Henle    schedule 29.10.2015
comment
@PeterC.Glade, когда у тебя будут проблемы из-за этого, ты вспомнишь меня. В любом случае system() - это еще одна вещь, которую я никогда не использую :). Если вам действительно нужна система(), вы должны быть на 100% уверены, что вам не нужен bash вместо C для таких вещей. Надеюсь, вы понимаете мою точку зрения.   -  person Michi    schedule 29.10.2015
comment
Как получить корневую оболочку, используя этот пример: ln -s /bin/bash ~/bin/rpi-update; PATH=~/bin:$PATH; update-system Как сообщил @Michi, для этого предназначен sudo.   -  person Andrew Henle    schedule 29.10.2015
comment
Я думал об использовании от passwd. Также есть бит setuid. Так что же делает passwd безопасным?   -  person Peter C. Glade    schedule 29.10.2015
comment
passwd имеет очень специфическое использование и не выполняет никаких внешних программ.   -  person dbush    schedule 29.10.2015
comment
Хорошо, я думаю, мне нужно получить больше информации о корневом доступе и sudo;) большое спасибо за вашу помощь;)   -  person Peter C. Glade    schedule 29.10.2015


Ответы (2)


Когда ваша программа запускается, эффективный идентификатор пользователя — root, но реальный идентификатор пользователя — это вы сами. Затем, когда вы вызываете system, настоящие и эффективные идентификаторы пользователей наследуются apt-get.

Кажется, что apt-get смотрит на реальный идентификатор пользователя при проверке разрешений. Поэтому вам нужно установить реальный идентификатор пользователя root в начале main:

setuid(0);

При этом использование sudo более безопасно, чем запуск программы с setuid-root, поскольку вы можете контролировать, кто имеет на это привилегии.

person dbush    schedule 29.10.2015
comment
Нет причин вызывать root для этого. По многим причинам безопасности. - person Michi; 29.10.2015
comment
При этом использование sudo более безопасно +1 за это :) - person Michi; 29.10.2015

Вам нужно судо:

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

int main (void) {
    int status = 0;

    if (status == 0) {
        status = system("sudo apt-get -y update");        }

    if (status == 0) {
        status = system("sudo apt-get -y dist-upgrade");
    }

    if (status == 0) {
        status = system("sudo apt-get -y upgrade");
    }

    if (status == 0) {
        status = system("sudo rpi-update");
    }

    if (status == 0) {
        status = system("sudo reboot");
    }
    return status;
}

Просто убедитесь, что у вашего пользователя есть привилегии root.

person Michi    schedule 29.10.2015
comment
Бит setuid устанавливает euid процесса. Процессу достаточно вызвать setuid(). sudo не требуется. См. ответ @dbush. - person Andrew Henle; 29.10.2015
comment
Да, это правда, но я никогда не рекомендую использовать пользователя root по какой-либо причине, по крайней мере, если вы знаете, что делаете. - person Michi; 29.10.2015
comment
Согласованный. Мой комментарий имел в виду только в контексте получения полного root-доступа из двоичного файла setuid, а не в отношении того, насколько небезопасным будет способ, используемый для получения этого доступа. Потому что пример предоставляет множество возможностей для шалостей. - person Andrew Henle; 29.10.2015