当前位置:   article > 正文

多线程中的uid_线程uid

线程uid

在内核级别,用户 ID 和 组 ID 是每个线程的属性,然而,POSIX 标准要求同一个进程里的多个线程共享相同的认证信息(credentials)。
在 NPTL (Native POSIX Threads Library)线程实现中,通过对某些系统调用进行封装,从而支持了这一要求。这里的封装函数包括 setuid(),它通过信号技术确保了当其中某个线程改变认证信息后,其他所有线程也会跟着改变对应的认证信息。

在 glibc 中,setuid() 最终会调用 __nptl_setxid(),其定义在 nptl/allocatestack.c 中:

  1. int
  2. attribute_hidden
  3. __nptl_setxid (struct xid_command *cmdp)
  4. {
  5. ...
  6. list_for_each (runp, &__stack_user)
  7. {
  8. struct pthread *t = list_entry (runp, struct pthread, list);
  9. if (t == self)
  10. continue;
  11. signalled += setxid_signal_thread (cmdp, t);
  12. }
  13. ...
  14. }

上述函数调用了 setxid_signal_thread() 来给其他线程发信号,其定义在 nptl/allocatestack.c 中:

  1. static int
  2. setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
  3. {
  4. if ((t->cancelhandling & SETXID_BITMASK) == 0)
  5. return 0;
  6. int val;
  7. pid_t pid = __getpid ();
  8. INTERNAL_SYSCALL_DECL (err);
  9. val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, t->tid, SIGSETXID);
  10. /* If this failed, it must have had not started yet or else exited. */
  11. if (!INTERNAL_SYSCALL_ERROR_P (val, err))
  12. {
  13. atomic_increment (&cmdp->cntr);
  14. return 1;
  15. }
  16. else
  17. return 0;
  18. }

可以看到上述函数通过 tgkill() 系统调用给当前进程的 t->tid 线程发了一个 SIGSETXID 信号。

SIGSETXID 信号的处理函数是 sighandler_setxid(),其定义在 ./nptl/nptl-init.c 中:

  1. /* We use the SIGSETXID signal in the setuid, setgid, etc. implementations to
  2. tell each thread to call the respective setxid syscall on itself. This is
  3. the handler. */
  4. static void
  5. sighandler_setxid (int sig, siginfo_t *si, void *ctx)
  6. {
  7. int result;
  8. ...
  9. /* Safety check. It would be possible to call this function for
  10. other signals and send a signal from another process. This is not
  11. correct and might even be a security problem. Try to catch as
  12. many incorrect invocations as possible. */
  13. if (sig != SIGSETXID
  14. || si->si_pid != __getpid ()
  15. || si->si_code != SI_TKILL)
  16. return;
  17. INTERNAL_SYSCALL_DECL (err);
  18. result = INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
  19. __xidcmd->id[1], __xidcmd->id[2]);
  20. ...
  21. }

上述函数通过 INTERNAL_SYSCALL_NCS() 宏进行了系统调用,其中 __xidcmd->syscall_no 是 setuid() 的系统调用号。
不过,如果在线程中 通过 syscall() 来旁路系统调用后,上述 POSIX 要求就不满足了,例如:

  1. //setuid(1001);
  2. syscall(SYS_setuid, 1001);


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/873293
推荐阅读
相关标签
  

闽ICP备14008679号