1616
1717struct ovl_lookup_data {
1818 struct super_block * sb ;
19+ struct dentry * dentry ;
1920 const struct ovl_layer * layer ;
2021 struct qstr name ;
2122 bool is_dir ;
@@ -24,6 +25,7 @@ struct ovl_lookup_data {
2425 bool stop ;
2526 bool last ;
2627 char * redirect ;
28+ char * upperredirect ;
2729 int metacopy ;
2830 /* Referring to last redirect xattr */
2931 bool absolute_redirect ;
@@ -1024,6 +1026,31 @@ int ovl_verify_lowerdata(struct dentry *dentry)
10241026 return ovl_maybe_validate_verity (dentry );
10251027}
10261028
1029+ /*
1030+ * Following redirects/metacopy can have security consequences: it's like a
1031+ * symlink into the lower layer without the permission checks.
1032+ *
1033+ * This is only a problem if the upper layer is untrusted (e.g comes from an USB
1034+ * drive). This can allow a non-readable file or directory to become readable.
1035+ *
1036+ * Only following redirects when redirects are enabled disables this attack
1037+ * vector when not necessary.
1038+ */
1039+ static bool ovl_check_follow_redirect (struct ovl_lookup_data * d )
1040+ {
1041+ struct ovl_fs * ofs = OVL_FS (d -> sb );
1042+
1043+ if (d -> metacopy && !ofs -> config .metacopy ) {
1044+ pr_warn_ratelimited ("refusing to follow metacopy origin for (%pd2)\n" , d -> dentry );
1045+ return false;
1046+ }
1047+ if ((d -> redirect || d -> upperredirect ) && !ovl_redirect_follow (ofs )) {
1048+ pr_warn_ratelimited ("refusing to follow redirect for (%pd2)\n" , d -> dentry );
1049+ return false;
1050+ }
1051+ return true;
1052+ }
1053+
10271054struct dentry * ovl_lookup (struct inode * dir , struct dentry * dentry ,
10281055 unsigned int flags )
10291056{
@@ -1039,20 +1066,22 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
10391066 unsigned int ctr = 0 ;
10401067 struct inode * inode = NULL ;
10411068 bool upperopaque = false;
1042- char * upperredirect = NULL ;
1069+ bool check_redirect = ( ovl_redirect_follow ( ofs ) || ofs -> numdatalayer ) ;
10431070 struct dentry * this ;
10441071 unsigned int i ;
10451072 int err ;
10461073 bool uppermetacopy = false;
10471074 int metacopy_size = 0 ;
10481075 struct ovl_lookup_data d = {
10491076 .sb = dentry -> d_sb ,
1077+ .dentry = dentry ,
10501078 .name = dentry -> d_name ,
10511079 .is_dir = false,
10521080 .opaque = false,
10531081 .stop = false,
1054- .last = ovl_redirect_follow ( ofs ) ? false : !ovl_numlower (poe ),
1082+ .last = check_redirect ? false : !ovl_numlower (poe ),
10551083 .redirect = NULL ,
1084+ .upperredirect = NULL ,
10561085 .metacopy = 0 ,
10571086 };
10581087
@@ -1094,8 +1123,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
10941123
10951124 if (d .redirect ) {
10961125 err = - ENOMEM ;
1097- upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1098- if (!upperredirect )
1126+ d . upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1127+ if (!d . upperredirect )
10991128 goto out_put_upper ;
11001129 if (d .redirect [0 ] == '/' )
11011130 poe = roe ;
@@ -1113,7 +1142,12 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11131142 for (i = 0 ; !d .stop && i < ovl_numlower (poe ); i ++ ) {
11141143 struct ovl_path lower = ovl_lowerstack (poe )[i ];
11151144
1116- if (!ovl_redirect_follow (ofs ))
1145+ if (!ovl_check_follow_redirect (& d )) {
1146+ err = - EPERM ;
1147+ goto out_put ;
1148+ }
1149+
1150+ if (!check_redirect )
11171151 d .last = i == ovl_numlower (poe ) - 1 ;
11181152 else if (d .is_dir || !ofs -> numdatalayer )
11191153 d .last = lower .layer -> idx == ovl_numlower (roe );
@@ -1126,13 +1160,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11261160 if (!this )
11271161 continue ;
11281162
1129- if ((uppermetacopy || d .metacopy ) && !ofs -> config .metacopy ) {
1130- dput (this );
1131- err = - EPERM ;
1132- pr_warn_ratelimited ("refusing to follow metacopy origin for (%pd2)\n" , dentry );
1133- goto out_put ;
1134- }
1135-
11361163 /*
11371164 * If no origin fh is stored in upper of a merge dir, store fh
11381165 * of lower dir and set upper parent "impure".
@@ -1185,23 +1212,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11851212 ctr ++ ;
11861213 }
11871214
1188- /*
1189- * Following redirects can have security consequences: it's like
1190- * a symlink into the lower layer without the permission checks.
1191- * This is only a problem if the upper layer is untrusted (e.g
1192- * comes from an USB drive). This can allow a non-readable file
1193- * or directory to become readable.
1194- *
1195- * Only following redirects when redirects are enabled disables
1196- * this attack vector when not necessary.
1197- */
1198- err = - EPERM ;
1199- if (d .redirect && !ovl_redirect_follow (ofs )) {
1200- pr_warn_ratelimited ("refusing to follow redirect for (%pd2)\n" ,
1201- dentry );
1202- goto out_put ;
1203- }
1204-
12051215 if (d .stop )
12061216 break ;
12071217
@@ -1212,10 +1222,16 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
12121222 }
12131223 }
12141224
1215- /* Defer lookup of lowerdata in data-only layers to first access */
1225+ /*
1226+ * Defer lookup of lowerdata in data-only layers to first access.
1227+ * Don't require redirect=follow and metacopy=on in this case.
1228+ */
12161229 if (d .metacopy && ctr && ofs -> numdatalayer && d .absolute_redirect ) {
12171230 d .metacopy = 0 ;
12181231 ctr ++ ;
1232+ } else if (!ovl_check_follow_redirect (& d )) {
1233+ err = - EPERM ;
1234+ goto out_put ;
12191235 }
12201236
12211237 /*
@@ -1298,28 +1314,34 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
12981314
12991315 /*
13001316 * It's safe to assign upperredirect here: the previous
1301- * assignment of happens only if upperdentry is non-NULL, and
1317+ * assignment happens only if upperdentry is non-NULL, and
13021318 * this one only if upperdentry is NULL.
13031319 */
1304- upperredirect = ovl_get_redirect_xattr (ofs , & upperpath , 0 );
1305- if (IS_ERR (upperredirect )) {
1306- err = PTR_ERR (upperredirect );
1307- upperredirect = NULL ;
1320+ d . upperredirect = ovl_get_redirect_xattr (ofs , & upperpath , 0 );
1321+ if (IS_ERR (d . upperredirect )) {
1322+ err = PTR_ERR (d . upperredirect );
1323+ d . upperredirect = NULL ;
13081324 goto out_free_oe ;
13091325 }
1326+
13101327 err = ovl_check_metacopy_xattr (ofs , & upperpath , NULL );
13111328 if (err < 0 )
13121329 goto out_free_oe ;
1313- uppermetacopy = err ;
1330+ d . metacopy = uppermetacopy = err ;
13141331 metacopy_size = err ;
1332+
1333+ if (!ovl_check_follow_redirect (& d )) {
1334+ err = - EPERM ;
1335+ goto out_free_oe ;
1336+ }
13151337 }
13161338
13171339 if (upperdentry || ctr ) {
13181340 struct ovl_inode_params oip = {
13191341 .upperdentry = upperdentry ,
13201342 .oe = oe ,
13211343 .index = index ,
1322- .redirect = upperredirect ,
1344+ .redirect = d . upperredirect ,
13231345 };
13241346
13251347 /* Store lowerdata redirect for lazy lookup */
@@ -1361,7 +1383,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
13611383 kfree (origin_path );
13621384 }
13631385 dput (upperdentry );
1364- kfree (upperredirect );
1386+ kfree (d . upperredirect );
13651387out :
13661388 kfree (d .redirect );
13671389 ovl_revert_creds (old_cred );
0 commit comments