Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs: move file_start_write() into direct_splice_actor()

The callers of do_splice_direct() hold file_start_write() on the output
file.

This may cause file permission hooks to be called indirectly on an
overlayfs lower layer, which is on the same filesystem of the output
file and could lead to deadlock with fanotify permission events.

To fix this potential deadlock, move file_start_write() from the callers
into the direct_splice_actor(), so file_start_write() will not be held
while splicing from the input file.

Suggested-by: Josef Bacik <josef@toxicpanda.com>
Link: https://lore.kernel.org/r/20231128214258.GA2398475@perftesting/
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231130141624.3338942-3-amir73il@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Amir Goldstein and committed by
Christian Brauner
da40448c 488e8f68

+16 -7
-2
fs/overlayfs/copy_up.c
··· 333 333 if (error) 334 334 break; 335 335 336 - ovl_start_write(dentry); 337 336 bytes = do_splice_direct(old_file, &old_pos, 338 337 new_file, &new_pos, 339 338 this_len, SPLICE_F_MOVE); 340 - ovl_end_write(dentry); 341 339 if (bytes <= 0) { 342 340 error = bytes; 343 341 break;
-2
fs/read_write.c
··· 1286 1286 retval = rw_verify_area(WRITE, out.file, &out_pos, count); 1287 1287 if (retval < 0) 1288 1288 goto fput_out; 1289 - file_start_write(out.file); 1290 1289 retval = do_splice_direct(in.file, &pos, out.file, &out_pos, 1291 1290 count, fl); 1292 - file_end_write(out.file); 1293 1291 } else { 1294 1292 if (out.file->f_flags & O_NONBLOCK) 1295 1293 fl |= SPLICE_F_NONBLOCK;
+16 -3
fs/splice.c
··· 1157 1157 struct splice_desc *sd) 1158 1158 { 1159 1159 struct file *file = sd->u.file; 1160 + long ret; 1160 1161 1161 - return do_splice_from(pipe, file, sd->opos, sd->total_len, 1162 - sd->flags); 1162 + file_start_write(file); 1163 + ret = do_splice_from(pipe, file, sd->opos, sd->total_len, sd->flags); 1164 + file_end_write(file); 1165 + return ret; 1166 + } 1167 + 1168 + static int splice_file_range_actor(struct pipe_inode_info *pipe, 1169 + struct splice_desc *sd) 1170 + { 1171 + struct file *file = sd->u.file; 1172 + 1173 + return do_splice_from(pipe, file, sd->opos, sd->total_len, sd->flags); 1163 1174 } 1164 1175 1165 1176 static void direct_file_splice_eof(struct splice_desc *sd) ··· 1244 1233 * 1245 1234 * Description: 1246 1235 * For use by generic_copy_file_range() and ->copy_file_range() methods. 1236 + * Like do_splice_direct(), but vfs_copy_file_range() already holds 1237 + * start_file_write() on @out file. 1247 1238 * 1248 1239 * Callers already called rw_verify_area() on the entire range. 1249 1240 */ ··· 1255 1242 lockdep_assert(file_write_started(out)); 1256 1243 1257 1244 return do_splice_direct_actor(in, ppos, out, opos, len, 0, 1258 - direct_splice_actor); 1245 + splice_file_range_actor); 1259 1246 } 1260 1247 EXPORT_SYMBOL(splice_file_range); 1261 1248