in reply to Not understanding the code to drop privileges in perlsec

I agree with your analysis. The example given in perlsec is at best confusing. Honestly, I am not convinced it would pass a code review.

So, the code could work correctly and maybe each line is there for a purpose but it is very far from clear as written. It would be useful if others more familiar with the internals of all this could chip in and correct any of my suppositions here which might well be wrong as it is not my area of expertise.


🦛

Replies are listed 'Best First'.
Re^2: Not understanding the code to drop privileges in perlsec
by ikegami (Patriarch) on Feb 22, 2024 at 14:46 UTC

    I think your claim that it's a no-op is wrong.

    setuid() sets the effective user ID of the calling process. If the calling process is privileged (more precisely: if the process has the CAP_SETUID capability in its user namespace), the real UID and saved set-user-ID are also set.

    Under Linux, setuid() is implemented like the POSIX version with the _POSIX_SAVED_IDS feature. This allows a set-user-ID (other than root) program to drop all of its user privileges, do some un-privileged work, and then reengage the original effective user ID in a secure manner.

    It was suggested to the OP that they to trace the ids throughout the program when they posted the exact same question on StackOverflow. You should also adopt that recommendation!

      Thank you very much!

      On SO I have been told to set the script suid or sgid, which leads to nowhere because the interpreter does not care about those flags. I admit that I should have written a further comment that describes my solution to that problem and my new findings.

      However, in the first post here, I have described that I have amended the code with print statements and what happened then. From the post:

      "My tests seem to confirm that point of view. I have made a test environment in Linux (Debian bullseye) where I can run the script setsuid-root or setsuid-other_user, and have inserted print statements after every assignment. Regardless of what my real user id was, and regardless of the setsuid of the script, I never encountered a situation where $UID and $orig_UID were different immediately before executing line 7."

      And that's still my problem. After I had learned how to execute a script suid / sgid, I have conducted a lot of tests, but could not construct a situation where lines 7 and 8 actually would effect anything.

      I've got an additional question:

      Before posting, I had read the man pages of setuid() and its colleagues, and I guess I have understood them.

      However, I couldn't find a statement anywhere about what function Perl actually uses to perform assignments to $(E)[U|G]ID. perlvar only tells us that it uses a syscall, which made me believe that it is not one of the setuid() functions. The latter are not syscalls; they are from the C library (please correct me if I am wrong).

      But from your post I got the impression that Perl uses indeed the setuid() functions to perform assignments to the user and group variables. Did I understand this correctly?

Re^2: Not understanding the code to drop privileges in perlsec
by Nocturnus (Scribe) on Feb 22, 2024 at 19:26 UTC

    Thank you very much for your support!

    I am sure that your analysis regarding the comparison operators is correct. perlvar states that the group ids actually are strings (and thus should be compared using eq in Perl) and that user ids are numbers (and thus should be compared using ==).

    That they use an array one time and two separate variables the other time does not worry me too much. Of course I agree with you that there should be much more comments.

    The main problem is that dropping privileges is seemingly is a no-op, but I am quite sure that actually it isn't one. For the life of me, I don't understand the sense, and even worse, I have conducted a lot of tests with setgid / setuid flags, but couldn't construct a situation where the code under # Drop privileges was not a no-op.