mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 08:45:18 -04:00
tls: convert getsockopt to sockopt_t
Continue converting the proto-layer getsockopt callbacks to the sockopt_t interface, converting do_tls_getsockopt() and its per-option helpers to take a sockopt_t. The thin tls_getsockopt() wrapper keeps its __user signature for now: it builds a user-backed sockopt_t with sockopt_init_user(), calls the helper, and writes the returned length back to optlen. The helpers use copy_to_iter() instead of copy_to_user(); the NULL optval check in the TLS_TX/TLS_RX path is preserved by testing the iterator user buffer. No functional change. Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Reviewed-by: Joe Damato <joe@dama.to> Acked-by: Stanislav Fomichev <sdf@fomichev.me> Signed-off-by: Breno Leitao <leitao@debian.org> Link: https://patch.msgid.link/20260729-getsockopt_phase4-v4-6-c44576757c17@debian.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
d05a7f0ab5
commit
c704990207
@@ -424,20 +424,16 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
|
||||
int __user *optlen, int tx)
|
||||
static int do_tls_getsockopt_conf(struct sock *sk, sockopt_t *opt, int tx)
|
||||
{
|
||||
int rc = 0;
|
||||
const struct tls_cipher_desc *cipher_desc;
|
||||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
struct tls_crypto_info *crypto_info;
|
||||
struct cipher_context *cctx;
|
||||
int len;
|
||||
int len = opt->optlen;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
if (!optval || (len < sizeof(*crypto_info))) {
|
||||
if (!opt->iter_out.ubuf || len < sizeof(*crypto_info)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -462,7 +458,8 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
|
||||
}
|
||||
|
||||
if (len == sizeof(*crypto_info)) {
|
||||
if (copy_to_user(optval, crypto_info, sizeof(*crypto_info)))
|
||||
if (copy_to_iter(crypto_info, sizeof(*crypto_info),
|
||||
&opt->iter_out) != sizeof(*crypto_info))
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@@ -478,44 +475,38 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
|
||||
memcpy(crypto_info_rec_seq(crypto_info, cipher_desc),
|
||||
cctx->rec_seq, cipher_desc->rec_seq);
|
||||
|
||||
if (copy_to_user(optval, crypto_info, cipher_desc->crypto_info))
|
||||
if (copy_to_iter(crypto_info, cipher_desc->crypto_info,
|
||||
&opt->iter_out) != cipher_desc->crypto_info)
|
||||
rc = -EFAULT;
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
|
||||
int __user *optlen)
|
||||
static int do_tls_getsockopt_tx_zc(struct sock *sk, sockopt_t *opt)
|
||||
{
|
||||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
unsigned int value;
|
||||
int len;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
int len = opt->optlen;
|
||||
|
||||
if (len != sizeof(value))
|
||||
return -EINVAL;
|
||||
|
||||
value = ctx->zerocopy_sendfile;
|
||||
if (copy_to_user(optval, &value, sizeof(value)))
|
||||
if (copy_to_iter(&value, sizeof(value), &opt->iter_out) != sizeof(value))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
|
||||
int __user *optlen)
|
||||
static int do_tls_getsockopt_no_pad(struct sock *sk, sockopt_t *opt)
|
||||
{
|
||||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
int value, len;
|
||||
int value, len = opt->optlen;
|
||||
|
||||
if (ctx->prot_info.version != TLS_1_3_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
if (len < sizeof(value))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -525,38 +516,31 @@ static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
|
||||
if (value < 0)
|
||||
return value;
|
||||
|
||||
if (put_user(sizeof(value), optlen))
|
||||
return -EFAULT;
|
||||
if (copy_to_user(optval, &value, sizeof(value)))
|
||||
opt->optlen = sizeof(value);
|
||||
if (copy_to_iter(&value, sizeof(value), &opt->iter_out) != sizeof(value))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_tls_getsockopt_tx_payload_len(struct sock *sk, char __user *optval,
|
||||
int __user *optlen)
|
||||
static int do_tls_getsockopt_tx_payload_len(struct sock *sk, sockopt_t *opt)
|
||||
{
|
||||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
u16 payload_len = ctx->tx_max_payload_len;
|
||||
int len;
|
||||
|
||||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
int len = opt->optlen;
|
||||
|
||||
if (len < sizeof(payload_len))
|
||||
return -EINVAL;
|
||||
|
||||
if (put_user(sizeof(payload_len), optlen))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user(optval, &payload_len, sizeof(payload_len)))
|
||||
opt->optlen = sizeof(payload_len);
|
||||
if (copy_to_iter(&payload_len, sizeof(payload_len),
|
||||
&opt->iter_out) != sizeof(payload_len))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_tls_getsockopt(struct sock *sk, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
static int do_tls_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -565,17 +549,16 @@ static int do_tls_getsockopt(struct sock *sk, int optname,
|
||||
switch (optname) {
|
||||
case TLS_TX:
|
||||
case TLS_RX:
|
||||
rc = do_tls_getsockopt_conf(sk, optval, optlen,
|
||||
optname == TLS_TX);
|
||||
rc = do_tls_getsockopt_conf(sk, opt, optname == TLS_TX);
|
||||
break;
|
||||
case TLS_TX_ZEROCOPY_RO:
|
||||
rc = do_tls_getsockopt_tx_zc(sk, optval, optlen);
|
||||
rc = do_tls_getsockopt_tx_zc(sk, opt);
|
||||
break;
|
||||
case TLS_RX_EXPECT_NO_PAD:
|
||||
rc = do_tls_getsockopt_no_pad(sk, optval, optlen);
|
||||
rc = do_tls_getsockopt_no_pad(sk, opt);
|
||||
break;
|
||||
case TLS_TX_MAX_PAYLOAD_LEN:
|
||||
rc = do_tls_getsockopt_tx_payload_len(sk, optval, optlen);
|
||||
rc = do_tls_getsockopt_tx_payload_len(sk, opt);
|
||||
break;
|
||||
default:
|
||||
rc = -ENOPROTOOPT;
|
||||
@@ -591,12 +574,25 @@ static int tls_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
sockopt_t opt;
|
||||
int err;
|
||||
|
||||
if (level != SOL_TLS)
|
||||
return ctx->sk_proto->getsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
|
||||
return do_tls_getsockopt(sk, optname, optval, optlen);
|
||||
err = sockopt_init_user(&opt, optval, optlen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = do_tls_getsockopt(sk, optname, &opt);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (put_user(opt.optlen, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_crypto_info(const struct tls_crypto_info *crypto_info,
|
||||
|
||||
Reference in New Issue
Block a user