Hi, I was a bit bored of auditing kernel code to find which rights add to be granted to filedescriptors lookup in various places, so i tried something new.
Currently, a process which wants to change its real uid/gid have to be privileges. That's why su is setuid for instance. And shared object are used to change the authentification method, the session managment etc. The openPAM library fills this goal on dragonFly. I decided to try solving this differently. I've added a new type of descriptors referencing an ucred structure [1]. The set of ucred structures owned by a process is the set of credentials the process has the right to setuid/setgid/setgroups. Hence, a process can grant crendential to another by passing a filedescriptor trough a unix domain socket. A cred structure descriptor is created by a new syscall, opencred(), which returns a descriptor to the credentials of the calling process. Read operation returns the xucred structure associated to the ucred structure of the filedescriptor. Write operation modify the ucred structure using the passed xucred structure if the process is allowed to do so. The write call implements the same policy as setuid/setgid/setgroups. The syscalls setuidfromfd/setgidfromfd/setgroupsfromfd change the credentials (not only effectives ids, but real ids too) using the credentials pointed to in the file descriptor. As for userspace, i'm experimenting with su. The goal is to have su connect to a unix domain socket, make a request, and receive a filedescriptor it can use to setuid. I think a pam_proxy lib could handle requests to a pam daemon. One issue of this design is the use of pam polices. Policies are per service authentication process, which are configured in /etc/pam.d/. In pam, the calling process tells himself the policy it wants to the pam library. In this design, it's ok since the calling process runs as uid=0, and is considered trusted. In the daemon design, any process could connect to the unix domain socket and should not be trusted. I think it can be worked around by using a wheel like specific group and evry process allowed to make request to the pam daemon could be setgid to this group, the sockets would then be owned by root and this group. I'm not even sure this model is working, i've only done some experiment with a modified su yet, and it's not clear if this work is worth the features it brings. Because the only point of this stuff is to drop uid=0 from some processes like su/login, etc and put them in a daemon which can be easily converted to capsicum sandboxing. The other side effect is that theses tools can use pam policy whitout shared object and can be statically linked. Thanks for reading, Joris [1] https://github.com/jorisgio/DragonFlyBSD/commit/c1c2b7c26c45c260aee50da0662ae0812bf4bcb4
