16
16
17
17
struct ovl_lookup_data {
18
18
struct super_block * sb ;
19
+ struct dentry * dentry ;
19
20
const struct ovl_layer * layer ;
20
21
struct qstr name ;
21
22
bool is_dir ;
@@ -24,6 +25,7 @@ struct ovl_lookup_data {
24
25
bool stop ;
25
26
bool last ;
26
27
char * redirect ;
28
+ char * upperredirect ;
27
29
int metacopy ;
28
30
/* Referring to last redirect xattr */
29
31
bool absolute_redirect ;
@@ -1024,6 +1026,31 @@ int ovl_verify_lowerdata(struct dentry *dentry)
1024
1026
return ovl_maybe_validate_verity (dentry );
1025
1027
}
1026
1028
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
+
1027
1054
struct dentry * ovl_lookup (struct inode * dir , struct dentry * dentry ,
1028
1055
unsigned int flags )
1029
1056
{
@@ -1039,20 +1066,21 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1039
1066
unsigned int ctr = 0 ;
1040
1067
struct inode * inode = NULL ;
1041
1068
bool upperopaque = false;
1042
- char * upperredirect = NULL ;
1043
1069
struct dentry * this ;
1044
1070
unsigned int i ;
1045
1071
int err ;
1046
1072
bool uppermetacopy = false;
1047
1073
int metacopy_size = 0 ;
1048
1074
struct ovl_lookup_data d = {
1049
1075
.sb = dentry -> d_sb ,
1076
+ .dentry = dentry ,
1050
1077
.name = dentry -> d_name ,
1051
1078
.is_dir = false,
1052
1079
.opaque = false,
1053
1080
.stop = false,
1054
1081
.last = ovl_redirect_follow (ofs ) ? false : !ovl_numlower (poe ),
1055
1082
.redirect = NULL ,
1083
+ .upperredirect = NULL ,
1056
1084
.metacopy = 0 ,
1057
1085
};
1058
1086
@@ -1094,8 +1122,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1094
1122
1095
1123
if (d .redirect ) {
1096
1124
err = - ENOMEM ;
1097
- upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1098
- if (!upperredirect )
1125
+ d . upperredirect = kstrdup (d .redirect , GFP_KERNEL );
1126
+ if (!d . upperredirect )
1099
1127
goto out_put_upper ;
1100
1128
if (d .redirect [0 ] == '/' )
1101
1129
poe = roe ;
@@ -1113,6 +1141,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1113
1141
for (i = 0 ; !d .stop && i < ovl_numlower (poe ); i ++ ) {
1114
1142
struct ovl_path lower = ovl_lowerstack (poe )[i ];
1115
1143
1144
+ if (!ovl_check_follow_redirect (& d )) {
1145
+ err = - EPERM ;
1146
+ goto out_put ;
1147
+ }
1148
+
1116
1149
if (!ovl_redirect_follow (ofs ))
1117
1150
d .last = i == ovl_numlower (poe ) - 1 ;
1118
1151
else if (d .is_dir || !ofs -> numdatalayer )
@@ -1126,13 +1159,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1126
1159
if (!this )
1127
1160
continue ;
1128
1161
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
-
1136
1162
/*
1137
1163
* If no origin fh is stored in upper of a merge dir, store fh
1138
1164
* of lower dir and set upper parent "impure".
@@ -1185,23 +1211,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1185
1211
ctr ++ ;
1186
1212
}
1187
1213
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
-
1205
1214
if (d .stop )
1206
1215
break ;
1207
1216
@@ -1212,6 +1221,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1212
1221
}
1213
1222
}
1214
1223
1224
+ if (!ovl_check_follow_redirect (& d )) {
1225
+ err = - EPERM ;
1226
+ goto out_put ;
1227
+ }
1228
+
1215
1229
/* Defer lookup of lowerdata in data-only layers to first access */
1216
1230
if (d .metacopy && ctr && ofs -> numdatalayer && d .absolute_redirect ) {
1217
1231
d .metacopy = 0 ;
@@ -1298,28 +1312,34 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1298
1312
1299
1313
/*
1300
1314
* 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
1302
1316
* this one only if upperdentry is NULL.
1303
1317
*/
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 ;
1308
1322
goto out_free_oe ;
1309
1323
}
1324
+
1310
1325
err = ovl_check_metacopy_xattr (ofs , & upperpath , NULL );
1311
1326
if (err < 0 )
1312
1327
goto out_free_oe ;
1313
- uppermetacopy = err ;
1328
+ d . metacopy = uppermetacopy = err ;
1314
1329
metacopy_size = err ;
1330
+
1331
+ if (!ovl_check_follow_redirect (& d )) {
1332
+ err = - EPERM ;
1333
+ goto out_free_oe ;
1334
+ }
1315
1335
}
1316
1336
1317
1337
if (upperdentry || ctr ) {
1318
1338
struct ovl_inode_params oip = {
1319
1339
.upperdentry = upperdentry ,
1320
1340
.oe = oe ,
1321
1341
.index = index ,
1322
- .redirect = upperredirect ,
1342
+ .redirect = d . upperredirect ,
1323
1343
};
1324
1344
1325
1345
/* Store lowerdata redirect for lazy lookup */
@@ -1361,7 +1381,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1361
1381
kfree (origin_path );
1362
1382
}
1363
1383
dput (upperdentry );
1364
- kfree (upperredirect );
1384
+ kfree (d . upperredirect );
1365
1385
out :
1366
1386
kfree (d .redirect );
1367
1387
ovl_revert_creds (old_cred );
0 commit comments