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 'kernel-6.19-rc1.cred' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull cred guard updates from Christian Brauner:
"This contains substantial credential infrastructure improvements
adding guard-based credential management that simplifies code and
eliminates manual reference counting in many subsystems.

Features:

- Kernel Credential Guards

Add with_kernel_creds() and scoped_with_kernel_creds() guards that
allow using the kernel credentials without allocating and copying
them. This was requested by Linus after seeing repeated
prepare_kernel_creds() calls that duplicate the kernel credentials
only to drop them again later.

The new guards completely avoid the allocation and never expose the
temporary variable to hold the kernel credentials anywhere in
callers.

- Generic Credential Guards

Add scoped_with_creds() guards for the common override_creds() and
revert_creds() pattern. This builds on earlier work that made
override_creds()/revert_creds() completely reference count free.

- Prepare Credential Guards

Add prepare credential guards for the more complex pattern of
preparing a new set of credentials and overriding the current
credentials with them:
- prepare_creds()
- modify new creds
- override_creds()
- revert_creds()
- put_cred()

Cleanups:

- Make init_cred static since it should not be directly accessed

- Add kernel_cred() helper to properly access the kernel credentials

- Fix scoped_class() macro that was introduced two cycles ago

- coredump: split out do_coredump() from vfs_coredump() for cleaner
credential handling

- coredump: move revert_cred() before coredump_cleanup()

- coredump: mark struct mm_struct as const

- coredump: pass struct linux_binfmt as const

- sev-dev: use guard for path"

* tag 'kernel-6.19-rc1.cred' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (36 commits)
trace: use override credential guard
trace: use prepare credential guard
coredump: use override credential guard
coredump: use prepare credential guard
coredump: split out do_coredump() from vfs_coredump()
coredump: mark struct mm_struct as const
coredump: pass struct linux_binfmt as const
coredump: move revert_cred() before coredump_cleanup()
sev-dev: use override credential guards
sev-dev: use prepare credential guard
sev-dev: use guard for path
cred: add prepare credential guard
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
...

+327 -366
+25 -34
drivers/base/firmware_loader/main.c
··· 829 829 size_t offset, u32 opt_flags) 830 830 { 831 831 struct firmware *fw = NULL; 832 - struct cred *kern_cred = NULL; 833 - const struct cred *old_cred; 834 832 bool nondirect = false; 835 833 int ret; 836 834 ··· 869 871 * called by a driver when serving an unrelated request from userland, we use 870 872 * the kernel credentials to read the file. 871 873 */ 872 - kern_cred = prepare_kernel_cred(&init_task); 873 - if (!kern_cred) { 874 - ret = -ENOMEM; 875 - goto out; 876 - } 877 - old_cred = override_creds(kern_cred); 874 + scoped_with_kernel_creds() { 875 + ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); 878 876 879 - ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); 880 - 881 - /* Only full reads can support decompression, platform, and sysfs. */ 882 - if (!(opt_flags & FW_OPT_PARTIAL)) 883 - nondirect = true; 877 + /* Only full reads can support decompression, platform, and sysfs. */ 878 + if (!(opt_flags & FW_OPT_PARTIAL)) 879 + nondirect = true; 884 880 885 881 #ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD 886 - if (ret == -ENOENT && nondirect) 887 - ret = fw_get_filesystem_firmware(device, fw->priv, ".zst", 888 - fw_decompress_zstd); 882 + if (ret == -ENOENT && nondirect) 883 + ret = fw_get_filesystem_firmware(device, fw->priv, ".zst", 884 + fw_decompress_zstd); 889 885 #endif 890 886 #ifdef CONFIG_FW_LOADER_COMPRESS_XZ 891 - if (ret == -ENOENT && nondirect) 892 - ret = fw_get_filesystem_firmware(device, fw->priv, ".xz", 893 - fw_decompress_xz); 887 + if (ret == -ENOENT && nondirect) 888 + ret = fw_get_filesystem_firmware(device, fw->priv, ".xz", 889 + fw_decompress_xz); 894 890 #endif 895 - if (ret == -ENOENT && nondirect) 896 - ret = firmware_fallback_platform(fw->priv); 891 + if (ret == -ENOENT && nondirect) 892 + ret = firmware_fallback_platform(fw->priv); 897 893 898 - if (ret) { 899 - if (!(opt_flags & FW_OPT_NO_WARN)) 900 - dev_warn(device, 901 - "Direct firmware load for %s failed with error %d\n", 902 - name, ret); 903 - if (nondirect) 904 - ret = firmware_fallback_sysfs(fw, name, device, 905 - opt_flags, ret); 906 - } else 907 - ret = assign_fw(fw, device); 908 - 909 - revert_creds(old_cred); 910 - put_cred(kern_cred); 894 + if (ret) { 895 + if (!(opt_flags & FW_OPT_NO_WARN)) 896 + dev_warn(device, 897 + "Direct firmware load for %s failed with error %d\n", 898 + name, ret); 899 + if (nondirect) 900 + ret = firmware_fallback_sysfs(fw, name, device, 901 + opt_flags, ret); 902 + } else { 903 + ret = assign_fw(fw, device); 904 + } 905 + } 911 906 912 907 out: 913 908 if (ret < 0) {
+19 -31
drivers/block/nbd.c
··· 52 52 static DEFINE_IDR(nbd_index_idr); 53 53 static DEFINE_MUTEX(nbd_index_mutex); 54 54 static struct workqueue_struct *nbd_del_wq; 55 - static struct cred *nbd_cred; 56 55 static int nbd_total_devices = 0; 57 56 58 57 struct nbd_sock { ··· 554 555 int result; 555 556 struct msghdr msg = {} ; 556 557 unsigned int noreclaim_flag; 557 - const struct cred *old_cred; 558 558 559 559 if (unlikely(!sock)) { 560 560 dev_err_ratelimited(disk_to_dev(nbd->disk), ··· 562 564 return -EINVAL; 563 565 } 564 566 565 - old_cred = override_creds(nbd_cred); 566 - 567 567 msg.msg_iter = *iter; 568 568 569 569 noreclaim_flag = memalloc_noreclaim_save(); 570 - do { 571 - sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; 572 - sock->sk->sk_use_task_frag = false; 573 - msg.msg_flags = msg_flags | MSG_NOSIGNAL; 574 570 575 - if (send) 576 - result = sock_sendmsg(sock, &msg); 577 - else 578 - result = sock_recvmsg(sock, &msg, msg.msg_flags); 571 + scoped_with_kernel_creds() { 572 + do { 573 + sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; 574 + sock->sk->sk_use_task_frag = false; 575 + msg.msg_flags = msg_flags | MSG_NOSIGNAL; 579 576 580 - if (result <= 0) { 581 - if (result == 0) 582 - result = -EPIPE; /* short read */ 583 - break; 584 - } 585 - if (sent) 586 - *sent += result; 587 - } while (msg_data_left(&msg)); 577 + if (send) 578 + result = sock_sendmsg(sock, &msg); 579 + else 580 + result = sock_recvmsg(sock, &msg, msg.msg_flags); 581 + 582 + if (result <= 0) { 583 + if (result == 0) 584 + result = -EPIPE; /* short read */ 585 + break; 586 + } 587 + if (sent) 588 + *sent += result; 589 + } while (msg_data_left(&msg)); 590 + } 588 591 589 592 memalloc_noreclaim_restore(noreclaim_flag); 590 - 591 - revert_creds(old_cred); 592 593 593 594 return result; 594 595 } ··· 2680 2683 return -ENOMEM; 2681 2684 } 2682 2685 2683 - nbd_cred = prepare_kernel_cred(&init_task); 2684 - if (!nbd_cred) { 2685 - destroy_workqueue(nbd_del_wq); 2686 - unregister_blkdev(NBD_MAJOR, "nbd"); 2687 - return -ENOMEM; 2688 - } 2689 - 2690 2686 if (genl_register_family(&nbd_genl_family)) { 2691 - put_cred(nbd_cred); 2692 2687 destroy_workqueue(nbd_del_wq); 2693 2688 unregister_blkdev(NBD_MAJOR, "nbd"); 2694 2689 return -EINVAL; ··· 2735 2746 /* Also wait for nbd_dev_remove_work() completes */ 2736 2747 destroy_workqueue(nbd_del_wq); 2737 2748 2738 - put_cred(nbd_cred); 2739 2749 idr_destroy(&nbd_index_idr); 2740 2750 unregister_blkdev(NBD_MAJOR, "nbd"); 2741 2751 }
+5 -12
drivers/crypto/ccp/sev-dev.c
··· 259 259 260 260 static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) 261 261 { 262 - struct file *fp; 263 - struct path root; 264 - struct cred *cred; 265 - const struct cred *old_cred; 262 + struct path root __free(path_put) = {}; 266 263 267 264 task_lock(&init_task); 268 265 get_fs_root(init_task.fs, &root); 269 266 task_unlock(&init_task); 270 267 271 - cred = prepare_creds(); 268 + CLASS(prepare_creds, cred)(); 272 269 if (!cred) 273 270 return ERR_PTR(-ENOMEM); 271 + 274 272 cred->fsuid = GLOBAL_ROOT_UID; 275 - old_cred = override_creds(cred); 276 273 277 - fp = file_open_root(&root, filename, flags, mode); 278 - path_put(&root); 279 - 280 - put_cred(revert_creds(old_cred)); 281 - 282 - return fp; 274 + scoped_with_creds(cred) 275 + return file_open_root(&root, filename, flags, mode); 283 276 } 284 277 285 278 static int sev_read_init_ex_file(void)
+2 -12
drivers/target/target_core_configfs.c
··· 3670 3670 { 3671 3671 struct configfs_subsystem *subsys = &target_core_fabrics; 3672 3672 struct t10_alua_lu_gp *lu_gp; 3673 - struct cred *kern_cred; 3674 - const struct cred *old_cred; 3675 3673 int ret; 3676 3674 3677 3675 pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage" ··· 3746 3748 if (ret < 0) 3747 3749 goto out; 3748 3750 3749 - /* We use the kernel credentials to access the target directory */ 3750 - kern_cred = prepare_kernel_cred(&init_task); 3751 - if (!kern_cred) { 3752 - ret = -ENOMEM; 3753 - goto out; 3754 - } 3755 - old_cred = override_creds(kern_cred); 3756 - target_init_dbroot(); 3757 - revert_creds(old_cred); 3758 - put_cred(kern_cred); 3751 + scoped_with_kernel_creds() 3752 + target_init_dbroot(); 3759 3753 3760 3754 return 0; 3761 3755
+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))) ··· 267 227 !(file->f_mode & FMODE_CAN_ODIRECT)) 268 228 return -EINVAL; 269 229 270 - old_cred = override_creds(ctx->cred); 271 - if (is_sync_kiocb(iocb)) { 272 - rwf_t rwf = iocb_to_rw_flags(flags); 273 - 274 - ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf); 275 - if (ctx->end_write) 276 - ctx->end_write(iocb, ret); 277 - } else { 278 - struct backing_aio *aio; 279 - 280 - ret = backing_aio_init_wq(iocb); 281 - if (ret) 282 - goto out; 283 - 284 - ret = -ENOMEM; 285 - aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL); 286 - if (!aio) 287 - goto out; 288 - 289 - aio->orig_iocb = iocb; 290 - aio->end_write = ctx->end_write; 291 - kiocb_clone(&aio->iocb, iocb, get_file(file)); 292 - aio->iocb.ki_flags = flags; 293 - aio->iocb.ki_complete = backing_aio_queue_completion; 294 - refcount_set(&aio->ref, 2); 295 - ret = vfs_iocb_iter_write(file, &aio->iocb, iter); 296 - backing_aio_put(aio); 297 - if (ret != -EIOCBQUEUED) 298 - backing_aio_cleanup(aio, ret); 299 - } 300 - out: 301 - revert_creds(old_cred); 302 - 303 - return ret; 230 + scoped_with_creds(ctx->cred) 231 + return do_backing_file_write_iter(file, iter, iocb, flags, ctx->end_write); 304 232 } 305 233 EXPORT_SYMBOL_GPL(backing_file_write_iter); 306 234 ··· 277 269 unsigned int flags, 278 270 struct backing_file_ctx *ctx) 279 271 { 280 - const struct cred *old_cred; 281 272 ssize_t ret; 282 273 283 274 if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) 284 275 return -EIO; 285 276 286 - old_cred = override_creds(ctx->cred); 287 - ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); 288 - revert_creds(old_cred); 277 + scoped_with_creds(ctx->cred) 278 + ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); 289 279 290 280 if (ctx->accessed) 291 281 ctx->accessed(iocb->ki_filp); ··· 297 291 size_t len, unsigned int flags, 298 292 struct backing_file_ctx *ctx) 299 293 { 300 - const struct cred *old_cred; 301 294 ssize_t ret; 302 295 303 296 if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING))) ··· 309 304 if (ret) 310 305 return ret; 311 306 312 - old_cred = override_creds(ctx->cred); 313 - file_start_write(out); 314 - ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); 315 - file_end_write(out); 316 - revert_creds(old_cred); 307 + scoped_with_creds(ctx->cred) { 308 + file_start_write(out); 309 + ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); 310 + file_end_write(out); 311 + } 317 312 318 313 if (ctx->end_write) 319 314 ctx->end_write(iocb, ret); ··· 325 320 int backing_file_mmap(struct file *file, struct vm_area_struct *vma, 326 321 struct backing_file_ctx *ctx) 327 322 { 328 - const struct cred *old_cred; 329 323 struct file *user_file = vma->vm_file; 330 324 int ret; 331 325 ··· 336 332 337 333 vma_set_file(vma, file); 338 334 339 - old_cred = override_creds(ctx->cred); 340 - ret = vfs_mmap(vma->vm_file, vma); 341 - revert_creds(old_cred); 335 + scoped_with_creds(ctx->cred) 336 + ret = vfs_mmap(vma->vm_file, vma); 342 337 343 338 if (ctx->accessed) 344 339 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);
+73 -73
fs/coredump.c
··· 1036 1036 1037 1037 static bool coredump_write(struct core_name *cn, 1038 1038 struct coredump_params *cprm, 1039 - struct linux_binfmt *binfmt) 1039 + const struct linux_binfmt *binfmt) 1040 1040 { 1041 1041 1042 1042 if (dump_interrupted()) ··· 1086 1086 return false; 1087 1087 } 1088 1088 1089 + static void do_coredump(struct core_name *cn, struct coredump_params *cprm, 1090 + size_t **argv, int *argc, const struct linux_binfmt *binfmt) 1091 + { 1092 + if (!coredump_parse(cn, cprm, argv, argc)) { 1093 + coredump_report_failure("format_corename failed, aborting core"); 1094 + return; 1095 + } 1096 + 1097 + switch (cn->core_type) { 1098 + case COREDUMP_FILE: 1099 + if (!coredump_file(cn, cprm, binfmt)) 1100 + return; 1101 + break; 1102 + case COREDUMP_PIPE: 1103 + if (!coredump_pipe(cn, cprm, *argv, *argc)) 1104 + return; 1105 + break; 1106 + case COREDUMP_SOCK_REQ: 1107 + fallthrough; 1108 + case COREDUMP_SOCK: 1109 + if (!coredump_socket(cn, cprm)) 1110 + return; 1111 + break; 1112 + default: 1113 + WARN_ON_ONCE(true); 1114 + return; 1115 + } 1116 + 1117 + /* Don't even generate the coredump. */ 1118 + if (cn->mask & COREDUMP_REJECT) 1119 + return; 1120 + 1121 + /* get us an unshared descriptor table; almost always a no-op */ 1122 + /* The cell spufs coredump code reads the file descriptor tables */ 1123 + if (unshare_files()) 1124 + return; 1125 + 1126 + if ((cn->mask & COREDUMP_KERNEL) && !coredump_write(cn, cprm, binfmt)) 1127 + return; 1128 + 1129 + coredump_sock_shutdown(cprm->file); 1130 + 1131 + /* Let the parent know that a coredump was generated. */ 1132 + if (cn->mask & COREDUMP_USERSPACE) 1133 + cn->core_dumped = true; 1134 + 1135 + /* 1136 + * When core_pipe_limit is set we wait for the coredump server 1137 + * or usermodehelper to finish before exiting so it can e.g., 1138 + * inspect /proc/<pid>. 1139 + */ 1140 + if (cn->mask & COREDUMP_WAIT) { 1141 + switch (cn->core_type) { 1142 + case COREDUMP_PIPE: 1143 + wait_for_dump_helpers(cprm->file); 1144 + break; 1145 + case COREDUMP_SOCK_REQ: 1146 + fallthrough; 1147 + case COREDUMP_SOCK: 1148 + coredump_sock_wait(cprm->file); 1149 + break; 1150 + default: 1151 + break; 1152 + } 1153 + } 1154 + } 1155 + 1089 1156 void vfs_coredump(const kernel_siginfo_t *siginfo) 1090 1157 { 1091 - struct cred *cred __free(put_cred) = NULL; 1092 1158 size_t *argv __free(kfree) = NULL; 1093 1159 struct core_state core_state; 1094 1160 struct core_name cn; 1095 - struct mm_struct *mm = current->mm; 1096 - struct linux_binfmt *binfmt = mm->binfmt; 1097 - const struct cred *old_cred; 1161 + const struct mm_struct *mm = current->mm; 1162 + const struct linux_binfmt *binfmt = mm->binfmt; 1098 1163 int argc = 0; 1099 1164 struct coredump_params cprm = { 1100 1165 .siginfo = siginfo, ··· 1181 1116 if (coredump_skip(&cprm, binfmt)) 1182 1117 return; 1183 1118 1184 - cred = prepare_creds(); 1119 + CLASS(prepare_creds, cred)(); 1185 1120 if (!cred) 1186 1121 return; 1187 1122 /* ··· 1196 1131 if (coredump_wait(siginfo->si_signo, &core_state) < 0) 1197 1132 return; 1198 1133 1199 - old_cred = override_creds(cred); 1200 - 1201 - if (!coredump_parse(&cn, &cprm, &argv, &argc)) { 1202 - coredump_report_failure("format_corename failed, aborting core"); 1203 - goto close_fail; 1204 - } 1205 - 1206 - switch (cn.core_type) { 1207 - case COREDUMP_FILE: 1208 - if (!coredump_file(&cn, &cprm, binfmt)) 1209 - goto close_fail; 1210 - break; 1211 - case COREDUMP_PIPE: 1212 - if (!coredump_pipe(&cn, &cprm, argv, argc)) 1213 - goto close_fail; 1214 - break; 1215 - case COREDUMP_SOCK_REQ: 1216 - fallthrough; 1217 - case COREDUMP_SOCK: 1218 - if (!coredump_socket(&cn, &cprm)) 1219 - goto close_fail; 1220 - break; 1221 - default: 1222 - WARN_ON_ONCE(true); 1223 - goto close_fail; 1224 - } 1225 - 1226 - /* Don't even generate the coredump. */ 1227 - if (cn.mask & COREDUMP_REJECT) 1228 - goto close_fail; 1229 - 1230 - /* get us an unshared descriptor table; almost always a no-op */ 1231 - /* The cell spufs coredump code reads the file descriptor tables */ 1232 - if (unshare_files()) 1233 - goto close_fail; 1234 - 1235 - if ((cn.mask & COREDUMP_KERNEL) && !coredump_write(&cn, &cprm, binfmt)) 1236 - goto close_fail; 1237 - 1238 - coredump_sock_shutdown(cprm.file); 1239 - 1240 - /* Let the parent know that a coredump was generated. */ 1241 - if (cn.mask & COREDUMP_USERSPACE) 1242 - cn.core_dumped = true; 1243 - 1244 - /* 1245 - * When core_pipe_limit is set we wait for the coredump server 1246 - * or usermodehelper to finish before exiting so it can e.g., 1247 - * inspect /proc/<pid>. 1248 - */ 1249 - if (cn.mask & COREDUMP_WAIT) { 1250 - switch (cn.core_type) { 1251 - case COREDUMP_PIPE: 1252 - wait_for_dump_helpers(cprm.file); 1253 - break; 1254 - case COREDUMP_SOCK_REQ: 1255 - fallthrough; 1256 - case COREDUMP_SOCK: 1257 - coredump_sock_wait(cprm.file); 1258 - break; 1259 - default: 1260 - break; 1261 - } 1262 - } 1263 - 1264 - close_fail: 1134 + scoped_with_creds(cred) 1135 + do_coredump(&cn, &cprm, &argv, &argc, binfmt); 1265 1136 coredump_cleanup(&cn, &cprm); 1266 - revert_creds(old_cred); 1267 1137 return; 1268 1138 } 1269 1139
+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 }
+28 -18
fs/nfs/localio.c
··· 615 615 nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_read_aio_complete_work */ 616 616 } 617 617 618 - static void nfs_local_call_read(struct work_struct *work) 618 + static void do_nfs_local_call_read(struct nfs_local_kiocb *iocb, struct file *filp) 619 619 { 620 - struct nfs_local_kiocb *iocb = 621 - container_of(work, struct nfs_local_kiocb, work); 622 - struct file *filp = iocb->kiocb.ki_filp; 623 - const struct cred *save_cred; 624 620 bool force_done = false; 625 621 ssize_t status; 626 622 int n_iters; 627 - 628 - save_cred = override_creds(filp->f_cred); 629 623 630 624 n_iters = atomic_read(&iocb->n_iters); 631 625 for (int i = 0; i < n_iters ; i++) { ··· 643 649 } 644 650 } 645 651 } 652 + } 646 653 647 - revert_creds(save_cred); 654 + static void nfs_local_call_read(struct work_struct *work) 655 + { 656 + struct nfs_local_kiocb *iocb = 657 + container_of(work, struct nfs_local_kiocb, work); 658 + struct file *filp = iocb->kiocb.ki_filp; 659 + 660 + scoped_with_creds(filp->f_cred) 661 + do_nfs_local_call_read(iocb, filp); 648 662 } 649 663 650 664 static int ··· 822 820 nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_write_aio_complete_work */ 823 821 } 824 822 825 - static void nfs_local_call_write(struct work_struct *work) 823 + static ssize_t do_nfs_local_call_write(struct nfs_local_kiocb *iocb, 824 + struct file *filp) 826 825 { 827 - struct nfs_local_kiocb *iocb = 828 - container_of(work, struct nfs_local_kiocb, work); 829 - struct file *filp = iocb->kiocb.ki_filp; 830 - unsigned long old_flags = current->flags; 831 - const struct cred *save_cred; 832 826 bool force_done = false; 833 827 ssize_t status; 834 828 int n_iters; 835 - 836 - current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO; 837 - save_cred = override_creds(filp->f_cred); 838 829 839 830 file_start_write(filp); 840 831 n_iters = atomic_read(&iocb->n_iters); ··· 854 859 } 855 860 file_end_write(filp); 856 861 857 - revert_creds(save_cred); 862 + return status; 863 + } 864 + 865 + static void nfs_local_call_write(struct work_struct *work) 866 + { 867 + struct nfs_local_kiocb *iocb = 868 + container_of(work, struct nfs_local_kiocb, work); 869 + struct file *filp = iocb->kiocb.ki_filp; 870 + unsigned long old_flags = current->flags; 871 + ssize_t status; 872 + 873 + current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO; 874 + 875 + scoped_with_creds(filp->f_cred) 876 + status = do_nfs_local_call_write(iocb, filp); 877 + 858 878 current->flags = old_flags; 859 879 } 860 880
+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)) {
+8 -7
include/linux/cleanup.h
··· 290 290 class_##_name##_t var __cleanup(class_##_name##_destructor) = \ 291 291 class_##_name##_constructor 292 292 293 - #define scoped_class(_name, var, args) \ 294 - for (CLASS(_name, var)(args); \ 295 - __guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \ 296 - ({ goto _label; })) \ 297 - if (0) { \ 298 - _label: \ 299 - break; \ 293 + #define __scoped_class(_name, var, _label, args...) \ 294 + for (CLASS(_name, var)(args); ; ({ goto _label; })) \ 295 + if (0) { \ 296 + _label: \ 297 + break; \ 300 298 } else 299 + 300 + #define scoped_class(_name, var, args...) \ 301 + __scoped_class(_name, var, __UNIQUE_ID(label), args) 301 302 302 303 /* 303 304 * DEFINE_GUARD(name, type, lock, unlock):
+22
include/linux/cred.h
··· 20 20 struct cred; 21 21 struct inode; 22 22 23 + extern struct task_struct init_task; 24 + 23 25 /* 24 26 * COW Supplementary groups list 25 27 */ ··· 158 156 extern int commit_creds(struct cred *); 159 157 extern void abort_creds(struct cred *); 160 158 extern struct cred *prepare_kernel_cred(struct task_struct *); 159 + static inline const struct cred *kernel_cred(void) 160 + { 161 + /* shut up sparse */ 162 + return rcu_dereference_raw(init_task.cred); 163 + } 161 164 extern int set_security_override(struct cred *, u32); 162 165 extern int set_security_override_from_ctx(struct cred *, const char *); 163 166 extern int set_create_files_as(struct cred *, struct inode *); ··· 186 179 { 187 180 return rcu_replace_pointer(current->cred, revert_cred, 1); 188 181 } 182 + 183 + DEFINE_CLASS(override_creds, 184 + const struct cred *, 185 + revert_creds(_T), 186 + override_creds(override_cred), const struct cred *override_cred) 187 + 188 + #define scoped_with_creds(cred) \ 189 + scoped_class(override_creds, __UNIQUE_ID(label), cred) 190 + 191 + #define scoped_with_kernel_creds() scoped_with_creds(kernel_cred()) 189 192 190 193 /** 191 194 * get_cred_many - Get references on a set of credentials ··· 279 262 { 280 263 put_cred_many(cred, 1); 281 264 } 265 + 266 + DEFINE_CLASS(prepare_creds, 267 + struct cred *, 268 + if (_T) put_cred(_T), 269 + prepare_creds(), void) 282 270 283 271 DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T)) 284 272
-1
include/linux/init_task.h
··· 25 25 extern struct files_struct init_files; 26 26 extern struct fs_struct init_fs; 27 27 extern struct nsproxy init_nsproxy; 28 - extern struct cred init_cred; 29 28 30 29 #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 31 30 #define INIT_PREV_CPUTIME(x) .prev_cputime = { \
+1 -1
include/linux/sched/coredump.h
··· 8 8 #define SUID_DUMP_USER 1 /* Dump as user of process */ 9 9 #define SUID_DUMP_ROOT 2 /* Dump as root */ 10 10 11 - static inline unsigned long __mm_flags_get_dumpable(struct mm_struct *mm) 11 + static inline unsigned long __mm_flags_get_dumpable(const struct mm_struct *mm) 12 12 { 13 13 /* 14 14 * By convention, dumpable bits are contained in first 32 bits of the
+27
init/init_task.c
··· 62 62 }; 63 63 #endif 64 64 65 + /* init to 2 - one for init_task, one to ensure it is never freed */ 66 + static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; 67 + 68 + /* 69 + * The initial credentials for the initial task 70 + */ 71 + static struct cred init_cred = { 72 + .usage = ATOMIC_INIT(4), 73 + .uid = GLOBAL_ROOT_UID, 74 + .gid = GLOBAL_ROOT_GID, 75 + .suid = GLOBAL_ROOT_UID, 76 + .sgid = GLOBAL_ROOT_GID, 77 + .euid = GLOBAL_ROOT_UID, 78 + .egid = GLOBAL_ROOT_GID, 79 + .fsuid = GLOBAL_ROOT_UID, 80 + .fsgid = GLOBAL_ROOT_GID, 81 + .securebits = SECUREBITS_DEFAULT, 82 + .cap_inheritable = CAP_EMPTY_SET, 83 + .cap_permitted = CAP_FULL_SET, 84 + .cap_effective = CAP_FULL_SET, 85 + .cap_bset = CAP_FULL_SET, 86 + .user = INIT_USER, 87 + .user_ns = &init_user_ns, 88 + .group_info = &init_groups, 89 + .ucounts = &init_ucounts, 90 + }; 91 + 65 92 /* 66 93 * Set up the first task table, touch at your own risk!. Base=0, 67 94 * limit=0x1fffff (=2MB)
+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
··· 5360 5360 struct cgroup_file_ctx *ctx = of->priv; 5361 5361 struct cgroup *src_cgrp, *dst_cgrp; 5362 5362 struct task_struct *task; 5363 - const struct cred *saved_cred; 5364 5363 ssize_t ret; 5365 5364 enum cgroup_attach_lock_mode lock_mode; 5366 5365 ··· 5382 5383 * permissions using the credentials from file open to protect against 5383 5384 * inherited fd attacks. 5384 5385 */ 5385 - saved_cred = override_creds(of->file->f_cred); 5386 - ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, 5387 - of->file->f_path.dentry->d_sb, 5388 - threadgroup, ctx->ns); 5389 - revert_creds(saved_cred); 5386 + scoped_with_creds(of->file->f_cred) 5387 + ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, 5388 + of->file->f_path.dentry->d_sb, 5389 + threadgroup, ctx->ns); 5390 5390 if (ret) 5391 5391 goto out_finish; 5392 5392
-27
kernel/cred.c
··· 35 35 36 36 static struct kmem_cache *cred_jar; 37 37 38 - /* init to 2 - one for init_task, one to ensure it is never freed */ 39 - static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; 40 - 41 - /* 42 - * The initial credentials for the initial task 43 - */ 44 - struct cred init_cred = { 45 - .usage = ATOMIC_INIT(4), 46 - .uid = GLOBAL_ROOT_UID, 47 - .gid = GLOBAL_ROOT_GID, 48 - .suid = GLOBAL_ROOT_UID, 49 - .sgid = GLOBAL_ROOT_GID, 50 - .euid = GLOBAL_ROOT_UID, 51 - .egid = GLOBAL_ROOT_GID, 52 - .fsuid = GLOBAL_ROOT_UID, 53 - .fsgid = GLOBAL_ROOT_GID, 54 - .securebits = SECUREBITS_DEFAULT, 55 - .cap_inheritable = CAP_EMPTY_SET, 56 - .cap_permitted = CAP_FULL_SET, 57 - .cap_effective = CAP_FULL_SET, 58 - .cap_bset = CAP_FULL_SET, 59 - .user = INIT_USER, 60 - .user_ns = &init_user_ns, 61 - .group_info = &init_groups, 62 - .ucounts = &init_ucounts, 63 - }; 64 - 65 38 /* 66 39 * The RCU callback to actually dispose of a set of credentials 67 40 */
+6 -16
kernel/trace/trace_events_user.c
··· 1449 1449 1450 1450 static int user_event_set_call_visible(struct user_event *user, bool visible) 1451 1451 { 1452 - int ret; 1453 - const struct cred *old_cred; 1454 - struct cred *cred; 1455 - 1456 - cred = prepare_creds(); 1457 - 1452 + CLASS(prepare_creds, cred)(); 1458 1453 if (!cred) 1459 1454 return -ENOMEM; 1460 1455 ··· 1464 1469 */ 1465 1470 cred->fsuid = GLOBAL_ROOT_UID; 1466 1471 1467 - old_cred = override_creds(cred); 1472 + scoped_with_creds(cred) { 1473 + if (visible) 1474 + return trace_add_event_call(&user->call); 1468 1475 1469 - if (visible) 1470 - ret = trace_add_event_call(&user->call); 1471 - else 1472 - ret = trace_remove_event_call(&user->call); 1473 - 1474 - revert_creds(old_cred); 1475 - put_cred(cred); 1476 - 1477 - return ret; 1476 + return trace_remove_event_call(&user->call); 1477 + } 1478 1478 } 1479 1479 1480 1480 static int destroy_user_event(struct user_event *user)
+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);
+4 -13
net/unix/af_unix.c
··· 1210 1210 unix_mkname_bsd(sunaddr, addr_len); 1211 1211 1212 1212 if (flags & SOCK_COREDUMP) { 1213 - const struct cred *cred; 1214 - struct cred *kcred; 1215 1213 struct path root; 1216 - 1217 - kcred = prepare_kernel_cred(&init_task); 1218 - if (!kcred) { 1219 - err = -ENOMEM; 1220 - goto fail; 1221 - } 1222 1214 1223 1215 task_lock(&init_task); 1224 1216 get_fs_root(init_task.fs, &root); 1225 1217 task_unlock(&init_task); 1226 1218 1227 - cred = override_creds(kcred); 1228 - err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path, 1229 - LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS | 1230 - LOOKUP_NO_MAGICLINKS, &path); 1231 - put_cred(revert_creds(cred)); 1219 + scoped_with_kernel_creds() 1220 + err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path, 1221 + LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS | 1222 + LOOKUP_NO_MAGICLINKS, &path); 1232 1223 path_put(&root); 1233 1224 if (err) 1234 1225 goto fail;
+1 -1
security/keys/process_keys.c
··· 51 51 if (!reg_keyring) { 52 52 reg_keyring = keyring_alloc(".user_reg", 53 53 user_ns->owner, INVALID_GID, 54 - &init_cred, 54 + kernel_cred(), 55 55 KEY_POS_WRITE | KEY_POS_SEARCH | 56 56 KEY_USR_VIEW | KEY_USR_READ, 57 57 0,