Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Aufs5 Standalone
Commits
d9a6b724
Commit
d9a6b724
authored
Mar 06, 2021
by
J. R. Okajima
Browse files
Merge branch 'aufs5.x-rcN/01modular' into aufs5.x-rcN/30stdalone
parents
a8170db3
acf24615
Changes
20
Hide whitespace changes
Inline
Side-by-side
fs/aufs/branch.h
View file @
d9a6b724
...
...
@@ -146,6 +146,11 @@ static inline struct dentry *au_br_dentry(struct au_branch *br)
return
br
->
br_path
.
dentry
;
}
static
inline
struct
user_namespace
*
au_br_userns
(
struct
au_branch
*
br
)
{
return
mnt_user_ns
(
br
->
br_path
.
mnt
);
}
static
inline
struct
super_block
*
au_br_sb
(
struct
au_branch
*
br
)
{
return
au_br_mnt
(
br
)
->
mnt_sb
;
...
...
@@ -304,6 +309,12 @@ struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
return
au_br_mnt
(
au_sbr
(
sb
,
bindex
));
}
static
inline
struct
user_namespace
*
au_sbr_userns
(
struct
super_block
*
sb
,
aufs_bindex_t
bindex
)
{
return
au_br_userns
(
au_sbr
(
sb
,
bindex
));
}
static
inline
struct
super_block
*
au_sbr_sb
(
struct
super_block
*
sb
,
aufs_bindex_t
bindex
)
{
...
...
fs/aufs/cpup.c
View file @
d9a6b724
...
...
@@ -164,7 +164,7 @@ struct au_cpup_reg_attr {
};
static
noinline_for_stack
int
cpup_iattr
(
struct
dentry
*
dst
,
aufs_bindex_t
bindex
,
struct
dentry
*
h_src
,
int
cpup_iattr
(
struct
dentry
*
dst
,
aufs_bindex_t
bindex
,
struct
path
*
h_src
,
struct
au_cpup_reg_attr
*
h_src_attr
)
{
int
err
,
sbits
,
icex
;
...
...
@@ -176,11 +176,11 @@ int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
struct
kstat
*
h_st
;
struct
au_branch
*
br
;
h_path
.
dentry
=
au_h_dptr
(
dst
,
bindex
);
h_idst
=
d_inode
(
h_path
.
dentry
);
br
=
au_sbr
(
dst
->
d_sb
,
bindex
);
h_path
.
mnt
=
au_br_mnt
(
br
);
h_isrc
=
d_inode
(
h_src
);
h_path
.
dentry
=
au_h_dptr
(
dst
,
bindex
);
h_idst
=
d_inode
(
h_path
.
dentry
);
h_isrc
=
d_inode
(
h_src
->
dentry
);
ia
.
ia_valid
=
ATTR_FORCE
|
ATTR_UID
|
ATTR_GID
|
ATTR_ATIME
|
ATTR_MTIME
|
ATTR_ATIME_SET
|
ATTR_MTIME_SET
;
...
...
@@ -224,7 +224,7 @@ int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
if
(
!
err
)
{
mnt_flags
=
au_mntflags
(
dst
->
d_sb
);
verbose
=
!!
au_opt_test
(
mnt_flags
,
VERBOSE
);
err
=
au_cpup_xattr
(
h_path
.
dentry
,
h_src
,
icex
,
verbose
);
err
=
au_cpup_xattr
(
&
h_path
,
h_src
,
icex
,
verbose
);
}
return
err
;
...
...
@@ -594,16 +594,18 @@ static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
int
err
;
struct
dentry
*
h_dentry
;
struct
inode
*
h_inode
;
struct
user_namespace
*
h_userns
;
h_userns
=
mnt_user_ns
(
h_path
->
mnt
);
h_dentry
=
h_path
->
dentry
;
h_inode
=
d_inode
(
h_dentry
);
/* forget_all_cached_acls(h_inode)); */
err
=
vfsub_removexattr
(
h_dentry
,
XATTR_NAME_POSIX_ACL_ACCESS
);
err
=
vfsub_removexattr
(
h_userns
,
h_dentry
,
XATTR_NAME_POSIX_ACL_ACCESS
);
AuTraceErr
(
err
);
if
(
err
==
-
EOPNOTSUPP
)
err
=
0
;
if
(
!
err
)
err
=
vfsub_acl_chmod
(
h_inode
,
mode
);
err
=
vfsub_acl_chmod
(
h_userns
,
h_inode
,
mode
);
AuTraceErr
(
err
);
return
err
;
...
...
@@ -614,8 +616,11 @@ static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
{
int
err
;
struct
inode
*
dir
,
*
inode
;
struct
user_namespace
*
h_userns
;
err
=
vfsub_removexattr
(
h_path
->
dentry
,
XATTR_NAME_POSIX_ACL_DEFAULT
);
h_userns
=
mnt_user_ns
(
h_path
->
mnt
);
err
=
vfsub_removexattr
(
h_userns
,
h_path
->
dentry
,
XATTR_NAME_POSIX_ACL_DEFAULT
);
AuTraceErr
(
err
);
if
(
err
==
-
EOPNOTSUPP
)
err
=
0
;
...
...
@@ -796,6 +801,7 @@ static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
struct
inode
*
dst_inode
,
*
h_dir
,
*
inode
,
*
delegated
,
*
src_inode
;
struct
super_block
*
sb
;
struct
au_branch
*
br
;
struct
path
h_src_path
;
/* to reduce stack size */
struct
{
struct
au_dtime
dt
;
...
...
@@ -887,7 +893,9 @@ static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
/* todo: necessary? */
/* au_pin_hdir_unlock(cpg->pin); */
err
=
cpup_iattr
(
cpg
->
dentry
,
cpg
->
bdst
,
h_src
,
&
a
->
h_src_attr
);
h_src_path
.
dentry
=
h_src
;
h_src_path
.
mnt
=
au_sbr_mnt
(
sb
,
cpg
->
bsrc
);
err
=
cpup_iattr
(
cpg
->
dentry
,
cpg
->
bdst
,
&
h_src_path
,
&
a
->
h_src_attr
);
if
(
unlikely
(
err
))
{
/* todo: necessary? */
/* au_pin_hdir_relock(cpg->pin); */
/* ignore an error */
...
...
@@ -1089,6 +1097,7 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
struct
dentry
*
dentry
,
*
parent
;
struct
file
*
h_file
;
struct
inode
*
h_dir
;
struct
user_namespace
*
h_userns
;
dentry
=
cpg
->
dentry
;
h_file
=
NULL
;
...
...
@@ -1102,7 +1111,8 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
parent
=
dget_parent
(
dentry
);
h_dir
=
au_h_iptr
(
d_inode
(
parent
),
cpg
->
bdst
);
if
(
!
au_test_h_perm_sio
(
h_dir
,
MAY_EXEC
|
MAY_WRITE
)
h_userns
=
au_sbr_userns
(
dentry
->
d_sb
,
cpg
->
bdst
);
if
(
!
au_test_h_perm_sio
(
h_userns
,
h_dir
,
MAY_EXEC
|
MAY_WRITE
)
&&
!
au_cpup_sio_test
(
cpg
->
pin
,
d_inode
(
dentry
)
->
i_mode
))
err
=
au_cpup_simple
(
cpg
);
else
{
...
...
@@ -1272,6 +1282,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
struct
inode
*
dir
,
*
h_dir
,
*
h_tmpdir
;
struct
au_wbr
*
wbr
;
struct
au_pin
wh_pin
,
*
pin_orig
;
struct
user_namespace
*
h_userns
;
dentry
=
cpg
->
dentry
;
bdst
=
cpg
->
bdst
;
...
...
@@ -1300,7 +1311,8 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
cpg
->
pin
=
&
wh_pin
;
}
if
(
!
au_test_h_perm_sio
(
h_tmpdir
,
MAY_EXEC
|
MAY_WRITE
)
h_userns
=
au_sbr_userns
(
dentry
->
d_sb
,
bdst
);
if
(
!
au_test_h_perm_sio
(
h_userns
,
h_tmpdir
,
MAY_EXEC
|
MAY_WRITE
)
&&
!
au_cpup_sio_test
(
cpg
->
pin
,
d_inode
(
dentry
)
->
i_mode
))
err
=
au_cpup_wh
(
cpg
,
file
);
else
{
...
...
fs/aufs/dentry.c
View file @
d9a6b724
...
...
@@ -35,6 +35,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
struct
dentry
*
h_dentry
;
struct
inode
*
h_inode
;
struct
au_branch
*
br
;
struct
user_namespace
*
h_userns
;
int
wh_found
,
opq
;
unsigned
char
wh_able
;
const
unsigned
char
allow_neg
=
!!
au_ftest_lkup
(
args
->
flags
,
ALLOW_NEG
);
...
...
@@ -43,9 +44,11 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
wh_found
=
0
;
br
=
au_sbr
(
dentry
->
d_sb
,
bindex
);
h_userns
=
au_br_userns
(
br
);
wh_able
=
!!
au_br_whable
(
br
->
br_perm
);
if
(
wh_able
)
wh_found
=
au_wh_test
(
h_parent
,
&
args
->
whname
,
ignore_perm
);
wh_found
=
au_wh_test
(
h_userns
,
h_parent
,
&
args
->
whname
,
ignore_perm
);
h_dentry
=
ERR_PTR
(
wh_found
);
if
(
!
wh_found
)
goto
real_lookup
;
...
...
@@ -62,7 +65,7 @@ real_lookup:
if
(
!
ignore_perm
)
h_dentry
=
vfsub_lkup_one
(
args
->
name
,
h_parent
);
else
h_dentry
=
au_sio_lkup_one
(
args
->
name
,
h_parent
);
h_dentry
=
au_sio_lkup_one
(
h_userns
,
args
->
name
,
h_parent
);
if
(
IS_ERR
(
h_dentry
))
{
if
(
PTR_ERR
(
h_dentry
)
==
-
ENAMETOOLONG
&&
!
allow_neg
)
...
...
@@ -97,7 +100,7 @@ real_lookup:
goto
out
;
/* success */
inode_lock_shared_nested
(
h_inode
,
AuLsc_I_CHILD
);
opq
=
au_diropq_test
(
h_dentry
);
opq
=
au_diropq_test
(
h_userns
,
h_dentry
);
inode_unlock_shared
(
h_inode
);
if
(
opq
>
0
)
au_set_dbdiropq
(
dentry
,
bindex
);
...
...
@@ -242,12 +245,13 @@ out:
return
err
;
}
struct
dentry
*
au_sio_lkup_one
(
struct
qstr
*
name
,
struct
dentry
*
parent
)
struct
dentry
*
au_sio_lkup_one
(
struct
user_namespace
*
userns
,
struct
qstr
*
name
,
struct
dentry
*
parent
)
{
struct
dentry
*
dentry
;
int
wkq_err
;
if
(
!
au_test_h_perm_sio
(
d_inode
(
parent
),
MAY_EXEC
))
if
(
!
au_test_h_perm_sio
(
userns
,
d_inode
(
parent
),
MAY_EXEC
))
dentry
=
vfsub_lkup_one
(
name
,
parent
);
else
{
struct
vfsub_lkup_one_args
args
=
{
...
...
@@ -272,14 +276,16 @@ int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
int
err
;
struct
dentry
*
parent
,
*
h_parent
,
*
h_dentry
;
struct
au_branch
*
br
;
struct
user_namespace
*
h_userns
;
parent
=
dget_parent
(
dentry
);
h_parent
=
au_h_dptr
(
parent
,
bindex
);
br
=
au_sbr
(
dentry
->
d_sb
,
bindex
);
h_userns
=
au_br_userns
(
br
);
if
(
wh
)
h_dentry
=
au_whtmp_lkup
(
h_parent
,
br
,
&
dentry
->
d_name
);
else
h_dentry
=
au_sio_lkup_one
(
&
dentry
->
d_name
,
h_parent
);
h_dentry
=
au_sio_lkup_one
(
h_userns
,
&
dentry
->
d_name
,
h_parent
);
err
=
PTR_ERR
(
h_dentry
);
if
(
IS_ERR
(
h_dentry
))
goto
out
;
...
...
fs/aufs/dentry.h
View file @
d9a6b724
...
...
@@ -73,7 +73,8 @@ struct au_do_lookup_args {
/* dentry.c */
extern
const
struct
dentry_operations
aufs_dop
,
aufs_dop_noreval
;
struct
au_branch
;
struct
dentry
*
au_sio_lkup_one
(
struct
qstr
*
name
,
struct
dentry
*
parent
);
struct
dentry
*
au_sio_lkup_one
(
struct
user_namespace
*
userns
,
struct
qstr
*
name
,
struct
dentry
*
parent
);
int
au_h_verify
(
struct
dentry
*
h_dentry
,
unsigned
int
udba
,
struct
inode
*
h_dir
,
struct
dentry
*
h_parent
,
struct
au_branch
*
br
);
...
...
fs/aufs/dir.c
View file @
d9a6b724
...
...
@@ -637,12 +637,14 @@ static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
int
err
,
wkq_err
;
struct
dentry
*
h_dentry
;
struct
inode
*
h_inode
;
struct
user_namespace
*
h_userns
;
h_userns
=
au_sbr_userns
(
dentry
->
d_sb
,
arg
->
bindex
);
h_dentry
=
au_h_dptr
(
dentry
,
arg
->
bindex
);
h_inode
=
d_inode
(
h_dentry
);
/* todo: i_mode changes anytime? */
inode_lock_shared_nested
(
h_inode
,
AuLsc_I_CHILD
);
err
=
au_test_h_perm_sio
(
h_inode
,
MAY_EXEC
|
MAY_READ
);
err
=
au_test_h_perm_sio
(
h_userns
,
h_inode
,
MAY_EXEC
|
MAY_READ
);
inode_unlock_shared
(
h_inode
);
if
(
!
err
)
err
=
do_test_empty
(
dentry
,
arg
);
...
...
fs/aufs/dirren.c
View file @
d9a6b724
...
...
@@ -267,6 +267,7 @@ static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
err
=
PTR_ERR
(
hinopath
.
dentry
);
if
(
IS_ERR
(
hinopath
.
dentry
))
goto
out_unlock
;
hinopath
.
mnt
=
path
->
mnt
;
err
=
0
;
flags
=
O_RDONLY
;
...
...
@@ -297,7 +298,6 @@ static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
}
flags
=
O_WRONLY
;
}
hinopath
.
mnt
=
path
->
mnt
;
hinofile
=
vfsub_dentry_open
(
&
hinopath
,
flags
);
if
(
suspend
)
au_hn_inode_unlock
(
hdir
);
...
...
fs/aufs/i_op.c
View file @
d9a6b724
...
...
@@ -32,6 +32,7 @@ static int h_permission(struct inode *h_inode, int mask,
{
int
err
;
const
unsigned
char
write_mask
=
!!
(
mask
&
(
MAY_WRITE
|
MAY_APPEND
));
struct
user_namespace
*
h_userns
;
err
=
-
EPERM
;
if
(
write_mask
&&
IS_IMMUTABLE
(
h_inode
))
...
...
@@ -51,19 +52,21 @@ static int h_permission(struct inode *h_inode, int mask,
* - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
* in this case, generic_permission() returns -EOPNOTSUPP.
*/
h_userns
=
mnt_user_ns
(
h_path
->
mnt
);
if
((
write_mask
&&
!
au_br_writable
(
brperm
))
||
(
au_test_nfs
(
h_inode
->
i_sb
)
&&
S_ISDIR
(
h_inode
->
i_mode
)
&&
write_mask
&&
!
(
mask
&
MAY_READ
))
||
!
h_inode
->
i_op
->
permission
)
{
/* AuLabel(generic_permission); */
/* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
err
=
generic_permission
(
h_inode
,
mask
);
err
=
generic_permission
(
h_userns
,
h_inode
,
mask
);
if
(
err
==
-
EOPNOTSUPP
&&
au_test_nfs_noacl
(
h_inode
))
err
=
h_inode
->
i_op
->
permission
(
h_inode
,
mask
);
err
=
h_inode
->
i_op
->
permission
(
h_userns
,
h_inode
,
mask
);
AuTraceErr
(
err
);
}
else
{
/* AuLabel(h_inode->permission); */
err
=
h_inode
->
i_op
->
permission
(
h_inode
,
mask
);
err
=
h_inode
->
i_op
->
permission
(
h_userns
,
h_inode
,
mask
);
AuTraceErr
(
err
);
}
...
...
@@ -76,7 +79,8 @@ out:
return
err
;
}
static
int
aufs_permission
(
struct
inode
*
inode
,
int
mask
)
static
int
aufs_permission
(
struct
user_namespace
*
userns
,
struct
inode
*
inode
,
int
mask
)
{
int
err
;
aufs_bindex_t
bindex
,
bbot
;
...
...
@@ -924,18 +928,20 @@ out:
return
err
;
}
static
int
aufs_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
ia
)
static
int
aufs_setattr
(
struct
user_namespace
*
userns
,
struct
dentry
*
dentry
,
struct
iattr
*
ia
)
{
int
err
;
struct
inode
*
inode
,
*
delegated
;
struct
super_block
*
sb
;
struct
file
*
file
;
struct
au_icpup_args
*
a
;
struct
user_namespace
*
h_userns
;
inode
=
d_inode
(
dentry
);
IMustLock
(
inode
);
err
=
setattr_prepare
(
dentry
,
ia
);
err
=
setattr_prepare
(
userns
,
dentry
,
ia
);
if
(
unlikely
(
err
))
goto
out
;
...
...
@@ -1028,8 +1034,10 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
* regardless aufs 'acl' option setting.
* why don't all acl-aware fs call this func from their ->setattr()?
*/
if
(
!
err
&&
(
ia
->
ia_valid
&
ATTR_MODE
))
err
=
vfsub_acl_chmod
(
a
->
h_inode
,
ia
->
ia_mode
);
if
(
!
err
&&
(
ia
->
ia_valid
&
ATTR_MODE
))
{
h_userns
=
mnt_user_ns
(
a
->
h_path
.
mnt
);
err
=
vfsub_acl_chmod
(
h_userns
,
a
->
h_inode
,
ia
->
ia_mode
);
}
if
(
!
err
)
au_cpup_attr_changeable
(
inode
);
...
...
@@ -1091,6 +1099,7 @@ ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
struct
super_block
*
sb
;
struct
au_icpup_args
*
a
;
struct
inode
*
h_inode
;
struct
user_namespace
*
h_userns
;
IMustLock
(
inode
);
...
...
@@ -1109,23 +1118,25 @@ ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
err
=
au_h_path_to_set_attr
(
dentry
,
a
,
&
h_path
);
if
(
unlikely
(
err
))
goto
out_di
;
h_userns
=
mnt_user_ns
(
h_path
.
mnt
);
inode_unlock
(
a
->
h_inode
);
switch
(
arg
->
type
)
{
case
AU_XATTR_SET
:
AuDebugOn
(
d_is_negative
(
h_path
.
dentry
));
err
=
vfsub_setxattr
(
h_path
.
dentry
,
err
=
vfsub_setxattr
(
h_userns
,
h_path
.
dentry
,
arg
->
u
.
set
.
name
,
arg
->
u
.
set
.
value
,
arg
->
u
.
set
.
size
,
arg
->
u
.
set
.
flags
);
break
;
case
AU_ACL_SET
:
err
=
-
EOPNOTSUPP
;
h_inode
=
d_inode
(
h_path
.
dentry
);
if
(
h_inode
->
i_op
->
set_acl
)
if
(
h_inode
->
i_op
->
set_acl
)
{
/* this will call posix_acl_update_mode */
err
=
h_inode
->
i_op
->
set_acl
(
h_inode
,
err
=
h_inode
->
i_op
->
set_acl
(
h_userns
,
h_inode
,
arg
->
u
.
acl_set
.
acl
,
arg
->
u
.
acl_set
.
type
);
}
break
;
}
if
(
!
err
)
...
...
@@ -1256,8 +1267,8 @@ out:
return
err
;
}
static
int
aufs_getattr
(
const
struct
path
*
path
,
struct
kst
at
*
st
,
u32
request
,
unsigned
int
query
)
static
int
aufs_getattr
(
struct
user_namespace
*
userns
,
const
struct
p
at
h
*
path
,
struct
kstat
*
st
,
u32
request
,
unsigned
int
query
)
{
int
err
;
unsigned
char
positive
;
...
...
@@ -1294,7 +1305,7 @@ static int aufs_getattr(const struct path *path, struct kstat *st,
goto
out_di
;
out_fill:
generic_fillattr
(
inode
,
st
);
generic_fillattr
(
userns
,
inode
,
st
);
out_di:
di_read_unlock
(
dentry
,
AuLock_IR
);
out_si:
...
...
fs/aufs/i_op_add.c
View file @
d9a6b724
...
...
@@ -366,8 +366,8 @@ out:
return
err
;
}
int
aufs_mknod
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
dev_t
dev
)
int
aufs_mknod
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
dev_t
dev
)
{
struct
simple_arg
arg
=
{
.
type
=
Mknod
,
...
...
@@ -379,7 +379,8 @@ int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
return
add_simple
(
dir
,
dentry
,
&
arg
);
}
int
aufs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
)
int
aufs_symlink
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
)
{
struct
simple_arg
arg
=
{
.
type
=
Symlink
,
...
...
@@ -388,8 +389,8 @@ int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
return
add_simple
(
dir
,
dentry
,
&
arg
);
}
int
aufs_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
bool
want_excl
)
int
aufs_create
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
bool
want_excl
)
{
struct
simple_arg
arg
=
{
.
type
=
Creat
,
...
...
@@ -416,7 +417,8 @@ int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
return
add_simple
(
dir
,
dentry
,
&
arg
);
}
int
aufs_tmpfile
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
)
int
aufs_tmpfile
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
)
{
int
err
;
aufs_bindex_t
bindex
;
...
...
@@ -424,6 +426,7 @@ int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
struct
dentry
*
parent
,
*
h_parent
,
*
h_dentry
;
struct
inode
*
h_dir
,
*
inode
;
struct
vfsmount
*
h_mnt
;
struct
user_namespace
*
h_userns
;
struct
au_wr_dir_args
wr_dir_args
=
{
.
force_btgt
=
-
1
,
.
flags
=
AuWrDir_TMPFILE
...
...
@@ -470,8 +473,9 @@ int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
if
(
unlikely
(
err
))
goto
out_parent
;
h_userns
=
mnt_user_ns
(
h_mnt
);
h_parent
=
au_h_dptr
(
parent
,
bindex
);
h_dentry
=
vfs_tmpfile
(
h_parent
,
mode
,
/*open_flag*/
0
);
h_dentry
=
vfs_tmpfile
(
h_userns
,
h_parent
,
mode
,
/*open_flag*/
0
);
if
(
IS_ERR
(
h_dentry
))
{
err
=
PTR_ERR
(
h_dentry
);
goto
out_mnt
;
...
...
@@ -827,7 +831,8 @@ out:
return
err
;
}
int
aufs_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
)
int
aufs_mkdir
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
)
{
int
err
,
rerr
;
aufs_bindex_t
bindex
;
...
...
fs/aufs/i_op_del.c
View file @
d9a6b724
...
...
@@ -94,6 +94,7 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
umode_t
h_mode
;
struct
dentry
*
h_dentry
,
*
h_latest
;
struct
inode
*
h_inode
;
struct
user_namespace
*
h_userns
;
h_dentry
=
au_h_dptr
(
dentry
,
bindex
);
if
(
d_really_is_positive
(
dentry
))
{
...
...
@@ -131,12 +132,13 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
* let's try heavy test.
*/
err
=
-
EACCES
;
h_userns
=
au_sbr_userns
(
dentry
->
d_sb
,
bindex
);
if
(
unlikely
(
!
au_opt_test
(
au_mntflags
(
dentry
->
d_sb
),
DIRPERM1
)
&&
au_test_h_perm
(
d_inode
(
h_parent
),
&&
au_test_h_perm
(
h_userns
,
d_inode
(
h_parent
),
MAY_EXEC
|
MAY_WRITE
)))
goto
out
;
h_latest
=
au_sio_lkup_one
(
&
dentry
->
d_name
,
h_parent
);
h_latest
=
au_sio_lkup_one
(
h_userns
,
&
dentry
->
d_name
,
h_parent
);
err
=
-
EIO
;
if
(
IS_ERR
(
h_latest
))
goto
out
;
...
...
fs/aufs/i_op_ren.c
View file @
d9a6b724
...
...
@@ -953,7 +953,8 @@ static void au_ren_rev_dt(int err, struct au_ren_args *a)
/* ---------------------------------------------------------------------- */
int
aufs_rename
(
struct
inode
*
_src_dir
,
struct
dentry
*
_src_dentry
,
int
aufs_rename
(
struct
user_namespace
*
userns
,
struct
inode
*
_src_dir
,
struct
dentry
*
_src_dentry
,
struct
inode
*
_dst_dir
,
struct
dentry
*
_dst_dentry
,
unsigned
int
_flags
)
{
...
...
fs/aufs/inode.c
View file @
d9a6b724
...
...
@@ -512,18 +512,20 @@ int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
return
err
;
}
int
au_test_h_perm
(
struct
inode
*
h_inode
,
int
mask
)
int
au_test_h_perm
(
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
int
mask
)
{
if
(
uid_eq
(
current_fsuid
(),
GLOBAL_ROOT_UID
))
return
0
;
return
inode_permission
(
h_inode
,
mask
);
return
inode_permission
(
h_userns
,
h_inode
,
mask
);
}
int
au_test_h_perm_sio
(
struct
inode
*
h_inode
,
int
mask
)
int
au_test_h_perm_sio
(
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
int
mask
)
{
if
(
au_test_nfs
(
h_inode
->
i_sb
)
&&
(
mask
&
MAY_WRITE
)
&&
S_ISDIR
(
h_inode
->
i_mode
))
mask
|=
MAY_READ
;
/* force permission check */
return
au_test_h_perm
(
h_inode
,
mask
);
return
au_test_h_perm
(
h_userns
,
h_inode
,
mask
);
}
fs/aufs/inode.h
View file @
d9a6b724
...
...
@@ -137,8 +137,10 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
struct
inode
*
au_new_inode
(
struct
dentry
*
dentry
,
int
must_new
);
int
au_test_ro
(
struct
super_block
*
sb
,
aufs_bindex_t
bindex
,
struct
inode
*
inode
);
int
au_test_h_perm
(
struct
inode
*
h_inode
,
int
mask
);
int
au_test_h_perm_sio
(
struct
inode
*
h_inode
,
int
mask
);
int
au_test_h_perm
(
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
int
mask
);
int
au_test_h_perm_sio
(
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
int
mask
);
static
inline
int
au_wh_ino
(
struct
super_block
*
sb
,
aufs_bindex_t
bindex
,
ino_t
h_ino
,
unsigned
int
d_type
,
ino_t
*
ino
)
...
...
@@ -213,18 +215,21 @@ int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
/* i_op_add.c */
int
au_may_add
(
struct
dentry
*
dentry
,
aufs_bindex_t
bindex
,
struct
dentry
*
h_parent
,
int
isdir
);
int
aufs_mknod
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
dev_t
dev
);
int
aufs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
);
int
aufs_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
bool
want_excl
);
int
aufs_mknod
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
dev_t
dev
);
int
aufs_symlink
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
);
int
aufs_create
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
bool
want_excl
);
struct
vfsub_aopen_args
;
int
au_aopen_or_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
vfsub_aopen_args
*
args
);
int
aufs_tmpfile
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
);
int
aufs_tmpfile
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
);
int
aufs_link
(
struct
dentry
*
src_dentry
,
struct
inode
*
dir
,
struct
dentry
*
dentry
);
int
aufs_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
);
int
aufs_mkdir
(
struct
user_namespace
*
userns
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
);
/* i_op_del.c */
int
au_wr_dir_need_wh
(
struct
dentry
*
dentry
,
int
isdir
,
aufs_bindex_t
*
bcpup
);
...
...
@@ -235,9 +240,10 @@ int aufs_rmdir(struct inode *dir, struct dentry *dentry);
/* i_op_ren.c */
int
au_wbr
(
struct
dentry
*
dentry
,
aufs_bindex_t
btgt
);
int
aufs_rename
(
struct
inode
*
src_dir
,
struct
dentry
*
src_dentry
,
struct
inode
*
dir
,
struct
dentry
*
dentry
,
unsigned
int
flags
);
int
aufs_rename
(
struct
user_namespace
*
userns
,
struct
inode
*
_src_dir
,
struct
dentry
*
_src_dentry
,
struct
inode
*
_dst_dir
,
struct
dentry
*
_dst_dentry
,
unsigned
int
_flags
);
/* iinfo.c */
struct
inode
*
au_h_iptr
(
struct
inode
*
inode
,
aufs_bindex_t
bindex
);
...
...
@@ -307,19 +313,20 @@ AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
#ifdef CONFIG_AUFS_XATTR
/* xattr.c */
int
au_cpup_xattr
(
struct
dentry
*
h_dst
,
struct
dentry
*
h_src
,
int
ignore_flags
,
int
au_cpup_xattr
(
struct
path
*
h_dst
,
struct
path
*
h_src
,
int
ignore_flags
,
unsigned
int
verbose
);
ssize_t
aufs_listxattr
(
struct
dentry
*
dentry
,
char
*
list
,
size_t
size
);
void
au_xattr_init
(
struct
super_block
*
sb
);
#else
AuStubInt0
(
au_cpup_xattr
,
struct
dentry
*
h_dst
,
struct
dentry
*
h_src
,
AuStubInt0
(
au_cpup_xattr
,
struct
path
*
h_dst
,
struct
path
*
h_src
,
int
ignore_flags
,
unsigned
int
verbose
);
AuStubVoid
(
au_xattr_init
,
struct
super_block
*
sb
);
#endif
#ifdef CONFIG_FS_POSIX_ACL
struct
posix_acl
*
aufs_get_acl
(
struct
inode
*
inode
,
int
type
);
int
aufs_set_acl
(
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
);
int
aufs_set_acl
(
struct
user_namespace
*
userns
,
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
);
#endif
#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
...
...
fs/aufs/posix_acl.c
View file @
d9a6b724
...
...
@@ -63,7 +63,8 @@ out:
return
acl
;
}
int
aufs_set_acl
(
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
)
int
aufs_set_acl
(
struct
user_namespace
*
userns
,
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
)
{
int
err
;
ssize_t
ssz
;
...
...
fs/aufs/super.c
View file @
d9a6b724
...
...
@@ -1039,7 +1039,10 @@ static void aufs_kill_sb(struct super_block *sb)
struct
file_system_type
aufs_fs_type
=
{
.
name
=
AUFS_FSTYPE
,
/* a race between rename and others */
.
fs_flags
=
FS_RENAME_DOES_D_MOVE
,
.
fs_flags
=
FS_RENAME_DOES_D_MOVE
/* untested */
/*| FS_ALLOW_IDMAP*/
,
.
mount
=
aufs_mount
,
.
kill_sb
=
aufs_kill_sb
,
/* no need to __module_get() and module_put(). */
...
...
fs/aufs/vfsub.c
View file @
d9a6b724
...
...
@@ -244,6 +244,7 @@ int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -253,9 +254,10 @@ int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_create
(
dir
,
path
->
dentry
,
mode
,
want_excl
);
err
=
vfs_create
(
userns
,
dir
,
path
->
dentry
,
mode
,
want_excl
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
*
path
;
...
...
@@ -277,6 +279,7 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -286,9 +289,10 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_symlink
(
dir
,
path
->
dentry
,
symname
);
err
=
vfs_symlink
(
userns
,
dir
,
path
->
dentry
,
symname
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
*
path
;
...
...
@@ -310,6 +314,7 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -319,9 +324,10 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_mknod
(
dir
,
path
->
dentry
,
mode
,
dev
);
err
=
vfs_mknod
(
userns
,
dir
,
path
->
dentry
,
mode
,
dev
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
*
path
;
...
...
@@ -354,6 +360,7 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -368,9 +375,10 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_link
(
src_dentry
,
dir
,
path
->
dentry
,
delegated_inode
);
err
=
vfs_link
(
src_dentry
,
userns
,
dir
,
path
->
dentry
,
delegated_inode
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
*
path
;
...
...
@@ -396,6 +404,7 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
struct
inode
**
delegated_inode
,
unsigned
int
flags
)
{
int
err
;
struct
renamedata
rd
;
struct
path
tmp
=
{
.
mnt
=
path
->
mnt
};
...
...
@@ -412,9 +421,16 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
if
(
unlikely
(
err
))
goto
out
;
rd
.
old_mnt_userns
=
mnt_user_ns
(
path
->
mnt
);
rd
.
old_dir
=
src_dir
;
rd
.
old_dentry
=
src_dentry
;
rd
.
new_mnt_userns
=
rd
.
old_mnt_userns
;
rd
.
new_dir
=
dir
;
rd
.
new_dentry
=
path
->
dentry
;
rd
.
delegated_inode
=
delegated_inode
;
rd
.
flags
=
flags
;
lockdep_off
();
err
=
vfs_rename
(
src_dir
,
src_dentry
,
dir
,
path
->
dentry
,
delegated_inode
,
flags
);
err
=
vfs_rename
(
&
rd
);
lockdep_on
();
if
(
!
err
)
{
int
did
;
...
...
@@ -438,6 +454,7 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -447,9 +464,10 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_mkdir
(
dir
,
path
->
dentry
,
mode
);
err
=
vfs_mkdir
(
userns
,
dir
,
path
->
dentry
,
mode
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
*
path
;
...
...
@@ -471,6 +489,7 @@ int vfsub_rmdir(struct inode *dir, struct path *path)
{
int
err
;
struct
dentry
*
d
;
struct
user_namespace
*
userns
;
IMustLock
(
dir
);
...
...
@@ -480,9 +499,10 @@ int vfsub_rmdir(struct inode *dir, struct path *path)
path
->
dentry
=
d
;
if
(
unlikely
(
err
))
goto
out
;
userns
=
mnt_user_ns
(
path
->
mnt
);
lockdep_off
();
err
=
vfs_rmdir
(
dir
,
path
->
dentry
);
err
=
vfs_rmdir
(
userns
,
dir
,
path
->
dentry
);
lockdep_on
();
if
(
!
err
)
{
struct
path
tmp
=
{
...
...
@@ -640,6 +660,7 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
int
err
;
struct
inode
*
h_inode
;
struct
super_block
*
h_sb
;
struct
user_namespace
*
h_userns
;
if
(
!
h_file
)
{
err
=
vfsub_truncate
(
h_path
,
length
);
...
...
@@ -655,8 +676,10 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
if
(
!
err
)
err
=
security_path_truncate
(
h_path
);
if
(
!
err
)
{
h_userns
=
mnt_user_ns
(
h_path
->
mnt
);
lockdep_off
();
err
=
do_truncate
(
h_path
->
dentry
,
length
,
attr
,
h_file
);
err
=
do_truncate
(
h_userns
,
h_path
->
dentry
,
length
,
attr
,
h_file
);
lockdep_on
();
}
lockdep_off
();
...
...
@@ -685,8 +708,10 @@ static void au_call_vfsub_mkdir(void *args)
int
vfsub_sio_mkdir
(
struct
inode
*
dir
,
struct
path
*
path
,
int
mode
)
{
int
err
,
do_sio
,
wkq_err
;
struct
user_namespace
*
userns
;
do_sio
=
au_test_h_perm_sio
(
dir
,
MAY_EXEC
|
MAY_WRITE
);
userns
=
mnt_user_ns
(
path
->
mnt
);
do_sio
=
au_test_h_perm_sio
(
userns
,
dir
,
MAY_EXEC
|
MAY_WRITE
);
if
(
!
do_sio
)
{
lockdep_off
();
err
=
vfsub_mkdir
(
dir
,
path
,
mode
);
...
...
@@ -721,8 +746,10 @@ static void au_call_vfsub_rmdir(void *args)
int
vfsub_sio_rmdir
(
struct
inode
*
dir
,
struct
path
*
path
)
{
int
err
,
do_sio
,
wkq_err
;
struct
user_namespace
*
userns
;
do_sio
=
au_test_h_perm_sio
(
dir
,
MAY_EXEC
|
MAY_WRITE
);
userns
=
mnt_user_ns
(
path
->
mnt
);
do_sio
=
au_test_h_perm_sio
(
userns
,
dir
,
MAY_EXEC
|
MAY_WRITE
);
if
(
!
do_sio
)
{
lockdep_off
();
err
=
vfsub_rmdir
(
dir
,
path
);
...
...
@@ -754,14 +781,16 @@ static void call_notify_change(void *args)
{
struct
notify_change_args
*
a
=
args
;
struct
inode
*
h_inode
;
struct
user_namespace
*
userns
;
h_inode
=
d_inode
(
a
->
path
->
dentry
);
IMustLock
(
h_inode
);
*
a
->
errp
=
-
EPERM
;
if
(
!
IS_IMMUTABLE
(
h_inode
)
&&
!
IS_APPEND
(
h_inode
))
{
userns
=
mnt_user_ns
(
a
->
path
->
mnt
);
lockdep_off
();
*
a
->
errp
=
notify_change
(
a
->
path
->
dentry
,
a
->
ia
,
*
a
->
errp
=
notify_change
(
userns
,
a
->
path
->
dentry
,
a
->
ia
,
a
->
delegated_inode
);
lockdep_on
();
if
(
!*
a
->
errp
)
...
...
@@ -818,6 +847,7 @@ static void call_unlink(void *args)
struct
unlink_args
*
a
=
args
;
struct
dentry
*
d
=
a
->
path
->
dentry
;
struct
inode
*
h_inode
;
struct
user_namespace
*
userns
;
const
int
stop_sillyrename
=
(
au_test_nfs
(
d
->
d_sb
)
&&
au_dcount
(
d
)
==
1
);
...
...
@@ -837,8 +867,9 @@ static void call_unlink(void *args)
ihold
(
h_inode
);
}
userns
=
mnt_user_ns
(
a
->
path
->
mnt
);
lockdep_off
();
*
a
->
errp
=
vfs_unlink
(
a
->
dir
,
d
,
a
->
delegated_inode
);
*
a
->
errp
=
vfs_unlink
(
userns
,
a
->
dir
,
d
,
a
->
delegated_inode
);
lockdep_on
();
if
(
!*
a
->
errp
)
{
struct
path
tmp
=
{
...
...
fs/aufs/vfsub.h
View file @
d9a6b724
...
...
@@ -234,17 +234,19 @@ static inline int vfsub_update_time(struct inode *h_inode,
}
#ifdef CONFIG_FS_POSIX_ACL
static
inline
int
vfsub_acl_chmod
(
struct
inode
*
h_inode
,
umode_t
h_mode
)
static
inline
int
vfsub_acl_chmod
(
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
umode_t
h_mode
)
{
int
err
;
err
=
posix_acl_chmod
(
h_inode
,
h_mode
);
err
=
posix_acl_chmod
(
h_userns
,
h_inode
,
h_mode
);
if
(
err
==
-
EOPNOTSUPP
)
err
=
0
;
return
err
;
}
#else
AuStubInt0
(
vfsub_acl_chmod
,
struct
inode
*
h_inode
,
umode_t
h_mode
);
AuStubInt0
(
vfsub_acl_chmod
,
struct
user_namespace
*
h_userns
,
struct
inode
*
h_inode
,
umode_t
h_mode
);
#endif
long
vfsub_splice_to
(
struct
file
*
in
,
loff_t
*
ppos
,
...
...
@@ -327,24 +329,26 @@ static inline int vfsub_getattr(const struct path *path, struct kstat *st)
/* ---------------------------------------------------------------------- */
static
inline
int
vfsub_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
static
inline
int
vfsub_setxattr
(
struct
user_namespace
*
userns
,
struct
dentry
*
dentry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
{
int
err
;
lockdep_off
();
err
=
vfs_setxattr
(
dentry
,
name
,
value
,
size
,
flags
);
err
=
vfs_setxattr
(
userns
,
dentry
,
name
,
value
,
size
,
flags
);
lockdep_on
();
return
err
;
}
static
inline
int
vfsub_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
)
static
inline
int
vfsub_removexattr
(
struct
user_namespace
*
userns
,
struct
dentry
*
dentry
,
const
char
*
name
)
{
int
err
;
lockdep_off
();
err
=
vfs_removexattr
(
dentry
,
name
);
err
=
vfs_removexattr
(
userns
,
dentry
,
name
);
lockdep_on
();
return
err
;
...
...
fs/aufs/whout.c
View file @
d9a6b724
...
...
@@ -64,7 +64,8 @@ int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
* test if the @wh_name exists under @h_parent.
* @try_sio specifies the necessary of super-io.
*/
int
au_wh_test
(
struct
dentry
*
h_parent
,
struct
qstr
*
wh_name
,
int
try_sio
)
int
au_wh_test
(
struct
user_namespace
*
h_userns
,
struct
dentry
*
h_parent
,
struct
qstr
*
wh_name
,
int
try_sio
)
{
int
err
;
struct
dentry
*
wh_dentry
;
...
...
@@ -72,7 +73,7 @@ int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
if
(
!
try_sio
)
wh_dentry
=
vfsub_lkup_one
(
wh_name
,
h_parent
);
else
wh_dentry
=
au_sio_lkup_one
(
wh_name
,
h_parent
);
wh_dentry
=
au_sio_lkup_one
(
h_userns
,
wh_name
,
h_parent
);
err
=
PTR_ERR
(
wh_dentry
);
if
(
IS_ERR
(
wh_dentry
))
{
if
(
err
==
-
ENAMETOOLONG
)
...
...
@@ -101,14 +102,14 @@ out:
/*
* test if the @h_dentry sets opaque or not.
*/
int
au_diropq_test
(
struct
dentry
*
h_dentry
)
int
au_diropq_test
(
struct
user_namespace
*
h_userns
,
struct
dentry
*
h_dentry
)
{
int
err
;
struct
inode
*
h_dir
;
h_dir
=
d_inode
(
h_dentry
);
err
=
au_wh_test
(
h_dentry
,
&
diropq_name
,
au_test_h_perm_sio
(
h_dir
,
MAY_EXEC
));
err
=
au_wh_test
(
h_userns
,
h_dentry
,
&
diropq_name
,
au_test_h_perm_sio
(
h_userns
,
h_dir
,
MAY_EXEC
));
return
err
;
}
...
...
@@ -125,6 +126,7 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
/* strict atomic_t is unnecessary here */
static
unsigned
short
cnt
;
struct
qstr
qs
;
struct
user_namespace
*
h_userns
;
BUILD_BUG_ON
(
sizeof
(
cnt
)
*
2
>
AUFS_WH_TMP_LEN
);
...
...
@@ -148,10 +150,11 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
*
p
++
=
'.'
;
AuDebugOn
(
name
+
qs
.
len
+
1
-
p
<=
AUFS_WH_TMP_LEN
);
h_userns
=
au_br_userns
(
br
);
qs
.
name
=
name
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
sprintf
(
p
,
"%.*x"
,
AUFS_WH_TMP_LEN
,
cnt
++
);
dentry
=
au_sio_lkup_one
(
&
qs
,
h_parent
);
dentry
=
au_sio_lkup_one
(
h_userns
,
&
qs
,
h_parent
);
if
(
IS_ERR
(
dentry
)
||
d_is_negative
(
dentry
))
goto
out_name
;
dput
(
dentry
);
...
...
@@ -750,9 +753,12 @@ struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
unsigned
int
flags
)
{
struct
dentry
*
diropq
,
*
h_dentry
;
struct
user_namespace
*
h_userns
;
h_userns
=
au_sbr_userns
(
dentry
->
d_sb
,
bindex
);
h_dentry
=
au_h_dptr
(
dentry
,
bindex
);
if
(
!
au_test_h_perm_sio
(
d_inode
(
h_dentry
),
MAY_EXEC
|
MAY_WRITE
))
if
(
!
au_test_h_perm_sio
(
h_userns
,
d_inode
(
h_dentry
),
MAY_EXEC
|
MAY_WRITE
))
diropq
=
do_diropq
(
dentry
,
bindex
,
flags
);
else
{
int
wkq_err
;
...
...
@@ -938,11 +944,13 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
struct
path
h_tmp
;
struct
inode
*
wh_inode
,
*
h_dir
;
struct
au_branch
*
br
;
struct
user_namespace
*
h_userns
;
h_dir
=
d_inode
(
wh_dentry
->
d_parent
);
/* dir inode is locked */
IMustLock
(
h_dir
);
br
=
au_sbr
(
dir
->
i_sb
,
bindex
);
h_userns
=
au_br_userns
(
br
);
wh_inode
=
d_inode
(
wh_dentry
);
inode_lock_nested
(
wh_inode
,
AuLsc_I_CHILD
);
...
...
@@ -950,7 +958,7 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
* someone else might change some whiteouts while we were sleeping.
* it means this whlist may have an obsoleted entry.
*/
if
(
!
au_test_h_perm_sio
(
wh_inode
,
MAY_EXEC
|
MAY_WRITE
))
if
(
!
au_test_h_perm_sio
(
h_userns
,
wh_inode
,
MAY_EXEC
|
MAY_WRITE
))
err
=
del_wh_children
(
wh_dentry
,
whlist
,
bindex
,
br
);
else
{
int
wkq_err
;
...
...
fs/aufs/whout.h
View file @
d9a6b724
...
...
@@ -29,8 +29,9 @@
/* whout.c */
int
au_wh_name_alloc
(
struct
qstr
*
wh
,
const
struct
qstr
*
name
);
int
au_wh_test
(
struct
dentry
*
h_parent
,
struct
qstr
*
wh_name
,
int
try_sio
);
int
au_diropq_test
(
struct
dentry
*
h_dentry
);
int
au_wh_test
(
struct
user_namespace
*
h_userns
,
struct
dentry
*
h_parent
,
struct
qstr
*
wh_name
,
int
try_sio
);
int
au_diropq_test
(
struct
user_namespace
*
h_userns
,
struct
dentry
*
h_dentry
);
struct
au_branch
;
struct
dentry
*
au_whtmp_lkup
(
struct
dentry
*
h_parent
,
struct
au_branch
*
br
,
struct
qstr
*
prefix
);
...
...
fs/aufs/xattr.c
View file @
d9a6b724
...
...
@@ -64,21 +64,26 @@ out:
static
const
int
au_xattr_out_of_list
=
AuBrAttr_ICEX_OTH
<<
1
;
static
int
au_do_cpup_xattr
(
struct
dentry
*
h_dst
,
struct
dentry
*
h_src
,
static
int
au_do_cpup_xattr
(
struct
path
*
h_dst
,
struct
path
*
h_src
,
char
*
name
,
char
**
buf
,
unsigned
int
ignore_flags
,
unsigned
int
verbose
)
{
int
err
;
ssize_t
ssz
;
struct
inode
*
h_idst
;
struct
dentry
*
h_dst_dentry
,
*
h_src_dentry
;
struct
user_namespace
*
h_dst_userns
,
*
h_src_userns
;
ssz
=
vfs_getxattr_alloc
(
h_src
,
name
,
buf
,
0
,
GFP_NOFS
);
h_src_userns
=
mnt_user_ns
(
h_src
->
mnt
);
h_src_dentry
=
h_src
->
dentry
;
ssz
=
vfs_getxattr_alloc
(
h_src_userns
,
h_src_dentry
,
name
,
buf
,
0
,
GFP_NOFS
);
err
=
ssz
;
if
(
unlikely
(
err
<=
0
))
{
if
(
err
==
-
ENODATA
||
(
err
==
-
EOPNOTSUPP
&&
((
ignore_flags
&
au_xattr_out_of_list
)
||
(
au_test_nfs_noacl
(
d_inode
(
h_src
))
||
(
au_test_nfs_noacl
(
d_inode
(
h_src
_dentry
))
&&
(
!
strcmp
(
name
,
XATTR_NAME_POSIX_ACL_ACCESS
)
||
!
strcmp
(
name
,
XATTR_NAME_POSIX_ACL_DEFAULT
))))
...
...
@@ -90,9 +95,12 @@ static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
}
/* unlock it temporary */
h_idst
=
d_inode
(
h_dst
);
h_dst_userns
=
mnt_user_ns
(
h_dst
->
mnt
);
h_dst_dentry
=
h_dst
->
dentry
;
h_idst
=
d_inode
(
h_dst_dentry
);
inode_unlock
(
h_idst
);
err
=
vfsub_setxattr
(
h_dst
,
name
,
*
buf
,
ssz
,
/*flags*/
0
);
err
=
vfsub_setxattr
(
h_dst_userns
,
h_dst_dentry
,
name
,
*
buf
,
ssz
,
/*flags*/
0
);
inode_lock_nested
(
h_idst
,
AuLsc_I_CHILD2
);
if
(
unlikely
(
err
))
{
if
(
verbose
||
au_debug_test
())
...
...
@@ -104,25 +112,28 @@ out:
return
err
;
}
int
au_cpup_xattr
(
struct
dentry
*
h_dst
,
struct
dentry
*
h_src
,
int
ignore_flags
,
int
au_cpup_xattr
(
struct
path
*
h_dst
,
struct
path
*
h_src
,
int
ignore_flags
,
unsigned
int
verbose
)
{
int
err
,
unlocked
,
acl_access
,
acl_default
;
ssize_t
ssz
;
struct
dentry
*
h_dst_dentry
,
*
h_src_dentry
;
struct
inode
*
h_isrc
,
*
h_idst
;
char
*
value
,
*
p
,
*
o
,
*
e
;
/* try stopping to update the source inode while we are referencing */
/* there should not be the parent-child relationship between them */
h_isrc
=
d_inode
(
h_src
);
h_idst
=
d_inode
(
h_dst
);
h_dst_dentry
=
h_dst
->
dentry
;
h_idst
=
d_inode
(
h_dst_dentry
);
h_src_dentry
=
h_src
->
dentry
;
h_isrc
=
d_inode
(
h_src_dentry
);
inode_unlock
(
h_idst
);
inode_lock_shared_nested
(
h_isrc
,
AuLsc_I_CHILD
);
inode_lock_nested
(
h_idst
,
AuLsc_I_CHILD2
);
unlocked
=
0
;
/* some filesystems don't list POSIX ACL, for example tmpfs */
ssz
=
vfs_listxattr
(
h_src
,
NULL
,
0
);
ssz
=
vfs_listxattr
(
h_src
_dentry
,
NULL
,
0
);
err
=
ssz
;
if
(
unlikely
(
err
<
0
))
{
AuTraceErr
(
err
);
...
...
@@ -141,7 +152,7 @@ int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
o
=
p
;
if
(
unlikely
(
!
p
))
goto
out
;
err
=
vfs_listxattr
(
h_src
,
p
,
ssz
);
err
=
vfs_listxattr
(
h_src
_dentry
,
p
,
ssz
);
}
inode_unlock_shared
(
h_isrc
);
unlocked
=
1
;
...
...
@@ -255,7 +266,7 @@ static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode,
break
;
case
AU_XATTR_GET
:
AuDebugOn
(
d_is_negative
(
h_path
.
dentry
));
err
=
vfs_getxattr
(
h_path
.
dentry
,
err
=
vfs_getxattr
(
mnt_user_ns
(
h_path
.
mnt
),
h_path
.
dentry
,
arg
->
u
.
get
.
name
,
arg
->
u
.
get
.
value
,
arg
->
u
.
get
.
size
);
break
;
...
...
@@ -327,6 +338,7 @@ static int au_xattr_get(const struct xattr_handler *handler,
}
static
int
au_xattr_set
(
const
struct
xattr_handler
*
handler
,
struct
user_namespace
*
userns
,
struct
dentry
*
dentry
,
struct
inode
*
inode
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
...
...
fs/aufs/xino.c
View file @
d9a6b724
...
...
@@ -258,7 +258,7 @@ struct file *au_xino_create2(struct super_block *sb, struct path *base,
}
/* no need to mnt_want_write() since we call dentry_open() later */
err
=
vfs_create
(
dir
,
path
.
dentry
,
0666
,
NULL
);
err
=
vfs_create
(
mnt_user_ns
(
base
->
mnt
),
dir
,
path
.
dentry
,
0666
,
NULL
);
if
(
unlikely
(
err
))
{
file
=
ERR_PTR
(
err
);
pr_err
(
"%pd create err %d
\n
"
,
dentry
,
err
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment