kernel-6.19-rc1.cred

-----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaSmOZQAKCRCRxhvAZXjc
 orJLAP9UD+dX6cicJDkzFZowDakmoIQkR5ZSDwChSlmvLcmquwEAlSq4svVd9Bdl
 7kOFUk71DqhVHrPAwO7ap0BxehokEAA=
 =Cli6
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2025-12-01 13:45:41 -08:00
commit 1d18101a64
24 changed files with 327 additions and 366 deletions

View File

@ -829,8 +829,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
size_t offset, u32 opt_flags) size_t offset, u32 opt_flags)
{ {
struct firmware *fw = NULL; struct firmware *fw = NULL;
struct cred *kern_cred = NULL;
const struct cred *old_cred;
bool nondirect = false; bool nondirect = false;
int ret; int ret;
@ -871,45 +869,38 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
* called by a driver when serving an unrelated request from userland, we use * called by a driver when serving an unrelated request from userland, we use
* the kernel credentials to read the file. * the kernel credentials to read the file.
*/ */
kern_cred = prepare_kernel_cred(&init_task); scoped_with_kernel_creds() {
if (!kern_cred) { ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
ret = -ENOMEM;
goto out;
}
old_cred = override_creds(kern_cred);
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); /* Only full reads can support decompression, platform, and sysfs. */
if (!(opt_flags & FW_OPT_PARTIAL))
/* Only full reads can support decompression, platform, and sysfs. */ nondirect = true;
if (!(opt_flags & FW_OPT_PARTIAL))
nondirect = true;
#ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD #ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD
if (ret == -ENOENT && nondirect) if (ret == -ENOENT && nondirect)
ret = fw_get_filesystem_firmware(device, fw->priv, ".zst", ret = fw_get_filesystem_firmware(device, fw->priv, ".zst",
fw_decompress_zstd); fw_decompress_zstd);
#endif #endif
#ifdef CONFIG_FW_LOADER_COMPRESS_XZ #ifdef CONFIG_FW_LOADER_COMPRESS_XZ
if (ret == -ENOENT && nondirect) if (ret == -ENOENT && nondirect)
ret = fw_get_filesystem_firmware(device, fw->priv, ".xz", ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
fw_decompress_xz); fw_decompress_xz);
#endif #endif
if (ret == -ENOENT && nondirect) if (ret == -ENOENT && nondirect)
ret = firmware_fallback_platform(fw->priv); ret = firmware_fallback_platform(fw->priv);
if (ret) { if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN)) if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device, dev_warn(device,
"Direct firmware load for %s failed with error %d\n", "Direct firmware load for %s failed with error %d\n",
name, ret); name, ret);
if (nondirect) if (nondirect)
ret = firmware_fallback_sysfs(fw, name, device, ret = firmware_fallback_sysfs(fw, name, device,
opt_flags, ret); opt_flags, ret);
} else } else {
ret = assign_fw(fw, device); ret = assign_fw(fw, device);
}
revert_creds(old_cred); }
put_cred(kern_cred);
out: out:
if (ret < 0) { if (ret < 0) {

View File

@ -52,7 +52,6 @@
static DEFINE_IDR(nbd_index_idr); static DEFINE_IDR(nbd_index_idr);
static DEFINE_MUTEX(nbd_index_mutex); static DEFINE_MUTEX(nbd_index_mutex);
static struct workqueue_struct *nbd_del_wq; static struct workqueue_struct *nbd_del_wq;
static struct cred *nbd_cred;
static int nbd_total_devices = 0; static int nbd_total_devices = 0;
struct nbd_sock { struct nbd_sock {
@ -555,7 +554,6 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
int result; int result;
struct msghdr msg = {} ; struct msghdr msg = {} ;
unsigned int noreclaim_flag; unsigned int noreclaim_flag;
const struct cred *old_cred;
if (unlikely(!sock)) { if (unlikely(!sock)) {
dev_err_ratelimited(disk_to_dev(nbd->disk), dev_err_ratelimited(disk_to_dev(nbd->disk),
@ -564,34 +562,33 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
return -EINVAL; return -EINVAL;
} }
old_cred = override_creds(nbd_cred);
msg.msg_iter = *iter; msg.msg_iter = *iter;
noreclaim_flag = memalloc_noreclaim_save(); noreclaim_flag = memalloc_noreclaim_save();
do {
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
sock->sk->sk_use_task_frag = false;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (send) scoped_with_kernel_creds() {
result = sock_sendmsg(sock, &msg); do {
else sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
result = sock_recvmsg(sock, &msg, msg.msg_flags); sock->sk->sk_use_task_frag = false;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (result <= 0) { if (send)
if (result == 0) result = sock_sendmsg(sock, &msg);
result = -EPIPE; /* short read */ else
break; result = sock_recvmsg(sock, &msg, msg.msg_flags);
}
if (sent) if (result <= 0) {
*sent += result; if (result == 0)
} while (msg_data_left(&msg)); result = -EPIPE; /* short read */
break;
}
if (sent)
*sent += result;
} while (msg_data_left(&msg));
}
memalloc_noreclaim_restore(noreclaim_flag); memalloc_noreclaim_restore(noreclaim_flag);
revert_creds(old_cred);
return result; return result;
} }
@ -2683,15 +2680,7 @@ static int __init nbd_init(void)
return -ENOMEM; return -ENOMEM;
} }
nbd_cred = prepare_kernel_cred(&init_task);
if (!nbd_cred) {
destroy_workqueue(nbd_del_wq);
unregister_blkdev(NBD_MAJOR, "nbd");
return -ENOMEM;
}
if (genl_register_family(&nbd_genl_family)) { if (genl_register_family(&nbd_genl_family)) {
put_cred(nbd_cred);
destroy_workqueue(nbd_del_wq); destroy_workqueue(nbd_del_wq);
unregister_blkdev(NBD_MAJOR, "nbd"); unregister_blkdev(NBD_MAJOR, "nbd");
return -EINVAL; return -EINVAL;
@ -2746,7 +2735,6 @@ static void __exit nbd_cleanup(void)
/* Also wait for nbd_dev_remove_work() completes */ /* Also wait for nbd_dev_remove_work() completes */
destroy_workqueue(nbd_del_wq); destroy_workqueue(nbd_del_wq);
put_cred(nbd_cred);
idr_destroy(&nbd_index_idr); idr_destroy(&nbd_index_idr);
unregister_blkdev(NBD_MAJOR, "nbd"); unregister_blkdev(NBD_MAJOR, "nbd");
} }

View File

@ -259,27 +259,20 @@ static int sev_cmd_buffer_len(int cmd)
static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
{ {
struct file *fp; struct path root __free(path_put) = {};
struct path root;
struct cred *cred;
const struct cred *old_cred;
task_lock(&init_task); task_lock(&init_task);
get_fs_root(init_task.fs, &root); get_fs_root(init_task.fs, &root);
task_unlock(&init_task); task_unlock(&init_task);
cred = prepare_creds(); CLASS(prepare_creds, cred)();
if (!cred) if (!cred)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
cred->fsuid = GLOBAL_ROOT_UID; cred->fsuid = GLOBAL_ROOT_UID;
old_cred = override_creds(cred);
fp = file_open_root(&root, filename, flags, mode); scoped_with_creds(cred)
path_put(&root); return file_open_root(&root, filename, flags, mode);
put_cred(revert_creds(old_cred));
return fp;
} }
static int sev_read_init_ex_file(void) static int sev_read_init_ex_file(void)

View File

@ -3670,8 +3670,6 @@ static int __init target_core_init_configfs(void)
{ {
struct configfs_subsystem *subsys = &target_core_fabrics; struct configfs_subsystem *subsys = &target_core_fabrics;
struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp *lu_gp;
struct cred *kern_cred;
const struct cred *old_cred;
int ret; int ret;
pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage" pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
@ -3748,16 +3746,8 @@ static int __init target_core_init_configfs(void)
if (ret < 0) if (ret < 0)
goto out; goto out;
/* We use the kernel credentials to access the target directory */ scoped_with_kernel_creds()
kern_cred = prepare_kernel_cred(&init_task); target_init_dbroot();
if (!kern_cred) {
ret = -ENOMEM;
goto out;
}
old_cred = override_creds(kern_cred);
target_init_dbroot();
revert_creds(old_cred);
put_cred(kern_cred);
return 0; return 0;

View File

@ -1640,10 +1640,10 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
static void aio_fsync_work(struct work_struct *work) static void aio_fsync_work(struct work_struct *work)
{ {
struct aio_kiocb *iocb = container_of(work, struct aio_kiocb, fsync.work); struct aio_kiocb *iocb = container_of(work, struct aio_kiocb, fsync.work);
const struct cred *old_cred = override_creds(iocb->fsync.creds);
iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync); scoped_with_creds(iocb->fsync.creds)
revert_creds(old_cred); iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync);
put_cred(iocb->fsync.creds); put_cred(iocb->fsync.creds);
iocb_put(iocb); iocb_put(iocb);
} }

View File

@ -157,13 +157,37 @@ static int backing_aio_init_wq(struct kiocb *iocb)
return sb_init_dio_done_wq(sb); return sb_init_dio_done_wq(sb);
} }
static int do_backing_file_read_iter(struct file *file, struct iov_iter *iter,
struct kiocb *iocb, int flags)
{
struct backing_aio *aio = NULL;
int ret;
if (is_sync_kiocb(iocb)) {
rwf_t rwf = iocb_to_rw_flags(flags);
return vfs_iter_read(file, iter, &iocb->ki_pos, rwf);
}
aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL);
if (!aio)
return -ENOMEM;
aio->orig_iocb = iocb;
kiocb_clone(&aio->iocb, iocb, get_file(file));
aio->iocb.ki_complete = backing_aio_rw_complete;
refcount_set(&aio->ref, 2);
ret = vfs_iocb_iter_read(file, &aio->iocb, iter);
backing_aio_put(aio);
if (ret != -EIOCBQUEUED)
backing_aio_cleanup(aio, ret);
return ret;
}
ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter, ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
struct kiocb *iocb, int flags, struct kiocb *iocb, int flags,
struct backing_file_ctx *ctx) struct backing_file_ctx *ctx)
{ {
struct backing_aio *aio = NULL;
const struct cred *old_cred;
ssize_t ret; ssize_t ret;
if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING))) if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING)))
@ -176,28 +200,8 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
!(file->f_mode & FMODE_CAN_ODIRECT)) !(file->f_mode & FMODE_CAN_ODIRECT))
return -EINVAL; return -EINVAL;
old_cred = override_creds(ctx->cred); scoped_with_creds(ctx->cred)
if (is_sync_kiocb(iocb)) { ret = do_backing_file_read_iter(file, iter, iocb, flags);
rwf_t rwf = iocb_to_rw_flags(flags);
ret = vfs_iter_read(file, iter, &iocb->ki_pos, rwf);
} else {
ret = -ENOMEM;
aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL);
if (!aio)
goto out;
aio->orig_iocb = iocb;
kiocb_clone(&aio->iocb, iocb, get_file(file));
aio->iocb.ki_complete = backing_aio_rw_complete;
refcount_set(&aio->ref, 2);
ret = vfs_iocb_iter_read(file, &aio->iocb, iter);
backing_aio_put(aio);
if (ret != -EIOCBQUEUED)
backing_aio_cleanup(aio, ret);
}
out:
revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(iocb->ki_filp); ctx->accessed(iocb->ki_filp);
@ -206,11 +210,47 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
} }
EXPORT_SYMBOL_GPL(backing_file_read_iter); EXPORT_SYMBOL_GPL(backing_file_read_iter);
static int do_backing_file_write_iter(struct file *file, struct iov_iter *iter,
struct kiocb *iocb, int flags,
void (*end_write)(struct kiocb *, ssize_t))
{
struct backing_aio *aio;
int ret;
if (is_sync_kiocb(iocb)) {
rwf_t rwf = iocb_to_rw_flags(flags);
ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf);
if (end_write)
end_write(iocb, ret);
return ret;
}
ret = backing_aio_init_wq(iocb);
if (ret)
return ret;
aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL);
if (!aio)
return -ENOMEM;
aio->orig_iocb = iocb;
aio->end_write = end_write;
kiocb_clone(&aio->iocb, iocb, get_file(file));
aio->iocb.ki_flags = flags;
aio->iocb.ki_complete = backing_aio_queue_completion;
refcount_set(&aio->ref, 2);
ret = vfs_iocb_iter_write(file, &aio->iocb, iter);
backing_aio_put(aio);
if (ret != -EIOCBQUEUED)
backing_aio_cleanup(aio, ret);
return ret;
}
ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter, ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
struct kiocb *iocb, int flags, struct kiocb *iocb, int flags,
struct backing_file_ctx *ctx) struct backing_file_ctx *ctx)
{ {
const struct cred *old_cred;
ssize_t ret; ssize_t ret;
if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING))) if (WARN_ON_ONCE(!(file->f_mode & FMODE_BACKING)))
@ -227,40 +267,8 @@ ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
!(file->f_mode & FMODE_CAN_ODIRECT)) !(file->f_mode & FMODE_CAN_ODIRECT))
return -EINVAL; return -EINVAL;
old_cred = override_creds(ctx->cred); scoped_with_creds(ctx->cred)
if (is_sync_kiocb(iocb)) { return do_backing_file_write_iter(file, iter, iocb, flags, ctx->end_write);
rwf_t rwf = iocb_to_rw_flags(flags);
ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf);
if (ctx->end_write)
ctx->end_write(iocb, ret);
} else {
struct backing_aio *aio;
ret = backing_aio_init_wq(iocb);
if (ret)
goto out;
ret = -ENOMEM;
aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL);
if (!aio)
goto out;
aio->orig_iocb = iocb;
aio->end_write = ctx->end_write;
kiocb_clone(&aio->iocb, iocb, get_file(file));
aio->iocb.ki_flags = flags;
aio->iocb.ki_complete = backing_aio_queue_completion;
refcount_set(&aio->ref, 2);
ret = vfs_iocb_iter_write(file, &aio->iocb, iter);
backing_aio_put(aio);
if (ret != -EIOCBQUEUED)
backing_aio_cleanup(aio, ret);
}
out:
revert_creds(old_cred);
return ret;
} }
EXPORT_SYMBOL_GPL(backing_file_write_iter); EXPORT_SYMBOL_GPL(backing_file_write_iter);
@ -269,15 +277,13 @@ ssize_t backing_file_splice_read(struct file *in, struct kiocb *iocb,
unsigned int flags, unsigned int flags,
struct backing_file_ctx *ctx) struct backing_file_ctx *ctx)
{ {
const struct cred *old_cred;
ssize_t ret; ssize_t ret;
if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING)))
return -EIO; return -EIO;
old_cred = override_creds(ctx->cred); scoped_with_creds(ctx->cred)
ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags);
revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(iocb->ki_filp); ctx->accessed(iocb->ki_filp);
@ -291,7 +297,6 @@ ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
size_t len, unsigned int flags, size_t len, unsigned int flags,
struct backing_file_ctx *ctx) struct backing_file_ctx *ctx)
{ {
const struct cred *old_cred;
ssize_t ret; ssize_t ret;
if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING))) if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING)))
@ -304,11 +309,11 @@ ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
if (ret) if (ret)
return ret; return ret;
old_cred = override_creds(ctx->cred); scoped_with_creds(ctx->cred) {
file_start_write(out); file_start_write(out);
ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags);
file_end_write(out); file_end_write(out);
revert_creds(old_cred); }
if (ctx->end_write) if (ctx->end_write)
ctx->end_write(iocb, ret); ctx->end_write(iocb, ret);
@ -320,7 +325,6 @@ EXPORT_SYMBOL_GPL(backing_file_splice_write);
int backing_file_mmap(struct file *file, struct vm_area_struct *vma, int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
struct backing_file_ctx *ctx) struct backing_file_ctx *ctx)
{ {
const struct cred *old_cred;
struct file *user_file = vma->vm_file; struct file *user_file = vma->vm_file;
int ret; int ret;
@ -332,9 +336,8 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
vma_set_file(vma, file); vma_set_file(vma, file);
old_cred = override_creds(ctx->cred); scoped_with_creds(ctx->cred)
ret = vfs_mmap(vma->vm_file, vma); ret = vfs_mmap(vma->vm_file, vma);
revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(user_file); ctx->accessed(user_file);

View File

@ -782,8 +782,6 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
return PTR_ERR(e); return PTR_ERR(e);
if (e->flags & MISC_FMT_OPEN_FILE) { if (e->flags & MISC_FMT_OPEN_FILE) {
const struct cred *old_cred;
/* /*
* Now that we support unprivileged binfmt_misc mounts make * Now that we support unprivileged binfmt_misc mounts make
* sure we use the credentials that the register @file was * sure we use the credentials that the register @file was
@ -791,9 +789,8 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
* didn't matter much as only a privileged process could open * didn't matter much as only a privileged process could open
* the register file. * the register file.
*/ */
old_cred = override_creds(file->f_cred); scoped_with_creds(file->f_cred)
f = open_exec(e->interpreter); f = open_exec(e->interpreter);
revert_creds(old_cred);
if (IS_ERR(f)) { if (IS_ERR(f)) {
pr_notice("register: failed to install interpreter file %s\n", pr_notice("register: failed to install interpreter file %s\n",
e->interpreter); e->interpreter);

View File

@ -1036,7 +1036,7 @@ static bool coredump_pipe(struct core_name *cn, struct coredump_params *cprm,
static bool coredump_write(struct core_name *cn, static bool coredump_write(struct core_name *cn,
struct coredump_params *cprm, struct coredump_params *cprm,
struct linux_binfmt *binfmt) const struct linux_binfmt *binfmt)
{ {
if (dump_interrupted()) if (dump_interrupted())
@ -1086,15 +1086,80 @@ static inline bool coredump_skip(const struct coredump_params *cprm,
return false; return false;
} }
static void do_coredump(struct core_name *cn, struct coredump_params *cprm,
size_t **argv, int *argc, const struct linux_binfmt *binfmt)
{
if (!coredump_parse(cn, cprm, argv, argc)) {
coredump_report_failure("format_corename failed, aborting core");
return;
}
switch (cn->core_type) {
case COREDUMP_FILE:
if (!coredump_file(cn, cprm, binfmt))
return;
break;
case COREDUMP_PIPE:
if (!coredump_pipe(cn, cprm, *argv, *argc))
return;
break;
case COREDUMP_SOCK_REQ:
fallthrough;
case COREDUMP_SOCK:
if (!coredump_socket(cn, cprm))
return;
break;
default:
WARN_ON_ONCE(true);
return;
}
/* Don't even generate the coredump. */
if (cn->mask & COREDUMP_REJECT)
return;
/* get us an unshared descriptor table; almost always a no-op */
/* The cell spufs coredump code reads the file descriptor tables */
if (unshare_files())
return;
if ((cn->mask & COREDUMP_KERNEL) && !coredump_write(cn, cprm, binfmt))
return;
coredump_sock_shutdown(cprm->file);
/* Let the parent know that a coredump was generated. */
if (cn->mask & COREDUMP_USERSPACE)
cn->core_dumped = true;
/*
* When core_pipe_limit is set we wait for the coredump server
* or usermodehelper to finish before exiting so it can e.g.,
* inspect /proc/<pid>.
*/
if (cn->mask & COREDUMP_WAIT) {
switch (cn->core_type) {
case COREDUMP_PIPE:
wait_for_dump_helpers(cprm->file);
break;
case COREDUMP_SOCK_REQ:
fallthrough;
case COREDUMP_SOCK:
coredump_sock_wait(cprm->file);
break;
default:
break;
}
}
}
void vfs_coredump(const kernel_siginfo_t *siginfo) void vfs_coredump(const kernel_siginfo_t *siginfo)
{ {
struct cred *cred __free(put_cred) = NULL;
size_t *argv __free(kfree) = NULL; size_t *argv __free(kfree) = NULL;
struct core_state core_state; struct core_state core_state;
struct core_name cn; struct core_name cn;
struct mm_struct *mm = current->mm; const struct mm_struct *mm = current->mm;
struct linux_binfmt *binfmt = mm->binfmt; const struct linux_binfmt *binfmt = mm->binfmt;
const struct cred *old_cred;
int argc = 0; int argc = 0;
struct coredump_params cprm = { struct coredump_params cprm = {
.siginfo = siginfo, .siginfo = siginfo,
@ -1116,7 +1181,7 @@ void vfs_coredump(const kernel_siginfo_t *siginfo)
if (coredump_skip(&cprm, binfmt)) if (coredump_skip(&cprm, binfmt))
return; return;
cred = prepare_creds(); CLASS(prepare_creds, cred)();
if (!cred) if (!cred)
return; return;
/* /*
@ -1131,74 +1196,9 @@ void vfs_coredump(const kernel_siginfo_t *siginfo)
if (coredump_wait(siginfo->si_signo, &core_state) < 0) if (coredump_wait(siginfo->si_signo, &core_state) < 0)
return; return;
old_cred = override_creds(cred); scoped_with_creds(cred)
do_coredump(&cn, &cprm, &argv, &argc, binfmt);
if (!coredump_parse(&cn, &cprm, &argv, &argc)) {
coredump_report_failure("format_corename failed, aborting core");
goto close_fail;
}
switch (cn.core_type) {
case COREDUMP_FILE:
if (!coredump_file(&cn, &cprm, binfmt))
goto close_fail;
break;
case COREDUMP_PIPE:
if (!coredump_pipe(&cn, &cprm, argv, argc))
goto close_fail;
break;
case COREDUMP_SOCK_REQ:
fallthrough;
case COREDUMP_SOCK:
if (!coredump_socket(&cn, &cprm))
goto close_fail;
break;
default:
WARN_ON_ONCE(true);
goto close_fail;
}
/* Don't even generate the coredump. */
if (cn.mask & COREDUMP_REJECT)
goto close_fail;
/* get us an unshared descriptor table; almost always a no-op */
/* The cell spufs coredump code reads the file descriptor tables */
if (unshare_files())
goto close_fail;
if ((cn.mask & COREDUMP_KERNEL) && !coredump_write(&cn, &cprm, binfmt))
goto close_fail;
coredump_sock_shutdown(cprm.file);
/* Let the parent know that a coredump was generated. */
if (cn.mask & COREDUMP_USERSPACE)
cn.core_dumped = true;
/*
* When core_pipe_limit is set we wait for the coredump server
* or usermodehelper to finish before exiting so it can e.g.,
* inspect /proc/<pid>.
*/
if (cn.mask & COREDUMP_WAIT) {
switch (cn.core_type) {
case COREDUMP_PIPE:
wait_for_dump_helpers(cprm.file);
break;
case COREDUMP_SOCK_REQ:
fallthrough;
case COREDUMP_SOCK:
coredump_sock_wait(cprm.file);
break;
default:
break;
}
}
close_fail:
coredump_cleanup(&cn, &cprm); coredump_cleanup(&cn, &cprm);
revert_creds(old_cred);
return; return;
} }

View File

@ -47,7 +47,6 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq) static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
{ {
const struct cred *old_cred;
struct iov_iter iter; struct iov_iter iter;
int ret; int ret;
@ -61,9 +60,8 @@ static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
rq->iocb.ki_flags = IOCB_DIRECT; rq->iocb.ki_flags = IOCB_DIRECT;
iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt, iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
rq->bio.bi_iter.bi_size); rq->bio.bi_iter.bi_size);
old_cred = override_creds(rq->iocb.ki_filp->f_cred); scoped_with_creds(rq->iocb.ki_filp->f_cred)
ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter); ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
revert_creds(old_cred);
if (ret != -EIOCBQUEUED) if (ret != -EIOCBQUEUED)
erofs_fileio_ki_complete(&rq->iocb, ret); erofs_fileio_ki_complete(&rq->iocb, ret);
} }

View File

@ -615,18 +615,12 @@ static void nfs_local_read_aio_complete(struct kiocb *kiocb, long ret)
nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_read_aio_complete_work */ nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_read_aio_complete_work */
} }
static void nfs_local_call_read(struct work_struct *work) static void do_nfs_local_call_read(struct nfs_local_kiocb *iocb, struct file *filp)
{ {
struct nfs_local_kiocb *iocb =
container_of(work, struct nfs_local_kiocb, work);
struct file *filp = iocb->kiocb.ki_filp;
const struct cred *save_cred;
bool force_done = false; bool force_done = false;
ssize_t status; ssize_t status;
int n_iters; int n_iters;
save_cred = override_creds(filp->f_cred);
n_iters = atomic_read(&iocb->n_iters); n_iters = atomic_read(&iocb->n_iters);
for (int i = 0; i < n_iters ; i++) { for (int i = 0; i < n_iters ; i++) {
if (iocb->iter_is_dio_aligned[i]) { if (iocb->iter_is_dio_aligned[i]) {
@ -649,8 +643,16 @@ static void nfs_local_call_read(struct work_struct *work)
} }
} }
} }
}
revert_creds(save_cred); static void nfs_local_call_read(struct work_struct *work)
{
struct nfs_local_kiocb *iocb =
container_of(work, struct nfs_local_kiocb, work);
struct file *filp = iocb->kiocb.ki_filp;
scoped_with_creds(filp->f_cred)
do_nfs_local_call_read(iocb, filp);
} }
static int static int
@ -820,20 +822,13 @@ static void nfs_local_write_aio_complete(struct kiocb *kiocb, long ret)
nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_write_aio_complete_work */ nfs_local_pgio_aio_complete(iocb); /* Calls nfs_local_write_aio_complete_work */
} }
static void nfs_local_call_write(struct work_struct *work) static ssize_t do_nfs_local_call_write(struct nfs_local_kiocb *iocb,
struct file *filp)
{ {
struct nfs_local_kiocb *iocb =
container_of(work, struct nfs_local_kiocb, work);
struct file *filp = iocb->kiocb.ki_filp;
unsigned long old_flags = current->flags;
const struct cred *save_cred;
bool force_done = false; bool force_done = false;
ssize_t status; ssize_t status;
int n_iters; int n_iters;
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
save_cred = override_creds(filp->f_cred);
file_start_write(filp); file_start_write(filp);
n_iters = atomic_read(&iocb->n_iters); n_iters = atomic_read(&iocb->n_iters);
for (int i = 0; i < n_iters ; i++) { for (int i = 0; i < n_iters ; i++) {
@ -859,7 +854,22 @@ static void nfs_local_call_write(struct work_struct *work)
} }
file_end_write(filp); file_end_write(filp);
revert_creds(save_cred); return status;
}
static void nfs_local_call_write(struct work_struct *work)
{
struct nfs_local_kiocb *iocb =
container_of(work, struct nfs_local_kiocb, work);
struct file *filp = iocb->kiocb.ki_filp;
unsigned long old_flags = current->flags;
ssize_t status;
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
scoped_with_creds(filp->f_cred)
status = do_nfs_local_call_write(iocb, filp);
current->flags = old_flags; current->flags = old_flags;
} }

View File

@ -306,15 +306,12 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
const char *type, void *data, const char *type, void *data,
size_t data_size, struct idmap *idmap) size_t data_size, struct idmap *idmap)
{ {
const struct cred *saved_cred;
struct key *rkey; struct key *rkey;
const struct user_key_payload *payload; const struct user_key_payload *payload;
ssize_t ret; ssize_t ret;
saved_cred = override_creds(id_resolver_cache); scoped_with_creds(id_resolver_cache)
rkey = nfs_idmap_request_key(name, namelen, type, idmap); rkey = nfs_idmap_request_key(name, namelen, type, idmap);
revert_creds(saved_cred);
if (IS_ERR(rkey)) { if (IS_ERR(rkey)) {
ret = PTR_ERR(rkey); ret = PTR_ERR(rkey);
goto out; goto out;

View File

@ -90,7 +90,6 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
size_t desc_len; size_t desc_len;
struct key *spnego_key; struct key *spnego_key;
const char *hostname = server->hostname; const char *hostname = server->hostname;
const struct cred *saved_cred;
/* length of fields (with semicolons): ver=0xyz ip4=ipaddress /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
host=hostname sec=mechanism uid=0xFF user=username */ host=hostname sec=mechanism uid=0xFF user=username */
@ -158,9 +157,8 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
dp += sprintf(dp, ";upcall_target=app"); dp += sprintf(dp, ";upcall_target=app");
cifs_dbg(FYI, "key description = %s\n", description); cifs_dbg(FYI, "key description = %s\n", description);
saved_cred = override_creds(spnego_cred); scoped_with_creds(spnego_cred)
spnego_key = request_key(&cifs_spnego_key_type, description, ""); spnego_key = request_key(&cifs_spnego_key_type, description, "");
revert_creds(saved_cred);
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
if (cifsFYI && !IS_ERR(spnego_key)) { if (cifsFYI && !IS_ERR(spnego_key)) {

View File

@ -290,15 +290,16 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
class_##_name##_t var __cleanup(class_##_name##_destructor) = \ class_##_name##_t var __cleanup(class_##_name##_destructor) = \
class_##_name##_constructor class_##_name##_constructor
#define scoped_class(_name, var, args) \ #define __scoped_class(_name, var, _label, args...) \
for (CLASS(_name, var)(args); \ for (CLASS(_name, var)(args); ; ({ goto _label; })) \
__guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \ if (0) { \
({ goto _label; })) \ _label: \
if (0) { \ break; \
_label: \
break; \
} else } else
#define scoped_class(_name, var, args...) \
__scoped_class(_name, var, __UNIQUE_ID(label), args)
/* /*
* DEFINE_GUARD(name, type, lock, unlock): * DEFINE_GUARD(name, type, lock, unlock):
* trivial wrapper around DEFINE_CLASS() above specifically * trivial wrapper around DEFINE_CLASS() above specifically

View File

@ -20,6 +20,8 @@
struct cred; struct cred;
struct inode; struct inode;
extern struct task_struct init_task;
/* /*
* COW Supplementary groups list * COW Supplementary groups list
*/ */
@ -156,6 +158,11 @@ extern struct cred *prepare_exec_creds(void);
extern int commit_creds(struct cred *); extern int commit_creds(struct cred *);
extern void abort_creds(struct cred *); extern void abort_creds(struct cred *);
extern struct cred *prepare_kernel_cred(struct task_struct *); extern struct cred *prepare_kernel_cred(struct task_struct *);
static inline const struct cred *kernel_cred(void)
{
/* shut up sparse */
return rcu_dereference_raw(init_task.cred);
}
extern int set_security_override(struct cred *, u32); extern int set_security_override(struct cred *, u32);
extern int set_security_override_from_ctx(struct cred *, const char *); extern int set_security_override_from_ctx(struct cred *, const char *);
extern int set_create_files_as(struct cred *, struct inode *); extern int set_create_files_as(struct cred *, struct inode *);
@ -180,6 +187,16 @@ static inline const struct cred *revert_creds(const struct cred *revert_cred)
return rcu_replace_pointer(current->cred, revert_cred, 1); return rcu_replace_pointer(current->cred, revert_cred, 1);
} }
DEFINE_CLASS(override_creds,
const struct cred *,
revert_creds(_T),
override_creds(override_cred), const struct cred *override_cred)
#define scoped_with_creds(cred) \
scoped_class(override_creds, __UNIQUE_ID(label), cred)
#define scoped_with_kernel_creds() scoped_with_creds(kernel_cred())
/** /**
* get_cred_many - Get references on a set of credentials * get_cred_many - Get references on a set of credentials
* @cred: The credentials to reference * @cred: The credentials to reference
@ -263,6 +280,11 @@ static inline void put_cred(const struct cred *cred)
put_cred_many(cred, 1); put_cred_many(cred, 1);
} }
DEFINE_CLASS(prepare_creds,
struct cred *,
if (_T) put_cred(_T),
prepare_creds(), void)
DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T)) DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T))
/** /**

View File

@ -25,7 +25,6 @@
extern struct files_struct init_files; extern struct files_struct init_files;
extern struct fs_struct init_fs; extern struct fs_struct init_fs;
extern struct nsproxy init_nsproxy; extern struct nsproxy init_nsproxy;
extern struct cred init_cred;
#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
#define INIT_PREV_CPUTIME(x) .prev_cputime = { \ #define INIT_PREV_CPUTIME(x) .prev_cputime = { \

View File

@ -8,7 +8,7 @@
#define SUID_DUMP_USER 1 /* Dump as user of process */ #define SUID_DUMP_USER 1 /* Dump as user of process */
#define SUID_DUMP_ROOT 2 /* Dump as root */ #define SUID_DUMP_ROOT 2 /* Dump as root */
static inline unsigned long __mm_flags_get_dumpable(struct mm_struct *mm) static inline unsigned long __mm_flags_get_dumpable(const struct mm_struct *mm)
{ {
/* /*
* By convention, dumpable bits are contained in first 32 bits of the * By convention, dumpable bits are contained in first 32 bits of the

View File

@ -62,6 +62,33 @@ unsigned long init_shadow_call_stack[SCS_SIZE / sizeof(long)] = {
}; };
#endif #endif
/* init to 2 - one for init_task, one to ensure it is never freed */
static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
/*
* The initial credentials for the initial task
*/
static struct cred init_cred = {
.usage = ATOMIC_INIT(4),
.uid = GLOBAL_ROOT_UID,
.gid = GLOBAL_ROOT_GID,
.suid = GLOBAL_ROOT_UID,
.sgid = GLOBAL_ROOT_GID,
.euid = GLOBAL_ROOT_UID,
.egid = GLOBAL_ROOT_GID,
.fsuid = GLOBAL_ROOT_UID,
.fsgid = GLOBAL_ROOT_GID,
.securebits = SECUREBITS_DEFAULT,
.cap_inheritable = CAP_EMPTY_SET,
.cap_permitted = CAP_FULL_SET,
.cap_effective = CAP_FULL_SET,
.cap_bset = CAP_FULL_SET,
.user = INIT_USER,
.user_ns = &init_user_ns,
.group_info = &init_groups,
.ucounts = &init_ucounts,
};
/* /*
* Set up the first task table, touch at your own risk!. Base=0, * Set up the first task table, touch at your own risk!. Base=0,
* limit=0x1fffff (=2MB) * limit=0x1fffff (=2MB)

View File

@ -520,26 +520,23 @@ static void fill_ac(struct bsd_acct_struct *acct)
static void acct_write_process(struct bsd_acct_struct *acct) static void acct_write_process(struct bsd_acct_struct *acct)
{ {
struct file *file = acct->file; struct file *file = acct->file;
const struct cred *cred;
acct_t *ac = &acct->ac; acct_t *ac = &acct->ac;
/* Perform file operations on behalf of whoever enabled accounting */ /* Perform file operations on behalf of whoever enabled accounting */
cred = override_creds(file->f_cred); scoped_with_creds(file->f_cred) {
/*
/* * First check to see if there is enough free_space to continue
* First check to see if there is enough free_space to continue * the process accounting system. Then get freeze protection. If
* the process accounting system. Then get freeze protection. If * the fs is frozen, just skip the write as we could deadlock
* the fs is frozen, just skip the write as we could deadlock * the system otherwise.
* the system otherwise. */
*/ if (check_free_space(acct) && file_start_write_trylock(file)) {
if (check_free_space(acct) && file_start_write_trylock(file)) { /* it's been opened O_APPEND, so position is irrelevant */
/* it's been opened O_APPEND, so position is irrelevant */ loff_t pos = 0;
loff_t pos = 0; __kernel_write(file, ac, sizeof(acct_t), &pos);
__kernel_write(file, ac, sizeof(acct_t), &pos); file_end_write(file);
file_end_write(file); }
} }
revert_creds(cred);
} }
static void do_acct_process(struct bsd_acct_struct *acct) static void do_acct_process(struct bsd_acct_struct *acct)

View File

@ -5360,7 +5360,6 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
struct cgroup_file_ctx *ctx = of->priv; struct cgroup_file_ctx *ctx = of->priv;
struct cgroup *src_cgrp, *dst_cgrp; struct cgroup *src_cgrp, *dst_cgrp;
struct task_struct *task; struct task_struct *task;
const struct cred *saved_cred;
ssize_t ret; ssize_t ret;
enum cgroup_attach_lock_mode lock_mode; enum cgroup_attach_lock_mode lock_mode;
@ -5383,11 +5382,10 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
* permissions using the credentials from file open to protect against * permissions using the credentials from file open to protect against
* inherited fd attacks. * inherited fd attacks.
*/ */
saved_cred = override_creds(of->file->f_cred); scoped_with_creds(of->file->f_cred)
ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, ret = cgroup_attach_permissions(src_cgrp, dst_cgrp,
of->file->f_path.dentry->d_sb, of->file->f_path.dentry->d_sb,
threadgroup, ctx->ns); threadgroup, ctx->ns);
revert_creds(saved_cred);
if (ret) if (ret)
goto out_finish; goto out_finish;

View File

@ -35,33 +35,6 @@ do { \
static struct kmem_cache *cred_jar; static struct kmem_cache *cred_jar;
/* init to 2 - one for init_task, one to ensure it is never freed */
static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
/*
* The initial credentials for the initial task
*/
struct cred init_cred = {
.usage = ATOMIC_INIT(4),
.uid = GLOBAL_ROOT_UID,
.gid = GLOBAL_ROOT_GID,
.suid = GLOBAL_ROOT_UID,
.sgid = GLOBAL_ROOT_GID,
.euid = GLOBAL_ROOT_UID,
.egid = GLOBAL_ROOT_GID,
.fsuid = GLOBAL_ROOT_UID,
.fsgid = GLOBAL_ROOT_GID,
.securebits = SECUREBITS_DEFAULT,
.cap_inheritable = CAP_EMPTY_SET,
.cap_permitted = CAP_FULL_SET,
.cap_effective = CAP_FULL_SET,
.cap_bset = CAP_FULL_SET,
.user = INIT_USER,
.user_ns = &init_user_ns,
.group_info = &init_groups,
.ucounts = &init_ucounts,
};
/* /*
* The RCU callback to actually dispose of a set of credentials * The RCU callback to actually dispose of a set of credentials
*/ */

View File

@ -1449,12 +1449,7 @@ static struct trace_event_functions user_event_funcs = {
static int user_event_set_call_visible(struct user_event *user, bool visible) static int user_event_set_call_visible(struct user_event *user, bool visible)
{ {
int ret; CLASS(prepare_creds, cred)();
const struct cred *old_cred;
struct cred *cred;
cred = prepare_creds();
if (!cred) if (!cred)
return -ENOMEM; return -ENOMEM;
@ -1469,17 +1464,12 @@ static int user_event_set_call_visible(struct user_event *user, bool visible)
*/ */
cred->fsuid = GLOBAL_ROOT_UID; cred->fsuid = GLOBAL_ROOT_UID;
old_cred = override_creds(cred); scoped_with_creds(cred) {
if (visible)
return trace_add_event_call(&user->call);
if (visible) return trace_remove_event_call(&user->call);
ret = trace_add_event_call(&user->call); }
else
ret = trace_remove_event_call(&user->call);
revert_creds(old_cred);
put_cred(cred);
return ret;
} }
static int destroy_user_event(struct user_event *user) static int destroy_user_event(struct user_event *user)

View File

@ -78,7 +78,6 @@ int dns_query(struct net *net,
{ {
struct key *rkey; struct key *rkey;
struct user_key_payload *upayload; struct user_key_payload *upayload;
const struct cred *saved_cred;
size_t typelen, desclen; size_t typelen, desclen;
char *desc, *cp; char *desc, *cp;
int ret, len; int ret, len;
@ -124,9 +123,8 @@ int dns_query(struct net *net,
/* make the upcall, using special credentials to prevent the use of /* make the upcall, using special credentials to prevent the use of
* add_key() to preinstall malicious redirections * add_key() to preinstall malicious redirections
*/ */
saved_cred = override_creds(dns_resolver_cache); scoped_with_creds(dns_resolver_cache)
rkey = request_key_net(&key_type_dns_resolver, desc, net, options); rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
revert_creds(saved_cred);
kfree(desc); kfree(desc);
if (IS_ERR(rkey)) { if (IS_ERR(rkey)) {
ret = PTR_ERR(rkey); ret = PTR_ERR(rkey);

View File

@ -1210,25 +1210,16 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
unix_mkname_bsd(sunaddr, addr_len); unix_mkname_bsd(sunaddr, addr_len);
if (flags & SOCK_COREDUMP) { if (flags & SOCK_COREDUMP) {
const struct cred *cred;
struct cred *kcred;
struct path root; struct path root;
kcred = prepare_kernel_cred(&init_task);
if (!kcred) {
err = -ENOMEM;
goto fail;
}
task_lock(&init_task); task_lock(&init_task);
get_fs_root(init_task.fs, &root); get_fs_root(init_task.fs, &root);
task_unlock(&init_task); task_unlock(&init_task);
cred = override_creds(kcred); scoped_with_kernel_creds()
err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path, err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path,
LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS | LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS |
LOOKUP_NO_MAGICLINKS, &path); LOOKUP_NO_MAGICLINKS, &path);
put_cred(revert_creds(cred));
path_put(&root); path_put(&root);
if (err) if (err)
goto fail; goto fail;

View File

@ -51,7 +51,7 @@ static struct key *get_user_register(struct user_namespace *user_ns)
if (!reg_keyring) { if (!reg_keyring) {
reg_keyring = keyring_alloc(".user_reg", reg_keyring = keyring_alloc(".user_reg",
user_ns->owner, INVALID_GID, user_ns->owner, INVALID_GID,
&init_cred, kernel_cred(),
KEY_POS_WRITE | KEY_POS_SEARCH | KEY_POS_WRITE | KEY_POS_SEARCH |
KEY_USR_VIEW | KEY_USR_READ, KEY_USR_VIEW | KEY_USR_READ,
0, 0,