LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Reset default permissions . . . (https://www.linuxquestions.org/questions/linux-newbie-8/reset-default-permissions-4175664501/)

sankeny 11-18-2019 04:57 PM

Reset default permissions . . .
 
I'm running "Ubuntu 18.04" with every update/upgrade patch installed.

I am accessing it via "ssh" from both inside and outside the network.

I can access it directly from a console monitor.

I issued the following command "sudo chmod -R 777 /" on a separately mounted drive, and of course, it began to reset all the permissions on my system "/" (dumb, dumb, dumb)

Now, "sudo" does not work, and I've disconnected via "ssh" and cannot access it remotely.

How can I reset default permissions on "/" from the console?

flshope 11-18-2019 08:30 PM

I don't think there is an easy answer to your problem. The following link

https://stackoverflow.com/questions/...debian-squeeze

contains the advice "... your options are (a) compare with a working Debian system and fix permissions manually or (b) backup and reinstallation. I'd recommend (b), which will probably be less time-consuming, and with (a) it is difficult to be sure you have got everything right."

This is a pretty old post. Perhaps there is a better solution by now.

For the future, let me say that I learned the hard way to always use the form

Code:

chmod --preserve-root ...
which causes chmod to "fail to operate recursively on '/'" (from man page).

sankeny 11-19-2019 02:06 AM

thanks . . .

scasey 11-19-2019 08:58 AM

The ~/.ssh directory must be readable only by the user, so
Code:

chmod 700 ~/.ssh
should restore your ability to ssh to the server. You'll need to do that for each user, of course.
On my server, inside ~/.ssh
Code:

-rw-r--r--.  1 root root 1198 May 26 17:18 authorized_keys
-rw-r--r--.  1 root root  425 Sep 20  2017 known_hosts

Good luck!

sankeny 11-19-2019 09:24 AM

that's a good start . . .

I'm thinking of my options. I have a man onsite who can enter a command such as that, then I can work remotely to either "fix" what I need or reinstall.

Fortunately, data storage is held separately (the disc from which I was working), so I can backup for safety but possibly retain the file structure. That way, I can perform a fresh installation of the OS disc only. That would likely be quickest as has been stated. It's three discs, one for the OS and two set in a hardware RAID to create a storage disc.

Firerat 11-19-2019 12:19 PM

many programs will refuse to run if they see non-std file permissions


what we need is to know the correct permissions and then chmod back,
yeah, I know obvious ;)

I note you are posting from Ubuntu, that will do ;)

on your working ( and one hopes very similar ) Ubuntu
as root
Code:

#!/bin/bash
Find () {
  find / -xdev -printf "%M %u/%g %9s %AY-%Am-%Ad %AH:%AM .%p\n"
}
bzip2 > MANIFEST.bz2 < <(Find)


#

that should be enough

another option ( which is slower and less likely to work well )

does not need root
does need mountpoint ( first arg. )

Code:

#!/bin/bash

MNTPOINT=${1:-/}

Extract () {
#
for deb in ${MNTPOINT%/}/var/cache/apt/archives/*deb
do
  echo "Extracting Manifest from ${deb##*/}" 1>&2
  tar -Jvtf - < <(unar "${deb}" *data.tar.xz -o -)
done
}
bzip2 > MANIFEST.bz2 < <(Extract)


#

unar is not usually installed by default


now,
mount the root partition of the ubuntu that needs to be fixed.


the following script takes two arguments, the first the MANIFEST.bz2
and the second is the mountpoint of the root partition you need to fix

it will only print the commands, not execute them
output to a file

Code:

sudo ./RestorePermisions.sh ./MANIFEST.bz2 /mnt/foobared/ | tee chmodcommands.txt
edit: added sudo
need sudo as it uses find to do initial sweep
it won't write anything ( unless you remove the XARGS echo )

review that file ( sorry it will have very long lines in it )


I never got round to writing a fancy menu for it


it dosn't try to fix home,
we can do that later

Code:

#!/bin/bash
Flags=( "${@}" ) # grab hold of flags early

################################################################################
# Default configuration
################################################################################
  manifest_missing="return 10"
  manifest_invalid="return 20"
      UnknownError="return 99"
  CompTypeUnknown="return 30"
        #MODE=Textual_to_Symbolic
        MODE=Textual_to_Octal
      Manifest="$1"
      MNTPOINT="$2"
        XARGS="xargs -r echo"
      # remove echo if you want to action immediately
################################################################################
Help () {
#TODO write this
  echo "Use the Force, read the src."
}
ChkManifest () {
  [[ -z "${Manifest}" ]] && $manifest_missing
  [[ -e "${Manifest}" ]] || $manifest_missing
  fileis=( $( file -i "${Manifest}" ) )
  case ${fileis[1]:0:(-1)} in
    text/plain)
      GREP="$( type -p grep )"
      ;;
    application/gzip)
      GREP="$( type -p zgrep )"
      ;;
    application/x-bzip2)
      GREP="$( type -p bzgrep )"
      ;;
    application/x-xz)
      GREP="$( type -p xzgrep )"
      ;;
    application/x-lzma)
      GREP="$( type -p lzgrep )"
      ;;
    application/x-zstd)
      GREP="$( type -p zstdgrep )"
      ;;
    *)
      $CompTypeUnknown
      ;;
  esac
  chk=( $($GREP -m1 -E -- "^[bcd-][rwx-]{9}.*[a-z]/?$" ${Manifest}) )
  [[ ${#chk[@]} == 6 ]] \
    && [[ ${chk[0]} =~ ^[bcdrwxsStT-]{10}$ ]] \
    && [[ ${chk[1]} =~ ^[a-z]*/[a-z]*$ ]] \
    && [[ ${chk[2]} =~ ^[0-9]+,?[0-9]*$ ]] \
    && [[ ${chk[3]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
    && [[ ${chk[4]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
    && [[ ${chk[5]} =~ ^[.]/[[:print:]]+$ ]] \
    || $manifest_invalid
return
}
ChkDistro () {
  DISTRO=$(grep -E ^ID=[[:print:]]+ ${MNTPOINT%/}/etc/os-release 2>/dev/null)
}
################################################################################
# GetIndex #
# unlikely with slackware's ( tar vtf package.txz )>> MANIFEST
# but if the manifest were in a different order to what we expect
# this could be used to find the array indices we need
# only PERMS, OWNER_GRP and FILEPATH are used in this script
# they are META[0] , META[1] and META[5]
GetIndex () {
################################################################################
for i in ${!chk[@]}
do
  [[ ${chk[i]} =~ ^[bcdrwxsStT-]{10}$ ]] \
    && PERMS=$i || continue
  [[ ${chk[i]} =~ ^[a-z]+/[a-z]+$ ]] \
    && OWN_GRP=$i || continue
  #[[ ${chk[i]} =~ ^[0-9]+,?[0-9]*$ ]] \
  # && SIZE=$i || continue
  #[[ ${chk[i]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
  # && FILEDATE=$i || continue
  #[[ ${chk[i]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
  # && FILETIME=$i || continue
  [[ ${chk[i]} =~ ^[.]/[[:print:]]+$ ]] \
    && FILE_PATH=$i || continue
done
}

ReadManifest () {
  sort -u -d -k6 <($GREP -E -- "$1" "${Manifest}" )
return 0
}
Textual_to_Octal () {
################################################################################
  S=0 # unset special bits by default
  # bash arrays start at 0, so 3 is 4th in string
  [[ ${1:3:1}  =~ [sS] ]] && S=$(( ${S} + 4 )) ##\
  [[ ${1:6:1}  =~ [sS] ]] && S=$(( ${S} + 2 ))  # set as per manifest
  [[ ${1:(-1)} =~ [tT] ]] && S=$(( ${S} + 1 )) ##/

  # only need to declare once
  [[ $p ]] || declare -A \
    p=(
      [r]="4" [w]="2" [x]="1" [-]="0"
      [s]="1" [S]="0" [t]="1" [T]="0"
      )
  # S ( s{u,g}id no exec. ) is unlikly to exist in manifest, but it is valid
  printf "0%d%d%d%d" \
    ${S} \
    $(( ${p[${1:1:1}]} + ${p[${1:2:1}]} + ${p[${1:3:1}]} )) \
    $(( ${p[${1:4:1}]} + ${p[${1:5:1}]} + ${p[${1:6:1}]} )) \
    $(( ${p[${1:7:1}]} + ${p[${1:8:1}]} + ${p[${1:9:1}]} ))

# ${1} is what we fed into the function ( drwxr-xr-x )
# p is our Associative (-A) array, bit values are indexed with textual char.
# :1:1} == r ( the second element of the string d(r)wxr-xr-x )
# special  User          Group        Other
# no s / S  ${p[r]} == 4  ${p[r]} == 4  ${p[r]} == 4
# no t / T  ${p[w]} == 2  ${p[-]} == 0  ${p[-]} == 0
#          ${p[x]} == 1  ${p[x]} == 1  ${p[x]} == 1
# sum == 0    sum  == 7    sum  == 5    sum  == 5  >>  0755

################################################################################
}
Textual_to_Symbolic () {
################################################################################

    SUID=",u-s"    ##\
    SGID=",g-s"      # unset special bits by default
    STICKY=",o-t"  ##/

  [[ ${1:3:1}  =~ [sS] ]] &&  SUID="s"  ##\
  [[ ${1:6:1}  =~ [sS] ]] &&  SGID="s"    # set as per manifest
  [[ ${1:(-1)} =~ [tT] ]] && STICKY="t"  ##/

  perms="${1//[st]/x}"      # s and t imply exec. bit
  perms="${perms//[ST-]/ }" # S and T imply no exec. bit
  perms="\
      u=${perms:1:3}${SUID},  \
      g=${perms:4:3}${SGID},  \
      o=${perms:7:3}${STICKY} \
      "
  perms="${perms//[[:space:]]}" # remove white space.

  printf "%s" "${perms}"

}
Hammer () {
################################################################################
# chmod pretty much everything
# Why?
# it will fix anything "extra" that is not in the manifest
# no real sense in leaving rogue 777 dirs/files hanging around

  # dirs 00755
  $XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
      -type d \
    ! -regex "${MNTPOINT%/}\(/lost.found\|/home\)/" \
    ! -perm 0755
  )

  # files in a /{s}bin/ 00755
  $XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
      -type f \
      -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
    ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
    ! -perm 0755
  )

  # files not in a /{s}bin/ 00644
  $XARGS chmod -v 00644 < <( find ${MNTPOINT%/}/ -xdev \
      -type f \
    ! -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
    ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
    ! -perm 0644
  )

# Yes, many more locations should have exec. scripts
# These will be fixed when manifest is processed
}
################################################################################
LVM () {
#TODO add option for this ( or look to see if needed )
  # lvm dirs
  $XARGS chmod -v 00700 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type d \
      -regex ".*/lvm/\(archive\|backup\|cache\)" \
    ! -perm 0700
  )
  # lvm files
  $XARGS chmod -v 00600 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type f \
      -regex ".*/lvm/\(archive\|backup\|cache\)/.*" \
    ! -perm 0600
  )
  $XARGS chmod -v 00444 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type f \
      -regex ".*/lvm/profile/.*" \
    ! -perm 0444
  )
}
################################################################################
QueryManifest (){
# [0]="Perms" [1]="Owner/Group [2]="Size|Major/Minor"
# [3]="Date"  [4]="Time"      [5]="Path/file"
while read -a META
do
  [[ $DISTRO =~ slackware ]] && {
  # fix 1994 var/run with incorrect perms
    [[ ${META[5]} == var/run/ && ${META[0]} == drwxrwxr-x ]] \
      && META[0]="drwxr-xr-x"
  }

  #PrintCosmetic $FUNCNAME "${META[5]}"

  # check file/dir exists
  [[ -e "${MNTPOINT%/}/${META[5]}" ]] \
    && printf "%s\n" "${MNTPOINT%/}/${META[5]#./}"

  [[ $DISTRO =~ slackware ]] && {
  #Slackware Specific
  # files ending .new may or may not exist
  # But these are temp. files, so check after stripping .new
    [[ ${META[5]:(-4)} == \.new ]] \
      || continue \
      && ni=${#META[@]} \
      && META[$ni]=${META[5]%.new}

    #PrintCosmetic $FUNCNAME "${META[$ni]}"

    [[ -e "${MNTPOINT%/}/${META[$ni]}" ]] \
      && printf "%s\n" "${MNTPOINT%/}/${META[$ni]#./}"
  }

done< <( ReadManifest "${1}" )
}
################################################################################
ErrorReport () {
ExitCode=$?
# since I'm posting this where tabs cannot be input I have removed leading tabs.
# the - in <<- strips the leading tabs from output
# if you want readability re-add the tabs,
# NOTE I lead with two spaces, IMO output looks better with a margin.
#
# The nice thing about this function is Creepers will not dare come near!
case ${ExitCode} in
  10) cat <<-EOF
  MANIFEST required
  $0 /path/to/MANIFEST.bz2
EOF
    ;;
  20) cat <<-EOF
  "${Manifest}" does not appear to be a validi Manifest
  edit the script to skip this test
  I will add a flag later
EOF
    ;;
  30) Foo=($(grep -o -E "(text|application)/[a-z-]*" "$0" ))
    Foo=(${Foo[@]#app*/})
    cat <<-EOF
  "${fileis[1]:0:(-1)}" not supported
  valid compressions are ${Foo[@]/x-}
EOF
    ;;
  99) cat <<-EOF
  Unknown Error
  I hope "$Error"
  makes some sense to you
EOF
    ;;
esac
exit ${ExitCode}
}
################################################################################
PrintCosmetic () {
# calls to this are commented out as it slows things down quite a bit.
# Although, the slowdown is just mins, not 10s of mins.
  case $1 in
    Filter|OwnGrpFilter)
      printf "%-${COLUMNS}s\n" "Current filter ${2}" 1>&2
      ;;
    QueryManifest)
      #TODO put prefix into a var
  [[ $(( ${#2} + 9 )) -gt ${COLUMNS} ]] \
    || printf "%-${COLUMNS}s\r" \
      "Checking ${2}" 1>&2 \
    && printf "%-${COLUMNS}s\r" \
      "Checking ${2:$(( $(( ${#2} + 9 )) - $COLUMNS ))}" 1>&2
      ;;
  esac
}
################################################################################
Filter () {
# Initially I had QueryManifest printing the chmod/chown for each line
# This Filter now groups each "unique" chmod and executes as a block via xargs
# Which should be much quicker ( but generated script will look ugly as hell )

  filter="${1:-[drwxstT-]{10}}" #TODO include block/char when root is MNTPOINT
  while read -a FILTER
  do
    #PrintCosmetic $FUNCNAME "${FILTER[0]}"

    $XARGS chmod -v $( $MODE ${FILTER[0]} ) \
      < <(QueryManifest "^${FILTER[0]}")
  done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
################################################################################
OwnGrpFilter () {
# I ignored chown for a while, this re-adds that, same logic as Filter
# with regards to doing as a block

# Note, seperate chown does greatly increase the processing time
# However, in the case of fixing a "chmod -R 777 /" chown would not be
# needed, so I figured it would be better to have as a non default option.

  filter="${1:- [a-z]+/[a-z]+ }"
  while read -a FILTER
  do
    #PrintCosmetic $FUNCNAME "\" ${FILTER[0]/\//:} \""
    $XARGS chown ${FILTER[0]/\//:} \
      < <(QueryManifest " ${FILTER[0]} ")
  done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
trap ErrorReport EXIT
################################################################################

ChkManifest || exit
Hammer
Filter
#OwnGrpFilter
################################################################################


sankeny 11-19-2019 01:41 PM

Excellent script!

HOWEVER . . .

I can login as a regular user (as created when installing Ubuntu) but not root, and I can no longer use "sudo" or "su root"

That means I cannot run the command above "chmod 700 ~/.ssh" or any variation to fix my remote login issue.

I plan to be at the console within the next week and do a re-installation. We are in the process of backing up any data we wish to keep.

Thanks for all the help! I will look more closely at your scripts and try them when I get a chance (probably this Saturday or next)

Rickkkk 11-19-2019 03:04 PM

Hi sankeny,

If you can actually solve your issue using firerat's recommendation, by all means. Before seeing his post, I was going to echo fishope's advice to reinstall. The last time I made a mistake with permissions, and it wasn't as far-reaching as your situation, I was never able to manually correct everything and had to reinstall.

Firerat's scripting abilities far outclass mine - so, again, if that does the trick - excellent - and kudos to firerat.

Let us know how you make out !

sankeny 11-19-2019 03:33 PM

[resolution pending] Reset default permissions . . .
 
I will post once I resolve the issue or post any specific issues I find which might help someone else. It may be after Thanksgiving.

Meanwhile, I will mark this "solved" just to let someone know that I have answers (though not resolved until later)

ANSWER: If you can login with root or access root authority via "sudo," then use "Fireat's" scripts. If not, reinstall. My personal experience is that it's likely the BEST solution - BACK UP DATA FIRST and don't make silly mistakes like I did. "chmod --preserve-root" is an excellent suggestion.



Thanks everyone!

Firerat 11-19-2019 05:24 PM

Quote:

Originally Posted by sankeny (Post 6059784)
I will post once I resolve the issue or post any specific issues I find which might help someone else. It may be after Thanksgiving.

Meanwhile, I will mark this "solved" just to let someone know that I have answers (though not resolved until later)

ANSWER: If you can login with root or access root authority via "sudo," then use "Fireat's" scripts. If not, reinstall. My personal experience is that it's likely the BEST solution - BACK UP DATA FIRST and don't make silly mistakes like I did. "chmod --preserve-root" is an excellent suggestion.



Thanks everyone!

no need to re-install
boot a liveCD
mount the root partition, and point the script at it



actually
if you have a "working" system, then this would generate a suitable command list

Code:

MP="/mnt/temproot/"
sudo find / -xdev -printf "sudo chmod %05m ${MP%/}%p\n"

the -xdev limits find to the one filesystem
if you have multiple mountpoints ( like /opt , /var ) adapt

Firerat 11-19-2019 06:15 PM

a more targeted generation

Code:

unset MNTPOINT
# unset as we are mapping a working systems perms
#

find ${MNTPOINT%/}/ \
    -xdev \
    -type f \
    -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
  ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
  ! -perm 0755 \
    -printf "%05m\t%p\n"

#

the bold bit is actually slackware specific, that can safely be removed


the idea with this one is,

for each sbin and bin dir on the "broken" partition, recursively chmod to 755
then run the "script" generated by the above find

the trick with restoring permissions is knowing what they should be.

The "big" script is a re-write of the one posted in
https://www.linuxquestions.org/quest...2/#post6041687
one of my posts in that thread explains the "%05m" in the recent ( find -printf )s


slackware's MANIFEST.bz2 was a handy reference point

the , ( unar some.deb | tar -Jvtf - ) seemed like a good way to get a "manifest" on Debian derivatives,
but it would depend on apt's caching policy
then I figured the
Code:

bzip2 > MANIFEST.bz2 < <( Find )
would be quicker/easier providing you have a suitable "template"

sankeny 11-19-2019 11:54 PM

Firerat --

not sure "why" I didn't think of this --

Quote:

Originally Posted by Fireat
no need to re-install
boot a liveCD
mount the root partition, and point the script at it

So, once I mount the damaged partition ("/" on the damaged Ubuntu), run the following --

Code:

unset MNTPOINT
# unset as we are mapping a working systems perms
#

find ${MNTPOINT%/}/ \
    -xdev \
    -type f \
    -regex "\(.*/s?bin/.*\)\|\" \
  ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
  ! -perm 0755 \
    -printf "%05m\t%p\n"

#

I will create it as a file called "Restore_file_permissions.sh" on my mounted "/" and run from there (just to simplify the process)

FWIW --

I enjoyed reading the link you posted - https://www.linuxquestions.org/quest...2/#post6041687 - as it explained your thought processes while writing/rewriting these scripts.

At first I thought YOU were "Alan Hicks" and felt HONORED that you would stoop to helping someone such as I who made a "dumb" mistake, and then I realized you were NOT the writer of the original Slackware script, though you are obviously a skilled programmer. I STILL FEEL HONORED that you would spend your time helping me resolve this issue.

I am not a newbie but I am not at your level, and I still make newbie mistakes! As stated above --

Quote:

Originally Posted by Rickkkk
Firerat's scripting abilities far outclass mine - so, again, if that does the trick - excellent - and kudos to firerat.

It appears I will tackle this firsthand Saturday, so will report over the weekend my results. Thanks again to everyone for their suggestions!

Firerat 11-20-2019 12:59 AM

not quite
( the bold didn't show up well for | )


Code:

# make bins fix
find / \
    -xdev \
    -type f \
    -regex "\(.*/s?bin/.*\) \
  ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
  ! -perm 0755 \
    -printf "chmod %05m\t%p\n"

you run that on a "good" install
it finds files in dirs. named sbin or bin, that are not perm 755

and prints what they should be
e.g.
Code:


04755    /usr/bin/sudo

on the "bad" partition
( /mnt/badpart )

Code:

find /mnt/badpart \
    -xdev \
    -type d \
    -regex "\(.*/s?bin/.*\) \

that is sbin and bin dirs.
they should have ( chmod -R 00755 ) run on them

Then, "run" the file generated by the "fix bins" find



but, to be honest, it is probably just easier to run the "find" in #6 to make the MANIFEST.bz2
on a "good" install ( as root because a normal user can't read some dirs. )

put that MANIFEST.bz2 and the "big script" on a usb stick/drive

boot a liveCD
make a mount point, mount the "bad" partition
and run ( as root )
Code:

the_script.sh /path/to/MANIFEST.bz2 /path/to/mountpoint/ > FixScript.sh
it might be worth un-commenting the
#PrintCosmetic $FUNCNAME
lines
, it takes a bit longer ( not much really )
but they print to stderr, so you will still see things when redirecting stdout to file

the FixScript.sh will look ugly ( very long lines )

alternately, remove the "echo" from the XARGS var.
it will then run the chmods as it finds them.

how well this will all work depends on how close the "good" is to the "bad" ( with respect to the installed packages )

sankeny 11-25-2019 04:16 AM

so, here's what I did to RESOLVE the issue --

(1) created a "liveDebian" boot USB (in hopes of being able to store the scripts needed)

Ubuntu "live-server" did not allow me to boot into a "live-session" nor did it include the tools I needed

(2) ran the following script found at #6 above . . .

Code:

#!/bin/bash
Find () {
  find / -xdev -printf "%M %u/%g %9s %AY-%Am-%Ad %AH:%AM .%p\n"
}
bzip2 > MANIFEST.bz2 < <(Find)


#

(3) discovered I couldn't "store" the script and "live-boot" at the same time, so created a 2nd USB to store my scripts

On reflection, no doubt I could have "stored" them on the "bad" partition which I had mounted. Nevertheless, I didn't.

(4) created a script from the following, also found at #6 above . . .

Code:

#!/bin/bash
Flags=( "${@}" ) # grab hold of flags early

################################################################################
# Default configuration
################################################################################
  manifest_missing="return 10"
  manifest_invalid="return 20"
      UnknownError="return 99"
  CompTypeUnknown="return 30"
        #MODE=Textual_to_Symbolic
        MODE=Textual_to_Octal
      Manifest="$1"
      MNTPOINT="$2"
        XARGS="xargs -r echo"
      # remove echo if you want to action immediately
################################################################################
Help () {
#TODO write this
  echo "Use the Force, read the src."
}
ChkManifest () {
  [[ -z "${Manifest}" ]] && $manifest_missing
  [[ -e "${Manifest}" ]] || $manifest_missing
  fileis=( $( file -i "${Manifest}" ) )
  case ${fileis[1]:0:(-1)} in
    text/plain)
      GREP="$( type -p grep )"
      ;;
    application/gzip)
      GREP="$( type -p zgrep )"
      ;;
    application/x-bzip2)
      GREP="$( type -p bzgrep )"
      ;;
    application/x-xz)
      GREP="$( type -p xzgrep )"
      ;;
    application/x-lzma)
      GREP="$( type -p lzgrep )"
      ;;
    application/x-zstd)
      GREP="$( type -p zstdgrep )"
      ;;
    *)
      $CompTypeUnknown
      ;;
  esac
  chk=( $($GREP -m1 -E -- "^[bcd-][rwx-]{9}.*[a-z]/?$" ${Manifest}) )
  [[ ${#chk[@]} == 6 ]] \
    && [[ ${chk[0]} =~ ^[bcdrwxsStT-]{10}$ ]] \
    && [[ ${chk[1]} =~ ^[a-z]*/[a-z]*$ ]] \
    && [[ ${chk[2]} =~ ^[0-9]+,?[0-9]*$ ]] \
    && [[ ${chk[3]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
    && [[ ${chk[4]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
    && [[ ${chk[5]} =~ ^[.]/[[:print:]]+$ ]] \
    || $manifest_invalid
return
}
ChkDistro () {
  DISTRO=$(grep -E ^ID=[[:print:]]+ ${MNTPOINT%/}/etc/os-release 2>/dev/null)
}
################################################################################
# GetIndex #
# unlikely with slackware's ( tar vtf package.txz )>> MANIFEST
# but if the manifest were in a different order to what we expect
# this could be used to find the array indices we need
# only PERMS, OWNER_GRP and FILEPATH are used in this script
# they are META[0] , META[1] and META[5]
GetIndex () {
################################################################################
for i in ${!chk[@]}
do
  [[ ${chk[i]} =~ ^[bcdrwxsStT-]{10}$ ]] \
    && PERMS=$i || continue
  [[ ${chk[i]} =~ ^[a-z]+/[a-z]+$ ]] \
    && OWN_GRP=$i || continue
  #[[ ${chk[i]} =~ ^[0-9]+,?[0-9]*$ ]] \
  # && SIZE=$i || continue
  #[[ ${chk[i]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
  # && FILEDATE=$i || continue
  #[[ ${chk[i]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
  # && FILETIME=$i || continue
  [[ ${chk[i]} =~ ^[.]/[[:print:]]+$ ]] \
    && FILE_PATH=$i || continue
done
}

ReadManifest () {
  sort -u -d -k6 <($GREP -E -- "$1" "${Manifest}" )
return 0
}
Textual_to_Octal () {
################################################################################
  S=0 # unset special bits by default
  # bash arrays start at 0, so 3 is 4th in string
  [[ ${1:3:1}  =~ [sS] ]] && S=$(( ${S} + 4 )) ##\
  [[ ${1:6:1}  =~ [sS] ]] && S=$(( ${S} + 2 ))  # set as per manifest
  [[ ${1:(-1)} =~ [tT] ]] && S=$(( ${S} + 1 )) ##/

  # only need to declare once
  [[ $p ]] || declare -A \
    p=(
      [r]="4" [w]="2" [x]="1" [-]="0"
      [s]="1" [S]="0" [t]="1" [T]="0"
      )
  # S ( s{u,g}id no exec. ) is unlikly to exist in manifest, but it is valid
  printf "0%d%d%d%d" \
    ${S} \
    $(( ${p[${1:1:1}]} + ${p[${1:2:1}]} + ${p[${1:3:1}]} )) \
    $(( ${p[${1:4:1}]} + ${p[${1:5:1}]} + ${p[${1:6:1}]} )) \
    $(( ${p[${1:7:1}]} + ${p[${1:8:1}]} + ${p[${1:9:1}]} ))

# ${1} is what we fed into the function ( drwxr-xr-x )
# p is our Associative (-A) array, bit values are indexed with textual char.
# :1:1} == r ( the second element of the string d(r)wxr-xr-x )
# special  User          Group        Other
# no s / S  ${p[r]} == 4  ${p[r]} == 4  ${p[r]} == 4
# no t / T  ${p[w]} == 2  ${p[-]} == 0  ${p[-]} == 0
#          ${p[x]} == 1  ${p[x]} == 1  ${p[x]} == 1
# sum == 0    sum  == 7    sum  == 5    sum  == 5  >>  0755

################################################################################
}
Textual_to_Symbolic () {
################################################################################

    SUID=",u-s"    ##\
    SGID=",g-s"      # unset special bits by default
    STICKY=",o-t"  ##/

  [[ ${1:3:1}  =~ [sS] ]] &&  SUID="s"  ##\
  [[ ${1:6:1}  =~ [sS] ]] &&  SGID="s"    # set as per manifest
  [[ ${1:(-1)} =~ [tT] ]] && STICKY="t"  ##/

  perms="${1//[st]/x}"      # s and t imply exec. bit
  perms="${perms//[ST-]/ }" # S and T imply no exec. bit
  perms="\
      u=${perms:1:3}${SUID},  \
      g=${perms:4:3}${SGID},  \
      o=${perms:7:3}${STICKY} \
      "
  perms="${perms//[[:space:]]}" # remove white space.

  printf "%s" "${perms}"

}
Hammer () {
################################################################################
# chmod pretty much everything
# Why?
# it will fix anything "extra" that is not in the manifest
# no real sense in leaving rogue 777 dirs/files hanging around

  # dirs 00755
  $XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
      -type d \
    ! -regex "${MNTPOINT%/}\(/lost.found\|/home\)/" \
    ! -perm 0755
  )

  # files in a /{s}bin/ 00755
  $XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
      -type f \
      -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
    ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
    ! -perm 0755
  )

  # files not in a /{s}bin/ 00644
  $XARGS chmod -v 00644 < <( find ${MNTPOINT%/}/ -xdev \
      -type f \
    ! -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
    ! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
    ! -perm 0644
  )

# Yes, many more locations should have exec. scripts
# These will be fixed when manifest is processed
}
################################################################################
LVM () {
#TODO add option for this ( or look to see if needed )
  # lvm dirs
  $XARGS chmod -v 00700 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type d \
      -regex ".*/lvm/\(archive\|backup\|cache\)" \
    ! -perm 0700
  )
  # lvm files
  $XARGS chmod -v 00600 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type f \
      -regex ".*/lvm/\(archive\|backup\|cache\)/.*" \
    ! -perm 0600
  )
  $XARGS chmod -v 00444 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
      -type f \
      -regex ".*/lvm/profile/.*" \
    ! -perm 0444
  )
}
################################################################################
QueryManifest (){
# [0]="Perms" [1]="Owner/Group [2]="Size|Major/Minor"
# [3]="Date"  [4]="Time"      [5]="Path/file"
while read -a META
do
  [[ $DISTRO =~ slackware ]] && {
  # fix 1994 var/run with incorrect perms
    [[ ${META[5]} == var/run/ && ${META[0]} == drwxrwxr-x ]] \
      && META[0]="drwxr-xr-x"
  }

  #PrintCosmetic $FUNCNAME "${META[5]}"

  # check file/dir exists
  [[ -e "${MNTPOINT%/}/${META[5]}" ]] \
    && printf "%s\n" "${MNTPOINT%/}/${META[5]#./}"

  [[ $DISTRO =~ slackware ]] && {
  #Slackware Specific
  # files ending .new may or may not exist
  # But these are temp. files, so check after stripping .new
    [[ ${META[5]:(-4)} == \.new ]] \
      || continue \
      && ni=${#META[@]} \
      && META[$ni]=${META[5]%.new}

    #PrintCosmetic $FUNCNAME "${META[$ni]}"

    [[ -e "${MNTPOINT%/}/${META[$ni]}" ]] \
      && printf "%s\n" "${MNTPOINT%/}/${META[$ni]#./}"
  }

done< <( ReadManifest "${1}" )
}
################################################################################
ErrorReport () {
ExitCode=$?
# since I'm posting this where tabs cannot be input I have removed leading tabs.
# the - in <<- strips the leading tabs from output
# if you want readability re-add the tabs,
# NOTE I lead with two spaces, IMO output looks better with a margin.
#
# The nice thing about this function is Creepers will not dare come near!
case ${ExitCode} in
  10) cat <<-EOF
  MANIFEST required
  $0 /path/to/MANIFEST.bz2
EOF
    ;;
  20) cat <<-EOF
  "${Manifest}" does not appear to be a validi Manifest
  edit the script to skip this test
  I will add a flag later
EOF
    ;;
  30) Foo=($(grep -o -E "(text|application)/[a-z-]*" "$0" ))
    Foo=(${Foo[@]#app*/})
    cat <<-EOF
  "${fileis[1]:0:(-1)}" not supported
  valid compressions are ${Foo[@]/x-}
EOF
    ;;
  99) cat <<-EOF
  Unknown Error
  I hope "$Error"
  makes some sense to you
EOF
    ;;
esac
exit ${ExitCode}
}
################################################################################
PrintCosmetic () {
# calls to this are commented out as it slows things down quite a bit.
# Although, the slowdown is just mins, not 10s of mins.
  case $1 in
    Filter|OwnGrpFilter)
      printf "%-${COLUMNS}s\n" "Current filter ${2}" 1>&2
      ;;
    QueryManifest)
      #TODO put prefix into a var
  [[ $(( ${#2} + 9 )) -gt ${COLUMNS} ]] \
    || printf "%-${COLUMNS}s\r" \
      "Checking ${2}" 1>&2 \
    && printf "%-${COLUMNS}s\r" \
      "Checking ${2:$(( $(( ${#2} + 9 )) - $COLUMNS ))}" 1>&2
      ;;
  esac
}
################################################################################
Filter () {
# Initially I had QueryManifest printing the chmod/chown for each line
# This Filter now groups each "unique" chmod and executes as a block via xargs
# Which should be much quicker ( but generated script will look ugly as hell )

  filter="${1:-[drwxstT-]{10}}" #TODO include block/char when root is MNTPOINT
  while read -a FILTER
  do
    #PrintCosmetic $FUNCNAME "${FILTER[0]}"

    $XARGS chmod -v $( $MODE ${FILTER[0]} ) \
      < <(QueryManifest "^${FILTER[0]}")
  done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
################################################################################
OwnGrpFilter () {
# I ignored chown for a while, this re-adds that, same logic as Filter
# with regards to doing as a block

# Note, seperate chown does greatly increase the processing time
# However, in the case of fixing a "chmod -R 777 /" chown would not be
# needed, so I figured it would be better to have as a non default option.

  filter="${1:- [a-z]+/[a-z]+ }"
  while read -a FILTER
  do
    #PrintCosmetic $FUNCNAME "\" ${FILTER[0]/\//:} \""
    $XARGS chown ${FILTER[0]/\//:} \
      < <(QueryManifest " ${FILTER[0]} ")
  done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
trap ErrorReport EXIT
################################################################################

ChkManifest || exit
Hammer
Filter
#OwnGrpFilter
################################################################################

(5) booted "liveDebian" and mounted the "bad" partition then ran the following . . .

Code:

the_script.sh /path/to/MANIFEST.bz2 /path/to/mountpoint/ > FixScript.sh
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Everything completed with no errors. HOWEVER, it didn't change the permissions as I had hoped.

It appeared to have changed "some" directories and files, but most of the dirs were still marked "drwzrwzrwz"

At this point, I decided to reinstall Ubuntu Server. I had some difficulty with the RAID partitioning - it was initially setup to "mirror" and we needed more disc space - so I "blew" the existing partitions and installed from "scratch" It had also given me problem installing "grub" This is a redeployed Mark VI Integrator, and we will now use it with more disc space (1 TB)

Thanks to "Firerat" for his efforts! If I had had more time, I would have consulted with him to make the scripts works. I am convinced the DO work.

pan64 11-25-2019 08:09 AM

just a comment:
you can analyze packages and restore permissions based on that information, but you cannot restore files created without installation (like log files). Also there are postinstall scripts which may make it even more difficult.
So you can completely restore your system only from a full backup.


All times are GMT -5. The time now is 02:14 AM.