tcp: ULP infrastructure
Subsystems (7)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v3 1/4 tcp: ULP infrastructure
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.
Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
modules will call:tcp_register_ulp(&tcp_tls_ulp_ops);
to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:
$ cat /proc/sys/net/ipv4/tcp_available_ulp tls
There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
--- include/net/inet_connection_sock.h | 4 ++ include/net/tcp.h | 25 +++++++ include/uapi/linux/tcp.h | 1 + net/ipv4/Makefile | 2 +- net/ipv4/sysctl_net_ipv4.c | 25 +++++++ net/ipv4/tcp.c | 28 ++++++++ net/ipv4/tcp_ipv4.c | 2 + net/ipv4/tcp_ulp.c | 134 +++++++++++++++++++++++++++++++++++++ 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 net/ipv4/tcp_ulp.c
include/net/inet_connection_sock.h +4 -0
@@ -75,6 +75,8 @@ struct inet_connection_sock_af_ops {* @icsk_pmtu_cookie Last pmtu seen by socket * @icsk_ca_ops Pluggable congestion control hook * @icsk_af_ops Operations which are AF_INET{4,6} specific +* @icsk_ulp_ops Pluggable ULP control hook +* @icsk_ulp_data ULP private data * @icsk_ca_state: Congestion control state * @icsk_retransmits: Number of unrecovered [RTO] timeouts * @icsk_pending: Scheduled timer event
@@ -97,6 +99,8 @@ struct inet_connection_sock {__u32 icsk_pmtu_cookie;const struct tcp_congestion_ops *icsk_ca_ops;const struct inet_connection_sock_af_ops *icsk_af_ops; +const struct tcp_ulp_ops *icsk_ulp_ops; +void *icsk_ulp_data;unsigned int (*icsk_sync_mss)(struct sock *sk,u32 pmtu); __u8 icsk_ca_state:6, icsk_ca_setsockopt:1,
include/net/tcp.h +25 -0
@@ -1991,4 +1991,29 @@ static inline void tcp_listendrop(const struct sock *sk)enum hrtimer_restart tcp_pace_kick (struct hrtimer *timer); +/* +* Interface for adding Upper Level Protocols over TCP +*/ + +#define TCP_ULP_NAME_MAX 16 +#define TCP_ULP_MAX 128 +#define TCP_ULP_BUF_MAX (TCP_ULP_NAME_MAX*TCP_ULP_MAX) + +struct tcp_ulp_ops { +struct list_head list; + +/* initialize ulp */ +int (*init)(struct sock *sk); +/* cleanup ulp */ +void (*release)(struct sock *sk); + +char name[TCP_ULP_NAME_MAX ]; +struct module *owner; +}; +int tcp_register_ulp (struct tcp_ulp_ops *type); +void tcp_unregister_ulp (struct tcp_ulp_ops *type); +int tcp_set_ulp (struct sock *sk,const char *name); +void tcp_get_available_ulp (char *buf,size_t len); +void tcp_cleanup_ulp (struct sock *sk); +#endif /* _TCP_H */
include/uapi/linux/tcp.h +1 -0
@@ -117,6 +117,7 @@ enum {#define TCP_SAVED_SYN 28/* Get SYN headers recorded for connection */ #define TCP_REPAIR_WINDOW 29/* Get/set window parameters */ #define TCP_FASTOPEN_CONNECT 30/* Attempt FastOpen with connect */ +#define TCP_ULP 31/* Attach a ULP to a TCP connection */ struct tcp_repair_opt {__u32 opt_code;
net/ipv4/Makefile +1 -1
@@ -8,7 +8,7 @@ obj-y := route.o inetpeer.o protocol.o \ inet_timewait_sock.o inet_connection_sock.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \ - tcp_rate.o tcp_recovery.o \ + tcp_rate.o tcp_recovery.o tcp_ulp.o \ tcp_offload.o datagram.o raw.o udp.o udplite.o \ udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o fib_notifier.o \
net/ipv4/sysctl_net_ipv4.c +25 -0
@@ -360,6 +360,25 @@ static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table, ret =proc_dointvec_minmax (table, write, buffer, lenp, ppos);if (write && ret ==0 )tcp_fastopen_active_timeout_reset (); + +return ret; +} + +static int proc_tcp_available_ulp (struct ctl_table *ctl, +int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +struct ctl_table tbl = { .maxlen =TCP_ULP_BUF_MAX , }; +int ret; + + tbl.data =kmalloc (tbl.maxlen,GFP_USER ); +if (!tbl.data) +return -ENOMEM ; +tcp_get_available_ulp (tbl.data,TCP_ULP_BUF_MAX ); + ret =proc_dostring (&tbl, write, buffer, lenp, ppos); +kfree (tbl.data); +return ret; }
@@ -686,6 +705,12 @@ static struct ctl_table ipv4_table[] = { .proc_handler = proc_dointvec_ms_jiffies, }, { + .procname = "tcp_available_ulp", + .maxlen = TCP_ULP_BUF_MAX, + .mode = 0444, + .proc_handler = proc_tcp_available_ulp, + }, + { .procname = "icmp_msgs_per_sec", .data = &sysctl_icmp_msgs_per_sec, .maxlen = sizeof(int),
net/ipv4/tcp.c +28 -0
@@ -2482,6 +2482,24 @@ static int do_tcp_setsockopt(struct sock *sk, int level,release_sock (sk);return err; } +case TCP_ULP : { +char name[TCP_ULP_NAME_MAX ]; + +if (optlen <1 ) +return -EINVAL ; + + val =strncpy_from_user (name, optval, +min_t (long,TCP_ULP_NAME_MAX -1 , + optlen)); +if (val <0 ) +return -EFAULT ; + name[val] =0 ; + +lock_sock (sk); + err =tcp_set_ulp (sk, name); +release_sock (sk); +return err; + }default :/* fallthru */ break ;
@@ -3038,6 +3056,16 @@ static int do_tcp_getsockopt(struct sock *sk, int level,return -EFAULT ;return 0 ; +case TCP_ULP : +if (get_user (len, optlen)) +return -EFAULT ; + len = min_t(unsigned int, len, TCP_ULP_NAME_MAX); +if (put_user (len, optlen)) +return -EFAULT ; +if (copy_to_user (optval, icsk->icsk_ulp_ops->name, len)) +return -EFAULT ; +return 0 ; +case TCP_THIN_LINEAR_TIMEOUTS : val = tp->thin_lto;break ;
net/ipv4/tcp_ipv4.c +2 -0
@@ -1860,6 +1860,8 @@ void tcp_v4_destroy_sock(struct sock *sk)tcp_cleanup_congestion_control (sk); +tcp_cleanup_ulp (sk); +/* Cleanup up the write buffer. */ tcp_write_queue_purge (sk);
net/ipv4/tcp_ulp.c new file +134 -0
134 lines not on this page · raw message
Signature · 1 line
2.9.3
Hello,
Quoted 25 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by
tcp_get_available_ulp, which is hooked up to /proc. Example:$ cat /proc/sys/net/ipv4/tcp_available_ulp tlsThere is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
Signed-off-by Boris Pismenny <[email protected]>Signed-off-by Dave Watson <[email protected]>
Quoted 11 lines
--- include/net/inet_connection_sock.h | 4 ++ include/net/tcp.h | 25 +++++++ include/uapi/linux/tcp.h | 1 + net/ipv4/Makefile | 2 +- net/ipv4/sysctl_net_ipv4.c | 25 +++++++ net/ipv4/tcp.c | 28 ++++++++ net/ipv4/tcp_ipv4.c | 2 + net/ipv4/tcp_ulp.c | 134 +++++++++++++++++++++++++++++++++++++ 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 net/ipv4/tcp_ulp.c
I know I'm pretty late to the game (and maybe this has already been discussed but I couldn't find anything in the archives), but I am wondering what the take is on potential races of the setsockopt() vs other system-calls.
For example one might race the setsockopt() with a sendmsg() and the sendmsg might end up blocking on the lock_sock in tcp_sendmsg, waiting for tcp_set_ulp() to finish changing sk_prot. When the setsockopt() finishes, we are then inside tcp_sendmsg() coming directly from sendmsg(), while we should have been in the ULP's sendmsg.
It seems like TLS-ULP is resilient to this (or at least, won't cause a panic), but there might be more exotic users of ULP in the future, that change other callbacks and then things might go wrong.
Thoughts?
Thanks,
Christoph
Quoted 50 lines · Christoph Paasch
Hello,
Quoted 25 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by
tcp_get_available_ulp, which is hooked up to /proc. Example:$ cat /proc/sys/net/ipv4/tcp_available_ulp tlsThere is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
Signed-off-by Boris Pismenny <[email protected]>Signed-off-by Dave Watson <[email protected]>Quoted 11 lines
--- include/net/inet_connection_sock.h | 4 ++ include/net/tcp.h | 25 +++++++ include/uapi/linux/tcp.h | 1 + net/ipv4/Makefile | 2 +- net/ipv4/sysctl_net_ipv4.c | 25 +++++++ net/ipv4/tcp.c | 28 ++++++++ net/ipv4/tcp_ipv4.c | 2 + net/ipv4/tcp_ulp.c | 134 +++++++++++++++++++++++++++++++++++++ 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 net/ipv4/tcp_ulp.cI know I'm pretty late to the game (and maybe this has already been discussed but I couldn't find anything in the archives), but I am wondering what the take is on potential races of the
setsockopt()vs other system-calls.For example one might race the
setsockopt()with asendmsg()and the sendmsg might end up blocking on thelock_sockintcp_sendmsg, waiting fortcp_set_ulp()to finish changingsk_prot. When thesetsockopt()finishes, we are then insidetcp_sendmsg()coming directly fromsendmsg(), while we should have been in the ULP's sendmsg.
Quoted 3 lines
It seems like TLS-ULP is resilient to this (or at least, won't cause a panic), but there might be more exotic users of ULP in the future, that change other callbacks and then things might go wrong.
Christoph,
I noticed this also. I think the easiest answer would be to just assume the caller understands the race condition and can synchronize itself. Other than that we'd probably have wake up everyone blocking on the socket without something like EAGAIN so they're forced to retry the operation. But even that might not easily yield an obvious point at which the socket can be safely changed.
Tom
Quoted 8 lines
Thoughts?
Thanks,
Christoph
Quoted 17 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by
tcp_get_available_ulp, which is hooked up to /proc. Example:
Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp tlsThere is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
Signed-off-by Boris Pismenny <[email protected]>Signed-off-by Dave Watson <[email protected]>
Hey Dave,
I'm seeing the following while fuzzing, which was bisected to this commit:
==================================================================
BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline] BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057 Read of size 4 at addr 0000000000000020 by task syz-executor1/15452 CPU: 0 PID: 15452 Comm: syz-executor1 Not tainted 4.12.0-rc6-next-20170623+ #173 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:16 [inline] dump_stack+0x11d/0x1e5 lib/dump_stack.c:52 kasan_report_error mm/kasan/report.c:349 [inline] kasan_report+0x15e/0x370 mm/kasan/report.c:408 check_memory_region_inline mm/kasan/kasan.c:260 [inline] check_memory_region+0x14b/0x1a0 mm/kasan/kasan.c:267 kasan_check_read+0x11/0x20 mm/kasan/kasan.c:272 copy_to_user include/linux/uaccess.h:168 [inline] do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057 tcp_getsockopt+0xb0/0xd0 net/ipv4/tcp.c:3194 sock_common_getsockopt+0x95/0xd0 net/core/sock.c:2863 SYSC_getsockopt net/socket.c:1869 [inline] SyS_getsockopt+0x180/0x360 net/socket.c:1851 do_syscall_64+0x267/0x740 arch/x86/entry/common.c:284 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x451759 RSP: 002b:00007f5dc2b1fc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000037 RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451759 RDX: 000000000000001f RSI: 0000000000000006 RDI: 0000000000000005 RBP: 0000000000000c30 R08: 00000000207bf000 R09: 0000000000000000 R10: 0000000020000ffc R11: 0000000000000216 R12: 00000000004b824b R13: 00000000ffffffff R14: 0000000000000005 R15: 0000000000000006 ================================================================== Disabling lock debugging due to kernel taint Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 15452 Comm: syz-executor1 Tainted: G B 4.12.0-rc6-next-20170623+ #173 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:16 [inline] dump_stack+0x11d/0x1e5 lib/dump_stack.c:52 panic+0x1bc/0x3ad kernel/panic.c:180 kasan_end_report+0x47/0x4f mm/kasan/report.c:176 kasan_report_error mm/kasan/report.c:356 [inline] kasan_report+0x167/0x370 mm/kasan/report.c:408 check_memory_region_inline mm/kasan/kasan.c:260 [inline] check_memory_region+0x14b/0x1a0 mm/kasan/kasan.c:267 kasan_check_read+0x11/0x20 mm/kasan/kasan.c:272 copy_to_user include/linux/uaccess.h:168 [inline] do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057 tcp_getsockopt+0xb0/0xd0 net/ipv4/tcp.c:3194 sock_common_getsockopt+0x95/0xd0 net/core/sock.c:2863 SYSC_getsockopt net/socket.c:1869 [inline] SyS_getsockopt+0x180/0x360 net/socket.c:1851 do_syscall_64+0x267/0x740 arch/x86/entry/common.c:284 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x451759 RSP: 002b:00007f5dc2b1fc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000037 RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451759 RDX: 000000000000001f RSI: 0000000000000006 RDI: 0000000000000005 RBP: 0000000000000c30 R08: 00000000207bf000 R09: 0000000000000000 R10: 0000000020000ffc R11: 0000000000000216 R12: 00000000004b824b R13: 00000000ffffffff R14: 0000000000000005 R15: 0000000000000006
Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: 0x24800000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) Rebooting in 86400 seconds..
Signature · 2 lines
Thanks, Sasha
Quoted 27 lines · Alexander (Sasha Levin)
Quoted 17 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by
tcp_get_available_ulp, which is hooked up to /proc. Example:Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp tlsThere is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
Signed-off-by Boris Pismenny <[email protected]>Signed-off-by Dave Watson <[email protected]>
Quoted 8 lines
Hey Dave,
I'm seeing the following while fuzzing, which was bisected to this commit:
==================================================================
BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline] BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057 Read of size 4 at addr 0000000000000020 by task syz-executor1/15452
At a glance, this looks like it was fixed already by
https://www.mail-archive.com/[email protected]/msg175226.html
Can you recheck with that patch, or verify that you already have it? Thanks.
Quoted 37 lines · Dave Watson
Quoted 27 lines · Alexander (Sasha Levin)
Quoted 17 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);to register/unregister their ulp, with an init function and name.
A list of registered ulps will be returned by
tcp_get_available_ulp, which is hooked up to /proc. Example:Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp tlsThere is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.
Signed-off-by Boris Pismenny <[email protected]>Signed-off-by Dave Watson <[email protected]>Quoted 8 lines
Hey Dave,
I'm seeing the following while fuzzing, which was bisected to this commit:
==================================================================
BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline] BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057 Read of size 4 at addr 0000000000000020 by task syz-executor1/15452
Quoted 6 lines
At a glance, this looks like it was fixed already by
https://www.mail-archive.com/[email protected]/msg175226.html
Can you recheck with that patch, or verify that you already have it? Thanks.
I've already tried this patch, it doesn't fix the issue I've reported.
Signature · 2 lines
Thanks, Sasha
Quoted 9 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
Hi Dave,
Thanks for this work. I think this functionality is going to have many uses!
One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:
setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));
Where ulp_param is a structure containing the ULP name as well as some ULP specific parameters that are passed to init_ulp. ulp_init could determine whether the socket family is appropriate for the ULP being requested.
Thanks,
Tom
Quoted 14 lines · Tom Herbert
Quoted 9 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:
Quoted 6 lines
setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));Where
ulp_paramis a structure containing the ULP name as well as some ULP specific parameters that are passed toinit_ulp.ulp_initcould determine whether the socket family is appropriate for the ULP being requested.
Using SOL_SOCKET instead seems reasonable to me. I can see how ulp_params could have some use, perhaps at a slight loss in clarity. TLS needs its own setsockopts anyway though, for renegotiate for example.
Quoted 22 lines · Dave Watson
Quoted 14 lines · Tom Herbert
Quoted 9 lines · Dave Watson
Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in
tcp_cong. The idea is that any ULP can add its own logic by changing the TCPproto_opsstructure to its own methods.Example usage:
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:
Quoted 6 lines
setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));Where
ulp_paramis a structure containing the ULP name as well as some ULP specific parameters that are passed toinit_ulp.ulp_initcould determine whether the socket family is appropriate for the ULP being requested.
Quoted 4 lines
Using
SOL_SOCKETinstead seems reasonable to me. I can see howulp_paramscould have some use, perhaps at a slight loss in clarity. TLS needs its own setsockopts anyway though, for renegotiate for example.
I'll post the changes shortly. The reason to include parameters with the setsockopt is so that we can push the ULP and start operations in one shot.
Tom
PATCH v3 2/4 tcp: export do_tcp_sendpages and tcp_rate_check_app_limited functions
In reply to a message not in the archiveExport do_tcp_sendpages and tcp_rate_check_app_limited, since tls will need to sendpages while the socket is already locked.
tcp_sendpage is exported, but requires the socket lock to not be held already.
--- include/net/tcp.h | 2 ++ net/ipv4/tcp.c | 5 +++-- net/ipv4/tcp_rate.c | 1 + 3 files changed, 6 insertions(+), 2 deletions(-)
include/net/tcp.h +2 -0
@@ -350,6 +350,8 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);int tcp_sendmsg (struct sock *sk,struct msghdr *msg,size_t size);int tcp_sendpage (struct sock *sk,struct page *page,int offset,size_t size,int flags); +ssize_t do_tcp_sendpages (struct sock *sk,struct page *page,int offset, +size_t size,int flags);void tcp_release_cb (struct sock *sk);void tcp_wfree (struct sk_buff *skb);void tcp_write_timer_handler (struct sock *sk);
net/ipv4/tcp.c +3 -2
@@ -901,8 +901,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)return mss_now; } -static ssize_t do_tcp_sendpages (struct sock *sk,struct page *page,int offset, -size_t size,int flags) +ssize_t do_tcp_sendpages (struct sock *sk,struct page *page,int offset, +size_t size,int flags) {struct tcp_sock *tp =tcp_sk (sk);int mss_now, size_goal;
@@ -1032,6 +1032,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, }return sk_stream_error (sk, flags, err); } +EXPORT_SYMBOL_GPL (do_tcp_sendpages);int tcp_sendpage (struct sock *sk,struct page *page,int offset,size_t size,int flags)
net/ipv4/tcp_rate.c +1 -0
@@ -185,3 +185,4 @@ void tcp_rate_check_app_limited(struct sock *sk) tp->app_limited = (tp->delivered +tcp_packets_in_flight (tp)) ? :1 ; } +EXPORT_SYMBOL_GPL (tcp_rate_check_app_limited);
Signature · 1 line
2.9.3
PATCH v3 3/4 tls: kernel TLS support
In reply to a message not in the archiveSoftware implementation of transport layer security, implemented using ULP infrastructure. tcp proto_ops are replaced with tls equivalents of sendmsg and sendpage.
Only symmetric crypto is done in the kernel, keys are passed by setsockopt after the handshake is complete. All control messages are supported via CMSG data - the actual symmetric encryption is the same, just the message type needs to be passed separately.
For user API, please see Documentation patch.
Pieces that can be shared between hw and sw implementation are in tls_main.c
--- MAINTAINERS | 10 + include/linux/socket.h | 1 + include/net/tls.h | 237 +++++++++++++++ include/uapi/linux/tls.h | 79 +++++ net/Kconfig | 1 + net/Makefile | 1 + net/tls/Kconfig | 12 + net/tls/Makefile | 7 + net/tls/tls_main.c | 487 ++++++++++++++++++++++++++++++ net/tls/tls_sw.c | 772 +++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 1607 insertions(+) create mode 100644 include/net/tls.h create mode 100644 include/uapi/linux/tls.h create mode 100644 net/tls/Kconfig create mode 100644 net/tls/Makefile create mode 100644 net/tls/tls_main.c create mode 100644 net/tls/tls_sw.c
MAINTAINERS +10 -0
@@ -8979,6 +8979,16 @@ F: net/ipv6/ F: include/net/ip* F: arch/x86/net/* +NETWORKING [TLS] +M: Ilya Lesokhin <[email protected]> +M: Aviad Yehezkel <[email protected]> +M: Dave Watson <[email protected]> +L: [email protected] +S: Maintained +F: net/tls/* +F: include/uapi/linux/tls.h +F: include/net/tls.h + NETWORKING [IPSEC] M: Steffen Klassert <[email protected]> M: Herbert Xu <[email protected]>
include/linux/socket.h +1 -0
@@ -334,6 +334,7 @@ struct ucred {#define SOL_ALG 279#define SOL_NFC 280#define SOL_KCM 281 +#define SOL_TLS 282/* IPX options */ #define IPX_TYPE 1
include/net/tls.h new file +237 -0
237 lines not on this page · raw message
include/uapi/linux/tls.h new file +79 -0
79 lines not on this page · raw message
net/Kconfig +1 -0
@@ -55,6 +55,7 @@ menu "Networking options" source "net/packet/Kconfig" source "net/unix/Kconfig" +source "net/tls/Kconfig" source "net/xfrm/Kconfig" source "net/iucv/Kconfig" source "net/smc/Kconfig"
net/Makefile +1 -0
@@ -15,6 +15,7 @@ obj-$(CONFIG_LLC) += llc/ obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ bpf/ obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_INET) += ipv4/ +obj-$(CONFIG_TLS) += tls/ obj-$(CONFIG_XFRM) += xfrm/ obj-$(CONFIG_UNIX) += unix/ obj-$(CONFIG_NET) += ipv6/
net/tls/Kconfig new file +12 -0
@@ -0,0 +1,12 @@ +# +# TLS configuration +# +config TLS + tristate "Transport Layer Security support" + depends on NET + default m + ---help--- + Enable kernel support for TLS protocol. This allows symmetric + encryption handling of the TLS protocol to be done in-kernel. + + If unsure, say M.
net/tls/Makefile new file +7 -0
@@ -0,0 +1,7 @@ +# +# Makefile for the TLS subsystem. +# + +obj-$(CONFIG_TLS) += tls.o + +tls-y := tls_main.o tls_sw.o
net/tls/tls_main.c new file +487 -0
487 lines not on this page · raw message
net/tls/tls_sw.c new file +772 -0
772 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
Quoted 10 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
include/net/tls.h new file +10
-0+ +static inline struct tls_context *tls_get_ctx (const struct sock *sk) +{ +struct inet_connection_sock *icsk =inet_csk (sk); + +return icsk->icsk_ulp_data; +} + +static inline struct tls_sw_context *tls_sw_ctx ( +const struct tls_context *tls_ctx)
include/net/tls.h line 233
Quoted 10 lines
include/net/tls.h new file +10
-0+{ +return (struct tls_sw_context *)tls_ctx->priv_ctx; +} + +static inline struct tls_offload_context *tls_offload_ctx ( +const struct tls_context *tls_ctx) +{ +return (struct tls_offload_context *)tls_ctx->priv_ctx; +} +
Since priv_ctx is void *, casts here are unnecessary.
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
In reply to Dave WatsonQuoted 5 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
net/tls/Kconfig new file +2
-0@@ -0,0 +1,12 @@ +# +# TLS configuration
net/tls/Kconfig line 12
Quoted 10 lines
net/tls/Kconfig new file +10
-0+# +config TLS + tristate "Transport Layer Security support" + depends on NET + default m + ---help--- + Enable kernel support for TLS protocol. This allows symmetric + encryption handling of the TLS protocol to be done in-kernel. + + If unsure, say M.
I understand that this will be useful to lots of people and most distributions will enable it. But the defacto policy in kernel configuration has been that new features in kernel default to being disabled.
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
Quoted 14 lines · Stephen Hemminger
Quoted 11 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
net/tls/Kconfig new file +8
-0@@ -0,0 +1,12 @@ +# +# TLS configuration +# +config TLS + tristate "Transport Layer Security support" + depends on NET + default m + ---help---
Quoted 8 lines
net/tls/Kconfig line 12
Quoted 4 lines
net/tls/Kconfig new file +4
-0+ Enable kernel support for TLS protocol. This allows symmetric + encryption handling of the TLS protocol to be done in-kernel. + + If unsure, say M.I understand that this will be useful to lots of people and most distributions will enable it. But the defacto policy in kernel configuration has been that new features in kernel default to being disabled.
Sure, will send a patch to switch to default n.
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
In reply to Dave WatsonSorry for replying to old mail...
Quoted 28 lines · Dave Watson
net/tls/tls_sw.c new file +28
-0+static int tls_do_encryption (struct tls_context *tls_ctx, +struct tls_sw_context *ctx,size_t data_len, +gfp_t flags) +{ +unsigned int req_size =sizeof (struct aead_request ) + +crypto_aead_reqsize (ctx->aead_send); +struct aead_request *aead_req; +int rc; + + aead_req =kmalloc (req_size, flags); +if (!aead_req) +return -ENOMEM ; + + ctx->sg_encrypted_data[0 ].offset += tls_ctx->prepend_size; + ctx->sg_encrypted_data[0 ].length -= tls_ctx->prepend_size; + +aead_request_set_tfm (aead_req, ctx->aead_send); +aead_request_set_ad (aead_req,TLS_AAD_SPACE_SIZE ); +aead_request_set_crypt (aead_req, ctx->sg_aead_in, ctx->sg_aead_out, + data_len, tls_ctx->iv); + rc =crypto_aead_encrypt (aead_req); + + ctx->sg_encrypted_data[0 ].offset -= tls_ctx->prepend_size; + ctx->sg_encrypted_data[0 ].length += tls_ctx->prepend_size; + +kfree (aead_req); +return rc; +}
...
Quoted 2 lines
net/tls/tls_sw.c new file +2
-0+int tls_set_sw_offload (struct sock *sk,struct tls_context *ctx) +{
...
net/tls/tls_sw.c line 747
Quoted 10 lines
net/tls/tls_sw.c new file +10
-0+ +if (!sw_ctx->aead_send) { + sw_ctx->aead_send =crypto_alloc_aead ("gcm(aes)" ,0 ,0 ); +if (IS_ERR (sw_ctx->aead_send)) { + rc =PTR_ERR (sw_ctx->aead_send); + sw_ctx->aead_send =NULL ; + goto free_rec_seq; + } + } +
When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.
Otherwise you will crash on an asynchronous crypto return, no?
Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
Quoted 21 lines · Steffen Klassert
Sorry for replying to old mail...
Quoted 2 lines
net/tls/tls_sw.c new file +2
-0+int tls_set_sw_offload (struct sock *sk,struct tls_context *ctx) +{...
net/tls/tls_sw.c line 747
Quoted 10 lines
net/tls/tls_sw.c new file +10
-0+ +if (!sw_ctx->aead_send) { + sw_ctx->aead_send =crypto_alloc_aead ("gcm(aes)" ,0 ,0 ); +if (IS_ERR (sw_ctx->aead_send)) { + rc =PTR_ERR (sw_ctx->aead_send); + sw_ctx->aead_send =NULL ; + goto free_rec_seq; + } + } +When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with
aead_request_set_callback(), or request for a synchronous algorithm.
Quoted 1 line
Otherwise you will crash on an asynchronous crypto return, no?
The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC) is the correct way to request synchronous algorithms only?
Quoted 2 lines
Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?
We hold the socket lock and only one crypto op can happen at a time, so we reuse the scatterlists.
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
Quoted 22 lines · Dave Watson
Quoted 21 lines · Steffen Klassert
Sorry for replying to old mail...
Quoted 2 lines
net/tls/tls_sw.c new file +2
-0+int tls_set_sw_offload (struct sock *sk,struct tls_context *ctx) +{...
net/tls/tls_sw.c line 747
Quoted 10 lines
net/tls/tls_sw.c new file +10
-0+ +if (!sw_ctx->aead_send) { + sw_ctx->aead_send =crypto_alloc_aead ("gcm(aes)" ,0 ,0 ); +if (IS_ERR (sw_ctx->aead_send)) { + rc =PTR_ERR (sw_ctx->aead_send); + sw_ctx->aead_send =NULL ; + goto free_rec_seq; + } + } +When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with
aead_request_set_callback(), or request for a synchronous algorithm.
Quoted 7 lines
Quoted 1 line
Otherwise you will crash on an asynchronous crypto return, no?
The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling
crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC)is the correct way to request synchronous algorithms only?
Yes, that means the CRYPTO_ALG_ASYNC bit is required to be 0, i.e. the algorithm must be synchronous. Currently it's requesting either a synchronous or asynchronous algorithm, and it will crash if it gets an async one.
Also I think even with a synchronous algorithm, tls_do_encryption() still needs to call aead_request_set_callback(), passing NULL for the callback and data, so that the request flags are initialized.
Eric
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
In reply to Dave WatsonQuoted 22 lines · Dave Watson
Quoted 21 lines · Steffen Klassert
Sorry for replying to old mail...
Quoted 2 lines
net/tls/tls_sw.c new file +2
-0+int tls_set_sw_offload (struct sock *sk,struct tls_context *ctx) +{...
net/tls/tls_sw.c line 747
Quoted 10 lines
net/tls/tls_sw.c new file +10
-0+ +if (!sw_ctx->aead_send) { + sw_ctx->aead_send =crypto_alloc_aead ("gcm(aes)" ,0 ,0 ); +if (IS_ERR (sw_ctx->aead_send)) { + rc =PTR_ERR (sw_ctx->aead_send); + sw_ctx->aead_send =NULL ; + goto free_rec_seq; + } + } +When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with
aead_request_set_callback(), or request for a synchronous algorithm.
Quoted 6 lines
Quoted 1 line
Otherwise you will crash on an asynchronous crypto return, no?
The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling
crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC)is the correct way to request synchronous algorithms only?
Yes, but then you loose the aes-ni based algorithms because they are asynchronous. If you want to have good crypto performance, it is better to implement the asynchronous callbacks.
Quoted 6 lines
Quoted 3 lines
Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?
We hold the socket lock and only one crypto op can happen at a time, so we reuse the scatterlists.
This is OK as long as the crypto happens synchronous. But as said above, I think this is not what you want.
Re: [PATCH v3 net-next 3/4] tls: kernel TLS support
Quoted 25 lines · Steffen Klassert
Quoted 24 lines · Dave Watson
Quoted 22 lines · Steffen Klassert
Sorry for replying to old mail...
Quoted 2 lines
net/tls/tls_sw.c new file +2
-0+int tls_set_sw_offload (struct sock *sk,struct tls_context *ctx) +{...
net/tls/tls_sw.c line 747
Quoted 10 lines
net/tls/tls_sw.c new file +10
-0+ +if (!sw_ctx->aead_send) { + sw_ctx->aead_send =crypto_alloc_aead ("gcm(aes)" ,0 ,0 ); +if (IS_ERR (sw_ctx->aead_send)) { + rc =PTR_ERR (sw_ctx->aead_send); + sw_ctx->aead_send =NULL ; + goto free_rec_seq; + } + } +When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with
aead_request_set_callback(), or request for a synchronous algorithm.Otherwise you will crash on an asynchronous crypto return, no?
Quoted 8 lines
Quoted 4 lines
The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling
crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC)is the correct way to request synchronous algorithms only?Yes, but then you loose the aes-ni based algorithms because they are asynchronous. If you want to have good crypto performance, it is better to implement the asynchronous callbacks.
Right, the trick is we want both aesni, and to guarantee that we are done using the input buffers before sendmsg() returns. For now I can set a callback, and wait on a completion. The initial use case of userspace openssl integration shouldn't hit the aesni async case anyway (!irq_fpu_usable())
PATCH v3 4/4 tls: Documentation
In reply to a message not in the archiveAdd documentation for the tcp ULP tls interface.
--- Documentation/networking/tls.txt | 135 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 Documentation/networking/tls.txt
Documentation/networking/tls.txt new file +135 -0
@@ -0,0 +1,135 @@ +Overview +======== + +Transport Layer Security (TLS) is a Upper Layer Protocol (ULP) that runs over +TCP. TLS provides end-to-end data integrity and confidentiality. + +User interface +============== + +Creating a TLS connection +------------------------- + +First create a new TCP socket and set the TLS ULP. + + sock = socket(AF_INET, SOCK_STREAM, 0); + setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")); + +Setting the TLS ULP allows us to set/get TLS socket options. Currently +only the symmetric encryption is handled in the kernel. After the TLS +handshake is complete, we have all the parameters required to move the +data-path to the kernel. There is a separate socket option for moving +the transmit and the receive into the kernel. + + /* From linux/tls.h */ + struct tls_crypto_info { + unsigned short version; + unsigned short cipher_type; + }; + + struct tls12_crypto_info_aes_gcm_128 { + struct tls_crypto_info info; + unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE]; + unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE]; + unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE]; + unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + }; + + + struct tls12_crypto_info_aes_gcm_128 crypto_info; + + crypto_info.info.version = TLS_1_2_VERSION; + crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; + memcpy(crypto_info.iv, iv_write, TLS_CIPHER_AES_GCM_128_IV_SIZE); + memcpy(crypto_info.rec_seq, seq_number_write, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(crypto_info.key, cipher_key_write, TLS_CIPHER_AES_GCM_128_KEY_SIZE); + memcpy(crypto_info.salt, implicit_iv_write, TLS_CIPHER_AES_GCM_128_SALT_SIZE); + + setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)); + +Sending TLS application data +---------------------------- + +After setting the TLS_TX socket option all application data sent over this +socket is encrypted using TLS and the parameters provided in the socket option. +For example, we can send an encrypted hello world record as follows: + + const char *msg = "hello world\n"; + send(sock, msg, strlen(msg)); + +send() data is directly encrypted from the userspace buffer provided +to the encrypted kernel send buffer if possible. + +The sendfile system call will send the file's data over TLS records of maximum +length (2^14). + + file = open(filename, O_RDONLY); + fstat(file, &stat); + sendfile(sock, file, &offset, stat.st_size); + +TLS records are created and sent after each send() call, unless +MSG_MORE is passed. MSG_MORE will delay creation of a record until +MSG_MORE is not passed, or the maximum record size is reached. + +The kernel will need to allocate a buffer for the encrypted data. +This buffer is allocated at the time send() is called, such that +either the entire send() call will return -ENOMEM (or block waiting +for memory), or the encryption will always succeed. If send() returns +-ENOMEM and some data was left on the socket buffer from a previous +call using MSG_MORE, the MSG_MORE data is left on the socket buffer. + +Send TLS control messages +------------------------- + +Other than application data, TLS has control messages such as alert +messages (record type 21) and handshake messages (record type 22), etc. +These messages can be sent over the socket by providing the TLS record type +via a CMSG. For example the following function sends @data of @length bytes +using a record of type @record_type. + +/* send TLS control message using record_type */ + static int klts_send_ctrl_message(int sock, unsigned char record_type, + void *data, size_t length) + { + struct msghdr msg = {0}; + int cmsg_len = sizeof(record_type); + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(cmsg_len)]; + struct iovec msg_iov; /* Vector of data to send/receive into. */ + + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_TLS; + cmsg->cmsg_type = TLS_SET_RECORD_TYPE; + cmsg->cmsg_len = CMSG_LEN(cmsg_len); + *CMSG_DATA(cmsg) = record_type; + msg.msg_controllen = cmsg->cmsg_len; + + msg_iov.iov_base = data; + msg_iov.iov_len = length; + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + return sendmsg(sock, &msg, 0); + } + +Control message data should be provided unencrypted, and will be +encrypted by the kernel. + +Integrating in to userspace TLS library +--------------------------------------- + +At a high level, the kernel TLS ULP is a replacement for the record +layer of a userspace TLS library. + +A patchset to OpenSSL to use ktls as the record layer is here: + +https://github.com/Mellanox/tls-openssl + +An example of calling send directly after a handshake using +gnutls. Since it doesn't implement a full record layer, control +messages are not supported: + +https://github.com/Mellanox/tls-af_ktls_tool
Signature · 1 line
2.9.3