Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Re: Not understanding the code to drop privileges in perlsec

by hippo (Bishop)
on Feb 22, 2024 at 10:35 UTC ( [id://11157837]=note: print w/replies, xml ) Need Help??

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.

  • If @temp, $orig_uid and $orig_gid are just there to hold the starting values, why is one an array and the other a set of 2 scalars? I think this is because the $GID contains not only the primary group but also all the secondary groups of the real user too and because it is a dualvar and therefore would unroll when the array were evaluated. I'd much prefer to have had that commented.
  • On the last line, there a numeric equality test between the UIDs and a string equality test between the GIDs. Again this is probably because of the potential non-numeric nature of $GID. But this is also uncommented in the code so we can only assume.
  • Like you, I don't see why the values of $UID and $GID are explicitly reset. Given the logic, this appears to be a no-op. Unless it is there to get around the "saved UID" - but again if that's the case it really should have a comment to say so.
  • The original code in perlsec uses a bareword filehandle which is generally discouraged nowadays.

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 (Beadle) 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.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11157837]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2024-04-22 01:06 GMT
Find Nodes?
    Voting Booth?

    No recent polls found