• R
    new attempt at making set*id() safe and robust · acb04806
    Rich Felker 提交于
    changing credentials in a multi-threaded program is extremely
    difficult on linux because it requires synchronizing the change
    between all threads, which have their own thread-local credentials on
    the kernel side. this is further complicated by the fact that changing
    the real uid can fail due to exceeding RLIMIT_NPROC, making it
    possible that the syscall will succeed in some threads but fail in
    others.
    
    the old __rsyscall approach being replaced was robust in that it would
    report failure if any one thread failed, but in this case, the program
    would be left in an inconsistent state where individual threads might
    have different uid. (this was not as bad as glibc, which would
    sometimes even fail to report the failure entirely!)
    
    the new approach being committed refuses to change real user id when
    it cannot temporarily set the rlimit to infinity. this is completely
    POSIX conformant since POSIX does not require an implementation to
    allow real-user-id changes for non-privileged processes whatsoever.
    still, setting the real uid can fail due to memory allocation in the
    kernel, but this can only happen if there is not already a cached
    object for the target user. thus, we forcibly serialize the syscalls
    attempts, and fail the entire operation on the first failure. this
    *should* lead to an all-or-nothing success/failure result, but it's
    still fragile and highly dependent on kernel developers not breaking
    things worse than they're already broken.
    
    ideally linux will eventually add a CLONE_USERCRED flag that would
    give POSIX conformant credential changes without any hacks from
    userspace, and all of this code would become redundant and could be
    removed ~10 years down the line when everyone has abandoned the old
    broken kernels. i'm not holding my breath...
    acb04806
setegid.c 135 字节