Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Privilege escalation from Python like from systemd

+3
−0

When you try to do a privileged systemd operation without the privilege, you get an escalation prompt:

$ systemctl stop docker
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to stop 'docker.service'.
Authenticating as: [MY USER NAME]
Password:

I've seen some other programs do this as well (don't recall which), so it seems like not a systemd-specific thing.

I want to write a Python program that occasionally does privileged things. Most of the time it does not do privileged things, so I don't want to tell users to run my program with sudo. Instead I want to ask for the escalation as needed, like systemctl does.

Is it possible in Python?

History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+3
−0

Generallly (assuming no exploit is found) it's not possible to escalate the privileges of an already running process, except via code that itself has kernel level access (running in ring 0 - this is presumably how systemd is able to do it). But from your own Python program running in user-land (as a script being interpreted by the python executable), you can only do this by starting a new process.

Fortunately, it's easy enough in Python to start new processes using the subprocess standard library. We can also use os.geteuid to determine Python's "effective user id" - i.e., 0 when the script is running as root, and nonzero otherwise. This allows us to create a script that spawns itself via sudo when not already running as root, and proceeds normally when it is. Something like:

#!/usr/bin/env python
# (or whatever other shebang is appropriate)

import os, sys, subprocess

# actual code to run as root, when this file is run as a script
def main(): 
    ...

if __name__ == '__main__':
    if os.geteuid() == 0:
        sys.exit(main())
    else:
        # assuming our script has chmod+x
        sys.exit(subprocess.call(['sudo', *sys.argv]))

Of course, the sudoers file can also be modified to allow running the script as root without a password. But for the use case of a script that only occasionally expects escalated privileges, it might be better to ask each time (the user likely wants a warning!) - and to defer the subprocess logic until it's actually necessary. This is tricky to set up; it may be easier to put the root-requiring logic in a separate script file (and perhaps use the standard output and/or error code of the root process to communicate back to the main program).


References:

History
Why does this post require moderator attention?
You might want to add some details to your flag.

1 comment thread

Is this how systemd does it? (2 comments)

Sign up to answer this question »