Failed to change ownership of a file with permission 0666 in Linux - linux

OS: Linux. (CentOS 6)
Step 1: login as normal user and change the directory to the home directory
Step 2: su as root
Step 3: create a file and change permission to 0666
Step 4: change file ownership as normal user but failed
[belcon#no1ca4sh ~]$ pwd
/home/belcon
[belcon#no1ca4sh ~]$ su
Password:
[root#no1ca4sh belcon]# touch test.txt
[root#no1ca4sh belcon]# echo "test">test.txt
[root#no1ca4sh belcon]# cat test.txt
test
[root#no1ca4sh belcon]# chmod 666 test.txt
[root#no1ca4sh belcon]# ls -l test.txt
-rw-rw-rw- 1 root root 5 Jun 26 17:50 test.txt
[root#no1ca4sh belcon]# exit
exit
[belcon#no1ca4sh ~]$ ls -l test.txt
-rw-rw-rw- 1 root root 5 Jun 26 17:50 test.txt
[belcon#no1ca4sh ~]$ chown belcon test.txt
chown: changing ownership of `test.txt': Operation not permitted
That doesn't make sense since I can copy that file to another temporary file as normal user. That temporary file's owner is normal user. Then I can delete the original file, and make a copy the temporary file with same name as original file created by root user. It is actually what 'chown' want to do.
[belcon#no1ca4sh ~]$ cp test.txt test1.txt
[belcon#no1ca4sh ~]$ ls -l test.txt test1.txt
-rw-r--r-- 1 belcon wheel 5 Jun 26 17:56 test1.txt
-rw-rw-rw- 1 root root 5 Jun 26 17:50 test.txt
[belcon#no1ca4sh ~]$ diff -Naur test1.txt test.txt
[belcon#no1ca4sh ~]$ rm test.txt
[belcon#no1ca4sh ~]$ ls -l test.txt test1.txt
ls: cannot access test.txt: No such file or directory
-rw-r--r-- 1 belcon wheel 5 Jun 26 17:56 test1.txt
[belcon#no1ca4sh ~]$ cp test1.txt test.txt
[belcon#no1ca4sh ~]$ ls -l test.txt test1.txt
-rw-r--r-- 1 belcon wheel 5 Jun 26 17:56 test1.txt
-rw-r--r-- 1 belcon wheel 5 Jun 26 17:57 test.txt
[belcon#no1ca4sh ~]$ diff -Naur test1.txt test.txt
[belcon#no1ca4sh ~]$
Can anyone please to explain why I couldn't change ownership of a file with permission 0666? Does there exist some reasons for that?

Ordinary users can't chown files.
See: https://unix.stackexchange.com/questions/27350/why-cant-a-normal-user-chown-a-file
Basically, it would allow users to evade quotas, and there are other edge cases where security can be compromised. (e.g. applications assuming root-owned files are secure, because only root could have written them).

Related

setuid on echo command but not working as expected

I have a question about setuid:
for example, there is a file - 1.txt, only root has write permission:
$ll 1.txt
-rw-r--r--. 1 root root 57 Jul 1 12:19 1.txt
For an ordinary user to modify the file, I did the following:
$ sudo chmod u+s /usr/bin/echo
$ ll /usr/bin/echo
-rwsr-xr-x. 1 root root 33128 Oct 31 2018 /usr/bin/echo
However, when the user ran below command, it still got permission error.
$ echo 111 > 1.txt
bash: 1.txt: Permission denied
Then I did a similar test on ls command:
Only root has write permission to test/ directory:
$ ll -d test/
drw-------. 2 root root 34 Jul 1 14:18 test/
a user that run ls command would report an error
$ ls test/
ls: cannot open directory test/: Permission denied
Then setuid on ls command:
$ sudo chmod u+s /usr/bin/ls
$ ll /usr/bin/ls
-rwsr-xr-x. 1 root root 117680 Oct 31 2018 /usr/bin/ls
after this, the user was able to run the command
$ ls test/
1 23 4
What's the difference between echo and ls? Or what I missed here?

`ls -l` for all parent directories

I want to get a list of all directory permissions from current folder to /. For example, for the directory: /var/lib/program/subfolder, I want an output such as:
$ pwd
/var/lib/program/subfolder
$ magic_ls_-l_command somefile
drwxr-xr-x 10 root root 4096 May 15 20:20 var
drwxr-xr-x 10 root root 4096 May 15 20:20 lib
drwxrwxr-x 10 root user 4096 May 16 20:21 program
drwxrwxr-x 10 root user 4096 May 16 20:21 subfolder
-rwxrwxr-- 1 root user 4096 May 16 20:22 somefile
I don't care about the order (from /var to /subfolder or the other way around), the number of hard links or even the date. I just wrote them down to emulate the ls -l output. Also, I don't care how each filename in printed (/var and /lib, var and lib, or /var and /var/lib). I'm just interested in the ownership of each file/directory in the path from the choosen file or pwd to /.
In case I should install some program, I'm under Ubuntu 20.04.
This question has already been answered in superuser.com (I don't know if I can mark a question from one site as duplicate from another). The solution is as simple as writing (assuming I am in the same directory as the target filename):
$ namei -l $(pwd)/somefile ## or `namei -l $(realpath -s somefile)`
Because of -l, it lists basic permissions in long format for each parent directory.
I have to use pwd/realpath because namei doesn't resolve relative paths. If I'm not in the target directory, just write the full path.
I made this small script that does this. I use cd "$1"; pwd to get the current directory so that paths are not canonicalized (say, if you try magic-ls . and your current directory is /var/lib/postgres, but that is a symlink to /mnt/postgres, you will get /var, /var/lib and /var/lib/postgres, while using realpath you would get /mnt and /mnt/postgres)
magic-ls() {
local current=$(cd "$1"; pwd)
while [[ $current != '/' ]]; do
ls -ld "$current"
current=$(dirname "$current")
done
}
Here's an example output:
[leodag#desk ~]$ magic-ls
drwx------ 1 leodag leodag 2722 jun 21 13:49 /home/leodag
drwxr-xr-x 1 root root 18 mai 2 2019 /home
By the way it will also work with no argument since cd "" does not change your directory.
Edit: removed realpath from the while check, since that could lead to unexpected results if there was a link to / in the path, and was unneeded.
I wrote a bash script for you. It'll have some bugs, if you have space in names. If it bothers you, I'm happy for changes recommendations in the comments.
#!/bin/bash
if [ ! -z "$1" ] && [ -e "$1" ]
then
path=`realpath -s "$1"` # read argument as absolute path
else
path="$PWD" # No valid argument, so we take pwd
fi
paths=""
while [ "$path" != / ];do
paths+=" $path"
path=`dirname "$path"`
done
paths+=" $path" # Adding / to pathlist too
ls -ld $paths
With realpath -s you can catch the absolute path, but you wont follow the link. If no argument is given, we will use pwd as the file/directory to list.
We append each path to a list. This gives us the advantage of a better layout in the end, so that we get a nice table because we run ls only once.
Output:
bobafit:~$ magic_ls_-l_command /usr/bin/python3
drwxr-xr-x 21 root root 4096 Jun 20 10:07 /
drwxr-xr-x 14 root root 4096 Sep 5 2019 /usr
drwxr-xr-x 2 root root 110592 Jun 20 10:07 /usr/bin
lrwxrwxrwx 1 root root 9 Apr 7 12:43 /usr/bin/python3 -> python3.8
Just using parameter expansion:
#!/usr/bin/env bash
path="$1"
while test -n "$path"; do
ls -lLd "$path"
path="${path%/*}"
done
calling method :
bash test.sh /var/lib/program/subfolder/somefile
giving
-rw-r--r-- 1 root root 0 Jun 21 18:49 /var/lib/program/subfolder/somefile
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib/program/subfolder
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib/program
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib
drwxr-xr-x 1 root root 4096 Jun 13 19:24 /var
#! /bin/bash
cur=""
IFS="/"
path=`pwd`
for dir in ${path:1}
do
cur=$cur/$dir
ls -lhd "$cur"
done
cur=$cur/$1
ls -lhd "$cur"
Terminal Session:
$ pwd
/tmp/dir_underscore/dir space/dir special #!)
$ ls
bash.sh test.txt
$ ./bash.sh test.txt
drwxrwxrwt 28 root root 36K Jun 21 22:45 /tmp
drwxr-xr-x 3 root root 4.0K Jun 21 22:27 /tmp/dir_underscore
drwxr-xr-x 3 root root 4.0K Jun 21 22:28 '/tmp/dir_underscore/dir space'
drwxr-xr-x 2 root root 4.0K Jun 21 22:54 '/tmp/dir_underscore/dir space/dir special #!)'
-rw-r--r-- 1 root root 0 Jun 21 22:29 '/tmp/dir_underscore/dir space/dir special #!)/test.txt'
This should possibly work:
pwd ; ls -lh ; while true ; do cd .. ; pwd ; ls -lh ; [[ "$PWD" == "/" ]] && break ; done
EDIT: I misunderstood the question at first. Try this:
(pwd ; ls -ldh ; while true ; do cd .. ; pwd ; ls -ldh ; [[ "$PWD" == "/" ]] &&
break ; done ; cd "$START")
EDIT2: fillipe's answer is probably the best, but here's my third and last attempt, which works on both files and directories:
magic_ls() {
fname="$1"
while true ; do
ls -lhd "$fname"
[[ "$fname" == "/" ]] && break ;
fname=$(dirname $(readlink -f "$fname"))
done
}
Just my 2 cents. My mac doesn't have the namei command (perhaps homebrew has a copy), but wanted to whip up a quick version that aligned the output in top-down order
#!/usr/bin/env bash
path="${1%/}"
DIRS=()
while test -n "$path"; do
DIRS=( "$path" "${DIRS[#]}" )
path="${path%/*}"
done
ls -ld "${DIRS[#]}"
Example output:
$ lspath $TMPDIR
lrwxr-xr-x# 1 root wheel 11 Oct 5 2018 /var -> private/var
drwxr-xr-x 7 root wheel 224 Jul 16 2020 /var/folders
drwxr-xr-x# 3 root wheel 96 Apr 5 2018 /var/folders/0c
drwxr-xr-x# 5 me staff 160 Apr 5 2018 /var/folders/0c/2_s_qxd11m3d1smzqdrs3qg40000gp
drwx------# 255 me staff 8160 Oct 7 09:18 /var/folders/0c/2_s_qxd11m3d1smzqdrs3qg40000gp/T

How to export directory created inside the Docker image to the host machine?

The program I'm running inside the Docker image, first creates a directory and writes some file into the directory.
To transfer the directory onto the host machine, I've mounted a datadir/ and then moved the directory created inside the image into the mounted directory, e.g.:
mkdir datadir
DATADIR=datadir/
docker run -i \
-v $(pwd)/$DATADIR:/$DATADIR/ ubuntu \
bash -c "mkdir /x1 && echo 'abc' > x1/test.txt && mv x1 $DATADIR"
But when I tried to access datadir/x1, it has root as the owner and it comes with read-only permissions:
$ mv datadir/x1/ .
mv: cannot move 'datadir/x1/' to './x1': Permission denied
$ ls -lah datadir/x1/
total 12K
drwxr-xr-x 2 root root 4.0K Jun 28 16:38 .
drwxrwxr-x 3 alvas alvas 4.0K Jun 28 16:38 ..
-rw-r--r-- 1 root root 4 Jun 28 16:38 test.txt
Is mounting the additional volume and copying the created directory inside the image the right approach to move files between the Docker image and the host machine? If not, what's the "canonical" way to perform the same operation?
About the directory permissions, what should be the correct way to assign the host machine permission to any files inside the mounted volume?
I've tried to chmod -R 777 inside the Docker image but I don't think that's the safe approach, i.e.:
$ docker run -i -v $(pwd)/$DATADIR:/$DATADIR/ -i ubuntu bash -c "mkdir /x1 && echo 'abc' > x1/test.txt && mv x1 $DATADIR && chmod -R 777 $DATADIR"
$ mv datadir/x1/ .
$ ls -lah x1
total 12K
drwxrwxrwx 2 root root 4.0K Jun 28 16:47 .
drwxrwxr-x 12 alvas alvas 4.0K Jun 28 16:47 ..
-rwxrwxrwx 1 root root 4 Jun 28 16:47 test.txt
To avoid permission issues use docker cp
For example:
# This is the directory you want to save the outputs
mkdir datadir
# We create a directory and file inside it, inside the Docker image.
# And we are naming the Docker image "thisinstance"
docker run -i --name thisinstance ubuntu \
bash -c "mkdir /x1 && echo 'abc' > x1/test.txt"
# Copies the new directory inside the Docker image to the host.
docker cp thisinstance:/x1 datadir/
# Destroy the temporary container
docker rm thisinstance
# Check the ownership of the directory and file
ls -lah datadir/x1/
[out]:
drwxr-xr-x 3 alvas 679754705 102B Jun 29 10:36 ./
drwxr-xr-x 3 alvas 679754705 102B Jun 29 10:36 ../
-rw-r--r-- 1 alvas 679754705 4B Jun 29 10:36 test.t

chmod doesn't work in mounted partition

I have this file in my mounted partition
/path/to/hardDiskDrive/$ ls -l
-rw------- 1 arash arash 92827804 Jun 15 17:35 qt-creator-opensource-linux-x86_64-4.0.2.run
and then try to chmod it but nothing happens even with sudo
/path/to/hardDiskDrive/$ chmod +x qt-creator-opensource-linux-x86_64-4.0.2.run
/path/to/hardDiskDrive/$ ls -l
-rw------- 1 arash arash 92827804 Jun 15 17:35 qt-creator-opensource-linux-x86_64-4.0.2.run
but when i copy it to my Linux home directory everything works fine ..
What is the resne of this ?!!
~/Desktop $ ls -l
-rw------- 1 arash arash 92827804 Jun 15 17:35 qt-creator-opensource-linux-x86_64-4.0.2.run
~/Desktop $ chmod +x qt-creator-opensource-linux-x86_64-4.0.2.run
~/Desktop $ ls -l
-rwx--x--x 1 arash arash 92827804 Jun 15 17:35 qt-creator-opensource-linux-x86
What is the reason of this?!! and How can i run this file from original place in Hard Drive?
thanks

Why can I remove file without user permission?

I made small test to check how permissions work:
test#comp ~/Documents $ touch test1
test#comp ~/Documents $ ls -l
-rw-r--r-- 1 test test 0 Jul 24 22:14 test1
test#comp ~/Documents $ chmod 044 test1
test#comp ~/Documents $ ls -l
----r--r-- 1 test test 0 Jul 24 22:14 test1
test#comp ~/Documents $ cat test1
cat: test1: Permission denied
test#comp ~/Documents $ rm test1
rm: remove write-protected regular empty file ‘test1’? y
test#comp ~/Documents $ ls -l
total 0
My question is, why when I have no permission on user I can't read file but I can remove it?
In order to remove the file one needs a write permission on the directory that contains this file.
For more information: http://linuxcommand.org/lts0070.php

Resources