174

Today I was told a tale by a Unix trainer where the root password got leaked to the students, and one of the fellas removed the execute permission from /usr/bin/chmod itself. How do you recover chmod in this case and make it executable again? Let's say getting it from an external source or recompiling it is not a preferable option, is there some smart hack that can recover this chmod itself?

Note that this happened a long time ago and I'm not looking for a solution for some current problem, just curious about what ways Unix provides us around such an issue.

Ketan
  • 9,226
Sundar R
  • 1,598
  • 7
    Since all the answers provided are equally "right answers" here, I'm not marking any one of them in particular. Thanks to everyone who answered, every answer was educative in some way. – Sundar R Jul 22 '13 at 17:36
  • 2
    Note that the "how do I do this without rebooting?" is as important an exercise as "How do I boot a rescue/installation media and fix this?". In my opinion you need to be able to do both - it might be a job saver some day. – Thorbjørn Ravn Andersen Jul 23 '13 at 08:28
  • 2
    The same question (and similar answers) exists on ServerFault, too. – SpellingD Jul 23 '13 at 19:30
  • 1
    @SpellingD Thanks. It's weird reading that thread, like an alternate universe version of this question with only slightly different answers. And someone there answers they've seen the question previously on slideshare, and someone comments on that one that they've seen it on Reddit too! – Sundar R Jul 23 '13 at 19:43
  • @Gilles'SO-stopbeingevil' This is not the same as your proposed duplicate. In that question, the whole directory was changed, no executable file remains to execute any action. Here, all executable files are available except chmod. The solutions for each problem are quite different. –  Jun 26 '20 at 01:29
  • @Isaac Yes, ok, all solutions from https://unix.stackexchange.com/questions/77852/how-to-recover-from-a-chmod-r-000-bin work, but here there are more solutions. – Gilles 'SO- stop being evil' Jun 26 '20 at 08:18

10 Answers10

214

You can run the loader directly, and pass it the command you want to run:

/lib/ld-linux.so /bin/chmod +x /bin/chmod

Your path to the loader might vary. On a 64-bit system you need to choose the right one based on how chmod was compiled; the 64-bit version is named something like /lib64/ld-linux-x86-64.so.2

user12345
  • 105
Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
112

The chmod utility relies on the chmod() system call (see man 2 chmod). So you could do this with a few lines of C, or just about any other language that has a wrapper around it (which would be most of them). Very few *nix systems are going to lack a C compiler and a perl interpreter; most linux distros require the later to work.

perl -e 'chmod 0755, "foobar.file"'
goldilocks
  • 87,661
  • 30
  • 204
  • 262
  • 3
    Thanks, that's sweet. I just tried it out in Perl and it worked. – Sundar R Jul 21 '13 at 19:28
  • Re: "most linux distros require the [perl interpreter] to work": Really? Can you elaborate a bit on that? – ruakh Jul 21 '13 at 19:55
  • @ruakh I would say this is rather true for python. – Nils Jul 21 '13 at 21:23
  • 2
    @ruakh, on Debian-based systems the perl-base package is marked as essential. Not having perl-base will make the package manager pretty unhappy. There are a large number of other essential/important tools like adduser that require perl, and are installed in an absolute bare-bones setup. – Zoredache Jul 22 '13 at 05:24
  • 1
    @ruakh The reason it is more true of perl than anything else is that perl 5 was around during linux's infancy, while (eg) python 2 was not. It is kind of the original "dynamically typed, object oriented interpreted" language. So in general the 3 most fundamental languages in the linux world would be 1) C, 2) bash, and 3) perl. Python has probably eclipsed it in popularity in recent years, but it is just not as historically relevant and thus less likely to be essential -- although in reality both of them are usually available anyway. – goldilocks Jul 22 '13 at 14:44
  • @goldilocks: I didn't mean "as opposed to Python" (since you didn't mention Python); I meant "as opposed to C"! – ruakh Jul 22 '13 at 15:12
  • @ruakh: Because most distos are binary based -- you don't need a C compiler, because everything is already compiled. However, you need bash to run the shell scripts, and if perl is fundamental, you need a perl interpreter too. So, eg., a default fedora or ubuntu install will probably include perl, but not gcc. Of course, C is the ground of everything (perl, python, and bash are written in C) but there does not need to be any C code at all on a running system, because it's all been compiled. – goldilocks Jul 22 '13 at 16:23
  • 1
    @goldilocks: Interesting! The Single Unix Specification does mark cc as "LEGACY" (and therefore optional), but I didn't realize that Linux distros were actually taking it up on that. :-P (Of course, it doesn't list perl at all, even as an optional utility.) – ruakh Jul 22 '13 at 16:38
  • @ruakh: I just stumbled across this old thread and thought I’d comment that ISTR that, about 20 years ago, Sun Microsystems (subsequently acquired by Oracle) was distributing SunOS and Solaris without a C compiler because they wanted to sell you theirs.  They claimed that this was to decrease the price they charged to low-end users in non-development environments, and of course that meant that developers paid more (or downloaded gcc). – G-Man Says 'Reinstate Monica' Oct 16 '17 at 20:27
76

Some systems also have busybox installed in which case you may run:

busybox chmod +x /bin/chmod

Since you were asking for hacks, I just thought of another one:

mv /bin/chmod /bin/chmod.orig
cp -a /bin/chown /bin/chmod

Now you have a /bin/chmod that's executable but it's actually chown (i.e. some other binary). Now all we have to do is overwrite it with the original binary.

dd if=/bin/chmod.orig of=/bin/chmod

It keeps the +x flag so you just stole the +x of another file for this one.

Of course, if all those alternative binaries (including the loader, perl, python, gcc et cetera) were chmod -x, fixing it from a rescue system may be the only option.

frostschutz
  • 48,978
  • Couldn't you just use cat instead of dd? – jw013 Jul 22 '13 at 17:18
  • Yes... I ended up using dd because at first I thought it may need conv=notrunc or similar to prevent replacing the file entirely, but it does work with most commands that write files after all (including cat, cp, ...). – frostschutz Jul 22 '13 at 17:44
  • 2
    great hack, really clever – Kiwy Mar 14 '14 at 08:49
  • 2
    +1, but why tamper with an existing system file at all?  Why not just do cp /bin/tr /bin/newchmod && cp /bin/chmod /bin/newchmod?  It seems that you don't need to specify any options to cp.  (I chose tr because it's a small file with a short, easy-to-type name; obviously, any executable file, such as /bin/chown, will work.) – G-Man Says 'Reinstate Monica' Aug 08 '15 at 20:25
  • @G-Man, good point, might be less confusing that way for package managers that track files by timestamps or something. – frostschutz Aug 08 '15 at 20:51
51

Easy. What you can do is prepare some other executable file, and then cp chmod over it.

 $ cp /bin/ls chmod
 $ cp /bin/chmod .

The first cp creates a file called chmod with executable permissions, but which is really the ls executable. The second cp populates this file with the binary code of chmod, while preserving the execute permissions of the target file (because we did not specify any options to carry over permissions of the source file).


Another approach is to use the install utility which is a glorified copying program which can set permissions in one step. (See the -m argument.)

$ install -m a+x /bin/chmod .
$ ./chmod # executes

The install program isn't part of the Unix specification, but it is found in BSD, and in GNU Coreutils. Both support the -m option with chmod-like syntax, both symbolic and octal.

Kaz
  • 8,273
16

First things off the top of my head,

  • Boot from any other source (network book, cd, etc.) and use the chmod on that source to set the permissions.
  • Write a tiny C program to change the permissions.
  • Write a perl script (ruby, php, python, etc.) to change the permissions

/usr/bin/chmod is just making a system call to change the permissions, you can make that system call yourself in any number of ways.

EightBitTony
  • 21,373
14

This is hackier than any of the other answers (with the possible exception of the ld-linux.so answer, which is a really clever hack), but may be more adaptable to other problems (especially if you fall into a time vortex and travel back to a Land Before Perl™).

  1. For safety, copy /bin/chmod to a safe place:

    cd
    cp /bin/chmod .
    
  2. Do echo chmod | cpio -oc > chmod.cpio
    This creates a cpio archive (not unlike a tar archive) containing chmod.  The -c option specifies that the file metadata is written in hex (i.e., in ASCII).

  3. vi chmod.cpio
    You’ll see something like

    0707010005DBFD000081A4000303E9000302010000000155C64D6E0000C01D000068E70000C361…chmod^@…
                       ↑↑↑
    

    followed by a mixture of control characters, standard ASCII characters, and extended ASCII characters.  Note that 0644 = 0x1A4 and 0755 = 0x1ED.  Find the 1A4 (starting at the 20th character position) and change it to 1ED.  Save and exit.

    • If you have a hex editor or something similar, it might be better to use that to avoid the risk that vi will contaminate the binary executable code in the file.  But I tried this with vi, and it seemed to work OK.
  4. cpio -i < chmod.cpio
    You now have a copy of chmod in your directory, protected 755.

Other archive programs may have similar capabilities.  In particular, cpio is old and may be deprecated; if you don’t have it, look for pax.

10

Or even easier - use setfacl which is often present on modern systems:

  1. Set executable permission for user:

    # setfacl -m u::rx /bin/chmod
    
  2. Now use the now executable binary to set its own permissions back to the original ones (i.e. for all users)

    # chmod +x /bin/chmod
    
  3. Drop extended ACL entries - optional, since there might have been a good reason why they were there in the first place.

    # setfacl -b /bin/chmod
    

Note, that setfacl can be used on a filesystem that doesn't support ACLs as well.

peterph
  • 30,838
7

rsync can also be used to change the file's permissions

# rsync /bin/chmod /tmp/chmod --chmod=ugo+x
# ls -al /tmp/chmod
  -rwxr-x--- 1 root root 52000 Sep  6 15:13 /tmp/chmod
#
peterph
  • 30,838
Ofer
  • 71
5

Pipe the contents of chmod into an already executable file

cp /usr/bin/executable_file ~/executable_file
cat /usr/bin/chmod > ~/executable_file
~/executable_file +x file_to_be_executed.sh
Parag
  • 151
0

Using setfacl:

setfacl -m u::rwx /bin/chmod

Easy/ Lazy Method ;)

rpm -qf /bin/chmod        # gets package name, coreutils
yum reinstall coreutils -y          # :D 

Test Results:

[root@h1 ~]# ll /bin/chmod 
-rwxr-xr-x. 1 root root 58656 Mar 15  2019 /bin/chmod
[root@h1 ~]# chmod 444 /bin/chmod 
[root@h1 ~]# ll /bin/chmod 
-r--r--r--. 1 root root 58656 Mar 15  2019 /bin/chmod
[root@h1 ~]# yum reinstall coreutils
Loaded plugins: product-id, search-disabled-repos, subscription-manager
Resolving Dependencies
--> Running transaction check
---> Package coreutils.x86_64 0:8.22-24.el7 will be reinstalled
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================================================================================================================================== Package Arch Version Repository Size ====================================================================================================================================================================================================== Reinstalling: coreutils x86_64 8.22-24.el7 rhel-7-server-rpms 3.3 M

Transaction Summary

Reinstall 1 Package

Total download size: 3.3 M Installed size: 14 M Is this ok [y/d/N]: y Downloading packages: coreutils-8.22-24.el7.x86_64.rpm | 3.3 MB 00:00:01
Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : coreutils-8.22-24.el7.x86_64 1/1 Verifying : coreutils-8.22-24.el7.x86_64 1/1

Installed: coreutils.x86_64 0:8.22-24.el7

Complete! [root@h1 ~]# ll /bin/chmod -rwxr-xr-x. 1 root root 58656 Mar 15 2019 /bin/chmod [root@h1 ~]#

Anto
  • 171