title: Processing entries from task_struct. Why some tasks->next have 0. How to go to next task than?
body: <p>I know about Kernel module macro for_each_process</p>
  
  <pre><code>struct task_struct *iter; 
  for_each_process(iter)
  { 
  if (iter-&gt;state &gt; 0)
  { 
    snprintf(buf, MAX_BUF_SIZE, " name: %s, pid: %d, parent id: %d, state: %ld", iter-&gt;group_leader-&gt;comm, iter-&gt;pid, iter-&gt;parent-&gt;pid, iter-&gt;state);
    print_string(buf); 
  }
  </code></pre>
  
  <p>It should go through task_struct tasks members and get the next member of tasks which is task_struct.</p>
  
  <p>Wrote this userland program, that should do the same:</p>
  
  <p>list-tasks.c</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/mman.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdbool.h&gt;
  
  
  
  long readtaskstruct(long address)
  {
  
      int fd;
      void *retp = NULL;
  
      long addr = address; 
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char nextstr;
      int page_size,offset;
  
  
      addrp = (long *) addr;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val;
  
      offset = addr &amp; 0xfff;
  
  
  
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd,ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
  
  
          memcpy(&amp;val,retp+(offset+784),4); //tasks next pointer
          val = val-620; //address to task_struct 
          munmap(retp,4096);
  
          close(fd);
  
  
      }
  
      return val;
  }           
  
  
  const char * readval(long address)
  {                
      int fd;
      void *retp = NULL;
  
  
      long addr = address;
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char *nextstr = calloc(sizeof(char),100);
      int page_size,offset;
  
      long *nextp = (long *) next;
      page_size = getpagesize();
      val = next &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val; 
  
      offset = next &amp; 0xfff;
      fd = open("/dev/mem", O_RDWR|O_SYNC);
  
      retp = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
          memcpy(nextstr,retp+(offset+996),100); //task-&gt;comm
  
  
  
          munmap(retp,4096);
      }
          return nextstr;
  }
  void main(void)
  {
  
  
  int ret = 0xc1a8cac0; //init_task
  
  ret = readtaskstruct(ret);
  printf("%s\n",readval(ret));
  
  
  
  
  }
  </code></pre>
  
  <p>It works.</p>
  
  <pre><code>$./list-tasks
  swapper/0
  </code></pre>
  
  <p>However, when I call it recursively, i.e:</p>
  
  <pre><code>  int ret = 0xc1a8cac0; //init_task
  
    while(1)
    {  
      ret = readtaskstruct(ret);
      printf("%s\n",readval(ret));
    }
  </code></pre>
  
  <p>It goes through first task->next and than somehow it seems that task->next is set to 0, since I get ret as 0.</p>
  
  <p>Why some tasks->next have 0 ... I though I should see a nice list of processes linking in tasks from one to the other. Why it breaks with 0 after first process. </p>
  
  <p>Anybody sees logical/programming error in list-tasks.c?</p>
  
  <p><strong>Update 1:</strong></p>
  
  <p>hmmm .. it seems to work correctly with for_each_process: more info <a href="https://0bin.net/paste/HCkEu8+daKo9Y8Z3#+M0vkO9KmtSmBSXBnuvQi73NsU2hrq0gWzJ6U8IHU4s" rel="nofollow noreferrer">https://0bin.net/paste/HCkEu8+daKo9Y8Z3#+M0vkO9KmtSmBSXBnuvQi73NsU2hrq0gWzJ6U8IHU4s</a>. Is my understanding correct that tasks member of structure task_struct will have members next and prev which point to task_structs?</p>
  
  <p>hmm my init_task is at 0xc1a8cac0 ... why I dont see it in for_each_process output from kernel module?</p>
  
  <p>ok so it is not listed there and than it links to next as 0xf58c0318 ...
  and this links next to 0x0</p>
  
  <p>just checked with GDB</p>
  
  <p>my question is why init_task is not listed in for_each_process macro?</p>
  
  <p>I guess I start with wrong process and the list ends ....</p>
  
  <p><strong>Update 2:</strong></p>
  
  <p>Live debugs</p>
  
  <p><a href="https://0bin.net/paste/h6YqUUQnKpIIPSMO#1mxZ5RR9zPIrbNOykeWHju58WZ-lOKhYhjaNnn/YEiq" rel="nofollow noreferrer">https://0bin.net/paste/h6YqUUQnKpIIPSMO#1mxZ5RR9zPIrbNOykeWHju58WZ-lOKhYhjaNnn/YEiq</a></p>
  
  <p>Modified the list-task.c to this:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/mman.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdbool.h&gt;
  
  
  
  long readtaskstruct(long address)
  {
  
      int fd;
      void *retp = NULL;
  
      long addr = address; 
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char nextstr;
      int page_size,offset;
  
  
      addrp = (long *) addr;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val;
  
      offset = addr &amp; 0xfff;
  
  
  
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd,ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
  
  
          memcpy(&amp;val,retp+(offset+620),4); //tasks next pointer
          //val = val-620; //address to task_struct 
          munmap(retp,4096);
  
          close(fd);
  
  
      }
  
      return val;
  }           
  
  
  const char * readval(long address)
  {                
      int fd;
      void *retp = NULL;
  
  
      long addr = address;
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char *nextstr = calloc(sizeof(char),100);
      int page_size,offset;
  
      long *nextp = (long *) next;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val; 
  
      offset = next &amp; 0xfff;
      fd = open("/dev/mem", O_RDWR|O_SYNC);
  
      retp = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
          memcpy(nextstr,retp+(offset+996),100); //task-&gt;comm
  
  
  
          munmap(retp,4096);
      }
      return nextstr;
  }
  void main(void)
  {
  
  
      int ret = 0xc1a8cac0; //init_task
  
      for(int i=0;i&lt;10;i++)
      {
          printf("0x%x\n",ret);
          ret = readtaskstruct(ret);
          printf("%s\n",readval(ret));
      }
  
  
  }
  </code></pre>
  
  <p><strong>Update 3:</strong></p>
  
  <p>Sweet works.</p>
  
  <pre><code>./list-task  |more
  Address:0xc1a8cac0
  Process:systemd
  Address:0xf58b8000
  Process:kthreadd
  Address:0xf58b89c0
  Process:ksoftirqd/0
  Address:0xf58b9380
  Process:kworker/0:0H
  Address:0xf58ba700
  Process:rcu_sched
  Address:0xf58bba80
  Process:rcu_bh
  Address:0xf58bc440
  Process:migration/0
  Address:0xf58bce00
  Process:migration/1
  Address:0xf58bf500
  Process:ksoftirqd/1
  Address:0xf58f0000
  Process:kworker/1:0H
  Address:0xf58f1380
  Process:migration/2
  Address:0xf58f1d40
  Process:ksoftirqd/2
  Address:0xf58f2700
  Process:kworker/2:0H
  Address:0xf58f3a80
  Process:migration/3
  Address:0xf58f4440
  Process:ksoftirqd/3
  Address:0xf58f4e00
  Process:kworker/3:0H
  Address:0xf58f6180
  Process:kdevtmpfs
  Address:0xf5948000
  Process:netns
  Address:0xf59b0000
  Process:kworker/u8:1
  .
  .
  .
  Process:VBoxClient
  Address:0xf594d7c0
  Process:VBoxClient
  Address:0xf0f0e180
  Process:VBoxClient
  Address:0xf513b0c0
  FAILED
  FAILED
  Process:
  Address:0x3513b000
  FAILED
  FAILED
  Process:
  Address:0x3513b000
  </code></pre>
  
  <p>list-task.c</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/mman.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdbool.h&gt;
  
  
  
  long readtaskstruct(long address)
  {
  
      int fd;
      void *retp = NULL;
  
      long addr = address; 
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char nextstr;
      int page_size,offset;
  
  
      addrp = (long *) addr;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val;
  
      offset = addr &amp; 0xfff;
  
  
  
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096*4, PROT_READ, MAP_SHARED, fd,ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
  
  
          memcpy(&amp;val,retp+(offset+620),4); //tasks next pointer
          if(val==0)
            return 0;
          val = val-620; //address to task_struct 
          munmap(retp,4096*4);
  
          close(fd);
  
  
      }
  
      return val;
  }           
  
  
  const char * readval(long address)
  {                
      int fd;
      void *retp = NULL;
  
  
      long addr = address;
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char *nextstr = calloc(sizeof(char),100);
      int page_size,offset;
  
      long *nextp = (long *) next;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val; 
  
      offset = addr &amp; 0xfff;
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096*4, PROT_READ, MAP_SHARED, fd, ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
          memcpy(nextstr,retp+(offset+996),100); //task-&gt;comm
  
  
  
          munmap(retp,4096*4);
      }
      return nextstr;
  }
  void main(void)
  {
  
  
      int ret = 0xc1a8cac0; //init_task
  
      while(1)
      {
          if(ret!=0)
          {
            printf("Address:0x%x\n",ret);
            ret = readtaskstruct(ret);
            printf("Process:%s\n",readval(ret));
          }else{
            break;
          }
      }
  
  
  }
  </code></pre>
  
  <p>How will I know however that the list is at the end? Now it fails with mmap, that's how I know it is done. Is there any better, eleganter way to tell it?</p>
  
  <p>Thanks,</p>
  
  <p><strong>Update 4:</strong></p>
  
  <p>Final version:</p>
  
  <p>list-task.c</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/mman.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdbool.h&gt;
  
  
  
  long readtaskstruct(long address)
  {
  
      int fd;
      void *retp = NULL;
  
      long addr = address; 
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char nextstr;
      int page_size,offset;
  
  
      addrp = (long *) addr;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val;
  
      offset = addr &amp; 0xfff;
  
  
  
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096*4, PROT_READ, MAP_SHARED, fd,ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
  
  
          memcpy(&amp;val,retp+(offset+620),4); //tasks next pointer
          if(val==0)
            return 0;
          val = val-620; //address to task_struct 
          munmap(retp,4096*4);
  
          close(fd);
  
  
      }
  
      return val;
  }           
  
  
  const char * readval(long address)
  {                
      int fd;
      void *retp = NULL;
  
  
      long addr = address;
      long *addrp = NULL;
  
      long next,prev;
      long val;
      char *nextstr = calloc(sizeof(char),100);
      int page_size,offset;
  
      long *nextp = (long *) next;
      page_size = getpagesize();
      val = addr &amp; ~(page_size-1)- 0xc0000000;
      long *ptr = (long *) val; 
  
      offset = addr &amp; 0xfff;
      fd = open("/dev/mem", O_RDWR|O_SYNC);
      retp = mmap(NULL, 4096*4, PROT_READ, MAP_SHARED, fd, ptr);
  
  
      if (retp == MAP_FAILED)
      {
          printf("FAILED\n");
      }
      else
      {
  
          memcpy(nextstr,retp+(offset+996),100); //task-&gt;comm
  
  
  
          munmap(retp,4096*4);
      }
      return nextstr;
  }
  void main(void)
  {
  
  
      int ret = 0xc1a8cac0; //init_task
  
      do
      {
            //printf("Address:0x%x\n",ret);
            ret = readtaskstruct(ret);
            printf("Process:%s\n",readval(ret));
      }while(ret!=0 &amp;&amp; ret!= 0xc1a8cac0);
  
  
  }
  </code></pre>