Dave Mills
2016-08-23 15:58:39 UTC
Hi,
I noticed and fixed this for myself last year but hadn't got around to
reporting it.. :(
It appears that the current implementation of dirperm1 doesn't use the
correct permission overriding method when checking for whiteouts in dentry.c
The below bash script can simulate the issue:
#!/bin/bash
BASE=/root/aufsissue
BASE2=$BASE/aufs
#Create testuser
#adduser testissue
#Cleanup previous executions
umount $BASE2/mnt 2>/dev/null
rm -R $BASE2 2>/dev/null
#Setup a mount directory and two branches to be overlaid
mkdir $BASE2 $BASE2/branch1 $BASE2/branch2 $BASE2/mnt
#Mount branch1 on $BASE2/mnt
mount -t aufs -o dirperm1,dio,br:$BASE2/branch1=rw none $BASE2/mnt
#make two test directories on the lower branch
mkdir $BASE2/mnt/test1 $BASE2/mnt/test2
#Change permissions of two test directories
chmod -R 755 $BASE2/mnt/test1
chmod -R 700 $BASE2/mnt/test2
#Mount branch2 over branch1 in $BASE2/mnt
mount -t aufs -o
remount,dirperm1,mod:$BASE2/branch1=ro+wh,prepend:$BASE2/branch2=rw none
$BASE2/mnt
#Change ownership of two test directories
chown -R testissue:testissue $BASE2/mnt/test1
chown -R testissue:testissue $BASE2/mnt/test2
#Works correctly
echo
echo This works correctly
su testissue -c "touch $BASE2/mnt/test1/works"
#ls shows file was created
ls -lart $BASE2/branch2/test1
#Fails as unable to check for whiteouts with au_wh_test
#Even though the user "testissue" has ownership it cant read whiteouts
#from the lower branch with permission 700 because at the lower branch
testissue isnt the owner.
#change dentry.c
#wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/0);
#to
#wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/ignore_perm);
echo
echo This fails
su testissue -c "touch $BASE2/mnt/test2/fails"
#ls shows no file was created
ls -lart $BASE2/branch2/test2
The below patch fixed the issue for me:
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -57,7 +57,7 @@
br = au_sbr(dentry->d_sb, bindex);
wh_able = !!au_br_whable(br->br_perm);
if (wh_able)
- wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/0);
+ wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/ignore_perm);
h_dentry = ERR_PTR(wh_found);
if (!wh_found)
goto real_lookup;
Regards
Dave
N.B. Its also listed as this bug in Docker
https://github.com/docker/docker/issues/20240
I noticed and fixed this for myself last year but hadn't got around to
reporting it.. :(
It appears that the current implementation of dirperm1 doesn't use the
correct permission overriding method when checking for whiteouts in dentry.c
The below bash script can simulate the issue:
#!/bin/bash
BASE=/root/aufsissue
BASE2=$BASE/aufs
#Create testuser
#adduser testissue
#Cleanup previous executions
umount $BASE2/mnt 2>/dev/null
rm -R $BASE2 2>/dev/null
#Setup a mount directory and two branches to be overlaid
mkdir $BASE2 $BASE2/branch1 $BASE2/branch2 $BASE2/mnt
#Mount branch1 on $BASE2/mnt
mount -t aufs -o dirperm1,dio,br:$BASE2/branch1=rw none $BASE2/mnt
#make two test directories on the lower branch
mkdir $BASE2/mnt/test1 $BASE2/mnt/test2
#Change permissions of two test directories
chmod -R 755 $BASE2/mnt/test1
chmod -R 700 $BASE2/mnt/test2
#Mount branch2 over branch1 in $BASE2/mnt
mount -t aufs -o
remount,dirperm1,mod:$BASE2/branch1=ro+wh,prepend:$BASE2/branch2=rw none
$BASE2/mnt
#Change ownership of two test directories
chown -R testissue:testissue $BASE2/mnt/test1
chown -R testissue:testissue $BASE2/mnt/test2
#Works correctly
echo
echo This works correctly
su testissue -c "touch $BASE2/mnt/test1/works"
#ls shows file was created
ls -lart $BASE2/branch2/test1
#Fails as unable to check for whiteouts with au_wh_test
#Even though the user "testissue" has ownership it cant read whiteouts
#from the lower branch with permission 700 because at the lower branch
testissue isnt the owner.
#change dentry.c
#wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/0);
#to
#wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/ignore_perm);
echo
echo This fails
su testissue -c "touch $BASE2/mnt/test2/fails"
#ls shows no file was created
ls -lart $BASE2/branch2/test2
The below patch fixed the issue for me:
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -57,7 +57,7 @@
br = au_sbr(dentry->d_sb, bindex);
wh_able = !!au_br_whable(br->br_perm);
if (wh_able)
- wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/0);
+ wh_found = au_wh_test(h_parent, wh_name, /*try_sio*/ignore_perm);
h_dentry = ERR_PTR(wh_found);
if (!wh_found)
goto real_lookup;
Regards
Dave
N.B. Its also listed as this bug in Docker
https://github.com/docker/docker/issues/20240