Меняем PID процесса в Linux с помощью модуля ядра.


Внимание! после смены PID - к oscill не будут подходить наши драйверы. Нужны будут другие. Если Вы это забудете - попытки установить oscill на новый ПК будут безуспешными.

PID - Product IDentifier / номер продукта- характеристика USB-устройства, вместе с VID (Vendor IDentifier - номер производителя) однозначно характеризующая это устройство со стороны хоста. По VID/PID устанавливаются и работают драйверы для каждого подключенного устройства.

Осциллографу usb.oscill присвоен уникальный VID+PID, соответственно им поставляются в комплекте (и доступны для загрузки на этом сайте) драйверы для Windows 98, 98SE, ME, 2000, XP, Vista, Seven. Однако, для следующих случаев:

  • использование oscill в ОС Linux (ПО в виртуальной машине) - вариант для FreeBSD
  • подключение oscill к Pocket PC / Windows Mobile через виртуальный COM-порт
  • Windows Seven 64bit с обязательным подписыванием драйверов

может понадобиться применение стандартных драйверов Silabs, для чего придется заменить PID oscill на PID Silabs. Это можно сделать специальной утилитой SetPID :

Рекомендуется изменять PID на EA61, и использовать новую версию ПО и DLL драйвер Silabs v3.X . В этом ПО предусмотрен автоматический и ручной выбор USB драйвера между v2.0 и v3.X. Для ручного выбора нужно сделать: Link-Setup-Port-Driver-V3

Внимание! Смена PID этой утилитой возможна только на ПК под управлением Windows, где уже установлен соответствующий текущему PID драйвер. Иначе, SetPID не увидит oscill . То есть, oscill должен присутствовать в "Диспетчере Устройств" "Панели Управления". Алгоритм:

  1. если уже установлен USB (или VCP) драйвер из этого раздела - утилита setpid покажет PID=840E, и можно сменить PID на generic SILABS;
  2. SetPID потеряет oscill, в Диспетчере Устройств он также исчезнет;
  3. Windows найдет новое устройство, для которого надо скачать стандартный драйвер от Silabs для PID EA60 или для PID EA61
  4. этот драйвер подписан, и с ним должна начать работать оболочка .

Обратная процедура:

  1. после установки стандартного драйвера, утилита SetPID обнаруживает oscill с PID=EA60 или EA61
  2. можно вернуть custom OSCILL PID нажатием соотв.кнопки
  3. SetPID покажет оригинальный PID oscill = 840E

Кроме setpid, для смены PID можно воспользоваться утилитой от Silabs: на этой странице выбрать an144.pdf и an144sw.zip

Примечание: Пользователь Usatenko на форуме опубликовал рецепт смены PID на единственном компьютере с Win7 64

  • Ненормальное программирование ,
  • Программирование
  • В этой статье мы попытаемся создать модуль ядра, способный изменить PID уже запущенного процесса в ОС Linux, а так же поэкспериментировать с процессами, получившими измененный PID.


    Предупреждение : смена PID - нестандартный процесс, и при определенных обстоятельствах может привести к панике ядра.

    Наш тестовый модуль будет реализовывать символьное устройство /dev/test, при чтении с которого процессу будет изменен PID. За пример реализации символьного устройства спасибо статье. Полный код модуля приведен в конце статьи. Конечно, самым правильным решением было добавить системный вызов в само ядро, однако это потребует перекомпиляцию ядра.

    Окружение

    Все действия по тестированию модуля выполнялись в виртуальной машине VirtualBox с 64 битным дистрибутивомLInux и версией ядра 4.14.4-1. Связь с машиной осуществлялась с помощью SSH.

    Попытка #1 простое решение

    Пару слов о current : переменная current указывает на структуру task_struct с описанием процесса в ядре(PID, UID, GID, cmdline, namespaces и т.д)

    Первой идеей было просто поменять параметр current->pid из модуля ядра на нужный.

    Static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { printk("PID: %d.\n",current->pid); current->pid = 1; printk("new PID: %d.\n",current->pid); , }
    Для проверки работоспособности модуля я написал программу на C++:

    #include #include #include int main() { std::cout << "My parent PID " << getppid() << std::endl; std::cout << "My PID " << getpid() << std::endl; std::fstream f("/dev/test",std::ios_base::in); if(!f) { std::cout << "f error"; return -1; } std::string str; f >> str; std::cout << "My new PID " << getpid() << std::endl; execl("/bin/bash","/bin/bash",NULL); }
    Загрузим модуль коммандой insmod, создадим /dev/test и попробуем.

    # ./a.out My parent PID 293 My PID 782 My new PID 782
    PID не изменился. Возможно, это не единственное место, где указывается PID.

    Попытка #2 дополнительные поля PID

    Если не current->pid является идентификатором процесса, то что является? Быстрый просмотр кода getpid() навел на структуру task_struct , описывающую процесс Linux и файл pid.c в исходном коде ядра. Нужная функция - __task_pid_nr_ns. В коде функции встречается обращение task->pids.pid, этот параметр мы и изменим

    Компилируем, пробуем

    Так как тестировал я по SSH, мне удалось получить вывод программы до падения ядра:

    My parent PID 293 My PID 1689 My new PID 1689
    Первый результат, уже что-то. Но PID все равно не изменился.

    Попытка #3 не экспортируемые символы ядра

    Более внимательное изучение pid.c дало функцию, которая делает то, что нам нужно
    static void __change_pid(struct task_struct *task, enum pid_type type,
    struct pid *new)
    Функция принимает задачу, для которой надо изменить PID, тип PID и, собственно, новый PID. Созданием нового PID занимается функция
    struct pid *alloc_pid(struct pid_namespace *ns)

    Эта функция принимает только пространство имен, в котором будет находиться новый PID, это пространство можно получить с помощью task_active_pid_ns .
    Но есть одна проблема: эти символы ядра не экспортируются ядром и не могут использоваться в модулях. В решении этой проблемы мне помогла замечательная . Код функции find_sym взят оттуда.

    Static asmlinkage void (*change_pidR)(struct task_struct *task, enum pid_type type, struct pid *pid); static asmlinkage struct pid* (*alloc_pidR)(struct pid_namespace *ns); static int __init test_init(void) { printk(KERN_ALERT "TEST driver loaded!\n"); change_pidR = find_sym("change_pid"); alloc_pidR = find_sym("alloc_pid"); ... } static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { printk("PID: %d.\n",current->pid); struct pid* newpid; newpid = alloc_pidR(task_active_pid_ns(current)); change_pidR(current,PIDTYPE_PID,newpid); printk("new PID: %d.\n",current->pid); ... }
    Комплируем, запускаем

    My parent PID 299 My PID 750 My new PID 751
    PID изменен! Ядро автоматически выделило нашей программе свободный PID. Но можно ли использовать PID, который занял другой процесс, например PID 1? Добавим после аллокации код

    Newpid->numbers.nr = 1;
    Комплируем, запускаем

    My parent PID 314 My PID 1172 My new PID 1
    Получаем настоящий PID 1!

    Bash выдал ошибку, из-за которой не будет работать переключение задач по комманде %n, но все остальные функции работают отлично.

    Интересные особенности процессов с измененным PID

    PID 0: войти нельзя выйти

    Вернемся к коду и изменим PID на 0.

    Newpid->numbers.nr = 0;
    Комплируем, запускаем

    My parent PID284 My PID 1517 My new PID 0
    Выходит PID 0 не такой и особенный? Радуемся, пишм exit и…

    Ядро падает! Ядро определило нашу задачу как IDLE TASK и, увидев завершение, просто упало. Видимо, перед завершением наша программа должна вернуть себе «нормальный» PID.

    Процесс-невидимка

    Вернемся к коду и выставим PID, гарантированно не занятый
    newpid->numbers.nr = 12345;

    Комплируем, запускаем

    My parent PID296 My PID 735 My new PID 12345
    Посмотрим, что находится в /proc

    1 148 19 224 288 37 79 86 93 consoles fb kcore locks partitions swaps version 10 149 2 226 29 4 8 87 acpi cpuinfo filesystems key-users meminfo sched_debug sys vmallocinfo 102 15 20 23 290 5 80 88 asound crypto fs keys misc schedstat sysrq-trigger vmstat 11 16 208 24 291 6 81 89 buddyinfo devices interrupts kmsg modules scsi sysvipc zoneinfo 12 17 21 25 296 7 82 9 bus diskstats iomem kpagecgroup mounts self thread-self 13 176 210 26 3 737 83 90 cgroups dma ioports kpagecount mtrr slabinfo timer_list 139 18 22 27 30 76 84 91 cmdline driver irq kpageflags net softirqs tty 14 182 222 28 31 78 85 92 config.gz execdomains kallsyms loadavg pagetypeinfo stat uptime
    Как видим /proc не определяет наш процесс, даже если мы заняли свободный PID. Предыдущего PID тоже нет в /proc, и это весьма странно. Возможно, мы находимся в другом пространстве имен и поэтому не видны основному /proc. Смонтируем новый /proc, и посмотрим что там

    1 14 18 210 25 291 738 81 9 bus devices fs key-users locks pagetypeinfo softirqs timer_list 10 148 182 22 26 296 741 82 90 cgroups diskstats interrupts keys meminfo partitions stat tty 102 149 19 222 27 30 76 83 92 cmdline dma iomem kmsg misc sched_debug swaps uptime 11 15 2 224 28 37 78 84 93 config.gz driver ioports kpagecgroup modules schedstat sys version 12 16 20 226 288 4 79 85 acpi consoles execdomains irq kpagecount mounts scsi sysrq-trigger vmallocinfo 13 17 208 23 29 6 8 86 asound cpuinfo fb kallsyms kpageflags mtrr self sysvipc vmstat 139 176 21 24 290 7 80 87 buddyinfo crypto filesystems kcore loadavg net slabinfo thread-self zoneinfo
    По прежнему нашего процесса нет, а значит мы в обычном пространстве имен. Проверим

    Ps -e | grep bash
    296 pts/0 00:00:00 bash

    Только один bash, с которого мы и запускали программу. Ни предыдущего PID, ни текущего в списке нет.



    В этой статье мы попытаемся создать модуль ядра, способный изменить PID уже запущенного процесса в ОС Linux, а так же поэкспериментировать с процессами, получившими измененный PID.


    Предупреждение : смена PID - нестандартный процесс, и при определенных обстоятельствах может привести к панике ядра.

    Наш тестовый модуль будет реализовывать символьное устройство /dev/test, при чтении с которого процессу будет изменен PID. За пример реализации символьного устройства спасибо этой статье. Полный код модуля приведен в конце статьи. Конечно, самым правильным решением было добавить системный вызов в само ядро, однако это потребует перекомпиляцию ядра.

    Окружение

    Все действия по тестированию модуля выполнялись в виртуальной машине VirtualBox с 64 битным дистрибутивомLInux и версией ядра 4.14.4-1. Связь с машиной осуществлялась с помощью SSH.

    Попытка #1 простое решение

    Пару слов о current : переменная current указывает на структуру task_struct с описанием процесса в ядре(PID, UID, GID, cmdline, namespaces и т.д)

    Первой идеей было просто поменять параметр current->pid из модуля ядра на нужный.

    Static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { printk("PID: %d.\n",current->pid); current->pid = 1; printk("new PID: %d.\n",current->pid); , }
    Для проверки работоспособности модуля я написал программу на C++:

    #include #include #include int main() { std::cout << "My parent PID " << getppid() << std::endl; std::cout << "My PID " << getpid() << std::endl; std::fstream f("/dev/test",std::ios_base::in); if(!f) { std::cout << "f error"; return -1; } std::string str; f >> str; std::cout << "My new PID " << getpid() << std::endl; execl("/bin/bash","/bin/bash",NULL); }
    Загрузим модуль коммандой insmod, создадим /dev/test и попробуем.

    # ./a.out My parent PID 293 My PID 782 My new PID 782
    PID не изменился. Возможно, это не единственное место, где указывается PID.

    Попытка #2 дополнительные поля PID

    Если не current->pid является идентификатором процесса, то что является? Быстрый просмотр кода getpid() навел на структуру task_struct , описывающую процесс Linux и файл pid.c в исходном коде ядра. Нужная функция - __task_pid_nr_ns. В коде функции встречается обращение task->pids.pid, этот параметр мы и изменим

    Компилируем, пробуем

    Так как тестировал я по SSH, мне удалось получить вывод программы до падения ядра:

    My parent PID 293 My PID 1689 My new PID 1689
    Первый результат, уже что-то. Но PID все равно не изменился.

    Попытка #3 не экспортируемые символы ядра

    Более внимательное изучение pid.c дало функцию, которая делает то, что нам нужно
    static void __change_pid(struct task_struct *task, enum pid_type type,
    struct pid *new)
    Функция принимает задачу, для которой надо изменить PID, тип PID и, собственно, новый PID. Созданием нового PID занимается функция
    struct pid *alloc_pid(struct pid_namespace *ns)

    Эта функция принимает только пространство имен, в котором будет находиться новый PID, это пространство можно получить с помощью task_active_pid_ns .
    Но есть одна проблема: эти символы ядра не экспортируются ядром и не могут использоваться в модулях. В решении этой проблемы мне помогла замечательная . Код функции find_sym взят оттуда.

    Static asmlinkage void (*change_pidR)(struct task_struct *task, enum pid_type type, struct pid *pid); static asmlinkage struct pid* (*alloc_pidR)(struct pid_namespace *ns); static int __init test_init(void) { printk(KERN_ALERT "TEST driver loaded!\n"); change_pidR = find_sym("change_pid"); alloc_pidR = find_sym("alloc_pid"); ... } static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { printk("PID: %d.\n",current->pid); struct pid* newpid; newpid = alloc_pidR(task_active_pid_ns(current)); change_pidR(current,PIDTYPE_PID,newpid); printk("new PID: %d.\n",current->pid); ... }
    Комплируем, запускаем

    My parent PID 299 My PID 750 My new PID 751
    PID изменен! Ядро автоматически выделило нашей программе свободный PID. Но можно ли использовать PID, который занял другой процесс, например PID 1? Добавим после аллокации код

    Newpid->numbers.nr = 1;
    Комплируем, запускаем

    My parent PID 314 My PID 1172 My new PID 1
    Получаем настоящий PID 1!

    Bash выдал ошибку, из-за которой не будет работать переключение задач по комманде %n, но все остальные функции работают отлично.

    Интересные особенности процессов с измененным PID

    PID 0: войти нельзя выйти

    Вернемся к коду и изменим PID на 0.

    Newpid->numbers.nr = 0;
    Комплируем, запускаем

    My parent PID284 My PID 1517 My new PID 0
    Выходит PID 0 не такой и особенный? Радуемся, пишм exit и…

    Ядро падает! Ядро определило нашу задачу как IDLE TASK и, увидев завершение, просто упало. Видимо, перед завершением наша программа должна вернуть себе «нормальный» PID.

    Процесс-невидимка

    Вернемся к коду и выставим PID, гарантированно не занятый
    newpid->numbers.nr = 12345;

    Комплируем, запускаем

    My parent PID296 My PID 735 My new PID 12345
    Посмотрим, что находится в /proc

    1 148 19 224 288 37 79 86 93 consoles fb kcore locks partitions swaps version 10 149 2 226 29 4 8 87 acpi cpuinfo filesystems key-users meminfo sched_debug sys vmallocinfo 102 15 20 23 290 5 80 88 asound crypto fs keys misc schedstat sysrq-trigger vmstat 11 16 208 24 291 6 81 89 buddyinfo devices interrupts kmsg modules scsi sysvipc zoneinfo 12 17 21 25 296 7 82 9 bus diskstats iomem kpagecgroup mounts self thread-self 13 176 210 26 3 737 83 90 cgroups dma ioports kpagecount mtrr slabinfo timer_list 139 18 22 27 30 76 84 91 cmdline driver irq kpageflags net softirqs tty 14 182 222 28 31 78 85 92 config.gz execdomains kallsyms loadavg pagetypeinfo stat uptime
    Как видим /proc не определяет наш процесс, даже если мы заняли свободный PID. Предыдущего PID тоже нет в /proc, и это весьма странно. Возможно, мы находимся в другом пространстве имен и поэтому не видны основному /proc. Смонтируем новый /proc, и посмотрим что там

    1 14 18 210 25 291 738 81 9 bus devices fs key-users locks pagetypeinfo softirqs timer_list 10 148 182 22 26 296 741 82 90 cgroups diskstats interrupts keys meminfo partitions stat tty 102 149 19 222 27 30 76 83 92 cmdline dma iomem kmsg misc sched_debug swaps uptime 11 15 2 224 28 37 78 84 93 config.gz driver ioports kpagecgroup modules schedstat sys version 12 16 20 226 288 4 79 85 acpi consoles execdomains irq kpagecount mounts scsi sysrq-trigger vmallocinfo 13 17 208 23 29 6 8 86 asound cpuinfo fb kallsyms kpageflags mtrr self sysvipc vmstat 139 176 21 24 290 7 80 87 buddyinfo crypto filesystems kcore loadavg net slabinfo thread-self zoneinfo
    По прежнему нашего процесса нет, а значит мы в обычном пространстве имен. Проверим

    Ps -e | grep bash
    296 pts/0 00:00:00 bash

    Только один bash, с которого мы и запускали программу. Ни предыдущего PID, ни текущего в списке нет.





    

    2024 © gtavrl.ru.