2016-02-01 12 views
5

Hier ist eine vollständige Quelle für ein Programm, das mein Problem demonstriert (das Betriebssystem Ubuntu 14.04 32-Bit, wenn es darauf ankommt):merkwürdiges Ergebnis, wenn ein Programm als root läuft

#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(int argc, const char *argv[]) 
{ 
    int status, fd; 

    printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); 

    fd = open("/dev/ttyS0", O_WRONLY); 
    if(fd < 0) 
    { 
     printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); 
     return 1; 
    } 
    printf("Successfully opened /dev/ttyS0\n"); 
    close(fd); 

    /* DROP PRIVILEGES */ 

    setgid(1000); 
    setuid(1000); 

    printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); 

    fd = open("/dev/ttyS0", O_WRONLY); 
    if(fd < 0) 
    { 
     printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); 
     return 1; 
    } 
    printf("Successfully opened /dev/ttyS0\n"); 
    return 0; 
} 

Es gibt zwei Benutzer in das System: root und ein normaler Benutzer ohne Rootberechtigung (nennen wir ihn "ubuntu") mit id = 1000. Das obige Programm versucht, einen seriellen Port (/ dev/ttyS0) zweimal zu öffnen: zuerst als root oder ubuntu (abhängig davon, wie es aufgerufen wird) und das zweite Mal immer als ubuntu. Der erste erfolglose Versuch führt zum Abbruch des Programms. Benutzer ubuntu ist ein Mitglied der Dialout-Gruppe, also hat er theoretisch die notwendigen Berechtigungen, um/dev/ttyS0 zu öffnen. Ich rufe das Programm auf vier verschiedene Arten:

1) läuft direkt als ubuntu

Aufruf:

< Weg zu meinem Programm >

2) als ubuntu laufen, aber unter Verwendung von sudo

Aufruf:

sudo -u ubuntu < Pfad zu meinem Programm >

3) als Root ausgeführt, aber mit Privilegien fallen gelassen derer ubuntu (so effektiv, wie ubuntu ausgeführt werden):

Aufruf:

Sudo su
Sudo -u ubuntu < Pfad zu meinem Programm >

In allen drei Fällen uns das folgende erwartete Ergebnis:

CURRENT UID: 1000, CURRENT GID: 1000 
Successfully opened /dev/ttyS0 

CURRENT UID: 1000, CURRENT GID: 1000 
Successfully opened /dev/ttyS0 

Im letzten Fall jedoch geschieht etwas Seltsames:

sudo su
< Weg zu meinem Programm >

Ergebnis:

4)

Aufruf direkt als root ausführen:

CURRENT UID: 0, CURRENT GID: 0 
Successfully opened /dev/ttyS0 

CURRENT UID: 1000, CURRENT GID: 1000 
Error opening /dev/ttyS0: Permission denied 

Natürlich sind es die letzten zwei Zeilen der Ausgabe, die ich nicht verstehe: Dieses Mal, wenn root seine Privilegien fallen lässt, stellt sich heraus, dass Ubuntu nicht genügend Rechte hat, um/dev/ttyS0 zu öffnen, aber warum? Wie unterscheidet sich dieser Fall von den Fällen 1-3?

Eine letzte Sache erwähnenswert:

setgid(1000); 

dazu: auch

setgid(20); /* 20 is the id of dialout group */ 

dann der letzte Versuch zu öffnen/dev/ttyS0 ist erfolgreich, wenn ich diese Zeile von meinem Code ändern .

Bedeutet das, dass die Informationen über Ubuntu, das Mitglied einer Dialout-Gruppe ist, aus irgendeinem Grund verloren gehen, wenn ich das Programm als root benutze und dann die Berechtigungen auf die von Ubuntu delete, indem ich uid und gid auf 1000 ändere? Kannst du mir bitte eine detaillierte Erklärung geben, was im Fall 4 meines Beispiels passiert und warum das Ergebnis anders ist, als ich erwartet habe?

+0

Google "echte und effektive Benutzer-ID". Oder [siehe dies] (http://stackoverflow.com/questions/32455684/difference-between-real-user-id-effective-user-id-and-saved-user-id). –

+0

Siehst du die gleichen Ergebnisse mit 'Seteuid' und' Setegid'? – tkausl

+0

Wenn ich alle Vorkommen von UID, GID, getuid(), getgid(), setuid (1000) und setgid (1000) mit EUID, EGID, geteuid(), getegid(), seteuid (1000) und setegid (1000) bzw. das Ergebnis bleibt in allen vier Fällen genau gleich. – Peter

Antwort

2

Einstellen der userid und groupid tut nicht Satz alle zusätzlichen Gruppen (d.h. alle Gruppen, die nicht die Hauptgruppe des Benutzers sind, aber in /etc/groups ihm zugewiesenen) automagically. Versuchen

initgroups("ubuntu", 1000); 

vor dem setgid() -Aufruf zu verwenden. Dann sollte der Prozess die Berechtigungen der DialOut -Gruppe haben.

+0

Danke, das muss der genaue Grund sein, warum mein Ansatz fehlgeschlagen ist. Anscheinend waren die Vorschläge von David Schwartz und Tkausi, die etwas mit euid/egid zu tun hatten, falsch. – Peter

Verwandte Themen