Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57ebc623 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-sockmap-tls-fixes'



Jakub Kicinski says:

====================
John says:

Resolve a series of splats discovered by syzbot and an unhash
TLS issue noted by Eric Dumazet.

The main issues revolved around interaction between TLS and
sockmap tear down. TLS and sockmap could both reset sk->prot
ops creating a condition where a close or unhash op could be
called forever. A rare race condition resulting from a missing
rcu sync operation was causing a use after free. Then on the
TLS side dropping the sock lock and re-acquiring it during the
close op could hang. Finally, sockmap must be deployed before
tls for current stack assumptions to be met. This is enforced
now. A feature series can enable it.

To fix this first refactor TLS code so the lock is held for the
entire teardown operation. Then add an unhash callback to ensure
TLS can not transition from ESTABLISHED to LISTEN state. This
transition is a similar bug to the one found and fixed previously
in sockmap. Then apply three fixes to sockmap to fix up races
on tear down around map free and close. Finally, if sockmap
is destroyed before TLS we add a new ULP op update to inform
the TLS stack it should not call sockmap ops. This last one
appears to be the most commonly found issue from syzbot.

v4:
 - fix some use after frees;
 - disable disconnect work for offload (ctx lifetime is much
   more complex);
 - remove some of the dead code which made it hard to understand
   (for me) that things work correctly (e.g. the checks TLS is
   the top ULP);
 - add selftets.
====================

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents 1d4126c4 d4d34185
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -513,3 +513,9 @@ Redirects leak clear text

In the RX direction, if segment has already been decrypted by the device
and it gets redirected or mirrored - clear text will be transmitted out.

shutdown() doesn't clear TLS state
----------------------------------

shutdown() system call allows for a TLS socket to be reused as a different
connection. Offload doesn't currently handle that.
+7 −1
Original line number Diff line number Diff line
@@ -354,6 +354,12 @@ static inline void sk_psock_restore_proto(struct sock *sk,
	sk->sk_write_space = psock->saved_write_space;

	if (psock->sk_proto) {
		struct inet_connection_sock *icsk = inet_csk(sk);
		bool has_ulp = !!icsk->icsk_ulp_data;

		if (has_ulp)
			tcp_update_ulp(sk, psock->sk_proto);
		else
			sk->sk_prot = psock->sk_proto;
		psock->sk_proto = NULL;
	}
+3 −0
Original line number Diff line number Diff line
@@ -2103,6 +2103,8 @@ struct tcp_ulp_ops {

	/* initialize ulp */
	int (*init)(struct sock *sk);
	/* update ulp */
	void (*update)(struct sock *sk, struct proto *p);
	/* cleanup ulp */
	void (*release)(struct sock *sk);

@@ -2114,6 +2116,7 @@ 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);
void tcp_update_ulp(struct sock *sk, struct proto *p);

#define MODULE_ALIAS_TCP_ULP(name)				\
	__MODULE_INFO(alias, alias_userspace, name);		\
+11 −4
Original line number Diff line number Diff line
@@ -107,9 +107,7 @@ struct tls_device {
enum {
	TLS_BASE,
	TLS_SW,
#ifdef CONFIG_TLS_DEVICE
	TLS_HW,
#endif
	TLS_HW_RECORD,
	TLS_NUM_CONFIG,
};
@@ -162,6 +160,7 @@ struct tls_sw_context_tx {
	int async_capable;

#define BIT_TX_SCHEDULED	0
#define BIT_TX_CLOSING		1
	unsigned long tx_bitmask;
};

@@ -272,6 +271,8 @@ struct tls_context {
	unsigned long flags;

	/* cache cold stuff */
	struct proto *sk_proto;

	void (*sk_destruct)(struct sock *sk);
	void (*sk_proto_close)(struct sock *sk, long timeout);

@@ -289,6 +290,8 @@ struct tls_context {

	struct list_head list;
	refcount_t refcount;

	struct work_struct gc;
};

enum tls_offload_ctx_dir {
@@ -355,13 +358,17 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
		  unsigned int optlen);

int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx);
void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx);
void tls_sw_strparser_done(struct tls_context *tls_ctx);
int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int tls_sw_sendpage(struct sock *sk, struct page *page,
		    int offset, size_t size, int flags);
void tls_sw_close(struct sock *sk, long timeout);
void tls_sw_free_resources_tx(struct sock *sk);
void tls_sw_cancel_work_tx(struct tls_context *tls_ctx);
void tls_sw_release_resources_tx(struct sock *sk);
void tls_sw_free_ctx_tx(struct tls_context *tls_ctx);
void tls_sw_free_resources_rx(struct sock *sk);
void tls_sw_release_resources_rx(struct sock *sk);
void tls_sw_free_ctx_rx(struct tls_context *tls_ctx);
int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
		   int nonblock, int flags, int *addr_len);
bool tls_sw_stream_read(const struct sock *sk);
+2 −2
Original line number Diff line number Diff line
@@ -585,12 +585,12 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);

void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
{
	rcu_assign_sk_user_data(sk, NULL);
	sk_psock_cork_free(psock);
	sk_psock_zap_ingress(psock);
	sk_psock_restore_proto(sk, psock);

	write_lock_bh(&sk->sk_callback_lock);
	sk_psock_restore_proto(sk, psock);
	rcu_assign_sk_user_data(sk, NULL);
	if (psock->progs.skb_parser)
		sk_psock_stop_strp(sk, psock);
	write_unlock_bh(&sk->sk_callback_lock);
Loading