From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/crypto/af_alg.c | 99 ++++++++++++++++++++++++++----------------------- 1 files changed, 53 insertions(+), 46 deletions(-) diff --git a/kernel/crypto/af_alg.c b/kernel/crypto/af_alg.c index d0276a4..9acb9d2 100644 --- a/kernel/crypto/af_alg.c +++ b/kernel/crypto/af_alg.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * af_alg: User-space algorithm interface * * This file provides the user-space API for algorithms. * * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * */ #include <linux/atomic.h> @@ -21,6 +16,7 @@ #include <linux/module.h> #include <linux/net.h> #include <linux/rwsem.h> +#include <linux/sched.h> #include <linux/sched/signal.h> #include <linux/security.h> @@ -174,7 +170,7 @@ sa->salg_name[addr_len - sizeof(*sa) - 1] = 0; type = alg_get_type(sa->salg_type); - if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) { + if (PTR_ERR(type) == -ENOENT) { request_module("algif-%s", sa->salg_type); type = alg_get_type(sa->salg_type); } @@ -206,8 +202,7 @@ return err; } -static int alg_setkey(struct sock *sk, char __user *ukey, - unsigned int keylen) +static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen) { struct alg_sock *ask = alg_sk(sk); const struct af_alg_type *type = ask->type; @@ -219,7 +214,7 @@ return -ENOMEM; err = -EFAULT; - if (copy_from_user(key, ukey, keylen)) + if (copy_from_sockptr(key, ukey, keylen)) goto out; err = type->setkey(ask->private, key, keylen); @@ -231,7 +226,7 @@ } static int alg_setsockopt(struct socket *sock, int level, int optname, - char __user *optval, unsigned int optlen) + sockptr_t optval, unsigned int optlen) { struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); @@ -263,6 +258,14 @@ if (!type->setauthsize) goto unlock; err = type->setauthsize(ask->private, optlen); + break; + case ALG_SET_DRBG_ENTROPY: + if (sock->state == SS_CONNECTED) + goto unlock; + if (!type->setentropy) + goto unlock; + + err = type->setentropy(ask->private, optval, optlen); } unlock: @@ -295,6 +298,11 @@ security_sock_graft(sk2, newsock); security_sk_clone(sk, sk2); + /* + * newsock->ops assigned here to allow type->accept call to override + * them when required. + */ + newsock->ops = type->ops; err = type->accept(ask->private, sk2); nokey = err == -ENOKEY; @@ -303,8 +311,6 @@ if (err) goto unlock; - - sk2->sk_family = PF_ALG; if (atomic_inc_return_relaxed(&ask->refcnt) == 1) sock_hold(sk); @@ -315,7 +321,6 @@ alg_sk(sk2)->parent = sk; alg_sk(sk2)->type = type; - newsock->ops = type->ops; newsock->state = SS_CONNECTED; if (nokey) @@ -346,7 +351,6 @@ .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, - .getsockopt = sock_no_getsockopt, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, .sendmsg = sock_no_sendmsg, @@ -384,7 +388,6 @@ sock->ops = &alg_proto_ops; sock_init_data(sock, sk); - sk->sk_family = PF_ALG; sk->sk_destruct = alg_sock_destruct; return 0; @@ -429,12 +432,12 @@ } EXPORT_SYMBOL_GPL(af_alg_make_sg); -void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new) +static void af_alg_link_sg(struct af_alg_sgl *sgl_prev, + struct af_alg_sgl *sgl_new) { sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg); } -EXPORT_SYMBOL_GPL(af_alg_link_sg); void af_alg_free_sg(struct af_alg_sgl *sgl) { @@ -445,7 +448,7 @@ } EXPORT_SYMBOL_GPL(af_alg_free_sg); -int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) +static int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) { struct cmsghdr *cmsg; @@ -484,7 +487,6 @@ return 0; } -EXPORT_SYMBOL_GPL(af_alg_cmsg_send); /** * af_alg_alloc_tsgl - allocate the TX SGL @@ -492,7 +494,7 @@ * @sk socket of connection to user space * @return: 0 upon success, < 0 upon error */ -int af_alg_alloc_tsgl(struct sock *sk) +static int af_alg_alloc_tsgl(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct af_alg_ctx *ctx = ask->private; @@ -521,7 +523,6 @@ return 0; } -EXPORT_SYMBOL_GPL(af_alg_alloc_tsgl); /** * aead_count_tsgl - Count number of TX SG entries @@ -536,17 +537,17 @@ */ unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset) { - struct alg_sock *ask = alg_sk(sk); - struct af_alg_ctx *ctx = ask->private; - struct af_alg_tsgl *sgl, *tmp; + const struct alg_sock *ask = alg_sk(sk); + const struct af_alg_ctx *ctx = ask->private; + const struct af_alg_tsgl *sgl; unsigned int i; unsigned int sgl_count = 0; if (!bytes) return 0; - list_for_each_entry_safe(sgl, tmp, &ctx->tsgl_list, list) { - struct scatterlist *sg = sgl->sg; + list_for_each_entry(sgl, &ctx->tsgl_list, list) { + const struct scatterlist *sg = sgl->sg; for (i = 0; i < sgl->cur; i++) { size_t bytes_count; @@ -644,12 +645,12 @@ } list_del(&sgl->list); - sock_kfree_s(sk, sgl, sizeof(*sgl) + sizeof(sgl->sg[0]) * - (MAX_SGL_ENTS + 1)); + sock_kfree_s(sk, sgl, struct_size(sgl, sg, MAX_SGL_ENTS + 1)); } if (!ctx->used) ctx->merge = 0; + ctx->init = ctx->more; } EXPORT_SYMBOL_GPL(af_alg_pull_tsgl); @@ -658,7 +659,7 @@ * * @areq Request holding the TX and RX SGL */ -void af_alg_free_areq_sgls(struct af_alg_async_req *areq) +static void af_alg_free_areq_sgls(struct af_alg_async_req *areq) { struct sock *sk = areq->sk; struct alg_sock *ask = alg_sk(sk); @@ -687,7 +688,6 @@ sock_kfree_s(sk, tsgl, areq->tsgl_entries * sizeof(*tsgl)); } } -EXPORT_SYMBOL_GPL(af_alg_free_areq_sgls); /** * af_alg_wait_for_wmem - wait for availability of writable memory @@ -696,7 +696,7 @@ * @flags If MSG_DONTWAIT is set, then only report if function would sleep * @return 0 when writable memory is available, < 0 upon error */ -int af_alg_wait_for_wmem(struct sock *sk, unsigned int flags) +static int af_alg_wait_for_wmem(struct sock *sk, unsigned int flags) { DEFINE_WAIT_FUNC(wait, woken_wake_function); int err = -ERESTARTSYS; @@ -721,7 +721,6 @@ return err; } -EXPORT_SYMBOL_GPL(af_alg_wait_for_wmem); /** * af_alg_wmem_wakeup - wakeup caller when writable memory is available @@ -751,9 +750,10 @@ * * @sk socket of connection to user space * @flags If MSG_DONTWAIT is set, then only report if function would sleep + * @min Set to minimum request size if partial requests are allowed. * @return 0 when writable memory is available, < 0 upon error */ -int af_alg_wait_for_data(struct sock *sk, unsigned flags) +int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min) { DEFINE_WAIT_FUNC(wait, woken_wake_function); struct alg_sock *ask = alg_sk(sk); @@ -771,7 +771,9 @@ if (signal_pending(current)) break; timeout = MAX_SCHEDULE_TIMEOUT; - if (sk_wait_event(sk, &timeout, (ctx->used || !ctx->more), + if (sk_wait_event(sk, &timeout, + ctx->init && (!ctx->more || + (min && ctx->used >= min)), &wait)) { err = 0; break; @@ -790,8 +792,7 @@ * * @sk socket of connection to user space */ - -void af_alg_data_wakeup(struct sock *sk) +static void af_alg_data_wakeup(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct af_alg_ctx *ctx = ask->private; @@ -809,7 +810,6 @@ sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); rcu_read_unlock(); } -EXPORT_SYMBOL_GPL(af_alg_data_wakeup); /** * af_alg_sendmsg - implementation of sendmsg system call handler @@ -836,8 +836,8 @@ struct af_alg_tsgl *sgl; struct af_alg_control con = {}; long copied = 0; - bool enc = 0; - bool init = 0; + bool enc = false; + bool init = false; int err = 0; if (msg->msg_controllen) { @@ -845,13 +845,13 @@ if (err) return err; - init = 1; + init = true; switch (con.op) { case ALG_OP_ENCRYPT: - enc = 1; + enc = true; break; case ALG_OP_DECRYPT: - enc = 0; + enc = false; break; default: return -EINVAL; @@ -862,10 +862,17 @@ } lock_sock(sk); - if (!ctx->more && ctx->used) { - err = -EINVAL; - goto unlock; + if (ctx->init && !ctx->more) { + if (ctx->used) { + err = -EINVAL; + goto unlock; + } + + pr_info_once( + "%s sent an empty control message without MSG_MORE.\n", + current->comm); } + ctx->init = true; if (init) { ctx->enc = enc; -- Gitblit v1.6.2