2010-11-11 44 views

Répondre

52

Habituellement, c'est une erreur de tester si l'utilisateur est root. POSIX ne nécessite même pas un utilisateur root, mais le laisse à l'implémentation pour déterminer comment les autorisations fonctionnent. Code tel que:

if (i_am_root) do_privileged_op(); else print_error(); 

va vraiment agacer les utilisateurs avec des modèles de privilèges avancés où la racine est pas nécessaire d'effectuer les opérations privilégiées nécessaires. Je me souviens dans les premiers jours de la gravure de CD sur Linux, je devais pirater partout dans la source cdrecord pour enlever toutes les vérifications inutiles pour voir si elle était en cours d'exécution en tant que root, quand cela a bien fonctionné avec la permission de lire /dev/sga.

Au lieu de cela, vous devriez toujours tentative l'opération privilégiée que vous devez effectuer et vérifier EPERM ou similaire si elle ne parvient pas à avertir l'utilisateur qu'ils ont des privilèges insuffisants (et devrait peut-être une nouvelle tentative en cours d'exécution en tant que root).

Le cas où il est utile de vérifier la racine vérifie si votre programme a été appelé "suid-root". Un test raisonnable serait:

uid_t uid=getuid(), euid=geteuid(); 
if (uid<0 || uid!=euid) { 
    /* We might have elevated privileges beyond that of the user who invoked 
    * the program, due to suid bit. Be very careful about trusting any data! */ 
} else { 
    /* Anything goes. */ 
} 

Notez que je laissais la possibilité (bien tiré par les cheveux, mais mieux d'être paranoïaque) que ce soit des appels pour obtenir uid/euid pourrait échouer, et que dans le cas d'échec nous devrions supposer que nous sommes suid et un utilisateur malveillant a en quelque sorte provoqué l'échec des appels système pour tenter de cacher que nous sommes suid.

+3

D'accord, complètement. – caf

+3

La base de normes Linux nécessite toutefois un utilisateur root. Juste pour info. Je ne suis pas en désaccord avec la prémisse globale, bien sûr.:) – dannysauer

+2

LSB a beaucoup de bugs, comme exiger des fonctions de la glibc interne visible accidentellement à gauche être disponible pour les applications. :-) –

26

getuid ou geteuid, selon ce que vous voulez vraiment dire. Dans les deux cas, 0 signifie racine.

if(geteuid() != 0) 
{ 
    // Tell user to run app as root, then exit. 
} 

Le point créé par R est valide. Vous devriez envisager des essais et erreurs, ou une autre approche qui ne nécessite pas explicitement root.

+1

Quelle est la différence entre getuid et geteuid? –

+1

'geteuid' renvoie l'ID utilisateur effectif, en tenant compte des appels à [' seteuid'] (http://www.opengroup.org/onlinepubs/009695399/functions/seteuid.html) ou similaire. 'getuid' renvoie l'identifiant réel de l'utilisateur. –

+7

'e' est pour 'efficace'; l'euid est celui qui est réellement utilisé pour les vérifications de permission. Normalement, l'uid et l'euid sont les mêmes, mais si vous êtes dans un programme setuid, quand il commence, 'getuid' renverra l'uid de l'utilisateur qui a appelé le programme et' geteuid' retournera l'uid de l'utilisateur possède l'exécutable. Vous pouvez définir l'uid sur l'uid, et inversement, avec 'seteuid()'. Les règles précises sont trop compliquées pour un commentaire. – zwol