2020-08-05 16:54:37

by Rouven Czerwinski

[permalink] [raw]
Subject: [PATCH 1/2] net: tls: add compat for get/setsockopt

If compat_{s,g}etsockopt for TLS are not implemented, the TLS layer will
never be called on a system where CONFIG_COMPAT is enabled and userspace
is 32bit. Implement both to support CONFIG_COMPAT.

Signed-off-by: Rouven Czerwinski <[email protected]>
---
net/tls/tls_main.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index ec10041c6b7d..92c5893fe692 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -450,6 +450,18 @@ static int tls_getsockopt(struct sock *sk, int level, int optname,
return do_tls_getsockopt(sk, optname, optval, optlen);
}

+static int tls_compat_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct tls_context *ctx = tls_get_ctx(sk);
+
+ if (level != SOL_TLS)
+ return ctx->sk_proto->compat_getsockopt(sk, level, optname,
+ optval, optlen);
+
+ return do_tls_getsockopt(sk, optname, optval, optlen);
+}
+
static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
unsigned int optlen, int tx)
{
@@ -611,6 +623,18 @@ static int tls_setsockopt(struct sock *sk, int level, int optname,
return do_tls_setsockopt(sk, optname, optval, optlen);
}

+static int tls_compat_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen)
+{
+ struct tls_context *ctx = tls_get_ctx(sk);
+
+ if (level != SOL_TLS)
+ return ctx->sk_proto->compat_setsockopt(sk, level, optname,
+ optval, optlen);
+
+ return do_tls_setsockopt(sk, optname, optval, optlen);
+}
+
struct tls_context *tls_ctx_create(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
@@ -660,6 +684,10 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
prot[TLS_BASE][TLS_BASE].setsockopt = tls_setsockopt;
prot[TLS_BASE][TLS_BASE].getsockopt = tls_getsockopt;
prot[TLS_BASE][TLS_BASE].close = tls_sk_proto_close;
+#ifdef CONFIG_COMPAT
+ prot[TLS_BASE][TLS_BASE].compat_setsockopt = tls_compat_setsockopt;
+ prot[TLS_BASE][TLS_BASE].compat_getsockopt = tls_compat_getsockopt;
+#endif

prot[TLS_SW][TLS_BASE] = prot[TLS_BASE][TLS_BASE];
prot[TLS_SW][TLS_BASE].sendmsg = tls_sw_sendmsg;
--
2.27.0


2020-08-05 20:01:35

by Rouven Czerwinski

[permalink] [raw]
Subject: [PATCH 2/2] net: tls: allow MSG_CMSG_COMPAT in sendmsg

The MSG_CMSG_COMPAT flag is valid if the system has CONFIG_COMPAT
enabled and a 32bit userspace.

Signed-off-by: Rouven Czerwinski <[email protected]>
---
net/tls/tls_sw.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 24f64bc0de18..a332ae123bda 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -935,7 +935,8 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
int ret = 0;
int pending;

- if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
+ if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
+ MSG_CMSG_COMPAT))
return -EOPNOTSUPP;

mutex_lock(&tls_ctx->tx_lock);
--
2.27.0

2020-08-06 00:46:24

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 1/2] net: tls: add compat for get/setsockopt


Neither of these patches apply cleanly to net-next. The compat handling
and TLS code has been changed quite a bit lately.

ALso, you must provide a proper header "[PATCH 0/N] ..." posting for your
patch series which explains at a high level what your patch series is doing,
how it is doing it, and why it is doing it that way.

Thank you.

2020-08-06 02:31:11

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/2] net: tls: add compat for get/setsockopt

Hi Rouven,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.8]
[cannot apply to next-20200805]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Rouven-Czerwinski/net-tls-add-compat-for-get-setsockopt/20200806-040123
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ecfd7940b8641da6e41ca94eba36876dc2ba827b
config: i386-randconfig-s002-20200805 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.2-117-g8c7aee71-dirty
# save the attached .config to linux build tree
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

net/tls/tls_main.c: In function 'tls_compat_getsockopt':
>> net/tls/tls_main.c:459:23: error: 'struct proto' has no member named 'compat_getsockopt'
459 | return ctx->sk_proto->compat_getsockopt(sk, level, optname,
| ^~
net/tls/tls_main.c: In function 'tls_compat_setsockopt':
>> net/tls/tls_main.c:632:23: error: 'struct proto' has no member named 'compat_setsockopt'
632 | return ctx->sk_proto->compat_setsockopt(sk, level, optname,
| ^~
At top level:
net/tls/tls_main.c:626:12: warning: 'tls_compat_setsockopt' defined but not used [-Wunused-function]
626 | static int tls_compat_setsockopt(struct sock *sk, int level, int optname,
| ^~~~~~~~~~~~~~~~~~~~~
net/tls/tls_main.c:453:12: warning: 'tls_compat_getsockopt' defined but not used [-Wunused-function]
453 | static int tls_compat_getsockopt(struct sock *sk, int level, int optname,
| ^~~~~~~~~~~~~~~~~~~~~

vim +459 net/tls/tls_main.c

452
453 static int tls_compat_getsockopt(struct sock *sk, int level, int optname,
454 char __user *optval, int __user *optlen)
455 {
456 struct tls_context *ctx = tls_get_ctx(sk);
457
458 if (level != SOL_TLS)
> 459 return ctx->sk_proto->compat_getsockopt(sk, level, optname,
460 optval, optlen);
461
462 return do_tls_getsockopt(sk, optname, optval, optlen);
463 }
464
465 static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
466 unsigned int optlen, int tx)
467 {
468 struct tls_crypto_info *crypto_info;
469 struct tls_crypto_info *alt_crypto_info;
470 struct tls_context *ctx = tls_get_ctx(sk);
471 size_t optsize;
472 int rc = 0;
473 int conf;
474
475 if (!optval || (optlen < sizeof(*crypto_info))) {
476 rc = -EINVAL;
477 goto out;
478 }
479
480 if (tx) {
481 crypto_info = &ctx->crypto_send.info;
482 alt_crypto_info = &ctx->crypto_recv.info;
483 } else {
484 crypto_info = &ctx->crypto_recv.info;
485 alt_crypto_info = &ctx->crypto_send.info;
486 }
487
488 /* Currently we don't support set crypto info more than one time */
489 if (TLS_CRYPTO_INFO_READY(crypto_info)) {
490 rc = -EBUSY;
491 goto out;
492 }
493
494 rc = copy_from_user(crypto_info, optval, sizeof(*crypto_info));
495 if (rc) {
496 rc = -EFAULT;
497 goto err_crypto_info;
498 }
499
500 /* check version */
501 if (crypto_info->version != TLS_1_2_VERSION &&
502 crypto_info->version != TLS_1_3_VERSION) {
503 rc = -EINVAL;
504 goto err_crypto_info;
505 }
506
507 /* Ensure that TLS version and ciphers are same in both directions */
508 if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) {
509 if (alt_crypto_info->version != crypto_info->version ||
510 alt_crypto_info->cipher_type != crypto_info->cipher_type) {
511 rc = -EINVAL;
512 goto err_crypto_info;
513 }
514 }
515
516 switch (crypto_info->cipher_type) {
517 case TLS_CIPHER_AES_GCM_128:
518 optsize = sizeof(struct tls12_crypto_info_aes_gcm_128);
519 break;
520 case TLS_CIPHER_AES_GCM_256: {
521 optsize = sizeof(struct tls12_crypto_info_aes_gcm_256);
522 break;
523 }
524 case TLS_CIPHER_AES_CCM_128:
525 optsize = sizeof(struct tls12_crypto_info_aes_ccm_128);
526 break;
527 default:
528 rc = -EINVAL;
529 goto err_crypto_info;
530 }
531
532 if (optlen != optsize) {
533 rc = -EINVAL;
534 goto err_crypto_info;
535 }
536
537 rc = copy_from_user(crypto_info + 1, optval + sizeof(*crypto_info),
538 optlen - sizeof(*crypto_info));
539 if (rc) {
540 rc = -EFAULT;
541 goto err_crypto_info;
542 }
543
544 if (tx) {
545 rc = tls_set_device_offload(sk, ctx);
546 conf = TLS_HW;
547 if (!rc) {
548 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXDEVICE);
549 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXDEVICE);
550 } else {
551 rc = tls_set_sw_offload(sk, ctx, 1);
552 if (rc)
553 goto err_crypto_info;
554 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXSW);
555 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXSW);
556 conf = TLS_SW;
557 }
558 } else {
559 rc = tls_set_device_offload_rx(sk, ctx);
560 conf = TLS_HW;
561 if (!rc) {
562 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICE);
563 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXDEVICE);
564 } else {
565 rc = tls_set_sw_offload(sk, ctx, 0);
566 if (rc)
567 goto err_crypto_info;
568 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXSW);
569 TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXSW);
570 conf = TLS_SW;
571 }
572 tls_sw_strparser_arm(sk, ctx);
573 }
574
575 if (tx)
576 ctx->tx_conf = conf;
577 else
578 ctx->rx_conf = conf;
579 update_sk_prot(sk, ctx);
580 if (tx) {
581 ctx->sk_write_space = sk->sk_write_space;
582 sk->sk_write_space = tls_write_space;
583 } else {
584 sk->sk_socket->ops = &tls_sw_proto_ops;
585 }
586 goto out;
587
588 err_crypto_info:
589 memzero_explicit(crypto_info, sizeof(union tls_crypto_context));
590 out:
591 return rc;
592 }
593
594 static int do_tls_setsockopt(struct sock *sk, int optname,
595 char __user *optval, unsigned int optlen)
596 {
597 int rc = 0;
598
599 switch (optname) {
600 case TLS_TX:
601 case TLS_RX:
602 lock_sock(sk);
603 rc = do_tls_setsockopt_conf(sk, optval, optlen,
604 optname == TLS_TX);
605 release_sock(sk);
606 break;
607 default:
608 rc = -ENOPROTOOPT;
609 break;
610 }
611 return rc;
612 }
613
614 static int tls_setsockopt(struct sock *sk, int level, int optname,
615 char __user *optval, unsigned int optlen)
616 {
617 struct tls_context *ctx = tls_get_ctx(sk);
618
619 if (level != SOL_TLS)
620 return ctx->sk_proto->setsockopt(sk, level, optname, optval,
621 optlen);
622
623 return do_tls_setsockopt(sk, optname, optval, optlen);
624 }
625
626 static int tls_compat_setsockopt(struct sock *sk, int level, int optname,
627 char __user *optval, unsigned int optlen)
628 {
629 struct tls_context *ctx = tls_get_ctx(sk);
630
631 if (level != SOL_TLS)
> 632 return ctx->sk_proto->compat_setsockopt(sk, level, optname,
633 optval, optlen);
634
635 return do_tls_setsockopt(sk, optname, optval, optlen);
636 }
637

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (8.02 kB)
.config.gz (34.11 kB)
Download all attachments

2020-08-06 06:43:47

by Rouven Czerwinski

[permalink] [raw]
Subject: Re: [PATCH 1/2] net: tls: add compat for get/setsockopt

On Wed, 2020-08-05 at 17:45 -0700, David Miller wrote:
> Neither of these patches apply cleanly to net-next. The compat handling
> and TLS code has been changed quite a bit lately.

Indeed, Patch 1 is no longer required on net-next. I'll drop the patch.

> ALso, you must provide a proper header "[PATCH 0/N] ..." posting for your
> patch series which explains at a high level what your patch series is doing,
> how it is doing it, and why it is doing it that way.

Since I'm now down to one patch I'll forgo the cover letter and expand
the commit message.

Thanks for the explanation,
Rouven