I ran chmod 222 /bin/chmod
to know more about chmod
. After that, when I run /bin/chmod
, I get permission denied
.
I tried to change the permissions of chmod
back to 755
, but it doesn't work.
Does anyone have tips about how to fix this?
I ran chmod 222 /bin/chmod
to know more about chmod
. After that, when I run /bin/chmod
, I get permission denied
.
I tried to change the permissions of chmod
back to 755
, but it doesn't work.
Does anyone have tips about how to fix this?
You made chmod
not executable.
There are three (no, actually four) options to revert from this situation:
Reinstall the coreutils
package, as mentioned in Artur Meinild's answer.
My preferred solution:
boot from an installation medium and start a live Ubuntu session.
start the Disks application, find the partition where your Ubuntu installation resides and mount it. Note the path where the partition is mounted (something like /media/username/somename
).
open a terminal and run:
sudo chmod 755 /media/username/somename/usr/bin/chmod
unmount the partition, shutdown the live session and reboot from your normal installation.
Be VERY CAREFUL when doing this! Run the following commands:
sudo cp -p /usr/bin/ls /tmp/chmod
sudo cp /usr/bin/chmod /tmp/chmod
sudo /tmp/chmod 755 /usr/bin/chmod
Explanation: first, we copy another file that is still executable (I chose /usr/bin/ls
) to /tmp/chmod
. By using the -p
parameter to the cp
command, we are preserving permissions, so we ensure that the resulting file is also executable.
Next, we overwrite the just created /tmp/chmod
file with the contents of actual /usr/bin/chmod
, but without preserving permissions. The contents of /tmp/chmod
is overwritten with actual chmod
, but it is still executable.
So we can use /tmp/chmod
to restore permissions on the actual /usr/bin/chmod
.
Optionally we can delete /tmp/chmod
, which is no more needed, but it is not necessary; on the next system boot, /tmp
directory will be cleared anyway.
You can use any programming language that supports the chmod()
system call. As Ubuntu by default contains the Python interpreter, it would be probably easiest to use Python:
sudo python3 -c 'import os; os.chmod("/usr/bin/chmod", 0755)'
/bin
by mistake. The emergency boot disk had executable binaries on it, but not a copy of chmod
!
– TripeHound
Aug 23 '23 at 16:58
cp
to just copy a different binary with appropriate permissions and overwrite it
– Josh
Aug 25 '23 at 01:20
/tmp
usually isn't a separate filesystem at all. It's just a regular directory under the root filesystem, at least in default install.
– raj
Aug 25 '23 at 14:22
dpkg-statoverride
dpkg-statoverride
is available by default on Ubuntu ... Its main purpose is to override ownership and mode of files ... and you can use it like this:
sudo dpkg-statoverride --update --add root root 755 /bin/chmod
rsync
rsync
is available by default on Ubuntu ... In --archive, -a
mode, it should only set the permissions (since the file will never change) ... i.e. when used in one shot like so:
sudo rsync -a --chmod=755 /bin/chmod /bin/chmod
install
commandThere is another utility called install
from GNU core utilities as well which should be available by default on your system … It’s mainly used for copying just compiled files and make them executable i.e. install them and hence the name … It should give the copied file the permissions of rwxr-xr-x
by default ... It also has the option -m
to alter permissions of that file selectively on-the-fly (while you might not need that option in this case as the defaults should suffice), but you can always do:
sudo install -m +x /bin/chmod mychmod
Then, you can simply do:
sudo ./mychmod 755 /bin/chmod
Another simple solution as well is to use the dynamic linker/loader itself ... This is a special way of running binaries as it doesn’t require permissions to do so (It is somewhat similar to running a non-executable shell script by passing it as an argument to /bin/sh
for example) … Depending on the architecture your binary was compiled for, you most likely want to use the amd64
variant ... Find its name and path on your system with for example:
$ dpkg -S 'ld-linux*'
manpages: /usr/share/man/man8/ld-linux.8.gz
manpages: /usr/share/man/man8/ld-linux.so.8.gz
libc6:amd64: /lib64/ld-linux-x86-64.so.2
libc6:i386: /lib/i386-linux-gnu/ld-linux.so.2
libc6-i386: /lib32/ld-linux.so.2
libc6:i386: /lib/ld-linux.so.2
libc6:amd64: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Then, simply use it in one shot like so:
sudo /lib64/ld-linux-x86-64.so.2 /bin/chmod 755 /bin/chmod
Search your system for other utilities that can change/set file permissions ... One way is to search the manuals with e.g. man -K "chmod"
... Here are some of what I found on my system:
chacl
(change the access control list of a file or directory):
sudo chacl u::rwx,g::r-x,o::r-x /bin/chmod
bwrap
(container setup utility):
sudo bwrap --die-with-parent --bind / / --chmod 755 /bin/chmod -- /bin/true
/usr/bin/ld.so
does the same thing, so the slightly simpler ld.so /bin/chmod 755 /bin/chmod
would suffice!
– marcelm
Aug 23 '23 at 20:31
/bin/chmod
still has read permission I think? So that method would work for mode 6xx
or 4xx
but not 2xx
– steeldriver
Aug 23 '23 at 22:51
cp /bin/ls ./ls; chmod 0 ./ls; /lib64/ld-linux-x86-64.so.2 ./ls
and I get an error). But if you're running it as root, you get to ignore such pesky details as the permission bits, as root usually does, so it works there. Nothing to do with the dynamic loader being special here. (That's not to say it wouldn't be special when the kernel loads it as part of the normal process of executing a binary file, but that's what we're doing here.)
– ilkkachu
Aug 24 '23 at 07:01
sudo
as in the example in my answer.
– Raffa
Aug 24 '23 at 07:03
sudo
or super user is needed anyway for that and for setting permissions on /bin/chmod
as well ... I was talking about particularly the loading and running/executing part hence the special notation ... I wasn't talking about the reading part though, my bad :-).
– Raffa
Aug 24 '23 at 08:15
umask 0222; cat /bin/chmod >chmod.copy
, and finally chmod.copy 0755 /bin/chmod; rm chmod.copy
?
– U. Windl
Aug 24 '23 at 09:35
sudo /lib64/ld-linux-x86-64.so.2 /bin/chmod
, then yes, ld-linux-x86-64.so.2
can read it because it's being run as root via sudo, and root is exempt from the permission bits checks on reading. With cat /bin/chmod >chmod.copy
, and given the mode 0222 (-w--w--w-), you won't be able to read it (as a regular user), since no-one has read access on it. Also, even if you do sudo sh -c 'cat /bin/chmod >chmod.copy'
, the new file gets created without the x permission because normally programs don't add it when creating files.
– ilkkachu
Aug 24 '23 at 09:45
You did one of the most obvious things should never do with chmod
- you changed chmod
itself to not be executable. Not even the powers of sudo
will make this command work again (in its current form - see the other answers though).
A way to get it working again would be to reinstall the GNU coreutils package with this command:
sudo apt install --reinstall coreutils
A general tip (that's especially important for Linux utilities): When learning about something, first read up on what each command does, secondly try out stuff in an isolated environment (container/VM), and only after that should you run commands on your production system.
In addition to all the other answers, if you have busybox
installed, you can use that by running:
sudo busybox chmod 0755 /usr/bin/chmod
Busybox can be installed by enabling the universe
repository, and then running:
sudo apt update && sudo apt install busybox
chmod 0755
to restore the permissions to what they originally were, instead of just adding the execute permission and leaving the other permissions off
– ilkkachu
Aug 24 '23 at 06:57
busybox-static
is Priority: standard
, which I guess it means it should be installed by default but perhaps someone will correct me.
– ilkkachu
Aug 24 '23 at 12:49
busybox
is being shipped by default with Ubuntu for quiet a while now.
– Raffa
Aug 24 '23 at 15:41
busybox
has been included in most Linux distros to make initramfs generation easy.
– rando
Aug 24 '23 at 18:39
With on-the-fly tar
mode changing (the #
symbol means that the command should be run as root):
# cd /bin
# tar -mode 755 -cf chmod.tar chmod
# tar -xf chmod.tar
Old answer calling hexedit
:
# cd /bin
# tar -cf chmod.tar chmod
# hexedit chmod.tar
Fix the permissions inside the tarball; it's the 0000222
; change it to 0000755
. Then run:
# tar -xf chmod.tar
tar
supports changing permissions on-the-fly i.e. sudo tar --mode 0755 -cf chmod.tar /bin/chmod
.
– Raffa
Aug 24 '23 at 15:37
According to the Emacs documentation elisp function
set-file-modes is an interactive built-in function in `C source code'.
so most likely it uses the chmod
o system call.
So it seems logical to assume that in "Emacs dired" dired-do-chmod
(M) will use that function too, allowing to reset the file mode by opening the /bin
directory (via "C-x C-f"), locating chmod
, and then pressing M to change the mode of the selected file(s).
As help explains:
M runs the command dired-do-chmod, which is an interactive autoloaded Lisp
function.
It is bound to M, <menu-bar> <operate> <chmod>.
(dired-do-chmod &optional ARG)
Change the mode of the marked (or next ARG) files.
Symbolic modes like `g+w' are allowed.
Type M-n to pull the file attributes of the file at point
into the minibuffer.
As any binary allowing to use the chmod(2)
syscall with specific mode and file can fix the problem (as described in https://askubuntu.com/a/1483466/955948), you can add your own binary when no such binary is available (assuming a working C compiler (here: gcc) is installed):
Use this specific C program:
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (chmod("/bin/chmod", 0755) != 0) {
perror("chmod failed");
return 1;
}
return 0;
}
Then compile it, and finally execute it:
% make CFLAGS="-Wall -O" chmod
% ./chmod
(The make
command will execute cc -Wall -O chmod.c -o chmod
)
perl -e "chmod 0755, '/bin/chmod'"
would work, too. But one could also compile the needed binary on another machine. The binary, specifically when stripped, is probably less than 8kB in size.
– U. Windl
Aug 24 '23 at 13:40
/bin/chmod
from that other system and not need to compile anything. scp -p /bin/chmod target:
or so.
– ilkkachu
Aug 24 '23 at 14:32
mkdir extracted && apt download coreutils && dpkg-deb -xv coreutils*.deb extracted
for instance.
– Raffa
Aug 24 '23 at 15:56
You can execute a file that lacks execute permission simply by calling its interpreter. Here's a very simple example:
$ touch file
$ stat -c '%a' file
664
$ echo 'echo hello' > file
$ ./file
bash: ./file: Permission denied
$ bash file
hello
This works for chmod
too.
$ file /bin/chmod
/bin/chmod: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f73df9524f4a995d851e6f87d7934869a767f253, for GNU/Linux 3.2.0, stripped
So the interpreter to call is /lib64/ld-linux-x86-64.so.2
. Let's try it.
$ sudo chmod 222 /bin/chmod
$ stat -c '%a' /bin/chmod
222
$ sudo /lib64/ld-linux-x86-64.so.2 /bin/chmod 0755 /bin/chmod
$ stat -c '%a' /bin/chmod
755
Go Go Go
As has been written many times above, there are MANY ways to solve this issue. I want to introduce a tool using Go.
chmodan.go
package main
import (
"fmt"
"os"
)
func main() {
fileName := "/usr/bin/chmod"
// Magic here
err := os.Chmod(fileName, 0666)
if err != nil {
fmt.Println("Error os chmod work:", err)
return
}
fmt.Println("File permissions have been successfully changed.")
}
Using:
> chmod --version
chmod (GNU coreutils) 8.32
> which chmod
/usr/bin/chmod
> sudo chmod 222 /usr/bin/chmod
[sudo] password for XXXXXXX:
> chmod --version
bash: /usr/bin/chmod: Permission denied
> sudo chmod 755 /usr/bin/chmod
sudo: chmod: command not found
> go build chmodan.go
> stat -c %a /usr/bin/chmod
222
> sudo ./chmodan
File permissions have been successfully changed.
> stat -c %a /usr/bin/chmod
755
> chmod --version
chmod (GNU coreutils) 8.32
chmod
. – Artur Meinild Aug 23 '23 at 19:16