kcmp

KCMP(2)         Ð ÑководÑÑво пÑогÑаммиÑÑа Linux         KCMP(2)



ÐÐЯ
       kcmp - ÑÑÐ°Ð²Ð½Ð¸Ð²Ð°ÐµÑ Ð´Ð²Ð° пÑоÑеÑÑа, опÑеделÑÑ
       иÑполÑзÑÑÑ Ð»Ð¸ они обÑий ÑеÑÑÑÑ ÑдÑа

ÐÐÐÐÐ
       #include <linux/kcmp.h>

       int kcmp(pid_t pid1, pid_t pid2, int type,
                unsigned long idx1, unsigned long idx2);

       ÐамеÑание: Ð glibc Ð½ÐµÑ Ð¾Ð±ÑÑÑоÑной ÑÑнкÑии длÑ
       данного ÑиÑÑемного вÑзова; ÑмоÑÑиÑе ÐÐÐÐЧÐÐÐЯ.

ÐÐÐСÐÐÐÐ
       СиÑÑемнÑй вÑзов kcmp() Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð´Ð»Ñ
       пÑовеÑки, иÑполÑзÑÑÑ Ð»Ð¸ два пÑоÑеÑÑа pid1 и pid2
       обÑий ÑеÑÑÑÑ ÑдÑа, напÑÐ¸Ð¼ÐµÑ Ð²Ð¸ÑÑÑалÑнÑÑ Ð¿Ð°Ð¼ÑÑÑ,
       ÑайловÑе деÑкÑипÑоÑÑ Ð¸ Ñ.д.

       ÐÑаво вÑзÑваÑÑ kcmp() опÑеделÑеÑÑÑ Ð¿ÑовеÑкой
       Ñежима доÑÑÑпа ptrace PTRACE_MODE_READ_REALCREDS вмеÑÑе Ñ
       pid1 и pid2; ÑмоÑÑиÑе ptrace(2).

       РаÑгÑменÑе type ÑказÑваеÑÑÑ ÐºÐ°ÐºÐ¾Ð¹ ÑеÑÑÑÑ Ð´Ð²ÑÑ
       пÑоÑеÑÑов нÑжно ÑÑавниваÑÑ. ÐопÑÑÑÐ¸Ð¼Ñ ÑледÑÑÑие
       знаÑениÑ:

       KCMP_FILE
              ÐÑовеÑиÑÑ, ÑÑо Ñайловой деÑкÑипÑÐ¾Ñ idx1 в
              пÑоÑеÑÑе pid1 ÑказÑÐ²Ð°ÐµÑ Ð½Ð° ÑÐ¾Ñ Ð¶Ðµ оÑкÑÑÑÑй
              ÑайловÑй деÑкÑипÑÐ¾Ñ (ÑмоÑÑиÑе open(2)) ÑÑо и
              ÑайловÑй деÑкÑипÑÐ¾Ñ idx2 в пÑоÑеÑÑе pid2.

       KCMP_FILES
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð´Ð¸Ð½ и ÑоÑ
              же Ð½Ð°Ð±Ð¾Ñ Ð¾ÑкÑÑÑÑÑ ÑайловÑÑ Ð´ÐµÑкÑипÑоÑов.
              ÐÑгÑменÑÑ idx1 и idx2 игноÑиÑÑÑÑÑÑ.

       KCMP_FS
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð±ÑÑÑ
              инÑоÑмаÑÐ¸Ñ Ð´Ð»Ñ Ñайловой ÑиÑÑÐµÐ¼Ñ (Ñ.е.
              маÑÐºÑ Ð¿Ñав ÑозданиÑ, ÑабоÑий каÑалог и
              коÑÐµÐ½Ñ Ñайловой ÑиÑÑемÑ). ÐÑгÑменÑÑ idx1 и
              idx2 игноÑиÑÑÑÑÑÑ.

       KCMP_IO
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð±Ñий
              конÑекÑÑ Ð²Ð²Ð¾Ð´Ð°-вÑвода. ÐÑгÑменÑÑ idx1 и idx2
              игноÑиÑÑÑÑÑÑ.

       KCMP_SIGHAND
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð±ÑÑÑ
              ÑаблиÑÑ Ð¾Ð±ÑабоÑÑиков Ñигналов. ÐÑгÑменÑÑ
              idx1 и idx2 игноÑиÑÑÑÑÑÑ.

       KCMP_SYSVSEM
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð±Ñий
              ÑпиÑок оÑÐ¼ÐµÐ½Ñ Ð¾Ð¿ÐµÑаÑий ÑемаÑоÑов System V.
              ÐÑгÑменÑÑ idx1 и idx2 игноÑиÑÑÑÑÑÑ.

       KCMP_VM
              ÐÑовеÑиÑÑ, иÑполÑзÑÑÑ Ð»Ð¸ пÑоÑеÑÑÑ Ð¾Ð±Ñее
              адÑеÑное пÑоÑÑÑанÑÑво. ÐÑгÑменÑÑ idx1 и idx2
              игноÑиÑÑÑÑÑÑ.

       ÐамеÑим, ÑÑо вÑзов kcmp() не заÑиÑÑн Ð¾Ñ Ð»Ð¾Ð¶Ð½ÑÑ
       ÑÑабаÑÑваний (false positives), коÑоÑÑе могÑÑ
       ÑлÑÑаÑÑÑÑ, еÑли пÑоÑеÑÑÑ Ð² ÑÑÐ¾Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð²ÑполнÑÑÑÑÑ.
       То еÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð´Ð¾ÑÑовеÑнÑÑ ÑезÑлÑÑаÑов
       пеÑед вÑполнением данного ÑиÑÑемного
       вÑзова нÑжно  поÑлаÑÑ Ð¿ÑоÑеÑÑам Ñигнал SIGSTOP
       (ÑмоÑÑиÑе signal(7)).

ÐÐÐÐÐ ÐЩÐÐÐÐÐ ÐÐÐЧÐÐÐÐ
       ÐÑи ÑÑпеÑном вÑполнении kcmp() возвÑаÑаеÑ
       ÑезÑлÑÑÐ°Ñ Ð°ÑиÑмеÑиÑеÑкого ÑложениÑ
       ÑказаÑелей ÑдÑа (когда ÑдÑо ÑÑавниваеÑ
       ÑеÑÑÑÑÑ, оно иÑполÑзÑÐµÑ Ð¸Ñ Ð°Ð´ÑеÑа памÑÑи).

       ÐÐ»Ñ Ð¿ÑоÑÑоÑÑ Ð¾Ð±ÑÑÑÐ½ÐµÐ½Ð¸Ñ ÑаÑÑмоÑÑим пÑимеÑ.
       ÐÑедположим, ÑÑо v1 и v2 â адÑеÑа ÑооÑвеÑÑÑвÑÑÑиÑ
       ÑеÑÑÑÑов и возвÑаÑаеÑÑÑ Ð·Ð½Ð°Ñение:

           0   v1 Ñавен v2; дÑÑгими Ñловами, два
               пÑоÑеÑÑа иÑполÑзÑÑÑ ÑеÑÑÑÑ ÑовмеÑÑно.

           1   v1 менÑÑе v2.

           2   v1 болÑÑе v2.

           3   v1 не Ñавен v2, но нÑÐ¶Ð½Ð°Ñ Ð¸Ð½ÑоÑмаÑиÑ
               недоÑÑÑпна.

       Ð ÑлÑÑае оÑибки возвÑаÑаеÑÑÑ -1 и знаÑение errno
       ÑÑÑанавливаеÑÑÑ ÑооÑвеÑÑÑвÑÑÑим обÑазом.

       ÐнаÑÐµÐ½Ð¸Ñ Ð²Ñзова kcmp() ÑпеÑиалÑно вÑбÑÐ°Ð½Ñ Ñак,
       ÑÑÐ¾Ð±Ñ Ð¸Ñ Ð»ÐµÐ³ÐºÐ¾ можно бÑло ÑпоÑÑдоÑиÑÑ. Ð
       ÑаÑÑноÑÑи, ÑÑо Ñдобно когда нÑжно ÑÑавниÑÑ
       болÑÑое колиÑеÑÑво ÑайловÑÑ Ð´ÐµÑкÑипÑоÑов.

ÐШÐÐÐÐ
       EBADF  ÐнаÑение type Ñавно KCMP_FILE и fd1 или fd2 не
              ÑвлÑÑÑÑÑ Ð¾ÑкÑÑÑÑми ÑайловÑми
              деÑкÑипÑоÑами.

       EINVAL ÐнаÑение type невеÑно.

       EPERM  ÐедоÑÑаÑоÑно пÑав Ð´Ð»Ñ Ð¿ÑоÑмоÑÑа ÑеÑÑÑÑов
              пÑоÑеÑÑа. ÐÐ»Ñ Ð¿ÑовеÑки пÑоÑеÑÑов ÑÑебÑеÑÑÑ
              Ð¼Ð°Ð½Ð´Ð°Ñ CAP_SYS_PTRACE, коÑоÑого Ñ Ð²Ð°Ñ Ð½ÐµÑ.
              Также могÑÑ Ð´ÐµÐ¹ÑÑвоваÑÑ Ð´ÑÑгие
              огÑаниÑÐµÐ½Ð¸Ñ ptrace, напÑимеÑ
              CONFIG_SECURITY_YAMA, коÑоÑое пÑи
              /proc/sys/kernel/yama/ptrace_scope Ñавном 2,
              огÑаниÑÐ¸Ð²Ð°ÐµÑ kcmp() доÑеÑними пÑоÑеÑÑами;
              ÑмоÑÑиÑе ptrace(2).

       ESRCH  ÐÑоÑеÑÑ pid1 или pid2 не ÑÑÑеÑÑвÑеÑ.

ÐÐРСÐÐ
       СиÑÑемнÑй вÑзов kcmp() впеÑвÑе поÑвилÑÑ Ð² Linux
       3.5.

СÐÐТÐÐТСТÐÐРСТÐÐÐÐРТÐÐ
       ÐÑзов kcmp() еÑÑÑ ÑолÑко в Linux и не должен
       иÑполÑзоваÑÑÑÑ Ð² пеÑеноÑимÑÑ Ð¿ÑогÑаммаÑ.

ÐÐÐÐЧÐÐÐЯ
       Ð glibc Ð½ÐµÑ Ð¾Ð±ÑÑÑки Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ ÑиÑÑемного
       вÑзова; запÑÑкайÑе его Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ syscall(2).

       ÐаннÑй ÑиÑÑемнÑй вÑзов доÑÑÑпен ÑолÑко, еÑли
       ÑдÑо ÑобÑано Ñ Ð¿Ð°ÑамеÑÑом CONFIG_CHECKPOINT_RESTORE.
       ÐÑновное пÑедназнаÑение вÑзова â
       возможноÑÑÑ Ð·Ð°ÑеÑки/воÑÑÑÐ°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²
       полÑзоваÑелÑÑком пÑоÑÑÑанÑÑве (CRIU).
       ÐлÑÑеÑнаÑивой ÑÑÐ¾Ð¼Ñ ÑиÑÑÐµÐ¼Ð½Ð¾Ð¼Ñ Ð²ÑÐ·Ð¾Ð²Ñ Ð±Ñло бÑ
       вÑÑÑавление ÑооÑвеÑÑÑвÑÑÑей инÑоÑмаÑии о
       пÑоÑеÑÑе в Ñайловой ÑиÑÑеме proc(5); Ñакой
       ваÑÐ¸Ð°Ð½Ñ Ð½Ðµ пÑигоден по пÑиÑинам
       безопаÑноÑÑи.

       ÐополниÑелÑнÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾Ð± обÑÐ¸Ñ ÑеÑÑÑÑаÑ
       ÑмоÑÑиÑе в clone(2).

ÐÐ ÐÐÐÐ
       ÐÐ°Ð½Ð½Ð°Ñ Ð¿ÑогÑамма иÑполÑзÑÐµÑ kcmp() пÑо
       пÑовеÑки Ñого, ÑÑо паÑа ÑайловÑÑ Ð´ÐµÑкÑипÑоÑов
       ÑказÑÐ²Ð°ÐµÑ Ð½Ð° одно и Ñоже оÑкÑÑÑое Ñайловое
       опиÑание. ÐÑогÑамма ÑеÑÑиÑÑÐµÑ ÑазлиÑнÑе ÑлÑÑаи
       Ð´Ð»Ñ Ð¿Ð°Ñ ÑайловÑÑ Ð´ÐµÑкÑипÑоÑов, опиÑаннÑÑ Ð²
       вÑводе пÑогÑаммÑ. ÐÑÐ¸Ð¼ÐµÑ ÑабоÑÑ Ð¿ÑогÑаммÑ:

           $ ./a.out
           PID ÑодиÑÐµÐ»Ñ 1144
           ÐÑкÑÑÑÑй ÑодиÑелем Ñайл на FD 3

           PID поÑомка поÑле fork() Ñавен 1145
                СÑавнение дÑбликаÑов FD из дÑÑÐ³Ð¸Ñ Ð¿ÑоÑеÑÑов:
                     kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> одинаков
           ÐÑкÑÑÑÑй поÑомком Ñайл на FD 4
                СÑавнение FD из ÑазлиÑнÑÑ open() одного пÑоÑеÑÑа:
                     kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> оÑлиÑаеÑÑÑ
           ÐÑÐ±Ð»Ð¸ÐºÐ°Ñ FD 3 поÑомка Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ FD 5
                СÑавнение дÑбликаÑов FD одного пÑоÑеÑÑа:
                     kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> одинаков

   ÐÑÑоднÑй код пÑогÑаммÑ

       #define _GNU_SOURCE
       #include <sys/syscall.h>
       #include <sys/wait.h>
       #include <sys/stat.h>
       #include <stdlib.h>
       #include <stdio.h>
       #include <unistd.h>
       #include <fcntl.h>
       #include <linux/kcmp.h>

       #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)

       static int
       kcmp(pid_t pid1, pid_t pid2, int type,
            unsigned long idx1, unsigned long idx2)
       {
           return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2);
       }

       static void
       test_kcmp(char *msg, id_t pid1, pid_t pid2, int fd_a, int fd_b)
       {
           printf("\t%s\n", msg);
           printf("\t\tkcmp(%ld, %ld, KCMP_FILE, %d, %d) ==> %s\n",
                   (long) pid1, (long) pid2, fd_a, fd_b,
                   (kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ?
                               "одинаков" : "оÑлиÑаеÑÑÑ");
       }

       int
       main(int argc, char *argv[])
       {
           int fd1, fd2, fd3;
           char pathname[] = "/tmp/kcmp.test";

           fd1 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
           if (fd1 == -1)
               errExit("open");

           printf("PID ÑодиÑÐµÐ»Ñ %ld\n", (long) getpid());
           printf("ÐÑкÑÑÑÑй ÑодиÑелем Ñайл на FD %d\n\n", fd1);

           switch (fork()) {
           case -1:
               errExit("fork");

           case 0:
               printf("PID поÑомка поÑле fork() Ñавен %ld\n", (long) getpid());

               test_kcmp("СÑавнение дÑбликаÑов FD из дÑÑÐ³Ð¸Ñ Ð¿ÑоÑеÑÑов:",
                       getpid(), getppid(), fd1, fd1);

               fd2 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
               if (fd2 == -1)
                   errExit("open");
               printf("ÐÑкÑÑÑÑй поÑомком Ñайл на FD %d\n", fd2);

               test_kcmp("СÑавнение FD из ÑазлиÑнÑÑ open() одного пÑоÑеÑÑа:",
                       getpid(), getpid(), fd1, fd2);

               fd3 = dup(fd1);
               if (fd3 == -1)
                   errExit("dup");
               printf("ÐÑÐ±Ð»Ð¸ÐºÐ°Ñ FD %d поÑомка Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ FD %d\n", fd1, fd3);

               test_kcmp("СÑавнение дÑбликаÑов FD одного пÑоÑеÑÑа:",
                       getpid(), getpid(), fd1, fd3);
               break;

           default:
               wait(NULL);
           }

           exit(EXIT_SUCCESS);
       }

СÐÐТРÐТРТÐÐÐÐ
       clone(2), unshare(2)



Linux                             2016-07-17                           KCMP(2)