title: Is this a bug in linux kernel concerning write to /proc/self/loginuid?
body: <p>There is a possibility that i found a bug in linux kernel. Let's consider application that write to /proc/self/loginuid from main thread and one auxiliary thread. The code is below:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;sys/syscall.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;fcntl.h&gt;
  
  void write_loginuid(char *str)
  {
      int fd;
  
      printf("%s\n", str);
  
      fd = open("/proc/self/loginuid", O_RDWR);
  
      if (fd &lt; 0) {
          perror(str);
          return;
      }
  
      if (write(fd, "0", 2) != 2) {
          printf("write\n");
          perror(str);
      }
  
      close(fd);
  }
  
  void *thread_function(void *arg)
  {
      fprintf(stderr, "Hello from thread! my pid = %u, tid = %u, parent pid = %u\n", getpid(), syscall(SYS_gettid), getppid());
  
      write_loginuid("thread");
  
      return NULL;
  }
  
  int main()
  {
      pthread_t thread;
  
      pthread_create(&amp;thread, NULL, thread_function, NULL);
  
      write_loginuid("main process");
  
      fprintf(stderr, "test my pid = %u, tid = %u, parent pid = %u\n", getpid(), syscall(SYS_gettid), getppid());
  
      pthread_join(thread, NULL);
      return 0;
  }
  </code></pre>
  
  <p>After executing this application we get:</p>
  
  <pre><code>main process
  test my pid = 3487, tid = 3487, parent pid = 3283
  Hello from thread! my pid = 3487, tid = 3488, parent pid = 3283
  thread
  write
  thread: Operation not permitted
  </code></pre>
  
  <p>That tells us the thread write failed by -EPERM.</p>
  
  <p>Looking at the kernel file fs/proc/base.c and function proc_loginuid_write() we see at the beginning check:</p>
  
  <pre class="lang-c prettyprint-override"><code>static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                     size_t count, loff_t *ppos)
  {
      struct inode * inode = file_inode(file);
      uid_t loginuid;
      kuid_t kloginuid;
      int rv;
  
      /* this is the probably buggy check */
      rcu_read_lock();
      if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
          rcu_read_unlock();
          return -EPERM;
      }
      rcu_read_unlock();
  </code></pre>
  
  <p>So, looking at the code above we see that only for exact PID (checked by me with printks) we pass through.Thread doesn't satisfy the condition, because compared pids differs.</p>
  
  <p>So my question is: is this a bug ? Why to not allow thread's of particular process to change the loginuid? I encountered this in login application that spawned another thread for PAM login.</p>