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,21 @@ 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 ;
10431069 struct dentry * this ;
10441070 unsigned int i ;
10451071 int err ;
10461072 bool uppermetacopy = false;
10471073 int metacopy_size = 0 ;
10481074 struct ovl_lookup_data d = {
10491075 .sb = dentry -> d_sb ,
1076+ .dentry = dentry ,
10501077 .name = dentry -> d_name ,
10511078 .is_dir = false,
10521079 .opaque = false,
10531080 .stop = false,
10541081 .last = ovl_redirect_follow (ofs ) ? false : !ovl_numlower (poe ),
10551082 .redirect = NULL ,
1083+ .upperredirect = NULL ,
10561084 .metacopy = 0 ,
10571085 };
10581086
@@ -1094,8 +1122,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
10941122
10951123 if (d .redirect ) {
10961124 err = - ENOMEM ;
1097- upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1098- if (!upperredirect )
1125+ d . upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1126+ if (!d . upperredirect )
10991127 goto out_put_upper ;
11001128 if (d .redirect [0 ] == '/' )
11011129 poe = roe ;
@@ -1113,6 +1141,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11131141 for (i = 0 ; !d .stop && i < ovl_numlower (poe ); i ++ ) {
11141142 struct ovl_path lower = ovl_lowerstack (poe )[i ];
11151143
1144+ if (!ovl_check_follow_redirect (& d )) {
1145+ err = - EPERM ;
1146+ goto out_put ;
1147+ }
1148+
11161149 if (!ovl_redirect_follow (ofs ))
11171150 d .last = i == ovl_numlower (poe ) - 1 ;
11181151 else if (d .is_dir || !ofs -> numdatalayer )
@@ -1126,13 +1159,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11261159 if (!this )
11271160 continue ;
11281161
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-
11361162 /*
11371163 * If no origin fh is stored in upper of a merge dir, store fh
11381164 * of lower dir and set upper parent "impure".
@@ -1185,23 +1211,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
11851211 ctr ++ ;
11861212 }
11871213
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-
12051214 if (d .stop )
12061215 break ;
12071216
@@ -1212,6 +1221,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
12121221 }
12131222 }
12141223
1224+ if (!ovl_check_follow_redirect (& d )) {
1225+ err = - EPERM ;
1226+ goto out_put ;
1227+ }
1228+
12151229 /* Defer lookup of lowerdata in data-only layers to first access */
12161230 if (d .metacopy && ctr && ofs -> numdatalayer && d .absolute_redirect ) {
12171231 d .metacopy = 0 ;
@@ -1298,28 +1312,34 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
12981312
12991313 /*
13001314 * It's safe to assign upperredirect here: the previous
1301- * assignment of happens only if upperdentry is non-NULL, and
1315+ * assignment happens only if upperdentry is non-NULL, and
13021316 * this one only if upperdentry is NULL.
13031317 */
1304- upperredirect = ovl_get_redirect_xattr (ofs , & upperpath , 0 );
1305- if (IS_ERR (upperredirect )) {
1306- err = PTR_ERR (upperredirect );
1307- upperredirect = NULL ;
1318+ d . upperredirect = ovl_get_redirect_xattr (ofs , & upperpath , 0 );
1319+ if (IS_ERR (d . upperredirect )) {
1320+ err = PTR_ERR (d . upperredirect );
1321+ d . upperredirect = NULL ;
13081322 goto out_free_oe ;
13091323 }
1324+
13101325 err = ovl_check_metacopy_xattr (ofs , & upperpath , NULL );
13111326 if (err < 0 )
13121327 goto out_free_oe ;
1313- uppermetacopy = err ;
1328+ d . metacopy = uppermetacopy = err ;
13141329 metacopy_size = err ;
1330+
1331+ if (!ovl_check_follow_redirect (& d )) {
1332+ err = - EPERM ;
1333+ goto out_free_oe ;
1334+ }
13151335 }
13161336
13171337 if (upperdentry || ctr ) {
13181338 struct ovl_inode_params oip = {
13191339 .upperdentry = upperdentry ,
13201340 .oe = oe ,
13211341 .index = index ,
1322- .redirect = upperredirect ,
1342+ .redirect = d . upperredirect ,
13231343 };
13241344
13251345 /* Store lowerdata redirect for lazy lookup */
@@ -1361,7 +1381,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
13611381 kfree (origin_path );
13621382 }
13631383 dput (upperdentry );
1364- kfree (upperredirect );
1384+ kfree (d . upperredirect );
13651385out :
13661386 kfree (d .redirect );
13671387 ovl_revert_creds (old_cred );
0 commit comments