Discussion:
dirperm1 and whiteouts bug
Dave Mills
2016-08-23 15:58:39 UTC
Permalink
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
Dave Mills
2016-08-23 16:28:01 UTC
Permalink
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/br
anch1=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/dock
er/docker/issues/20240

Loading...