How to Detect Sudo Privileges in a Program (Unix/Linux/MacOS Examples)


1 views

When writing CLI tools or system utilities, you might need to modify program behavior based on whether it's executed with sudo privileges. A classic example is MacPorts' output - when suggesting follow-up commands, it should include 'sudo' if the original command used it.

The most reliable method checks the SUDO_UID environment variable:


#include <stdlib.h>
#include <stdio.h>

int is_sudo() {
    return getenv("SUDO_UID") != NULL;
}

int main() {
    if (is_sudo()) {
        printf("Running with sudo privileges\n");
    } else {
        printf("Running as normal user\n");
    }
    return 0;
}

For shell scripts, you can use:


#!/bin/bash

if [ -n "$SUDO_USER" ]; then
    PREFIX="sudo "
else
    PREFIX=""
fi

echo "Run this command: ${PREFIX}port upgrade outdated"

Another approach compares user IDs:


#include <unistd.h>

int is_sudo() {
    return geteuid() == 0 && getuid() != 0;
}

This works because sudo changes the effective UID to root (0) while maintaining the original UID.

Be aware of these scenarios:

  • Direct root login (both UIDs are 0)
  • Programs with setuid bit set
  • Different sudo configurations that might not set environment variables

Here's how MacPorts could implement this:


#!/usr/bin/env tclsh

if {[info exists env(SUDO_USER)]} {
    set prefix "sudo "
} else {
    set prefix ""
}

puts "Run: ${prefix}port upgrade outdated"

For Python implementation:


import os

def is_sudo():
    return 'SUDO_USER' in os.environ or os.geteuid() == 0

if is_sudo():
    print("Command to run: sudo port upgrade outdated")
else:
    print("Command to run: port upgrade outdated")

When implementing sudo detection:

  • Never rely solely on environment variables
  • Always verify using multiple methods
  • Consider using capabilities instead of full root when possible

In Unix-like systems, processes executed with sudo inherit different environment characteristics than regular processes. When building CLI tools or system utilities, we often need to adapt behavior based on execution context.

Here are several robust approaches to detect sudo context programmatically:

1. Checking Environment Variables

def is_sudo():
    return 'SUDO_USER' in os.environ or os.geteuid() == 0

# Example usage:
if is_sudo():
    print("Running with elevated privileges")

2. Examining Process UID/GID

# C implementation
#include 

int is_sudo_context() {
    return (geteuid() == 0) && (getuid() != 0);
}

3. Checking Parent Process Information

# Bash implementation
if [[ $(ps -o comm= -p $PPID) =~ "sudo" ]]; then
    echo "Running under sudo"
fi

MacOS handles sudo slightly differently than Linux:

# MacOS-specific check
if [[ $(sysctl -n kern.superuser) -eq 1 ]]; then
    echo "Running as superuser"
fi

Extending the original MacPorts use case:

#!/bin/bash

is_sudo() {
    [ "$(id -u)" -eq 0 ] && [ -n "$SUDO_USER" ]
}

if is_sudo; then
    echo "sudo port upgrade outdated"
else
    echo "port upgrade outdated"
fi

Always validate:

  • Check both effective and real UIDs
  • Verify environment variables aren't spoofed
  • Use multiple detection methods for reliability

For Python applications:

import os, pwd

def is_sudo():
    try:
        return os.geteuid() == 0 and pwd.getpwuid(os.getuid()).pw_name != 'root'
    except:
        return False