2010-09-21 28 views
3

Après ne pas avoir une réponse que j'aimais pour this question about chroot, je suis allé et roulé ma propre solution:Quelqu'un voit aucun problème dans ce programme

#include <unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 
#include <stdio.h> 
extern char **environ; 

int main(int argc, char** argv, char** envp) { 
    char* path = "/"; 
    char* name = "nobody"; 
    char* exe = "/bin/false"; 
    struct passwd *pass; 

    if(argc < 4) { printf("Need more args: username chroot exe args...\n"); return 1; } 
    name = argv[1]; 
    path = argv[2]; 
    exe = argv[3]; 

    if(!(pass = getpwnam(name))) { printf("Unknown user %s", name); return 2; } 

    if(chroot(path)) { 
    if(errno == EPERM) { printf("chroot not allowed\n"); return 3; } 
    printf("chroot failed\n"); 
    return 4; 
    } 
    chdir("/"); 

    if(setgid(pass->pw_gid)) { printf("setgid failed: %d\n", pass->pw_gid); return 5; } 
    if(setuid(pass->pw_uid)) { printf("setuid failed: %d\n", pass->pw_uid); return 6; } 

    environ = envp; 
    execvp(exe, argv + 3); 

    printf("exec of %s failed\n", exe); 
    return 7; 
} 

Quelqu'un voit-il des bugs dans ce (ou encore mieux, connaître des un outil qui le rend redondant)?

Répondre

3
  1. Pourquoi attribuez-vous par défaut path, name, exe, si vous les écrasez de toute façon? Vous ne devez pas renvoyer des valeurs négatives de main(). Cela rend la valeur de retour réelle peu claire, car POSIX n'utilise que les 8 bits les moins significatifs (c'est-à-dire que -1 est renvoyé sous la forme 255, etc.).
  2. Vous ne devriez pas compter sur getuid(); chroot() fonctionnerait aussi la capacité CAP_SYS_CHROOT. Au lieu de cela, vous pouvez essayer de chroot() et vérifier si errno == EPERM.
  3. chroot() ne modifie pas le répertoire de travail en cours; Je pense que vous devriez appeler chdir() aussi.
  4. Qu'est-ce que l'affectation environ = envp fait exactement? Il semble hacky.
  5. Dans tous les cas, vous pouvez ajouter de meilleurs rapports d'erreurs.

Enfin, chrootuid est probablement l'outil que vous recherchiez.

+0

1) Les valeurs par défaut évitent toute une classe de bogues. 5) 'environnement' est utilisé par' execvp' et je ne me souviens pas s'il est défini par défaut. 6): b – BCS

+0

En ce qui concerne chrootuid, ce n'est pas un outil standard et suppose que je veux utiliser syslog (et je ne le fais pas, donc je ne peux pas l'utiliser tel quel). Étant donné que je cherchais à m'éloigner a) d'avoir à installer quelque chose et b) d'écrire le mien, cela n'a aucun avantage pour moi. – BCS

+0

est défini par défaut, AFAIK c'est l'équivalent POSIX de envp. Ainsi, vous mélangez deux standards de codage. Et je ne pense pas que vous pourriez trouver quelque chose de mieux. Surtout que vous voulez acquérir l'UID/GID avant d'entrer chroot. –