TODO: A figure would be nice
In the BSD model, things are relatively straighforward. The setuid call takes one argument, and sets the real and effective uid to the given value.
By calling setuid(user_uid), the application can set both uid variables to the user uid. There is no way you can get back the privileged uid: with all uid variables set to the user uid, the process looks just like any other unprivileged process to the operating system kernel! So, unless the caller is the root user, any attempt to regain the privileged uid will be denied. In other words, this call permanently drops all privilege the application was granted by being installed with the set-user bit on.
Dropping privilege temporarily, i.e. changing the effective uid in a way that allows us to restore the previous state, is more difficult. There is a seteuid call that lets you change the effective uid; but at least in the case of set-user applications, this doesn't do what we want: by changing the effective uid to the one of the caller, we also end up with both effective and real uid set to the user uid, and no way to recover the privileged uid later.
There is however a third function called setreuid that lets you assign different values to the real and effective uid simultaneously. This is commonly called as setreuid(priv_uid, user_uid), which swaps the real and effective uid, so that the effective uid becomes the user uid, and the privileged uid is assigned to the real uid. Thus, any subsequent access checks are done with the new effective uid, which happens to be the uid of invoking user.
The beauty of this is that you can revert to the original state just by swapping uids again: setreuid(user_uid, priv_uid). Now the real uid variable holds the user uid again, and the effetive uid variable holds the privileged uid.
TODO: Difference between setuid programs and setuid system call?