0

I have a strange behavior at my raspberry pi.

I wrote a small C-Program to update the RPi. It just calls via system() "apt-get update && apt-get dist-upgrade && apt-get upgrade && rpi-update && reboot"

With the setuid-bit the program will be running as root.

Why a c program ? Because the setuid-bit don't works with bash scripts.

As a super user there is no problem.

If I run the program as an normal user I got this error after "apt-get update" (sorry for the german version):

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

The setuid-bit is set and the owner of the executable is root. So why I have another behavior ?

Here is the code:

main.c:

#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}
Peter C. Glade
  • 543
  • 2
  • 8
  • 16
  • Maybe you should fist check if your package manager not already running. Your user has privileges ? Any way you should use sudo there. – Michi Oct 29 '15 at 18:35
  • But why i have to use sudo if the program runs with root privileges (from the setuid-bit) ? I thought it's the same as if running as root itself ? – Peter C. Glade Oct 29 '15 at 18:41
  • 1
    Never use root, use sudo instead for security reasons. – Michi Oct 29 '15 at 18:42
  • So there is a difference running something as root or with sudo ? – Peter C. Glade Oct 29 '15 at 18:44
  • @PeterC.Glade There's a huge difference. The code you posted can be leveraged to allow any user who calls it to obtain full root access. See https://en.wikipedia.org/wiki/Setuid#Security for a start. – Andrew Henle Oct 29 '15 at 18:46
  • @PeterC.Glade when you get yourself in trouble because of that, well you will remember me. Any way system() is also one thing which i never use it :). If you really need system() you should be 100% sure that you don't need bash instead of C for such things. Hope you understand my point. – Michi Oct 29 '15 at 18:52
  • 3
    How to get a root shell using this example: `ln -s /bin/bash ~/bin/rpi-update; PATH=~/bin:$PATH; update-system` As @Michi posted, this is what `sudo` is for. – Andrew Henle Oct 29 '15 at 18:58
  • I thought of the useage from passwd. There is a setuid-bit too. So what makes passwd secure ? – Peter C. Glade Oct 29 '15 at 19:07
  • `passwd` has very specific usage and does not execute any external program. – dbush Oct 29 '15 at 19:11
  • Ok, i think i have to get more informations about root access and sudo ;) thanks a lot for your help ;) – Peter C. Glade Oct 29 '15 at 19:12

2 Answers2

2

When your program runs, the effective user ID is root, but the real user ID is yourself. Then when you call system, the real and effective user IDs get inherited by apt-get.

It seems that apt-get looks at the real user ID when checking permissions. So you need to set the real user ID to root at the beginning of main:

setuid(0);

That being said, using sudo is more secure that running a setuid-root program, since you can control who has the privileges to do so.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

You need sudo:

#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;
}

Just make sure that your user has root privileges.

Michi
  • 5,175
  • 7
  • 33
  • 58
  • The setuid bit sets the euid of the process. The process just needs to call `setuid()`. `sudo` is unecessary. See @dbush's answer. – Andrew Henle Oct 29 '15 at 18:44
  • Yes that's true, but i never recommend tu use root user for any reason, at least if you know that are you doing. – Michi Oct 29 '15 at 18:46
  • 1
    Agreed. My comment was meant only in the context of obtaining full root access from a setuid-binary, not how insecure the manner used to get that access would be. Because the example provides multiple opportunities for mischief. – Andrew Henle Oct 29 '15 at 18:51