Почему sysctl создает E_INVAL в Mac OS X?

Ниже приведен урезанный (проверки на ошибки/нулевые значения опущены) фрагмент кода C/Obj-C, который использует sysctl для получения argv определенного процесса с PID 50.

...
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);
...

Первый вызов sysctl (для определения размера массива строк argv) завершается успешно. Возвращаемая длина составляет ~ 1600, больше, чем я ожидал, но я полагаю, что это разумно. Маллок преуспевает. Второй вызов sysctl возвращает -1, устанавливая для errno значение 22, E_INVAL.

Я просмотрел другой код, в том числе из этот вопрос, но не вижу проблемы с моей. Что мне не хватает?


person DNS    schedule 02.04.2010    source источник


Ответы (1)


Я попытался обернуть ваш код в программу, и она отлично работает и распечатывает argv другого процесса и т. д. при запросе одного из моих собственных процессов, т. е. с тем же uid, что и у процесса, вызывающего sysctl() .

Аспект «больше, чем я ожидал» заключается в том, что возвращаются переменные среды процесса, а также аргументы командной строки. (Непонятно, в каком формате вся эта информация.)

Когда я спрашиваю о процессе другого пользователя, я получаю тот же EINVAL из второго sysctl, который вы видели. Я предполагаю, что это считается необоснованным любопытством к процессам других людей, но вы могли бы подумать, что первый sysctl тоже потерпит неудачу.

(При запросе о несуществующем pid первый sysctl завершается с ошибкой EINVAL.)

Все это кажется сильно задокументированным: в Leopard KERN_PROCARGS даже не появляется на справочной странице sysctl.

person John Marshall    schedule 02.04.2010
comment
Это и есть; когда я пытаюсь использовать собственный PID, он работает. Я также немного покопался в с открытым исходным кодом. .apple.com/source/xnu/xnu-792.12.6/bsd/kern/ (см. sysctl_procargsx), и он действительно проверяет разрешения в случае фактического получения аргументов, но не тогда, когда вы просто получаете длина. Теперь мне просто интересно, как «ps» может получить аргументы для всех процессов, но я думаю, что это отдельный вопрос. - person DNS; 03.04.2010
comment
Обычный подход для ps состоит в том, чтобы иметь root с правами setuid и, таким образом, иметь возможность произвольно использовать KERN_PROCARGS или другие сверхспособности. Этот исходный код sysctl_procargsx() интересен тем, что он просто возвращает базу пользовательского стека — возврат кадра стека main(argc,argv,envp) проясняет, почему также возвращаются переменные среды, и говорит... ... что-то о формате возвращаемых данных. - person John Marshall; 03.04.2010