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.

Merge tag 'ovl-update-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs

Pull overlayfs updates from Amir Goldstein:

- Fix a syzbot reported NULL pointer deref with bfs lower layers

- Fix a copy up failure of large file from lower fuse fs

- Followup cleanup of backing_file API from Miklos

- Introduction and use of revert/override_creds_light() helpers, that
were suggested by Christian as a mitigation to cache line bouncing
and false sharing of fields in overlayfs creator_cred long lived
struct cred copy.

- Store up to two backing file references (upper and lower) in an
ovl_file container instead of storing a single backing file in
file->private_data.

This is used to avoid the practice of opening a short lived backing
file for the duration of some file operations and to avoid the
specialized use of FDPUT_FPUT in such occasions, that was getting in
the way of Al's fd_file() conversions.

* tag 'ovl-update-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
ovl: Filter invalid inodes with missing lookup function
ovl: convert ovl_real_fdget() callers to ovl_real_file()
ovl: convert ovl_real_fdget_path() callers to ovl_real_file_path()
ovl: store upper real file in ovl_file struct
ovl: allocate a container struct ovl_file for ovl private context
ovl: do not open non-data lower file for fsync
ovl: Optimize override/revert creds
ovl: pass an explicit reference of creators creds to callers
ovl: use wrapper ovl_revert_creds()
fs/backing-file: Convert to revert/override_creds_light()
cred: Add a light version of override/revert_creds()
backing-file: clean up the API
ovl: properly handle large files in ovl_security_fileattr

+357 -242
+27 -28
fs/backing-file.c
··· 80 80 refcount_t ref; 81 81 struct kiocb *orig_iocb; 82 82 /* used for aio completion */ 83 - void (*end_write)(struct file *, loff_t, ssize_t); 83 + void (*end_write)(struct kiocb *iocb, ssize_t); 84 84 struct work_struct work; 85 85 long res; 86 86 }; ··· 108 108 struct kiocb *iocb = &aio->iocb; 109 109 struct kiocb *orig_iocb = aio->orig_iocb; 110 110 111 - if (aio->end_write) 112 - aio->end_write(orig_iocb->ki_filp, iocb->ki_pos, res); 113 - 114 111 orig_iocb->ki_pos = iocb->ki_pos; 112 + if (aio->end_write) 113 + aio->end_write(orig_iocb, res); 114 + 115 115 backing_aio_put(aio); 116 116 } 117 117 ··· 176 176 !(file->f_mode & FMODE_CAN_ODIRECT)) 177 177 return -EINVAL; 178 178 179 - old_cred = override_creds(ctx->cred); 179 + old_cred = override_creds_light(ctx->cred); 180 180 if (is_sync_kiocb(iocb)) { 181 181 rwf_t rwf = iocb_to_rw_flags(flags); 182 182 ··· 197 197 backing_aio_cleanup(aio, ret); 198 198 } 199 199 out: 200 - revert_creds(old_cred); 200 + revert_creds_light(old_cred); 201 201 202 202 if (ctx->accessed) 203 - ctx->accessed(ctx->user_file); 203 + ctx->accessed(iocb->ki_filp); 204 204 205 205 return ret; 206 206 } ··· 219 219 if (!iov_iter_count(iter)) 220 220 return 0; 221 221 222 - ret = file_remove_privs(ctx->user_file); 222 + ret = file_remove_privs(iocb->ki_filp); 223 223 if (ret) 224 224 return ret; 225 225 ··· 233 233 */ 234 234 flags &= ~IOCB_DIO_CALLER_COMP; 235 235 236 - old_cred = override_creds(ctx->cred); 236 + old_cred = override_creds_light(ctx->cred); 237 237 if (is_sync_kiocb(iocb)) { 238 238 rwf_t rwf = iocb_to_rw_flags(flags); 239 239 240 240 ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf); 241 241 if (ctx->end_write) 242 - ctx->end_write(ctx->user_file, iocb->ki_pos, ret); 242 + ctx->end_write(iocb, ret); 243 243 } else { 244 244 struct backing_aio *aio; 245 245 ··· 264 264 backing_aio_cleanup(aio, ret); 265 265 } 266 266 out: 267 - revert_creds(old_cred); 267 + revert_creds_light(old_cred); 268 268 269 269 return ret; 270 270 } 271 271 EXPORT_SYMBOL_GPL(backing_file_write_iter); 272 272 273 - ssize_t backing_file_splice_read(struct file *in, loff_t *ppos, 273 + ssize_t backing_file_splice_read(struct file *in, struct kiocb *iocb, 274 274 struct pipe_inode_info *pipe, size_t len, 275 275 unsigned int flags, 276 276 struct backing_file_ctx *ctx) ··· 281 281 if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) 282 282 return -EIO; 283 283 284 - old_cred = override_creds(ctx->cred); 285 - ret = vfs_splice_read(in, ppos, pipe, len, flags); 286 - revert_creds(old_cred); 284 + old_cred = override_creds_light(ctx->cred); 285 + ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); 286 + revert_creds_light(old_cred); 287 287 288 288 if (ctx->accessed) 289 - ctx->accessed(ctx->user_file); 289 + ctx->accessed(iocb->ki_filp); 290 290 291 291 return ret; 292 292 } 293 293 EXPORT_SYMBOL_GPL(backing_file_splice_read); 294 294 295 295 ssize_t backing_file_splice_write(struct pipe_inode_info *pipe, 296 - struct file *out, loff_t *ppos, size_t len, 297 - unsigned int flags, 296 + struct file *out, struct kiocb *iocb, 297 + size_t len, unsigned int flags, 298 298 struct backing_file_ctx *ctx) 299 299 { 300 300 const struct cred *old_cred; ··· 306 306 if (!out->f_op->splice_write) 307 307 return -EINVAL; 308 308 309 - ret = file_remove_privs(ctx->user_file); 309 + ret = file_remove_privs(iocb->ki_filp); 310 310 if (ret) 311 311 return ret; 312 312 313 - old_cred = override_creds(ctx->cred); 313 + old_cred = override_creds_light(ctx->cred); 314 314 file_start_write(out); 315 - ret = out->f_op->splice_write(pipe, out, ppos, len, flags); 315 + ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); 316 316 file_end_write(out); 317 - revert_creds(old_cred); 317 + revert_creds_light(old_cred); 318 318 319 319 if (ctx->end_write) 320 - ctx->end_write(ctx->user_file, ppos ? *ppos : 0, ret); 320 + ctx->end_write(iocb, ret); 321 321 322 322 return ret; 323 323 } ··· 329 329 const struct cred *old_cred; 330 330 int ret; 331 331 332 - if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING)) || 333 - WARN_ON_ONCE(ctx->user_file != vma->vm_file)) 332 + if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING))) 334 333 return -EIO; 335 334 336 335 if (!file->f_op->mmap) ··· 337 338 338 339 vma_set_file(vma, file); 339 340 340 - old_cred = override_creds(ctx->cred); 341 + old_cred = override_creds_light(ctx->cred); 341 342 ret = call_mmap(vma->vm_file, vma); 342 - revert_creds(old_cred); 343 + revert_creds_light(old_cred); 343 344 344 345 if (ctx->accessed) 345 - ctx->accessed(ctx->user_file); 346 + ctx->accessed(vma->vm_file); 346 347 347 348 return ret; 348 349 }
+18 -14
fs/fuse/passthrough.c
··· 18 18 fuse_invalidate_atime(inode); 19 19 } 20 20 21 - static void fuse_passthrough_end_write(struct file *file, loff_t pos, ssize_t ret) 21 + static void fuse_passthrough_end_write(struct kiocb *iocb, ssize_t ret) 22 22 { 23 - struct inode *inode = file_inode(file); 23 + struct inode *inode = file_inode(iocb->ki_filp); 24 24 25 - fuse_write_update_attr(inode, pos, ret); 25 + fuse_write_update_attr(inode, iocb->ki_pos, ret); 26 26 } 27 27 28 28 ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter) ··· 34 34 ssize_t ret; 35 35 struct backing_file_ctx ctx = { 36 36 .cred = ff->cred, 37 - .user_file = file, 38 37 .accessed = fuse_file_accessed, 39 38 }; 40 39 ··· 61 62 ssize_t ret; 62 63 struct backing_file_ctx ctx = { 63 64 .cred = ff->cred, 64 - .user_file = file, 65 65 .end_write = fuse_passthrough_end_write, 66 66 }; 67 67 ··· 86 88 struct file *backing_file = fuse_file_passthrough(ff); 87 89 struct backing_file_ctx ctx = { 88 90 .cred = ff->cred, 89 - .user_file = in, 90 91 .accessed = fuse_file_accessed, 91 92 }; 93 + struct kiocb iocb; 94 + ssize_t ret; 92 95 93 96 pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, 94 - backing_file, ppos ? *ppos : 0, len, flags); 97 + backing_file, *ppos, len, flags); 95 98 96 - return backing_file_splice_read(backing_file, ppos, pipe, len, flags, 97 - &ctx); 99 + init_sync_kiocb(&iocb, in); 100 + iocb.ki_pos = *ppos; 101 + ret = backing_file_splice_read(backing_file, &iocb, pipe, len, flags, &ctx); 102 + *ppos = iocb.ki_pos; 103 + 104 + return ret; 98 105 } 99 106 100 107 ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe, ··· 112 109 ssize_t ret; 113 110 struct backing_file_ctx ctx = { 114 111 .cred = ff->cred, 115 - .user_file = out, 116 112 .end_write = fuse_passthrough_end_write, 117 113 }; 114 + struct kiocb iocb; 118 115 119 116 pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, 120 - backing_file, ppos ? *ppos : 0, len, flags); 117 + backing_file, *ppos, len, flags); 121 118 122 119 inode_lock(inode); 123 - ret = backing_file_splice_write(pipe, backing_file, ppos, len, flags, 124 - &ctx); 120 + init_sync_kiocb(&iocb, out); 121 + iocb.ki_pos = *ppos; 122 + ret = backing_file_splice_write(pipe, backing_file, &iocb, len, flags, &ctx); 123 + *ppos = iocb.ki_pos; 125 124 inode_unlock(inode); 126 125 127 126 return ret; ··· 135 130 struct file *backing_file = fuse_file_passthrough(ff); 136 131 struct backing_file_ctx ctx = { 137 132 .cred = ff->cred, 138 - .user_file = file, 139 133 .accessed = fuse_file_accessed, 140 134 }; 141 135
+1 -1
fs/overlayfs/copy_up.c
··· 1259 1259 dput(parent); 1260 1260 dput(next); 1261 1261 } 1262 - revert_creds(old_cred); 1262 + ovl_revert_creds(old_cred); 1263 1263 1264 1264 return err; 1265 1265 }
+47 -21
fs/overlayfs/dir.c
··· 553 553 goto out_dput; 554 554 } 555 555 556 - static int ovl_setup_cred_for_create(struct dentry *dentry, struct inode *inode, 557 - umode_t mode, const struct cred *old_cred) 556 + static const struct cred *ovl_setup_cred_for_create(struct dentry *dentry, 557 + struct inode *inode, 558 + umode_t mode, 559 + const struct cred *old_cred) 558 560 { 559 561 int err; 560 562 struct cred *override_cred; 561 563 562 564 override_cred = prepare_creds(); 563 565 if (!override_cred) 564 - return -ENOMEM; 566 + return ERR_PTR(-ENOMEM); 565 567 566 568 override_cred->fsuid = inode->i_uid; 567 569 override_cred->fsgid = inode->i_gid; ··· 571 569 old_cred, override_cred); 572 570 if (err) { 573 571 put_cred(override_cred); 574 - return err; 572 + return ERR_PTR(err); 575 573 } 576 - put_cred(override_creds(override_cred)); 577 - put_cred(override_cred); 578 574 579 - return 0; 575 + /* 576 + * Caller is going to match this with revert_creds_light() and drop 577 + * referenec on the returned creds. 578 + * We must be called with creator creds already, otherwise we risk 579 + * leaking creds. 580 + */ 581 + old_cred = override_creds_light(override_cred); 582 + WARN_ON_ONCE(old_cred != ovl_creds(dentry->d_sb)); 583 + 584 + return override_cred; 580 585 } 581 586 582 587 static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, 583 588 struct ovl_cattr *attr, bool origin) 584 589 { 585 590 int err; 586 - const struct cred *old_cred; 591 + const struct cred *old_cred, *new_cred = NULL; 587 592 struct dentry *parent = dentry->d_parent; 588 593 589 594 old_cred = ovl_override_creds(dentry->d_sb); ··· 619 610 * create a new inode, so just use the ovl mounter's 620 611 * fs{u,g}id. 621 612 */ 622 - err = ovl_setup_cred_for_create(dentry, inode, attr->mode, old_cred); 623 - if (err) 613 + new_cred = ovl_setup_cred_for_create(dentry, inode, attr->mode, 614 + old_cred); 615 + err = PTR_ERR(new_cred); 616 + if (IS_ERR(new_cred)) { 617 + new_cred = NULL; 624 618 goto out_revert_creds; 619 + } 625 620 } 626 621 627 622 if (!ovl_dentry_is_whiteout(dentry)) ··· 634 621 err = ovl_create_over_whiteout(dentry, inode, attr); 635 622 636 623 out_revert_creds: 637 - revert_creds(old_cred); 624 + ovl_revert_creds(old_cred); 625 + put_cred(new_cred); 638 626 return err; 639 627 } 640 628 ··· 716 702 717 703 old_cred = ovl_override_creds(dentry->d_sb); 718 704 err = ovl_set_redirect(dentry, false); 719 - revert_creds(old_cred); 705 + ovl_revert_creds(old_cred); 720 706 721 707 return err; 722 708 } ··· 926 912 err = ovl_remove_upper(dentry, is_dir, &list); 927 913 else 928 914 err = ovl_remove_and_whiteout(dentry, &list); 929 - revert_creds(old_cred); 915 + ovl_revert_creds(old_cred); 930 916 if (!err) { 931 917 if (is_dir) 932 918 clear_nlink(dentry->d_inode); ··· 1306 1292 out_unlock: 1307 1293 unlock_rename(new_upperdir, old_upperdir); 1308 1294 out_revert_creds: 1309 - revert_creds(old_cred); 1295 + ovl_revert_creds(old_cred); 1310 1296 if (update_nlink) 1311 1297 ovl_nlink_end(new); 1312 1298 else ··· 1320 1306 static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, 1321 1307 struct inode *inode, umode_t mode) 1322 1308 { 1323 - const struct cred *old_cred; 1309 + const struct cred *old_cred, *new_cred = NULL; 1324 1310 struct path realparentpath; 1325 1311 struct file *realfile; 1312 + struct ovl_file *of; 1326 1313 struct dentry *newdentry; 1327 1314 /* It's okay to set O_NOATIME, since the owner will be current fsuid */ 1328 1315 int flags = file->f_flags | OVL_OPEN_FLAGS; 1329 1316 int err; 1330 1317 1331 1318 old_cred = ovl_override_creds(dentry->d_sb); 1332 - err = ovl_setup_cred_for_create(dentry, inode, mode, old_cred); 1333 - if (err) 1319 + new_cred = ovl_setup_cred_for_create(dentry, inode, mode, old_cred); 1320 + err = PTR_ERR(new_cred); 1321 + if (IS_ERR(new_cred)) { 1322 + new_cred = NULL; 1334 1323 goto out_revert_creds; 1324 + } 1335 1325 1336 1326 ovl_path_upper(dentry->d_parent, &realparentpath); 1337 1327 realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath, ··· 1345 1327 if (err) 1346 1328 goto out_revert_creds; 1347 1329 1330 + of = ovl_file_alloc(realfile); 1331 + if (!of) { 1332 + fput(realfile); 1333 + err = -ENOMEM; 1334 + goto out_revert_creds; 1335 + } 1336 + 1348 1337 /* ovl_instantiate() consumes the newdentry reference on success */ 1349 1338 newdentry = dget(realfile->f_path.dentry); 1350 1339 err = ovl_instantiate(dentry, inode, newdentry, false, file); 1351 1340 if (!err) { 1352 - file->private_data = realfile; 1341 + file->private_data = of; 1353 1342 } else { 1354 1343 dput(newdentry); 1355 - fput(realfile); 1344 + ovl_file_free(of); 1356 1345 } 1357 1346 out_revert_creds: 1358 - revert_creds(old_cred); 1347 + ovl_revert_creds(old_cred); 1348 + put_cred(new_cred); 1359 1349 return err; 1360 1350 } 1361 1351 ··· 1415 1389 put_realfile: 1416 1390 /* Without FMODE_OPENED ->release() won't be called on @file */ 1417 1391 if (!(file->f_mode & FMODE_OPENED)) 1418 - fput(file->private_data); 1392 + ovl_file_free(file->private_data); 1419 1393 put_inode: 1420 1394 iput(inode); 1421 1395 drop_write:
+194 -141
fs/overlayfs/file.c
··· 51 51 realfile = backing_file_open(&file->f_path, flags, realpath, 52 52 current_cred()); 53 53 } 54 - revert_creds(old_cred); 54 + ovl_revert_creds(old_cred); 55 55 56 56 pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n", 57 57 file, file, ovl_whatisit(inode, realinode), file->f_flags, ··· 89 89 return 0; 90 90 } 91 91 92 - static int ovl_real_fdget_meta(const struct file *file, struct fd *real, 93 - bool allow_meta) 92 + struct ovl_file { 93 + struct file *realfile; 94 + struct file *upperfile; 95 + }; 96 + 97 + struct ovl_file *ovl_file_alloc(struct file *realfile) 94 98 { 95 - struct dentry *dentry = file_dentry(file); 96 - struct file *realfile = file->private_data; 97 - struct path realpath; 98 - int err; 99 + struct ovl_file *of = kzalloc(sizeof(struct ovl_file), GFP_KERNEL); 99 100 100 - real->word = (unsigned long)realfile; 101 + if (unlikely(!of)) 102 + return NULL; 101 103 102 - if (allow_meta) { 103 - ovl_path_real(dentry, &realpath); 104 - } else { 105 - /* lazy lookup and verify of lowerdata */ 106 - err = ovl_verify_lowerdata(dentry); 107 - if (err) 108 - return err; 104 + of->realfile = realfile; 105 + return of; 106 + } 109 107 110 - ovl_path_realdata(dentry, &realpath); 111 - } 112 - if (!realpath.dentry) 113 - return -EIO; 108 + void ovl_file_free(struct ovl_file *of) 109 + { 110 + fput(of->realfile); 111 + if (of->upperfile) 112 + fput(of->upperfile); 113 + kfree(of); 114 + } 114 115 115 - /* Has it been copied up since we'd opened it? */ 116 - if (unlikely(file_inode(realfile) != d_inode(realpath.dentry))) { 117 - struct file *f = ovl_open_realfile(file, &realpath); 118 - if (IS_ERR(f)) 119 - return PTR_ERR(f); 120 - real->word = (unsigned long)f | FDPUT_FPUT; 121 - return 0; 116 + static bool ovl_is_real_file(const struct file *realfile, 117 + const struct path *realpath) 118 + { 119 + return file_inode(realfile) == d_inode(realpath->dentry); 120 + } 121 + 122 + static struct file *ovl_real_file_path(const struct file *file, 123 + struct path *realpath) 124 + { 125 + struct ovl_file *of = file->private_data; 126 + struct file *realfile = of->realfile; 127 + 128 + if (WARN_ON_ONCE(!realpath->dentry)) 129 + return ERR_PTR(-EIO); 130 + 131 + /* 132 + * If the realfile that we want is not where the data used to be at 133 + * open time, either we'd been copied up, or it's an fsync of a 134 + * metacopied file. We need the upperfile either way, so see if it 135 + * is already opened and if it is not then open and store it. 136 + */ 137 + if (unlikely(!ovl_is_real_file(realfile, realpath))) { 138 + struct file *upperfile = READ_ONCE(of->upperfile); 139 + struct file *old; 140 + 141 + if (!upperfile) { /* Nobody opened upperfile yet */ 142 + upperfile = ovl_open_realfile(file, realpath); 143 + if (IS_ERR(upperfile)) 144 + return upperfile; 145 + 146 + /* Store the upperfile for later */ 147 + old = cmpxchg_release(&of->upperfile, NULL, upperfile); 148 + if (old) { /* Someone opened upperfile before us */ 149 + fput(upperfile); 150 + upperfile = old; 151 + } 152 + } 153 + /* 154 + * Stored file must be from the right inode, unless someone's 155 + * been corrupting the upper layer. 156 + */ 157 + if (WARN_ON_ONCE(!ovl_is_real_file(upperfile, realpath))) 158 + return ERR_PTR(-EIO); 159 + 160 + realfile = upperfile; 122 161 } 123 162 124 163 /* Did the flags change since open? */ 125 - if (unlikely((file->f_flags ^ realfile->f_flags) & ~OVL_OPEN_FLAGS)) 126 - return ovl_change_flags(realfile, file->f_flags); 164 + if (unlikely((file->f_flags ^ realfile->f_flags) & ~OVL_OPEN_FLAGS)) { 165 + int err = ovl_change_flags(realfile, file->f_flags); 127 166 128 - return 0; 129 - } 130 - 131 - static int ovl_real_fdget(const struct file *file, struct fd *real) 132 - { 133 - if (d_is_dir(file_dentry(file))) { 134 - struct file *f = ovl_dir_real_file(file, false); 135 - if (IS_ERR(f)) 136 - return PTR_ERR(f); 137 - real->word = (unsigned long)f; 138 - return 0; 167 + if (err) 168 + return ERR_PTR(err); 139 169 } 140 170 141 - return ovl_real_fdget_meta(file, real, false); 171 + return realfile; 172 + } 173 + 174 + static struct file *ovl_real_file(const struct file *file) 175 + { 176 + struct dentry *dentry = file_dentry(file); 177 + struct path realpath; 178 + int err; 179 + 180 + if (d_is_dir(dentry)) { 181 + struct file *f = ovl_dir_real_file(file, false); 182 + 183 + if (WARN_ON_ONCE(!f)) 184 + return ERR_PTR(-EIO); 185 + return f; 186 + } 187 + 188 + /* lazy lookup and verify of lowerdata */ 189 + err = ovl_verify_lowerdata(dentry); 190 + if (err) 191 + return ERR_PTR(err); 192 + 193 + ovl_path_realdata(dentry, &realpath); 194 + 195 + return ovl_real_file_path(file, &realpath); 142 196 } 143 197 144 198 static int ovl_open(struct inode *inode, struct file *file) ··· 200 146 struct dentry *dentry = file_dentry(file); 201 147 struct file *realfile; 202 148 struct path realpath; 149 + struct ovl_file *of; 203 150 int err; 204 151 205 152 /* lazy lookup and verify lowerdata */ ··· 223 168 if (IS_ERR(realfile)) 224 169 return PTR_ERR(realfile); 225 170 226 - file->private_data = realfile; 171 + of = ovl_file_alloc(realfile); 172 + if (!of) { 173 + fput(realfile); 174 + return -ENOMEM; 175 + } 176 + 177 + file->private_data = of; 227 178 228 179 return 0; 229 180 } 230 181 231 182 static int ovl_release(struct inode *inode, struct file *file) 232 183 { 233 - fput(file->private_data); 234 - 184 + ovl_file_free(file->private_data); 235 185 return 0; 236 186 } 237 187 238 188 static loff_t ovl_llseek(struct file *file, loff_t offset, int whence) 239 189 { 240 190 struct inode *inode = file_inode(file); 241 - struct fd real; 191 + struct file *realfile; 242 192 const struct cred *old_cred; 243 193 loff_t ret; 244 194 ··· 259 199 return vfs_setpos(file, 0, 0); 260 200 } 261 201 262 - ret = ovl_real_fdget(file, &real); 263 - if (ret) 264 - return ret; 202 + realfile = ovl_real_file(file); 203 + if (IS_ERR(realfile)) 204 + return PTR_ERR(realfile); 265 205 266 206 /* 267 207 * Overlay file f_pos is the master copy that is preserved ··· 271 211 * files, so we use the real file to perform seeks. 272 212 */ 273 213 ovl_inode_lock(inode); 274 - fd_file(real)->f_pos = file->f_pos; 214 + realfile->f_pos = file->f_pos; 275 215 276 216 old_cred = ovl_override_creds(inode->i_sb); 277 - ret = vfs_llseek(fd_file(real), offset, whence); 278 - revert_creds(old_cred); 217 + ret = vfs_llseek(realfile, offset, whence); 218 + ovl_revert_creds(old_cred); 279 219 280 - file->f_pos = fd_file(real)->f_pos; 220 + file->f_pos = realfile->f_pos; 281 221 ovl_inode_unlock(inode); 282 - 283 - fdput(real); 284 222 285 223 return ret; 286 224 } ··· 289 231 ovl_copyattr(file_inode(file)); 290 232 } 291 233 292 - static void ovl_file_end_write(struct file *file, loff_t pos, ssize_t ret) 234 + static void ovl_file_end_write(struct kiocb *iocb, ssize_t ret) 293 235 { 294 - ovl_file_modified(file); 236 + ovl_file_modified(iocb->ki_filp); 295 237 } 296 238 297 239 static void ovl_file_accessed(struct file *file) ··· 325 267 static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) 326 268 { 327 269 struct file *file = iocb->ki_filp; 328 - struct fd real; 329 - ssize_t ret; 270 + struct file *realfile; 330 271 struct backing_file_ctx ctx = { 331 272 .cred = ovl_creds(file_inode(file)->i_sb), 332 - .user_file = file, 333 273 .accessed = ovl_file_accessed, 334 274 }; 335 275 336 276 if (!iov_iter_count(iter)) 337 277 return 0; 338 278 339 - ret = ovl_real_fdget(file, &real); 340 - if (ret) 341 - return ret; 279 + realfile = ovl_real_file(file); 280 + if (IS_ERR(realfile)) 281 + return PTR_ERR(realfile); 342 282 343 - ret = backing_file_read_iter(fd_file(real), iter, iocb, iocb->ki_flags, 344 - &ctx); 345 - fdput(real); 346 - 347 - return ret; 283 + return backing_file_read_iter(realfile, iter, iocb, iocb->ki_flags, 284 + &ctx); 348 285 } 349 286 350 287 static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) 351 288 { 352 289 struct file *file = iocb->ki_filp; 353 290 struct inode *inode = file_inode(file); 354 - struct fd real; 291 + struct file *realfile; 355 292 ssize_t ret; 356 293 int ifl = iocb->ki_flags; 357 294 struct backing_file_ctx ctx = { 358 295 .cred = ovl_creds(inode->i_sb), 359 - .user_file = file, 360 296 .end_write = ovl_file_end_write, 361 297 }; 362 298 ··· 361 309 /* Update mode */ 362 310 ovl_copyattr(inode); 363 311 364 - ret = ovl_real_fdget(file, &real); 365 - if (ret) 312 + realfile = ovl_real_file(file); 313 + ret = PTR_ERR(realfile); 314 + if (IS_ERR(realfile)) 366 315 goto out_unlock; 367 316 368 317 if (!ovl_should_sync(OVL_FS(inode->i_sb))) ··· 374 321 * this property in case it is set by the issuer. 375 322 */ 376 323 ifl &= ~IOCB_DIO_CALLER_COMP; 377 - ret = backing_file_write_iter(fd_file(real), iter, iocb, ifl, &ctx); 378 - fdput(real); 324 + ret = backing_file_write_iter(realfile, iter, iocb, ifl, &ctx); 379 325 380 326 out_unlock: 381 327 inode_unlock(inode); ··· 386 334 struct pipe_inode_info *pipe, size_t len, 387 335 unsigned int flags) 388 336 { 389 - struct fd real; 337 + struct file *realfile; 390 338 ssize_t ret; 391 339 struct backing_file_ctx ctx = { 392 340 .cred = ovl_creds(file_inode(in)->i_sb), 393 - .user_file = in, 394 341 .accessed = ovl_file_accessed, 395 342 }; 343 + struct kiocb iocb; 396 344 397 - ret = ovl_real_fdget(in, &real); 398 - if (ret) 399 - return ret; 345 + realfile = ovl_real_file(in); 346 + if (IS_ERR(realfile)) 347 + return PTR_ERR(realfile); 400 348 401 - ret = backing_file_splice_read(fd_file(real), ppos, pipe, len, flags, &ctx); 402 - fdput(real); 349 + init_sync_kiocb(&iocb, in); 350 + iocb.ki_pos = *ppos; 351 + ret = backing_file_splice_read(realfile, &iocb, pipe, len, flags, &ctx); 352 + *ppos = iocb.ki_pos; 403 353 404 354 return ret; 405 355 } ··· 409 355 /* 410 356 * Calling iter_file_splice_write() directly from overlay's f_op may deadlock 411 357 * due to lock order inversion between pipe->mutex in iter_file_splice_write() 412 - * and file_start_write(fd_file(real)) in ovl_write_iter(). 358 + * and file_start_write(realfile) in ovl_write_iter(). 413 359 * 414 360 * So do everything ovl_write_iter() does and call iter_file_splice_write() on 415 361 * the real file. ··· 417 363 static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, 418 364 loff_t *ppos, size_t len, unsigned int flags) 419 365 { 420 - struct fd real; 366 + struct file *realfile; 421 367 struct inode *inode = file_inode(out); 422 368 ssize_t ret; 423 369 struct backing_file_ctx ctx = { 424 370 .cred = ovl_creds(inode->i_sb), 425 - .user_file = out, 426 371 .end_write = ovl_file_end_write, 427 372 }; 373 + struct kiocb iocb; 428 374 429 375 inode_lock(inode); 430 376 /* Update mode */ 431 377 ovl_copyattr(inode); 432 378 433 - ret = ovl_real_fdget(out, &real); 434 - if (ret) 379 + realfile = ovl_real_file(out); 380 + ret = PTR_ERR(realfile); 381 + if (IS_ERR(realfile)) 435 382 goto out_unlock; 436 383 437 - ret = backing_file_splice_write(pipe, fd_file(real), ppos, len, flags, &ctx); 438 - fdput(real); 384 + init_sync_kiocb(&iocb, out); 385 + iocb.ki_pos = *ppos; 386 + ret = backing_file_splice_write(pipe, realfile, &iocb, len, flags, &ctx); 387 + *ppos = iocb.ki_pos; 439 388 440 389 out_unlock: 441 390 inode_unlock(inode); ··· 448 391 449 392 static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync) 450 393 { 451 - struct fd real; 394 + struct dentry *dentry = file_dentry(file); 395 + enum ovl_path_type type; 396 + struct path upperpath; 397 + struct file *upperfile; 452 398 const struct cred *old_cred; 453 399 int ret; 454 400 ··· 459 399 if (ret <= 0) 460 400 return ret; 461 401 462 - ret = ovl_real_fdget_meta(file, &real, !datasync); 463 - if (ret) 464 - return ret; 465 - 466 402 /* Don't sync lower file for fear of receiving EROFS error */ 467 - if (file_inode(fd_file(real)) == ovl_inode_upper(file_inode(file))) { 468 - old_cred = ovl_override_creds(file_inode(file)->i_sb); 469 - ret = vfs_fsync_range(fd_file(real), start, end, datasync); 470 - revert_creds(old_cred); 471 - } 403 + type = ovl_path_type(dentry); 404 + if (!OVL_TYPE_UPPER(type) || (datasync && OVL_TYPE_MERGE(type))) 405 + return 0; 472 406 473 - fdput(real); 407 + ovl_path_upper(dentry, &upperpath); 408 + upperfile = ovl_real_file_path(file, &upperpath); 409 + if (IS_ERR(upperfile)) 410 + return PTR_ERR(upperfile); 411 + 412 + old_cred = ovl_override_creds(file_inode(file)->i_sb); 413 + ret = vfs_fsync_range(upperfile, start, end, datasync); 414 + ovl_revert_creds(old_cred); 474 415 475 416 return ret; 476 417 } 477 418 478 419 static int ovl_mmap(struct file *file, struct vm_area_struct *vma) 479 420 { 480 - struct file *realfile = file->private_data; 421 + struct ovl_file *of = file->private_data; 481 422 struct backing_file_ctx ctx = { 482 423 .cred = ovl_creds(file_inode(file)->i_sb), 483 - .user_file = file, 484 424 .accessed = ovl_file_accessed, 485 425 }; 486 426 487 - return backing_file_mmap(realfile, vma, &ctx); 427 + return backing_file_mmap(of->realfile, vma, &ctx); 488 428 } 489 429 490 430 static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len) 491 431 { 492 432 struct inode *inode = file_inode(file); 493 - struct fd real; 433 + struct file *realfile; 494 434 const struct cred *old_cred; 495 435 int ret; 496 436 ··· 501 441 if (ret) 502 442 goto out_unlock; 503 443 504 - ret = ovl_real_fdget(file, &real); 505 - if (ret) 444 + realfile = ovl_real_file(file); 445 + ret = PTR_ERR(realfile); 446 + if (IS_ERR(realfile)) 506 447 goto out_unlock; 507 448 508 449 old_cred = ovl_override_creds(file_inode(file)->i_sb); 509 - ret = vfs_fallocate(fd_file(real), mode, offset, len); 510 - revert_creds(old_cred); 450 + ret = vfs_fallocate(realfile, mode, offset, len); 451 + ovl_revert_creds(old_cred); 511 452 512 453 /* Update size */ 513 454 ovl_file_modified(file); 514 - 515 - fdput(real); 516 455 517 456 out_unlock: 518 457 inode_unlock(inode); ··· 521 462 522 463 static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice) 523 464 { 524 - struct fd real; 465 + struct file *realfile; 525 466 const struct cred *old_cred; 526 467 int ret; 527 468 528 - ret = ovl_real_fdget(file, &real); 529 - if (ret) 530 - return ret; 469 + realfile = ovl_real_file(file); 470 + if (IS_ERR(realfile)) 471 + return PTR_ERR(realfile); 531 472 532 473 old_cred = ovl_override_creds(file_inode(file)->i_sb); 533 - ret = vfs_fadvise(fd_file(real), offset, len, advice); 534 - revert_creds(old_cred); 535 - 536 - fdput(real); 474 + ret = vfs_fadvise(realfile, offset, len, advice); 475 + ovl_revert_creds(old_cred); 537 476 538 477 return ret; 539 478 } ··· 547 490 loff_t len, unsigned int flags, enum ovl_copyop op) 548 491 { 549 492 struct inode *inode_out = file_inode(file_out); 550 - struct fd real_in, real_out; 493 + struct file *realfile_in, *realfile_out; 551 494 const struct cred *old_cred; 552 495 loff_t ret; 553 496 ··· 560 503 goto out_unlock; 561 504 } 562 505 563 - ret = ovl_real_fdget(file_out, &real_out); 564 - if (ret) 506 + realfile_out = ovl_real_file(file_out); 507 + ret = PTR_ERR(realfile_out); 508 + if (IS_ERR(realfile_out)) 565 509 goto out_unlock; 566 510 567 - ret = ovl_real_fdget(file_in, &real_in); 568 - if (ret) { 569 - fdput(real_out); 511 + realfile_in = ovl_real_file(file_in); 512 + ret = PTR_ERR(realfile_in); 513 + if (IS_ERR(realfile_in)) 570 514 goto out_unlock; 571 - } 572 515 573 516 old_cred = ovl_override_creds(file_inode(file_out)->i_sb); 574 517 switch (op) { 575 518 case OVL_COPY: 576 - ret = vfs_copy_file_range(fd_file(real_in), pos_in, 577 - fd_file(real_out), pos_out, len, flags); 519 + ret = vfs_copy_file_range(realfile_in, pos_in, 520 + realfile_out, pos_out, len, flags); 578 521 break; 579 522 580 523 case OVL_CLONE: 581 - ret = vfs_clone_file_range(fd_file(real_in), pos_in, 582 - fd_file(real_out), pos_out, len, flags); 524 + ret = vfs_clone_file_range(realfile_in, pos_in, 525 + realfile_out, pos_out, len, flags); 583 526 break; 584 527 585 528 case OVL_DEDUPE: 586 - ret = vfs_dedupe_file_range_one(fd_file(real_in), pos_in, 587 - fd_file(real_out), pos_out, len, 529 + ret = vfs_dedupe_file_range_one(realfile_in, pos_in, 530 + realfile_out, pos_out, len, 588 531 flags); 589 532 break; 590 533 } 591 - revert_creds(old_cred); 534 + ovl_revert_creds(old_cred); 592 535 593 536 /* Update size */ 594 537 ovl_file_modified(file_out); 595 - 596 - fdput(real_in); 597 - fdput(real_out); 598 538 599 539 out_unlock: 600 540 inode_unlock(inode_out); ··· 636 582 637 583 static int ovl_flush(struct file *file, fl_owner_t id) 638 584 { 639 - struct fd real; 585 + struct file *realfile; 640 586 const struct cred *old_cred; 641 - int err; 587 + int err = 0; 642 588 643 - err = ovl_real_fdget(file, &real); 644 - if (err) 645 - return err; 589 + realfile = ovl_real_file(file); 590 + if (IS_ERR(realfile)) 591 + return PTR_ERR(realfile); 646 592 647 - if (fd_file(real)->f_op->flush) { 593 + if (realfile->f_op->flush) { 648 594 old_cred = ovl_override_creds(file_inode(file)->i_sb); 649 - err = fd_file(real)->f_op->flush(fd_file(real), id); 650 - revert_creds(old_cred); 595 + err = realfile->f_op->flush(realfile, id); 596 + ovl_revert_creds(old_cred); 651 597 } 652 - fdput(real); 653 598 654 599 return err; 655 600 }
+16 -11
fs/overlayfs/inode.c
··· 80 80 inode_lock(upperdentry->d_inode); 81 81 old_cred = ovl_override_creds(dentry->d_sb); 82 82 err = ovl_do_notify_change(ofs, upperdentry, attr); 83 - revert_creds(old_cred); 83 + ovl_revert_creds(old_cred); 84 84 if (!err) 85 85 ovl_copyattr(dentry->d_inode); 86 86 inode_unlock(upperdentry->d_inode); ··· 280 280 stat->nlink = dentry->d_inode->i_nlink; 281 281 282 282 out: 283 - revert_creds(old_cred); 283 + ovl_revert_creds(old_cred); 284 284 285 285 return err; 286 286 } ··· 317 317 mask |= MAY_READ; 318 318 } 319 319 err = inode_permission(mnt_idmap(realpath.mnt), realinode, mask); 320 - revert_creds(old_cred); 320 + ovl_revert_creds(old_cred); 321 321 322 322 return err; 323 323 } ··· 334 334 335 335 old_cred = ovl_override_creds(dentry->d_sb); 336 336 p = vfs_get_link(ovl_dentry_real(dentry), done); 337 - revert_creds(old_cred); 337 + ovl_revert_creds(old_cred); 338 338 return p; 339 339 } 340 340 ··· 469 469 470 470 old_cred = ovl_override_creds(inode->i_sb); 471 471 acl = ovl_get_acl_path(&realpath, posix_acl_xattr_name(type), noperm); 472 - revert_creds(old_cred); 472 + ovl_revert_creds(old_cred); 473 473 } 474 474 475 475 return acl; ··· 498 498 old_cred = ovl_override_creds(dentry->d_sb); 499 499 real_acl = vfs_get_acl(mnt_idmap(realpath.mnt), realdentry, 500 500 acl_name); 501 - revert_creds(old_cred); 501 + ovl_revert_creds(old_cred); 502 502 if (IS_ERR(real_acl)) { 503 503 err = PTR_ERR(real_acl); 504 504 goto out; ··· 523 523 err = ovl_do_set_acl(ofs, realdentry, acl_name, acl); 524 524 else 525 525 err = ovl_do_remove_acl(ofs, realdentry, acl_name); 526 - revert_creds(old_cred); 526 + ovl_revert_creds(old_cred); 527 527 ovl_drop_write(dentry); 528 528 529 529 /* copy c/mtime */ ··· 600 600 601 601 old_cred = ovl_override_creds(inode->i_sb); 602 602 err = realinode->i_op->fiemap(realinode, fieinfo, start, len); 603 - revert_creds(old_cred); 603 + ovl_revert_creds(old_cred); 604 604 605 605 return err; 606 606 } ··· 616 616 struct file *file; 617 617 unsigned int cmd; 618 618 int err; 619 + unsigned int flags; 619 620 620 - file = dentry_open(realpath, O_RDONLY, current_cred()); 621 + flags = O_RDONLY; 622 + if (force_o_largefile()) 623 + flags |= O_LARGEFILE; 624 + 625 + file = dentry_open(realpath, flags, current_cred()); 621 626 if (IS_ERR(file)) 622 627 return PTR_ERR(file); 623 628 ··· 676 671 err = ovl_set_protattr(inode, upperpath.dentry, fa); 677 672 if (!err) 678 673 err = ovl_real_fileattr_set(&upperpath, fa); 679 - revert_creds(old_cred); 674 + ovl_revert_creds(old_cred); 680 675 ovl_drop_write(dentry); 681 676 682 677 /* ··· 738 733 old_cred = ovl_override_creds(inode->i_sb); 739 734 err = ovl_real_fileattr_get(&realpath, fa); 740 735 ovl_fileattr_prot_flags(inode, fa); 741 - revert_creds(old_cred); 736 + ovl_revert_creds(old_cred); 742 737 743 738 return err; 744 739 }
+5 -5
fs/overlayfs/namei.c
··· 961 961 if (err == 0) 962 962 ovl_set_flag(OVL_VERIFIED_DIGEST, inode); 963 963 964 - revert_creds(old_cred); 964 + ovl_revert_creds(old_cred); 965 965 } 966 966 967 967 ovl_inode_unlock(inode); ··· 995 995 996 996 old_cred = ovl_override_creds(dentry->d_sb); 997 997 err = ovl_lookup_data_layers(dentry, redirect, &datapath); 998 - revert_creds(old_cred); 998 + ovl_revert_creds(old_cred); 999 999 if (err) 1000 1000 goto out_err; 1001 1001 ··· 1342 1342 1343 1343 ovl_dentry_init_reval(dentry, upperdentry, OVL_I_E(inode)); 1344 1344 1345 - revert_creds(old_cred); 1345 + ovl_revert_creds(old_cred); 1346 1346 if (origin_path) { 1347 1347 dput(origin_path->dentry); 1348 1348 kfree(origin_path); ··· 1366 1366 kfree(upperredirect); 1367 1367 out: 1368 1368 kfree(d.redirect); 1369 - revert_creds(old_cred); 1369 + ovl_revert_creds(old_cred); 1370 1370 return ERR_PTR(err); 1371 1371 } 1372 1372 ··· 1423 1423 dput(this); 1424 1424 } 1425 1425 } 1426 - revert_creds(old_cred); 1426 + ovl_revert_creds(old_cred); 1427 1427 1428 1428 return positive; 1429 1429 }
+4
fs/overlayfs/overlayfs.h
··· 421 421 void ovl_drop_write(struct dentry *dentry); 422 422 struct dentry *ovl_workdir(struct dentry *dentry); 423 423 const struct cred *ovl_override_creds(struct super_block *sb); 424 + void ovl_revert_creds(const struct cred *old_cred); 424 425 425 426 static inline const struct cred *ovl_creds(struct super_block *sb) 426 427 { ··· 855 854 int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa); 856 855 int ovl_fileattr_set(struct mnt_idmap *idmap, 857 856 struct dentry *dentry, struct fileattr *fa); 857 + struct ovl_file; 858 + struct ovl_file *ovl_file_alloc(struct file *realfile); 859 + void ovl_file_free(struct ovl_file *of); 858 860 859 861 /* copy_up.c */ 860 862 int ovl_copy_up(struct dentry *dentry);
+4 -4
fs/overlayfs/readdir.c
··· 290 290 } 291 291 inode_unlock(dir->d_inode); 292 292 } 293 - revert_creds(old_cred); 293 + ovl_revert_creds(old_cred); 294 294 295 295 return err; 296 296 } ··· 808 808 } 809 809 err = 0; 810 810 out: 811 - revert_creds(old_cred); 811 + ovl_revert_creds(old_cred); 812 812 return err; 813 813 } 814 814 ··· 860 860 861 861 old_cred = ovl_override_creds(file_inode(file)->i_sb); 862 862 res = ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE)); 863 - revert_creds(old_cred); 863 + ovl_revert_creds(old_cred); 864 864 865 865 return res; 866 866 } ··· 987 987 988 988 old_cred = ovl_override_creds(dentry->d_sb); 989 989 err = ovl_dir_read_merged(dentry, list, &root); 990 - revert_creds(old_cred); 990 + ovl_revert_creds(old_cred); 991 991 if (err) 992 992 return err; 993 993
+11 -3
fs/overlayfs/util.c
··· 65 65 { 66 66 struct ovl_fs *ofs = OVL_FS(sb); 67 67 68 - return override_creds(ofs->creator_cred); 68 + return override_creds_light(ofs->creator_cred); 69 + } 70 + 71 + void ovl_revert_creds(const struct cred *old_cred) 72 + { 73 + revert_creds_light(old_cred); 69 74 } 70 75 71 76 /* ··· 202 197 203 198 bool ovl_dentry_weird(struct dentry *dentry) 204 199 { 200 + if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry)) 201 + return true; 202 + 205 203 return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT | 206 204 DCACHE_MANAGE_TRANSIT | 207 205 DCACHE_OP_HASH | ··· 1186 1178 * value relative to the upper inode nlink in an upper inode xattr. 1187 1179 */ 1188 1180 err = ovl_set_nlink_upper(dentry); 1189 - revert_creds(old_cred); 1181 + ovl_revert_creds(old_cred); 1190 1182 if (err) 1191 1183 goto out_drop_write; 1192 1184 ··· 1211 1203 1212 1204 old_cred = ovl_override_creds(dentry->d_sb); 1213 1205 ovl_cleanup_index(dentry); 1214 - revert_creds(old_cred); 1206 + ovl_revert_creds(old_cred); 1215 1207 } 1216 1208 1217 1209 ovl_inode_unlock(inode);
+4 -5
fs/overlayfs/xattrs.c
··· 47 47 ovl_path_lower(dentry, &realpath); 48 48 old_cred = ovl_override_creds(dentry->d_sb); 49 49 err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0); 50 - revert_creds(old_cred); 50 + ovl_revert_creds(old_cred); 51 51 if (err < 0) 52 52 goto out; 53 53 } ··· 72 72 WARN_ON(flags != XATTR_REPLACE); 73 73 err = ovl_do_removexattr(ofs, realdentry, name); 74 74 } 75 - revert_creds(old_cred); 75 + ovl_revert_creds(old_cred); 76 76 ovl_drop_write(dentry); 77 77 78 78 /* copy c/mtime */ ··· 91 91 ovl_i_path_real(inode, &realpath); 92 92 old_cred = ovl_override_creds(dentry->d_sb); 93 93 res = vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size); 94 - revert_creds(old_cred); 94 + ovl_revert_creds(old_cred); 95 95 return res; 96 96 } 97 97 ··· 121 121 122 122 old_cred = ovl_override_creds(dentry->d_sb); 123 123 res = vfs_listxattr(realdentry, list, size); 124 - revert_creds(old_cred); 124 + ovl_revert_creds(old_cred); 125 125 if (res <= 0 || size == 0) 126 126 return res; 127 127 ··· 268 268 return ofs->config.userxattr ? ovl_user_xattr_handlers : 269 269 ovl_trusted_xattr_handlers; 270 270 } 271 -
+5 -6
include/linux/backing-file.h
··· 14 14 15 15 struct backing_file_ctx { 16 16 const struct cred *cred; 17 - struct file *user_file; 18 - void (*accessed)(struct file *); 19 - void (*end_write)(struct file *, loff_t, ssize_t); 17 + void (*accessed)(struct file *file); 18 + void (*end_write)(struct kiocb *iocb, ssize_t); 20 19 }; 21 20 22 21 struct file *backing_file_open(const struct path *user_path, int flags, ··· 30 31 ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter, 31 32 struct kiocb *iocb, int flags, 32 33 struct backing_file_ctx *ctx); 33 - ssize_t backing_file_splice_read(struct file *in, loff_t *ppos, 34 + ssize_t backing_file_splice_read(struct file *in, struct kiocb *iocb, 34 35 struct pipe_inode_info *pipe, size_t len, 35 36 unsigned int flags, 36 37 struct backing_file_ctx *ctx); 37 38 ssize_t backing_file_splice_write(struct pipe_inode_info *pipe, 38 - struct file *out, loff_t *ppos, size_t len, 39 - unsigned int flags, 39 + struct file *out, struct kiocb *iocb, 40 + size_t len, unsigned int flags, 40 41 struct backing_file_ctx *ctx); 41 42 int backing_file_mmap(struct file *file, struct vm_area_struct *vma, 42 43 struct backing_file_ctx *ctx);
+18
include/linux/cred.h
··· 172 172 cred->cap_inheritable)); 173 173 } 174 174 175 + /* 176 + * Override creds without bumping reference count. Caller must ensure 177 + * reference remains valid or has taken reference. Almost always not the 178 + * interface you want. Use override_creds()/revert_creds() instead. 179 + */ 180 + static inline const struct cred *override_creds_light(const struct cred *override_cred) 181 + { 182 + const struct cred *old = current->cred; 183 + 184 + rcu_assign_pointer(current->cred, override_cred); 185 + return old; 186 + } 187 + 188 + static inline void revert_creds_light(const struct cred *revert_cred) 189 + { 190 + rcu_assign_pointer(current->cred, revert_cred); 191 + } 192 + 175 193 /** 176 194 * get_new_cred_many - Get references on a new set of credentials 177 195 * @cred: The new credentials to reference
+3 -3
kernel/cred.c
··· 485 485 */ 486 486 const struct cred *override_creds(const struct cred *new) 487 487 { 488 - const struct cred *old = current->cred; 488 + const struct cred *old; 489 489 490 490 kdebug("override_creds(%p{%ld})", new, 491 491 atomic_long_read(&new->usage)); ··· 499 499 * visible to other threads under RCU. 500 500 */ 501 501 get_new_cred((struct cred *)new); 502 - rcu_assign_pointer(current->cred, new); 502 + old = override_creds_light(new); 503 503 504 504 kdebug("override_creds() = %p{%ld}", old, 505 505 atomic_long_read(&old->usage)); ··· 521 521 kdebug("revert_creds(%p{%ld})", old, 522 522 atomic_long_read(&old->usage)); 523 523 524 - rcu_assign_pointer(current->cred, old); 524 + revert_creds_light(old); 525 525 put_cred(override); 526 526 } 527 527 EXPORT_SYMBOL(revert_creds);