2010-04-02 37 views
0

Voici une épuré (contrôle d'erreur/null omis) extrait de code C/Obj-C qui utilise sysctl pour obtenir le argv d'un processus particulier avec PID 50.Pourquoi sysctl produit-il E_INVAL sous Mac OS X?

... 
int getProcessArgs[3] = { CTL_KERN, KERN_PROCARGS, 50 }; 
sysctl(getProcessArgs, 3, NULL, &length, NULL, 0); 
char* processArgs = malloc(length * sizeof(char)); 
sysctl(getProcessArgs, 3, processArgs, &length, NULL, 0); 
... 

Le premier appel à sysctl (pour déterminer la taille du tableau de chaînes argv) réussit. La longueur retournée est ~ 1600, plus grande que ce à quoi je m'attendais, mais je suppose qu'elle n'est pas déraisonnable. Malloc réussit. Le deuxième appel à sysctl renvoie -1, définissant errno à 22, E_INVAL.

J'ai regardé un autre code, y compris celui de this question, mais ne peux pas voir le problème avec le mien. Qu'est-ce que je rate?

Répondre

2

J'ai essayé envelopper votre code en un programme, et il fonctionne très bien et imprime l'autre argv de processus etc lorsque vous demandez l'un de mes propres processus, à savoir, l'un avec le même uid que le processus en invoquant sysctl(). L'aspect "plus grand que ce à quoi je m'attendais" est dû au fait que les variables d'environnement du processus sont renvoyées ainsi que les arguments de la ligne de commande. (Il est pas évident que le format de ces informations est.)

Pour toute demande au sujet d'un autre processus de l'utilisateur, je reçois le même EINVAL de la deuxième sysctl que vous avez été voir. Je suppose que cela est considéré comme une curiosité déraisonnable à propos des processus des autres, mais on pourrait penser que le premier sysctl échouerait aussi.

(Pour toute demande d'un pid inexistant, la première sysctl échoue avec EINVAL.)

Tout cela semble être massivement underdocumented: Leopard, KERN_PROCARGS ne semble même pas dans la page de manuel sysctl.

+0

Voilà ce que c'est; quand j'essaie avec un PID auto-détenu, ça marche. J'ai aussi fait quelques recherches sur http://www.opensource.apple.com/source/xnu/xnu-792.12.6/bsd/kern/kern_sysctl.c (voir sysctl_procargsx), et il vérifie en fait les permissions dans le en fait-obtenir-args cas, mais pas quand vous obtenez juste la longueur. Maintenant je me demande juste comment 'ps' est capable d'obtenir les args pour tous les processus, mais je suppose que c'est pour une question séparée. – DNS

+0

L'approche habituelle pour 'ps' est d'être setuid root et ainsi pouvoir utiliser arbitrairement KERN_PROCARGS ou d'autres superpuissances. Ce code source sysctl_procargsx() est intéressant en ce qu'il retourne juste la base de la pile utilisateur - retourner le cadre de la pile principale (argc, argv, envp) permet de comprendre pourquoi les variables d'environnement sont aussi retournées, et dit ... er ... quelque chose sur le format des données renvoyées. –