Изменение вывода Linux 'ps' путем изменения argv [0]

Я пытаюсь заставить программу изменить то, что 'ps' отображает в качестве имени CMD процесса, используя технику, которую я видел, рекомендованную для простого наложения памяти, на которую указывает argv [0]. Вот пример программы, которую я написал.

#include <iostream>
#include <cstring>
#include <sys/prctl.h>
#include <linux/prctl.h>
using std::cout;
using std::endl;
using std::memcpy;

int main(int argc, char** argv)  {
    if ( argc < 2 ) {
        cout << "You forgot to give new name." << endl;
        return 1;
    }

    // Set new 'ps' command name - NOTE that it can't be longer than
    // what was originally in argv[0]!

    const char *ps_name = argv[1];
    size_t arg0_strlen = strlen(argv[0]);
    size_t ps_strlen = strlen(ps_name);
    cout << "Original argv[0] is '" << argv[0] << "'" << endl;

    // truncate if needed
    size_t copy_len = (ps_strlen < arg0_strlen) ? ps_strlen+1 : arg0_strlen;
    memcpy((void *)argv[0], ps_name, copy_len);
    cout << "New name for ps is '" << argv[0] << "'" << endl;

    cout << "Now spin.  Go run ps -ef and see what command is." << endl;
    while (1) {};
}

Результат:

$ ./ps_test2 foo
Original argv[0] is './ps_test2'
New name for ps is 'foo'
Now spin.  Go run ps -ef and see what command is.

Результат ps -ef:

5079     28952  9142 95 15:55 pts/20   00:00:08 foo _test2 foo

Ясно, что "foo" был вставлен, но его нулевой ограничитель либо игнорировался, либо превращался в пробел. Завершающая часть исходного argv [0] все еще видна.

Как я могу заменить строку, выводимую ps?


person Chap    schedule 30.04.2014    source источник
comment
Парень, что находится внутри специального /proc/$pid/cmdline файла? Вы можете сделать это hexdump -C?   -  person osgx    schedule 01.05.2014
comment
00000000 66 6f 6f 00 5f 74 65 73 74 00 66 6f 6f 00 62 61 | foo._test.foo.ba | 00000010 72 00 | р. |   -  person Chap    schedule 01.05.2014
comment
@osgx: Ну, я не могу его правильно отформатировать, но он соответствует описанию тетромино ниже.   -  person Chap    schedule 01.05.2014


Ответы (1)


Вам нужно переписать всю командную строку, которая в Linux хранится как непрерывный буфер с аргументами, разделенными нулями.

Что-то типа:

size_t cmdline_len = argv[argc-1] + strlen(argv[argc-1]) - argv[0];
size_t copy_len = (ps_strlen + 1 < cmdline_len) ? ps_strlen + 1 : cmdline_len;
memcpy(argv[0], ps_name, copy_len);
memset(argv[0] + copy_len, 0, cmdline_len - copy_len);
person tetromino    schedule 01.05.2014
comment
Кажется, это правильно. И я проверил, что argv [1..n] указывают на эти аргументы с завершающим нулем, а это означает, что я буду сбивать argv [1..n]. Что-то, о чем нужно знать. - person Chap; 01.05.2014