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 patch series "credentials guards: the easy cases"

Christian Brauner <brauner@kernel.org> says:

This converts all users of override_creds() to rely on credentials
guards. Leave all those that do the prepare_creds() + modify creds +
override_creds() dance alone for now. Some of them qualify for their own
variant.

* patches from https://patch.msgid.link/20251103-work-creds-guards-simple-v1-0-a3e156839e7f@kernel.org:
net/dns_resolver: use credential guards in dns_query()
cgroup: use credential guards in cgroup_attach_permissions()
act: use credential guards in acct_write_process()
smb: use credential guards in cifs_get_spnego_key()
nfs: use credential guards in nfs_idmap_get_key()
nfs: use credential guards in nfs_local_call_write()
nfs: use credential guards in nfs_local_call_read()
erofs: use credential guards
binfmt_misc: use credential guards
backing-file: use credential guards for mmap
backing-file: use credential guards for splice write
backing-file: use credential guards for splice read
backing-file: use credential guards for writes
backing-file: use credential guards for reads
aio: use credential guards
cred: add {scoped_}with_creds() guards

Link: https://patch.msgid.link/20251103-work-creds-guards-simple-v1-0-a3e156839e7f@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

+142 -149
+3 -3
fs/aio.c
··· 1640 1640 static void aio_fsync_work(struct work_struct *work) 1641 1641 { 1642 1642 struct aio_kiocb *iocb = container_of(work, struct aio_kiocb, fsync.work); 1643 - const struct cred *old_cred = override_creds(iocb->fsync.creds); 1644 1643 1645 - iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync); 1646 - revert_creds(old_cred); 1644 + scoped_with_creds(iocb->fsync.creds) 1645 + iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync); 1646 + 1647 1647 put_cred(iocb->fsync.creds); 1648 1648 iocb_put(iocb); 1649 1649 }
+76 -73
fs/backing-file.c
··· 157 157 return sb_init_dio_done_wq(sb); 158 158 } 159 159 160 + static int do_backing_file_read_iter(struct file *file, struct iov_iter *iter, 161 + struct kiocb *iocb, int flags) 162 + { 163 + struct backing_aio *aio = NULL; 164 + int ret; 165 + 166 + if (is_sync_kiocb(iocb)) { 167 + rwf_t rwf = iocb_to_rw_flags(flags); 168 + 169 + return vfs_iter_read(file, iter, &iocb->ki_pos, rwf); 170 + } 171 + 172 + aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL); 173 + if (!aio) 174 + return -ENOMEM; 175 + 176 + aio->orig_iocb = iocb; 177 + kiocb_clone(&aio->iocb, iocb, get_file(file)); 178 + aio->iocb.ki_complete = backing_aio_rw_complete; 179 + refcount_set(&aio->ref, 2); 180 + ret = vfs_iocb_iter_read(file, &aio->iocb, iter); 181 + backing_aio_put(aio); 182 + if (ret != -EIOCBQUEUED) 183 + backing_aio_cleanup(aio, ret); 184 + return ret; 185 + } 160 186 161 187 ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter, 162 188 struct kiocb *iocb, int flags, 163 189 struct backing_file_ctx *ctx) 164 190 { 165 - struct backing_aio *aio = NULL; 166 - const struct cred *old_cred; 167 191 ssize_t ret; 168 192 169 193 if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING))) ··· 200 176 !(file->f_mode & FMODE_CAN_ODIRECT)) 201 177 return -EINVAL; 202 178 203 - old_cred = override_creds(ctx->cred); 204 - if (is_sync_kiocb(iocb)) { 205 - rwf_t rwf = iocb_to_rw_flags(flags); 206 - 207 - ret = vfs_iter_read(file, iter, &iocb->ki_pos, rwf); 208 - } else { 209 - ret = -ENOMEM; 210 - aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL); 211 - if (!aio) 212 - goto out; 213 - 214 - aio->orig_iocb = iocb; 215 - kiocb_clone(&aio->iocb, iocb, get_file(file)); 216 - aio->iocb.ki_complete = backing_aio_rw_complete; 217 - refcount_set(&aio->ref, 2); 218 - ret = vfs_iocb_iter_read(file, &aio->iocb, iter); 219 - backing_aio_put(aio); 220 - if (ret != -EIOCBQUEUED) 221 - backing_aio_cleanup(aio, ret); 222 - } 223 - out: 224 - revert_creds(old_cred); 179 + scoped_with_creds(ctx->cred) 180 + ret = do_backing_file_read_iter(file, iter, iocb, flags); 225 181 226 182 if (ctx->accessed) 227 183 ctx->accessed(iocb->ki_filp); ··· 210 206 } 211 207 EXPORT_SYMBOL_GPL(backing_file_read_iter); 212 208 209 + static int do_backing_file_write_iter(struct file *file, struct iov_iter *iter, 210 + struct kiocb *iocb, int flags, 211 + void (*end_write)(struct kiocb *, ssize_t)) 212 + { 213 + struct backing_aio *aio; 214 + int ret; 215 + 216 + if (is_sync_kiocb(iocb)) { 217 + rwf_t rwf = iocb_to_rw_flags(flags); 218 + 219 + ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf); 220 + if (end_write) 221 + end_write(iocb, ret); 222 + return ret; 223 + } 224 + 225 + ret = backing_aio_init_wq(iocb); 226 + if (ret) 227 + return ret; 228 + 229 + aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL); 230 + if (!aio) 231 + return -ENOMEM; 232 + 233 + aio->orig_iocb = iocb; 234 + aio->end_write = end_write; 235 + kiocb_clone(&aio->iocb, iocb, get_file(file)); 236 + aio->iocb.ki_flags = flags; 237 + aio->iocb.ki_complete = backing_aio_queue_completion; 238 + refcount_set(&aio->ref, 2); 239 + ret = vfs_iocb_iter_write(file, &aio->iocb, iter); 240 + backing_aio_put(aio); 241 + if (ret != -EIOCBQUEUED) 242 + backing_aio_cleanup(aio, ret); 243 + return ret; 244 + } 245 + 213 246 ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter, 214 247 struct kiocb *iocb, int flags, 215 248 struct backing_file_ctx *ctx) 216 249 { 217 - const struct cred *old_cred; 218 250 ssize_t ret; 219 251 220 252 if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING))) ··· 273 233 */ 274 234 flags &= ~IOCB_DIO_CALLER_COMP; 275 235 276 - old_cred = override_creds(ctx->cred); 277 - if (is_sync_kiocb(iocb)) { 278 - rwf_t rwf = iocb_to_rw_flags(flags); 279 - 280 - ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf); 281 - if (ctx->end_write) 282 - ctx->end_write(iocb, ret); 283 - } else { 284 - struct backing_aio *aio; 285 - 286 - ret = backing_aio_init_wq(iocb); 287 - if (ret) 288 - goto out; 289 - 290 - ret = -ENOMEM; 291 - aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL); 292 - if (!aio) 293 - goto out; 294 - 295 - aio->orig_iocb = iocb; 296 - aio->end_write = ctx->end_write; 297 - kiocb_clone(&aio->iocb, iocb, get_file(file)); 298 - aio->iocb.ki_flags = flags; 299 - aio->iocb.ki_complete = backing_aio_queue_completion; 300 - refcount_set(&aio->ref, 2); 301 - ret = vfs_iocb_iter_write(file, &aio->iocb, iter); 302 - backing_aio_put(aio); 303 - if (ret != -EIOCBQUEUED) 304 - backing_aio_cleanup(aio, ret); 305 - } 306 - out: 307 - revert_creds(old_cred); 308 - 309 - return ret; 236 + scoped_with_creds(ctx->cred) 237 + return do_backing_file_write_iter(file, iter, iocb, flags, ctx->end_write); 310 238 } 311 239 EXPORT_SYMBOL_GPL(backing_file_write_iter); 312 240 ··· 283 275 unsigned int flags, 284 276 struct backing_file_ctx *ctx) 285 277 { 286 - const struct cred *old_cred; 287 278 ssize_t ret; 288 279 289 280 if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) 290 281 return -EIO; 291 282 292 - old_cred = override_creds(ctx->cred); 293 - ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); 294 - revert_creds(old_cred); 283 + scoped_with_creds(ctx->cred) 284 + ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); 295 285 296 286 if (ctx->accessed) 297 287 ctx->accessed(iocb->ki_filp); ··· 303 297 size_t len, unsigned int flags, 304 298 struct backing_file_ctx *ctx) 305 299 { 306 - const struct cred *old_cred; 307 300 ssize_t ret; 308 301 309 302 if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING))) ··· 315 310 if (ret) 316 311 return ret; 317 312 318 - old_cred = override_creds(ctx->cred); 319 - file_start_write(out); 320 - ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); 321 - file_end_write(out); 322 - revert_creds(old_cred); 313 + scoped_with_creds(ctx->cred) { 314 + file_start_write(out); 315 + ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); 316 + file_end_write(out); 317 + } 323 318 324 319 if (ctx->end_write) 325 320 ctx->end_write(iocb, ret); ··· 331 326 int backing_file_mmap(struct file *file, struct vm_area_struct *vma, 332 327 struct backing_file_ctx *ctx) 333 328 { 334 - const struct cred *old_cred; 335 329 struct file *user_file = vma->vm_file; 336 330 int ret; 337 331 ··· 342 338 343 339 vma_set_file(vma, file); 344 340 345 - old_cred = override_creds(ctx->cred); 346 - ret = vfs_mmap(vma->vm_file, vma); 347 - revert_creds(old_cred); 341 + scoped_with_creds(ctx->cred) 342 + ret = vfs_mmap(vma->vm_file, vma); 348 343 349 344 if (ctx->accessed) 350 345 ctx->accessed(user_file);
+2 -5
fs/binfmt_misc.c
··· 782 782 return PTR_ERR(e); 783 783 784 784 if (e->flags & MISC_FMT_OPEN_FILE) { 785 - const struct cred *old_cred; 786 - 787 785 /* 788 786 * Now that we support unprivileged binfmt_misc mounts make 789 787 * sure we use the credentials that the register @file was ··· 789 791 * didn't matter much as only a privileged process could open 790 792 * the register file. 791 793 */ 792 - old_cred = override_creds(file->f_cred); 793 - f = open_exec(e->interpreter); 794 - revert_creds(old_cred); 794 + scoped_with_creds(file->f_cred) 795 + f = open_exec(e->interpreter); 795 796 if (IS_ERR(f)) { 796 797 pr_notice("register: failed to install interpreter file %s\n", 797 798 e->interpreter);
+2 -4
fs/erofs/fileio.c
··· 47 47 48 48 static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq) 49 49 { 50 - const struct cred *old_cred; 51 50 struct iov_iter iter; 52 51 int ret; 53 52 ··· 60 61 rq->iocb.ki_flags = IOCB_DIRECT; 61 62 iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt, 62 63 rq->bio.bi_iter.bi_size); 63 - old_cred = override_creds(rq->iocb.ki_filp->f_cred); 64 - ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter); 65 - revert_creds(old_cred); 64 + scoped_with_creds(rq->iocb.ki_filp->f_cred) 65 + ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter); 66 66 if (ret != -EIOCBQUEUED) 67 67 erofs_fileio_ki_complete(&rq->iocb, ret); 68 68 }
+32 -27
fs/nfs/localio.c
··· 595 595 struct nfs_local_kiocb *iocb = 596 596 container_of(work, struct nfs_local_kiocb, work); 597 597 struct file *filp = iocb->kiocb.ki_filp; 598 - const struct cred *save_cred; 599 598 ssize_t status; 600 599 601 - save_cred = override_creds(filp->f_cred); 600 + scoped_with_creds(filp->f_cred) { 601 + for (int i = 0; i < iocb->n_iters ; i++) { 602 + if (iocb->iter_is_dio_aligned[i]) { 603 + iocb->kiocb.ki_flags |= IOCB_DIRECT; 604 + iocb->kiocb.ki_complete = nfs_local_read_aio_complete; 605 + iocb->aio_complete_work = nfs_local_read_aio_complete_work; 606 + } 602 607 603 - for (int i = 0; i < iocb->n_iters ; i++) { 604 - if (iocb->iter_is_dio_aligned[i]) { 605 - iocb->kiocb.ki_flags |= IOCB_DIRECT; 606 - iocb->kiocb.ki_complete = nfs_local_read_aio_complete; 607 - iocb->aio_complete_work = nfs_local_read_aio_complete_work; 608 - } 609 - 610 - iocb->kiocb.ki_pos = iocb->offset[i]; 611 - status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]); 612 - if (status != -EIOCBQUEUED) { 613 - nfs_local_pgio_done(iocb->hdr, status); 614 - if (iocb->hdr->task.tk_status) 615 - break; 608 + iocb->kiocb.ki_pos = iocb->offset[i]; 609 + status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]); 610 + if (status != -EIOCBQUEUED) { 611 + nfs_local_pgio_done(iocb->hdr, status); 612 + if (iocb->hdr->task.tk_status) 613 + break; 614 + } 616 615 } 617 616 } 618 - 619 - revert_creds(save_cred); 620 617 621 618 if (status != -EIOCBQUEUED) { 622 619 nfs_local_read_done(iocb, status); ··· 781 784 nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_write_aio_complete_work */ 782 785 } 783 786 784 - static void nfs_local_call_write(struct work_struct *work) 787 + static ssize_t do_nfs_local_call_write(struct nfs_local_kiocb *iocb, 788 + struct file *filp) 785 789 { 786 - struct nfs_local_kiocb *iocb = 787 - container_of(work, struct nfs_local_kiocb, work); 788 - struct file *filp = iocb->kiocb.ki_filp; 789 - unsigned long old_flags = current->flags; 790 - const struct cred *save_cred; 791 790 ssize_t status; 792 - 793 - current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO; 794 - save_cred = override_creds(filp->f_cred); 795 791 796 792 file_start_write(filp); 797 793 for (int i = 0; i < iocb->n_iters ; i++) { ··· 830 840 } 831 841 file_end_write(filp); 832 842 833 - revert_creds(save_cred); 843 + return status; 844 + } 845 + 846 + static void nfs_local_call_write(struct work_struct *work) 847 + { 848 + struct nfs_local_kiocb *iocb = 849 + container_of(work, struct nfs_local_kiocb, work); 850 + struct file *filp = iocb->kiocb.ki_filp; 851 + unsigned long old_flags = current->flags; 852 + ssize_t status; 853 + 854 + current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO; 855 + 856 + scoped_with_creds(filp->f_cred) 857 + status = do_nfs_local_call_write(iocb, filp); 858 + 834 859 current->flags = old_flags; 835 860 836 861 if (status != -EIOCBQUEUED) {
+2 -5
fs/nfs/nfs4idmap.c
··· 306 306 const char *type, void *data, 307 307 size_t data_size, struct idmap *idmap) 308 308 { 309 - const struct cred *saved_cred; 310 309 struct key *rkey; 311 310 const struct user_key_payload *payload; 312 311 ssize_t ret; 313 312 314 - saved_cred = override_creds(id_resolver_cache); 315 - rkey = nfs_idmap_request_key(name, namelen, type, idmap); 316 - revert_creds(saved_cred); 317 - 313 + scoped_with_creds(id_resolver_cache) 314 + rkey = nfs_idmap_request_key(name, namelen, type, idmap); 318 315 if (IS_ERR(rkey)) { 319 316 ret = PTR_ERR(rkey); 320 317 goto out;
+2 -4
fs/smb/client/cifs_spnego.c
··· 90 90 size_t desc_len; 91 91 struct key *spnego_key; 92 92 const char *hostname = server->hostname; 93 - const struct cred *saved_cred; 94 93 95 94 /* length of fields (with semicolons): ver=0xyz ip4=ipaddress 96 95 host=hostname sec=mechanism uid=0xFF user=username */ ··· 157 158 dp += sprintf(dp, ";upcall_target=app"); 158 159 159 160 cifs_dbg(FYI, "key description = %s\n", description); 160 - saved_cred = override_creds(spnego_cred); 161 - spnego_key = request_key(&cifs_spnego_key_type, description, ""); 162 - revert_creds(saved_cred); 161 + scoped_with_creds(spnego_cred) 162 + spnego_key = request_key(&cifs_spnego_key_type, description, ""); 163 163 164 164 #ifdef CONFIG_CIFS_DEBUG2 165 165 if (cifsFYI && !IS_ERR(spnego_key)) {
+4 -2
include/linux/cred.h
··· 192 192 revert_creds(_T), 193 193 override_creds(override_cred), const struct cred *override_cred) 194 194 195 - #define scoped_with_kernel_creds() \ 196 - scoped_class(override_creds, __UNIQUE_ID(cred), kernel_cred()) 195 + #define scoped_with_creds(cred) \ 196 + scoped_class(override_creds, __UNIQUE_ID(label), cred) 197 + 198 + #define scoped_with_kernel_creds() scoped_with_creds(kernel_cred()) 197 199 198 200 /** 199 201 * get_cred_many - Get references on a set of credentials
+13 -16
kernel/acct.c
··· 520 520 static void acct_write_process(struct bsd_acct_struct *acct) 521 521 { 522 522 struct file *file = acct->file; 523 - const struct cred *cred; 524 523 acct_t *ac = &acct->ac; 525 524 526 525 /* Perform file operations on behalf of whoever enabled accounting */ 527 - cred = override_creds(file->f_cred); 528 - 529 - /* 530 - * First check to see if there is enough free_space to continue 531 - * the process accounting system. Then get freeze protection. If 532 - * the fs is frozen, just skip the write as we could deadlock 533 - * the system otherwise. 534 - */ 535 - if (check_free_space(acct) && file_start_write_trylock(file)) { 536 - /* it's been opened O_APPEND, so position is irrelevant */ 537 - loff_t pos = 0; 538 - __kernel_write(file, ac, sizeof(acct_t), &pos); 539 - file_end_write(file); 526 + scoped_with_creds(file->f_cred) { 527 + /* 528 + * First check to see if there is enough free_space to continue 529 + * the process accounting system. Then get freeze protection. If 530 + * the fs is frozen, just skip the write as we could deadlock 531 + * the system otherwise. 532 + */ 533 + if (check_free_space(acct) && file_start_write_trylock(file)) { 534 + /* it's been opened O_APPEND, so position is irrelevant */ 535 + loff_t pos = 0; 536 + __kernel_write(file, ac, sizeof(acct_t), &pos); 537 + file_end_write(file); 538 + } 540 539 } 541 - 542 - revert_creds(cred); 543 540 } 544 541 545 542 static void do_acct_process(struct bsd_acct_struct *acct)
+4 -6
kernel/cgroup/cgroup.c
··· 5363 5363 struct cgroup_file_ctx *ctx = of->priv; 5364 5364 struct cgroup *src_cgrp, *dst_cgrp; 5365 5365 struct task_struct *task; 5366 - const struct cred *saved_cred; 5367 5366 ssize_t ret; 5368 5367 enum cgroup_attach_lock_mode lock_mode; 5369 5368 ··· 5385 5386 * permissions using the credentials from file open to protect against 5386 5387 * inherited fd attacks. 5387 5388 */ 5388 - saved_cred = override_creds(of->file->f_cred); 5389 - ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, 5390 - of->file->f_path.dentry->d_sb, 5391 - threadgroup, ctx->ns); 5392 - revert_creds(saved_cred); 5389 + scoped_with_creds(of->file->f_cred) 5390 + ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, 5391 + of->file->f_path.dentry->d_sb, 5392 + threadgroup, ctx->ns); 5393 5393 if (ret) 5394 5394 goto out_finish; 5395 5395
+2 -4
net/dns_resolver/dns_query.c
··· 78 78 { 79 79 struct key *rkey; 80 80 struct user_key_payload *upayload; 81 - const struct cred *saved_cred; 82 81 size_t typelen, desclen; 83 82 char *desc, *cp; 84 83 int ret, len; ··· 123 124 /* make the upcall, using special credentials to prevent the use of 124 125 * add_key() to preinstall malicious redirections 125 126 */ 126 - saved_cred = override_creds(dns_resolver_cache); 127 - rkey = request_key_net(&key_type_dns_resolver, desc, net, options); 128 - revert_creds(saved_cred); 127 + scoped_with_creds(dns_resolver_cache) 128 + rkey = request_key_net(&key_type_dns_resolver, desc, net, options); 129 129 kfree(desc); 130 130 if (IS_ERR(rkey)) { 131 131 ret = PTR_ERR(rkey);