docker/machine

chmod of home directory : "permission denied" on overlayfs, works with aufs (OSX / DockerMachine)

dieswaytoofast opened this issue · 14 comments

(docker-machine version: 0.7.0; VirtualBox version: 5.0.16 r105871; OSX version: 10.11.4 (15E65))

A newly created user can't chmod their home directory if the storage-driver is overlayfs. It works perfectly with aufs though.
This isn't restricted to home directories. Users can not change permissions on the 'top-most' directory they own.
e.g. Given A / B / C (with A owned by root, and B and C owned by someuser), someuser can change permissions on C, but not on B

Note that there are no host-mounted directories, volumes, etc. This is with a default/baseline ubuntu container...

To test this

Overlay
Create the machine
paglierino:mahesh$ docker-machine create -d virtualbox --engine-storage-driver=overlay dev
Connect to the machine, and start up ubuntu

paglierino:mahesh$ docker-machine ssh default
docker@default:~$ docker run -it ubuntu /bin/bash

Add a user

root@61448047d92a:/# adduser --disabled-password --uid 501 --home /var/lib/postgresql --shell /bin/bash --gecos 'PostgreSQL administrator' postgres
Adding user `postgres' ...
Adding new group `postgres' (501) ...
Adding new user `postgres' (501) with group `postgres' ...
Creating home directory `/var/lib/postgresql' ...
Copying files from `/etc/skel' ...

Try to change permissions for that user, and fial

root@61448047d92a:/# su - postgres
postgres@61448047d92a:~$ pwd
/var/lib/postgresql
postgres@61448047d92a:~$ ls -ald .
drwxr-xr-x 2 postgres postgres 4096 Apr 16 20:16 .
postgres@61448047d92a:~$ chmod 700 .
chmod: changing permissions of '.': Operation not permitted
postgres@61448047d92a:~$ ls -ald .
drwxr-xr-x 2 postgres postgres 4096 Apr 16 20:16 

aufs
Create the machine
paglierino:mahesh$ docker-machine create -d virtualbox --engine-storage-driver=aufs notdev
Connect to the machine, and start up ubuntu

paglierino:mahesh$ docker-machine ssh notdev
docker@default:~$ docker run -it ubuntu /bin/bash

Add a user

root@9ec0a58c827e:/# adduser --disabled-password --uid 501 --home /var/lib/postgresql --shell /bin/bash --gecos 'PostgreSQL administrator' postgres
Adding user `postgres' ...
Adding new group `postgres' (501) ...
Adding new user `postgres' (501) with group `postgres' ...
Creating home directory `/var/lib/postgresql' ...
Copying files from `/etc/skel' ...

Try to change permissions for that user, and profit

root@1f32cac40882:/# su - postgres
postgres@1f32cac40882:~$ ls -ald .
drwxr-xr-x 2 postgres postgres 4096 Apr 16 20:15 .
postgres@1f32cac40882:~$ pwd
/var/lib/postgresql
postgres@1f32cac40882:~$ chmod 700 .
postgres@1f32cac40882:~$ ls -ald .
drwx------ 2 postgres postgres 4096 Apr 16 20:15 .

Hi @dieswaytoofast, thanks for the issue and the detailed steps to reproduce. I think it's an upstream Engine issue and not a Machine issue. It seems that the result should be the same on any system running Docker. Please re-open the ticket at https://github.com/docker/docker/issues/new and the maintainers there may be able to help you.

This works for me on overlay, on a host not created with machine (docker4mac), so I think something else is causing the failure. Can you strace the failing chmod?

@justincormack I get:

postgres@768f5591ab0c:~$ strace chmod 700 .
strace: test_ptrace_setoptions_for_all: PTRACE_TRACEME doesn't work: Operation not permitted
strace: test_ptrace_setoptions_for_all: unexpected exit status 1

Maybe I need more cap in the container?

Alright yeah here we go. Running with --privileged allowed strace to actually work.

postgres@c38c69c41ae1:~$ strace chmod 700 .
execve("/bin/chmod", ["chmod", "700", "."], [/* 13 vars */]) = 0
brk(0)                                  = 0x1f9d000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f18cd6000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=9703, ...}) = 0
mmap(NULL, 9703, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8f18cd3000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8f186f1000
mprotect(0x7f8f188ac000, 2093056, PROT_NONE) = 0
mmap(0x7f8f18aab000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7f8f18aab000
mmap(0x7f8f18ab1000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8f18ab1000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f18cd2000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f18cd0000
arch_prctl(ARCH_SET_FS, 0x7f8f18cd0740) = 0
mprotect(0x7f8f18aab000, 16384, PROT_READ) = 0
mprotect(0x60c000, 4096, PROT_READ)     = 0
mprotect(0x7f8f18cd8000, 4096, PROT_READ) = 0
munmap(0x7f8f18cd3000, 9703)            = 0
brk(0)                                  = 0x1f9d000
brk(0x1fbe000)                          = 0x1fbe000
umask(0)                                = 02
stat(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
fchmodat(AT_FDCWD, ".", 0700)           = -1 EPERM (Operation not permitted)
open("/usr/lib/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory)
write(2, "chmod: ", 7chmod: )                  = 7
write(2, "changing permissions of '.'", 27changing permissions of '.') = 27
write(2, ": Operation not permitted", 25: Operation not permitted) = 25
write(2, "\n", 1
)                       = 1
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

Thats not very helpful. Which kernel is this?

@justincormack 4.1.19

Linux default 4.1.19-boot2docker #1 SMP Thu Apr 7 02:41:05 UTC 2016 x86_64 GNU/Linux

It does look very much like https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1555997 but in a different kernel version. I wonder if the bug got backported? You could test not in a container with this https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1555997/comments/3

(docker for mac seems fine, but it switched to 4.4 series kernel recently, used to be almost same kernel as boot2docker)

I'll try that minimal dupe and see if I get same results

Yup. It's a 🐞 upstream

docker@default:~$ mkdir /tmp/lower /tmp/upper /tmp/work /tmp/merged
docker@default:~$ sudo mount -t overlay overlay -o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work /tmp/merged
docker@default:~$ sudo touch /tmp/merged/testfile
docker@default:~$ sudo chown +x /tmp/merged/testfile
chown: unknown user +x
docker@default:~$ sudo chown $USER:$USER /tmp/merged/testfile
docker@default:~$ chmod +x /tmp/merged/testfile
chmod: /tmp/merged/testfile: Operation not permitted

@tianon FYI

Lovely -- think it's time we bumped boot2docker to the 4.4 series too? 😄

(It's a longterm, just like 4.1.)

Since we're working on this elsewhere, going to go ahead and close. Thanks @dieswaytoofast @justincormack @tianon for your effort.