mirror of https://github.com/torvalds/linux.git
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:
commit
1d18101a64
|
|
@ -829,8 +829,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
|||
size_t offset, u32 opt_flags)
|
||||
{
|
||||
struct firmware *fw = NULL;
|
||||
struct cred *kern_cred = NULL;
|
||||
const struct cred *old_cred;
|
||||
bool nondirect = false;
|
||||
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
|
||||
* the kernel credentials to read the file.
|
||||
*/
|
||||
kern_cred = prepare_kernel_cred(&init_task);
|
||||
if (!kern_cred) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
old_cred = override_creds(kern_cred);
|
||||
scoped_with_kernel_creds() {
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
|
||||
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
|
||||
|
||||
/* Only full reads can support decompression, platform, and sysfs. */
|
||||
if (!(opt_flags & FW_OPT_PARTIAL))
|
||||
nondirect = true;
|
||||
/* Only full reads can support decompression, platform, and sysfs. */
|
||||
if (!(opt_flags & FW_OPT_PARTIAL))
|
||||
nondirect = true;
|
||||
|
||||
#ifdef CONFIG_FW_LOADER_COMPRESS_ZSTD
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, ".zst",
|
||||
fw_decompress_zstd);
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, ".zst",
|
||||
fw_decompress_zstd);
|
||||
#endif
|
||||
#ifdef CONFIG_FW_LOADER_COMPRESS_XZ
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
|
||||
fw_decompress_xz);
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
|
||||
fw_decompress_xz);
|
||||
#endif
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = firmware_fallback_platform(fw->priv);
|
||||
if (ret == -ENOENT && nondirect)
|
||||
ret = firmware_fallback_platform(fw->priv);
|
||||
|
||||
if (ret) {
|
||||
if (!(opt_flags & FW_OPT_NO_WARN))
|
||||
dev_warn(device,
|
||||
"Direct firmware load for %s failed with error %d\n",
|
||||
name, ret);
|
||||
if (nondirect)
|
||||
ret = firmware_fallback_sysfs(fw, name, device,
|
||||
opt_flags, ret);
|
||||
} else
|
||||
ret = assign_fw(fw, device);
|
||||
|
||||
revert_creds(old_cred);
|
||||
put_cred(kern_cred);
|
||||
if (ret) {
|
||||
if (!(opt_flags & FW_OPT_NO_WARN))
|
||||
dev_warn(device,
|
||||
"Direct firmware load for %s failed with error %d\n",
|
||||
name, ret);
|
||||
if (nondirect)
|
||||
ret = firmware_fallback_sysfs(fw, name, device,
|
||||
opt_flags, ret);
|
||||
} else {
|
||||
ret = assign_fw(fw, device);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
static DEFINE_IDR(nbd_index_idr);
|
||||
static DEFINE_MUTEX(nbd_index_mutex);
|
||||
static struct workqueue_struct *nbd_del_wq;
|
||||
static struct cred *nbd_cred;
|
||||
static int nbd_total_devices = 0;
|
||||
|
||||
struct nbd_sock {
|
||||
|
|
@ -555,7 +554,6 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
|
|||
int result;
|
||||
struct msghdr msg = {} ;
|
||||
unsigned int noreclaim_flag;
|
||||
const struct cred *old_cred;
|
||||
|
||||
if (unlikely(!sock)) {
|
||||
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;
|
||||
}
|
||||
|
||||
old_cred = override_creds(nbd_cred);
|
||||
|
||||
msg.msg_iter = *iter;
|
||||
|
||||
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)
|
||||
result = sock_sendmsg(sock, &msg);
|
||||
else
|
||||
result = sock_recvmsg(sock, &msg, msg.msg_flags);
|
||||
scoped_with_kernel_creds() {
|
||||
do {
|
||||
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
|
||||
sock->sk->sk_use_task_frag = false;
|
||||
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
|
||||
|
||||
if (result <= 0) {
|
||||
if (result == 0)
|
||||
result = -EPIPE; /* short read */
|
||||
break;
|
||||
}
|
||||
if (sent)
|
||||
*sent += result;
|
||||
} while (msg_data_left(&msg));
|
||||
if (send)
|
||||
result = sock_sendmsg(sock, &msg);
|
||||
else
|
||||
result = sock_recvmsg(sock, &msg, msg.msg_flags);
|
||||
|
||||
if (result <= 0) {
|
||||
if (result == 0)
|
||||
result = -EPIPE; /* short read */
|
||||
break;
|
||||
}
|
||||
if (sent)
|
||||
*sent += result;
|
||||
} while (msg_data_left(&msg));
|
||||
}
|
||||
|
||||
memalloc_noreclaim_restore(noreclaim_flag);
|
||||
|
||||
revert_creds(old_cred);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2683,15 +2680,7 @@ static int __init nbd_init(void)
|
|||
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)) {
|
||||
put_cred(nbd_cred);
|
||||
destroy_workqueue(nbd_del_wq);
|
||||
unregister_blkdev(NBD_MAJOR, "nbd");
|
||||
return -EINVAL;
|
||||
|
|
@ -2746,7 +2735,6 @@ static void __exit nbd_cleanup(void)
|
|||
/* Also wait for nbd_dev_remove_work() completes */
|
||||
destroy_workqueue(nbd_del_wq);
|
||||
|
||||
put_cred(nbd_cred);
|
||||
idr_destroy(&nbd_index_idr);
|
||||
unregister_blkdev(NBD_MAJOR, "nbd");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
struct file *fp;
|
||||
struct path root;
|
||||
struct cred *cred;
|
||||
const struct cred *old_cred;
|
||||
struct path root __free(path_put) = {};
|
||||
|
||||
task_lock(&init_task);
|
||||
get_fs_root(init_task.fs, &root);
|
||||
task_unlock(&init_task);
|
||||
|
||||
cred = prepare_creds();
|
||||
CLASS(prepare_creds, cred)();
|
||||
if (!cred)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cred->fsuid = GLOBAL_ROOT_UID;
|
||||
old_cred = override_creds(cred);
|
||||
|
||||
fp = file_open_root(&root, filename, flags, mode);
|
||||
path_put(&root);
|
||||
|
||||
put_cred(revert_creds(old_cred));
|
||||
|
||||
return fp;
|
||||
scoped_with_creds(cred)
|
||||
return file_open_root(&root, filename, flags, mode);
|
||||
}
|
||||
|
||||
static int sev_read_init_ex_file(void)
|
||||
|
|
|
|||
|
|
@ -3670,8 +3670,6 @@ static int __init target_core_init_configfs(void)
|
|||
{
|
||||
struct configfs_subsystem *subsys = &target_core_fabrics;
|
||||
struct t10_alua_lu_gp *lu_gp;
|
||||
struct cred *kern_cred;
|
||||
const struct cred *old_cred;
|
||||
int ret;
|
||||
|
||||
pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
|
||||
|
|
@ -3748,16 +3746,8 @@ static int __init target_core_init_configfs(void)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* We use the kernel credentials to access the target directory */
|
||||
kern_cred = prepare_kernel_cred(&init_task);
|
||||
if (!kern_cred) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
old_cred = override_creds(kern_cred);
|
||||
target_init_dbroot();
|
||||
revert_creds(old_cred);
|
||||
put_cred(kern_cred);
|
||||
scoped_with_kernel_creds()
|
||||
target_init_dbroot();
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
6
fs/aio.c
6
fs/aio.c
|
|
@ -1640,10 +1640,10 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
|
|||
static void aio_fsync_work(struct work_struct *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);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(iocb->fsync.creds)
|
||||
iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync);
|
||||
|
||||
put_cred(iocb->fsync.creds);
|
||||
iocb_put(iocb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,13 +157,37 @@ static int backing_aio_init_wq(struct kiocb *iocb)
|
|||
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,
|
||||
struct kiocb *iocb, int flags,
|
||||
struct backing_file_ctx *ctx)
|
||||
{
|
||||
struct backing_aio *aio = NULL;
|
||||
const struct cred *old_cred;
|
||||
ssize_t ret;
|
||||
|
||||
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))
|
||||
return -EINVAL;
|
||||
|
||||
old_cred = override_creds(ctx->cred);
|
||||
if (is_sync_kiocb(iocb)) {
|
||||
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);
|
||||
scoped_with_creds(ctx->cred)
|
||||
ret = do_backing_file_read_iter(file, iter, iocb, flags);
|
||||
|
||||
if (ctx->accessed)
|
||||
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);
|
||||
|
||||
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,
|
||||
struct kiocb *iocb, int flags,
|
||||
struct backing_file_ctx *ctx)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
ssize_t ret;
|
||||
|
||||
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))
|
||||
return -EINVAL;
|
||||
|
||||
old_cred = override_creds(ctx->cred);
|
||||
if (is_sync_kiocb(iocb)) {
|
||||
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;
|
||||
scoped_with_creds(ctx->cred)
|
||||
return do_backing_file_write_iter(file, iter, iocb, flags, ctx->end_write);
|
||||
}
|
||||
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,
|
||||
struct backing_file_ctx *ctx)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
ssize_t ret;
|
||||
|
||||
if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING)))
|
||||
return -EIO;
|
||||
|
||||
old_cred = override_creds(ctx->cred);
|
||||
ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(ctx->cred)
|
||||
ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags);
|
||||
|
||||
if (ctx->accessed)
|
||||
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,
|
||||
struct backing_file_ctx *ctx)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
ssize_t ret;
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
old_cred = override_creds(ctx->cred);
|
||||
file_start_write(out);
|
||||
ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags);
|
||||
file_end_write(out);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(ctx->cred) {
|
||||
file_start_write(out);
|
||||
ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags);
|
||||
file_end_write(out);
|
||||
}
|
||||
|
||||
if (ctx->end_write)
|
||||
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,
|
||||
struct backing_file_ctx *ctx)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
struct file *user_file = vma->vm_file;
|
||||
int ret;
|
||||
|
||||
|
|
@ -332,9 +336,8 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
|
|||
|
||||
vma_set_file(vma, file);
|
||||
|
||||
old_cred = override_creds(ctx->cred);
|
||||
ret = vfs_mmap(vma->vm_file, vma);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(ctx->cred)
|
||||
ret = vfs_mmap(vma->vm_file, vma);
|
||||
|
||||
if (ctx->accessed)
|
||||
ctx->accessed(user_file);
|
||||
|
|
|
|||
|
|
@ -782,8 +782,6 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
|
|||
return PTR_ERR(e);
|
||||
|
||||
if (e->flags & MISC_FMT_OPEN_FILE) {
|
||||
const struct cred *old_cred;
|
||||
|
||||
/*
|
||||
* Now that we support unprivileged binfmt_misc mounts make
|
||||
* 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
|
||||
* the register file.
|
||||
*/
|
||||
old_cred = override_creds(file->f_cred);
|
||||
f = open_exec(e->interpreter);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(file->f_cred)
|
||||
f = open_exec(e->interpreter);
|
||||
if (IS_ERR(f)) {
|
||||
pr_notice("register: failed to install interpreter file %s\n",
|
||||
e->interpreter);
|
||||
|
|
|
|||
146
fs/coredump.c
146
fs/coredump.c
|
|
@ -1036,7 +1036,7 @@ static bool coredump_pipe(struct core_name *cn, struct coredump_params *cprm,
|
|||
|
||||
static bool coredump_write(struct core_name *cn,
|
||||
struct coredump_params *cprm,
|
||||
struct linux_binfmt *binfmt)
|
||||
const struct linux_binfmt *binfmt)
|
||||
{
|
||||
|
||||
if (dump_interrupted())
|
||||
|
|
@ -1086,15 +1086,80 @@ static inline bool coredump_skip(const struct coredump_params *cprm,
|
|||
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)
|
||||
{
|
||||
struct cred *cred __free(put_cred) = NULL;
|
||||
size_t *argv __free(kfree) = NULL;
|
||||
struct core_state core_state;
|
||||
struct core_name cn;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct linux_binfmt *binfmt = mm->binfmt;
|
||||
const struct cred *old_cred;
|
||||
const struct mm_struct *mm = current->mm;
|
||||
const struct linux_binfmt *binfmt = mm->binfmt;
|
||||
int argc = 0;
|
||||
struct coredump_params cprm = {
|
||||
.siginfo = siginfo,
|
||||
|
|
@ -1116,7 +1181,7 @@ void vfs_coredump(const kernel_siginfo_t *siginfo)
|
|||
if (coredump_skip(&cprm, binfmt))
|
||||
return;
|
||||
|
||||
cred = prepare_creds();
|
||||
CLASS(prepare_creds, cred)();
|
||||
if (!cred)
|
||||
return;
|
||||
/*
|
||||
|
|
@ -1131,74 +1196,9 @@ void vfs_coredump(const kernel_siginfo_t *siginfo)
|
|||
if (coredump_wait(siginfo->si_signo, &core_state) < 0)
|
||||
return;
|
||||
|
||||
old_cred = override_creds(cred);
|
||||
|
||||
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:
|
||||
scoped_with_creds(cred)
|
||||
do_coredump(&cn, &cprm, &argv, &argc, binfmt);
|
||||
coredump_cleanup(&cn, &cprm);
|
||||
revert_creds(old_cred);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
struct iov_iter iter;
|
||||
int ret;
|
||||
|
||||
|
|
@ -61,9 +60,8 @@ static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
|
|||
rq->iocb.ki_flags = IOCB_DIRECT;
|
||||
iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
|
||||
rq->bio.bi_iter.bi_size);
|
||||
old_cred = override_creds(rq->iocb.ki_filp->f_cred);
|
||||
ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
|
||||
revert_creds(old_cred);
|
||||
scoped_with_creds(rq->iocb.ki_filp->f_cred)
|
||||
ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
|
||||
if (ret != -EIOCBQUEUED)
|
||||
erofs_fileio_ki_complete(&rq->iocb, ret);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
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;
|
||||
ssize_t status;
|
||||
int n_iters;
|
||||
|
||||
save_cred = override_creds(filp->f_cred);
|
||||
|
||||
n_iters = atomic_read(&iocb->n_iters);
|
||||
for (int i = 0; i < n_iters ; 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
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
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;
|
||||
ssize_t status;
|
||||
int n_iters;
|
||||
|
||||
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
|
||||
save_cred = override_creds(filp->f_cred);
|
||||
|
||||
file_start_write(filp);
|
||||
n_iters = atomic_read(&iocb->n_iters);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,15 +306,12 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
|
|||
const char *type, void *data,
|
||||
size_t data_size, struct idmap *idmap)
|
||||
{
|
||||
const struct cred *saved_cred;
|
||||
struct key *rkey;
|
||||
const struct user_key_payload *payload;
|
||||
ssize_t ret;
|
||||
|
||||
saved_cred = override_creds(id_resolver_cache);
|
||||
rkey = nfs_idmap_request_key(name, namelen, type, idmap);
|
||||
revert_creds(saved_cred);
|
||||
|
||||
scoped_with_creds(id_resolver_cache)
|
||||
rkey = nfs_idmap_request_key(name, namelen, type, idmap);
|
||||
if (IS_ERR(rkey)) {
|
||||
ret = PTR_ERR(rkey);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
|
|||
size_t desc_len;
|
||||
struct key *spnego_key;
|
||||
const char *hostname = server->hostname;
|
||||
const struct cred *saved_cred;
|
||||
|
||||
/* length of fields (with semicolons): ver=0xyz ip4=ipaddress
|
||||
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");
|
||||
|
||||
cifs_dbg(FYI, "key description = %s\n", description);
|
||||
saved_cred = override_creds(spnego_cred);
|
||||
spnego_key = request_key(&cifs_spnego_key_type, description, "");
|
||||
revert_creds(saved_cred);
|
||||
scoped_with_creds(spnego_cred)
|
||||
spnego_key = request_key(&cifs_spnego_key_type, description, "");
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
if (cifsFYI && !IS_ERR(spnego_key)) {
|
||||
|
|
|
|||
|
|
@ -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##_constructor
|
||||
|
||||
#define scoped_class(_name, var, args) \
|
||||
for (CLASS(_name, var)(args); \
|
||||
__guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \
|
||||
({ goto _label; })) \
|
||||
if (0) { \
|
||||
_label: \
|
||||
break; \
|
||||
#define __scoped_class(_name, var, _label, args...) \
|
||||
for (CLASS(_name, var)(args); ; ({ goto _label; })) \
|
||||
if (0) { \
|
||||
_label: \
|
||||
break; \
|
||||
} else
|
||||
|
||||
#define scoped_class(_name, var, args...) \
|
||||
__scoped_class(_name, var, __UNIQUE_ID(label), args)
|
||||
|
||||
/*
|
||||
* DEFINE_GUARD(name, type, lock, unlock):
|
||||
* trivial wrapper around DEFINE_CLASS() above specifically
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
struct cred;
|
||||
struct inode;
|
||||
|
||||
extern struct task_struct init_task;
|
||||
|
||||
/*
|
||||
* COW Supplementary groups list
|
||||
*/
|
||||
|
|
@ -156,6 +158,11 @@ extern struct cred *prepare_exec_creds(void);
|
|||
extern int commit_creds(struct cred *);
|
||||
extern void abort_creds(struct cred *);
|
||||
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_from_ctx(struct cred *, const char *);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
* @cred: The credentials to reference
|
||||
|
|
@ -263,6 +280,11 @@ static inline void put_cred(const struct cred *cred)
|
|||
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))
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
extern struct files_struct init_files;
|
||||
extern struct fs_struct init_fs;
|
||||
extern struct nsproxy init_nsproxy;
|
||||
extern struct cred init_cred;
|
||||
|
||||
#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
|
||||
#define INIT_PREV_CPUTIME(x) .prev_cputime = { \
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#define SUID_DUMP_USER 1 /* Dump as user of process */
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -62,6 +62,33 @@ unsigned long init_shadow_call_stack[SCS_SIZE / sizeof(long)] = {
|
|||
};
|
||||
#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,
|
||||
* limit=0x1fffff (=2MB)
|
||||
|
|
|
|||
|
|
@ -520,26 +520,23 @@ static void fill_ac(struct bsd_acct_struct *acct)
|
|||
static void acct_write_process(struct bsd_acct_struct *acct)
|
||||
{
|
||||
struct file *file = acct->file;
|
||||
const struct cred *cred;
|
||||
acct_t *ac = &acct->ac;
|
||||
|
||||
/* Perform file operations on behalf of whoever enabled accounting */
|
||||
cred = override_creds(file->f_cred);
|
||||
|
||||
/*
|
||||
* First check to see if there is enough free_space to continue
|
||||
* the process accounting system. Then get freeze protection. If
|
||||
* the fs is frozen, just skip the write as we could deadlock
|
||||
* the system otherwise.
|
||||
*/
|
||||
if (check_free_space(acct) && file_start_write_trylock(file)) {
|
||||
/* it's been opened O_APPEND, so position is irrelevant */
|
||||
loff_t pos = 0;
|
||||
__kernel_write(file, ac, sizeof(acct_t), &pos);
|
||||
file_end_write(file);
|
||||
scoped_with_creds(file->f_cred) {
|
||||
/*
|
||||
* First check to see if there is enough free_space to continue
|
||||
* the process accounting system. Then get freeze protection. If
|
||||
* the fs is frozen, just skip the write as we could deadlock
|
||||
* the system otherwise.
|
||||
*/
|
||||
if (check_free_space(acct) && file_start_write_trylock(file)) {
|
||||
/* it's been opened O_APPEND, so position is irrelevant */
|
||||
loff_t pos = 0;
|
||||
__kernel_write(file, ac, sizeof(acct_t), &pos);
|
||||
file_end_write(file);
|
||||
}
|
||||
}
|
||||
|
||||
revert_creds(cred);
|
||||
}
|
||||
|
||||
static void do_acct_process(struct bsd_acct_struct *acct)
|
||||
|
|
|
|||
|
|
@ -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 *src_cgrp, *dst_cgrp;
|
||||
struct task_struct *task;
|
||||
const struct cred *saved_cred;
|
||||
ssize_t ret;
|
||||
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
|
||||
* inherited fd attacks.
|
||||
*/
|
||||
saved_cred = override_creds(of->file->f_cred);
|
||||
ret = cgroup_attach_permissions(src_cgrp, dst_cgrp,
|
||||
of->file->f_path.dentry->d_sb,
|
||||
threadgroup, ctx->ns);
|
||||
revert_creds(saved_cred);
|
||||
scoped_with_creds(of->file->f_cred)
|
||||
ret = cgroup_attach_permissions(src_cgrp, dst_cgrp,
|
||||
of->file->f_path.dentry->d_sb,
|
||||
threadgroup, ctx->ns);
|
||||
if (ret)
|
||||
goto out_finish;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,33 +35,6 @@ do { \
|
|||
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
int ret;
|
||||
const struct cred *old_cred;
|
||||
struct cred *cred;
|
||||
|
||||
cred = prepare_creds();
|
||||
|
||||
CLASS(prepare_creds, cred)();
|
||||
if (!cred)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1469,17 +1464,12 @@ static int user_event_set_call_visible(struct user_event *user, bool visible)
|
|||
*/
|
||||
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)
|
||||
ret = trace_add_event_call(&user->call);
|
||||
else
|
||||
ret = trace_remove_event_call(&user->call);
|
||||
|
||||
revert_creds(old_cred);
|
||||
put_cred(cred);
|
||||
|
||||
return ret;
|
||||
return trace_remove_event_call(&user->call);
|
||||
}
|
||||
}
|
||||
|
||||
static int destroy_user_event(struct user_event *user)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ int dns_query(struct net *net,
|
|||
{
|
||||
struct key *rkey;
|
||||
struct user_key_payload *upayload;
|
||||
const struct cred *saved_cred;
|
||||
size_t typelen, desclen;
|
||||
char *desc, *cp;
|
||||
int ret, len;
|
||||
|
|
@ -124,9 +123,8 @@ int dns_query(struct net *net,
|
|||
/* make the upcall, using special credentials to prevent the use of
|
||||
* add_key() to preinstall malicious redirections
|
||||
*/
|
||||
saved_cred = override_creds(dns_resolver_cache);
|
||||
rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
|
||||
revert_creds(saved_cred);
|
||||
scoped_with_creds(dns_resolver_cache)
|
||||
rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
|
||||
kfree(desc);
|
||||
if (IS_ERR(rkey)) {
|
||||
ret = PTR_ERR(rkey);
|
||||
|
|
|
|||
|
|
@ -1210,25 +1210,16 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
|
|||
unix_mkname_bsd(sunaddr, addr_len);
|
||||
|
||||
if (flags & SOCK_COREDUMP) {
|
||||
const struct cred *cred;
|
||||
struct cred *kcred;
|
||||
struct path root;
|
||||
|
||||
kcred = prepare_kernel_cred(&init_task);
|
||||
if (!kcred) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
task_lock(&init_task);
|
||||
get_fs_root(init_task.fs, &root);
|
||||
task_unlock(&init_task);
|
||||
|
||||
cred = override_creds(kcred);
|
||||
err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path,
|
||||
LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS |
|
||||
LOOKUP_NO_MAGICLINKS, &path);
|
||||
put_cred(revert_creds(cred));
|
||||
scoped_with_kernel_creds()
|
||||
err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path,
|
||||
LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS |
|
||||
LOOKUP_NO_MAGICLINKS, &path);
|
||||
path_put(&root);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static struct key *get_user_register(struct user_namespace *user_ns)
|
|||
if (!reg_keyring) {
|
||||
reg_keyring = keyring_alloc(".user_reg",
|
||||
user_ns->owner, INVALID_GID,
|
||||
&init_cred,
|
||||
kernel_cred(),
|
||||
KEY_POS_WRITE | KEY_POS_SEARCH |
|
||||
KEY_USR_VIEW | KEY_USR_READ,
|
||||
0,
|
||||
|
|
|
|||
Loading…
Reference in New Issue