1

I am not a newb. I am a professional imploring to other professionals over their discoveries of a quick solution to a common problem, and I know what chmod -R is.
This is in response to the -1 rating instantly given to my question, for those who might shrug off the seriousness of my inquiry, or dismiss its validity.


Experimenting with sshfs between my desktop and a remote server running Kali linux as root (Default for Kali). Managed to bugger up all file & folder permissions/ownership on the system. I have managed to repair some, with a simple chmod -R 0755 where appropriate, but have noticed many are still not fixed.

Wondering if there is a bash script or other script or program that could help to restore the correct owner & permissions?

I have found a similar script, but it is primarily aimed at repairing home directories.

Script, Below:

#!/bin/bash
read -r -p "Correct file and folder permissions? [y/N] " chse
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
  echo "Processing ..."
  find -H $(pwd) -type d -exec chmod 0755 {} \;
  # set dirs to 755
  find -H $(pwd) -type f \( -iname '*.so.*' -o -iname '*.so' \) -exec chmod 0644 {} \;
  # libs
  IFS=$'\n'
  for value in $(find -H $(pwd) -type f ! \( -iname '*.so.*' -o -iname '*.so' -o -iname '*.bak' \) -printf '%p\n'); do
    tstbin=$(readelf -l "$value" 2>/dev/null | grep -Pio 'executable|shared')
    if [ -z "$tstbin" ]; then
      tstbat=$(cat "$value" | head -c2 | grep -io '#!')
      if [ -n "$tstbat" ]; then
        perm=$(stat -c '%a' "$value")
        if [ "$perm" != "755" ]; then
          chmod 755 $value
          echo "Set script  755 $value"
          # set batch to 755
        fi
      else
        perm=$(stat -c '%a' "$value")
        if [ "$perm" != "644" ]; then
          chmod 644 $value
          echo "Set regular 644 $value"
          # set regular files to 644
        fi
      fi
      # above aren't elf binary
    else
      perm=$(stat -c '%a' "$value")
      if [ "$perm" != "755" ]; then
        chmod 755 $value
        echo "Set binary  755 $value"
        # set elf binaries to 755
      fi
    fi
  done
  unset IFS
  # process linux permissions for files and folders
else
  echo "Aborted."
fi

Anyone found anything more substantial that can fix permissions and ownership for a file system?


--> Update: <--

Not discovering a desirable solution, I have taken to modifying the above script and making it facilitate my desired resolution:

permafix.sh - Gist on github

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'


# ====================================================================
# --> Documentation <--
# ---------------------
#
# 0755 21 root root  .
# 0755 21 root root  ..
# 0755  2 root root  bin
# 0755  4 root root  boot
# 0755 15 root root  dev
# 0755 53 root root  etc
# 0755  4 root root  home
# 0755  7 root root  lib
# 0700  2 root root  lost+found
# 0755  6 root root  media
# 0755  2 root root  mnt
# 0755  4 root root  opt
# dr-xr-xr-x 87 root root  proc # Not touching this.
# 0744  8 root root  root
# 0755  2 root root  sbin
# 0755  3 root root  share
# 0755  4 root root  srv
# 0755 12 root root  sys
# 1777  7 root root  tmp
# 0755 12 root root  usr
# 0755 13 root root  var
#
# ========================================================================

read -r -p "Correct file and folder permissions? [y/N] " chse
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
    echo "Processing ..."
    #################
    # Special Cases #
    #################
    
    SDIR=("/lost+found" "/root" "/tmp")
    for sd in ${SDIR[-1]}; do
        perm=$(stat -c '%a' "$sd")
        user=$(stat -c '%U' "$sd")
        group=$(stat -c '%G' "$sd")
        if [ $sd = "/tmp" ]; then
            if [ "$perm" != 1777 ]; then
                chmod 1777 $sd
                echo "Set directory to 177 $sd"
            fi
        elif [ $sd = "/lost+found" ]; then
            if [ "$perm" != 0700 ]; then
                chmod 0700 $sd
                echo "Set directory to 0700 $sd"
            fi
        elif [ $sd = "/root" ]; then
            if [ "$perm" != 744 ];then
                chmod 744 $sd
                echo "Set directory to 744 $sd"
            fi
        else
            echo "Abort!"
        fi
        # Do change in ownership
        if [ "$user" != root ]; then
            chown root $sd
            echo "Set user to root $sd"
        fi
        if [ "$group" != root ]; then
            chgrp root $sd
            echo "Set group to root $sd"
        fi
    done
    ###############
    # Directories #
    ###############
    DIR=("/bin" "/boot" "/dev" "/etc" "/home" "/lib" "/media" "/mnt" "/opt" "/sbin" "/share" "/srv" "/sys" "/usr" "/var")
    for pd in ${DIR[-1]}; do
        perm=$(stat -c '%a' "$pd")
        user=$(stat -c '%U' "$pd")
        group=$(stat -c '%G' "$pd")
        if [ "$perm" != 755 ]; then
            chmod 755 $pd
            echo "Set directory to 755 $pd"
        fi
        if [ "$user" != root ]; then
            chown root $pd
            echo "Set user to root $pd"
        fi
        if [ "$group" != root ]; then
            chgrp root $pd
            echo "Set group to root $pd"
        fi

        ############################
        # Subdirectories and files #
        ############################
        # chmod directories to 755
        find -H $pd -type d -exec chmod 0755 {} \;
        # Check library files
        find -H $pd -type f \( -iname '*.so.*' -o -iname '*.so' \) -exec chmod 0644 {} \;
    done
        
    #------#
    # libs #
    #------#
    # Assign Variables
    LIBFILES=$(find -H "$(pwd)" -type f ! \( -iname '*.so.*' -o -iname '*.so' -o -iname '*.bak' \) -printf '%p\n')
    # Now do the hustle
    for PLF in $LIBFILES; do
        tstbin=$(readelf -l "$PLF" 2>/dev/null | grep -Pio 'executable|shared')
        if [ -z "$tstbin" ]; then
            tstbat=$(cat "$PLF" | head -c2 | grep -io '#!')
            if [ -n "$tstbat" ]; then
                perm=$(stat -c '%a' "$PLF")
                if [ "$perm" != "755" ]; then
                    chmod 755 $PLF
                    echo "Set script 755 $PLF"
                    # set batch to 755
                fi
            else
                perm=$(stat -c '%a' "$PLF")
                if [ "$perm" != "644" ]; then
                    chmod 644 $PLF
                    echo "Set regular 644 $PLF"
                    # set regular files to 644
                fi
            fi
            # above aren't elf binary
        else
            perm=$(stat -c '%a' "$PLF")
            if [ "$perm" != "755" ]; then
                chmod 755 $PLF
                echo "Set binary 755 $PLF"
                # set elf binaries to 755
            fi
        fi
    done
    unset IFS
    # process linux permissions for files and folders
else
    # When shit goes pear shaped
    echo "Aborted."
fi

There are other ways of doing this, and also better ways to write the code. But, it works for now.

--->Yet another update<---

I fixed a careless error in the script correctly relocation the position of several variables that were formerly inaccessible due to script structure.

Please use this link to acquire the most recent version of this script.

Paul
  • 2,755
  • 6
  • 24
  • 35
Anoduck
  • 23
  • 4
  • 1
    Copy off any unique data and re-install the system if you don't have backups. – Bob May 31 '21 at 09:21
  • 1
    Nope, not doing that. The system is too far developed. A simple script such as `sudo chmod 755 chmod -R 755 /bin /boot /dev /etc/ /home /lib /lib64 /media /mnt /opt /run /sbin /srv /usr /var && sudo chmod -R 777 /initrd.img /vmlinuz && sudo chmod -R 1777 /tmp && sudo chmod -R 555 /proc && sudo chmod -R 555 /sys && sudo chmod -R 744 /root`, would be better. Not the solution I am asking for, but still better. – Anoduck May 31 '21 at 22:09
  • 1
    You are damn right, I upvoted to bring in interest. I've seen servers been destroyed by `chmod -R`. It would be nice for each distro to have such a RevertTodefaultPermissions.sh; MacOSX had something similar in the past, don't know if it still exists. A friendly advice (but not a cure), use ACLs wherever possible. They can be removed and start over without impacting the system. They helped me mitigate the problem you describe. – Krackout Jun 01 '21 at 08:35
  • 2
    The problem is that no script or solution will be completely conclusive. You performed a "destructive action" that can't be reverted without a backup. Partial fixes include querying the package management system and using the default permissions stored from installed packages and forcing the correct default permissions on the main directory tree but that won't restore the rest of your permissions, which were either changed from their default, set by different ways such manually by admins and owners, by scripts/tools, post-install scripts in packages, systemd unit files, UMASK or inherited. – Bob Jun 01 '21 at 09:03

1 Answers1

2

A simple script to fix arbitrary broken permissions on a general purpose system does not exist. You, your users, and the software you use can set whatever permissions you like to meet your requirements. Overly broad permission changes are a loss of that metadata.

First, determine how permissions were broken, for example chmod chown setfacl or chcon commands. If ownership is wrong, you'll need to fix that, such as giving a file in a home directory back to its owner. Beware there are subtle things here, like chown will clear setuid flags. For example, /usr/bin/ping might not work, if it loses setuid root. Do you know which other of your programs need setuid? More complex ACLs or selinux labels are not in your solution, but could complicate things if they also are wrong.

You can attempt to fix permissions to what they were on package install. On Debian based systems, you might feed dpkg --contents output into a chmod chown script. Downloading .debs for all installed packages for dpkg to query is an exercise for the reader. This does nothing for user data, or software not installed via deb.

Identify sensitive information previously protected by file permissions. Including but not limited to ssh and gpg private keys. Consider changing these credentials out of an abundance of caution.

Regarding the rest of user data, hard to say. Users generally, but not always, own files in their home directories. Multiple user shared directories could get tricky, as the correct owner and mode might no longer be known.

Backups should restore with correct permissions, if they existed.

Tedious work to fix correctly. Document by writing automation scripting that fixes permissions on your data directories. Hopefully backups will fix things next time, but might as well have policy on what the permissions should be.

John Mahowald
  • 30,009
  • 1
  • 17
  • 32
  • This is in theory what resolved the issue that I was experiencing, except I went about accomplishing it differently. I discovered this wiki entry searching for a resolution: https://wiki.debian.org/Permissions/ResetPackagePermissions Apparently, a simple `sudo apt install --reinstall ~i` did the trick. Since then, I have only experienced one issue that was corrected with `chmod -R 644` quite easily. – Anoduck Jun 09 '21 at 21:00