Geänderte Berechtigungen mit setuid/setgid gehen nicht richtig
-
Ich möchte ein Programm auf eine serielle Schnittstelle zugreifen lassen. Das Programm wird als root gestartet (daemon) und ändert anfangs seine Rechte (User/Group):
void changeRights() { char* grp = "meinegrp"; char* usr = "meinusr"; struct group *my_group; if ( (my_group = getgrnam( grp )) == NULL ) printf("error getgrnam"); if ( setegid( my_group->gr_gid ) < 0 ) printf("error setgid"); struct passwd *my_user; if ( (my_user = getpwnam( usr )) == NULL ) printf("error getpwnam"); if ( seteuid( my_user->pw_uid ) < 0 ) printf("error setuid"); }
Der user "meinusr" ist auch in der Gruppe "uucp", so dass er eigentlich Zugriff auf die seriellen Schnittstellen hat. Bin ich unter dem Benutzernamen angemeldet, geht auch ein
$ echo "test" > /dev/ttyS0
Wenn ich das Programm als root starte und die Änderung der User/Gruppe weglasse, geht es.
Wenn ich das Programm - mit oder ohne Änderung von User/Gruppe - als user "meinusr" starte, geht es auch.
Aber starte ich das Programm als "root", kommt beim Öffnen der seriellen Schnittstelle die Fehlermeldung "Permission denied"!
Wo liegt da mein Fehler?
*Ergänzung:
Ich habe verschiedenes getestet, und das Programm scheint mit den Berechtigungen für meinegrp/meinusr zu arbeiten (bspw. beim Erstellen von Dateien). Der Zugriff aufs serielle Device geht allerdings nur, wenn ich anstatt meinegrp die Gruppe uucp angebe. Nur muss es da doch eine andere Lösung geben...*
-
Ich habe jetzt eine Lösung gefunden:
Die Rechte der Nebengruppen (supplementary groups) werden mit setuid()/setgid() nicht gesetzt.
Dazu gibt es die nicht-POSIX-konforme Funktion setgroups():struct group *myGroup; gid_t grp_ids[2]; if ( (myGroup = getgrnam("uucp")) == NULL ) printf("error getgrnam(uucp)"); grp_ids[0] = myGroup->gr_gid; if ( (myGroup = getgrnam("meinegrp")) == NULL ) printf("error getgrnam(meinegrp)"); grp_ids[1] = myGroup->gr_gid; // only superuser may use this function, if(-1 == setgroups(2, grp_ids)) perror("error in setgroups; errno");
Hab's getestet und es funktioniert.