Commit 1de5900c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'bug-fixes-for-net-handshake'

Chuck Lever says:

====================
Bug fixes for net/handshake

Paolo observed that there is a possible leak of sock->file. I
haven't looked into that yet, but it seems to be separate from
the fixes in this series, so no need to hold these up.
====================

The submissions mentions net-next but it means netdev (perhaps
merge window left over when trees are converged). In any case,
it should have gone into net, but was instead applied to net-next
as commit deb2e484 ("Merge branch 'net-handshake-fixes'").
These are fixes tho, and Chuck needs them to make progress with
the client so double-merging them into net... it is what it is :(

Link: https://lore.kernel.org/r/168381978252.84244.1933636428135211300.stgit@91.116.238.104.host.secureserver.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0c615f1c 26fb5480
...@@ -68,6 +68,9 @@ attribute-sets: ...@@ -68,6 +68,9 @@ attribute-sets:
type: nest type: nest
nested-attributes: x509 nested-attributes: x509
multi-attr: true multi-attr: true
-
name: peername
type: string
- -
name: done name: done
attributes: attributes:
...@@ -105,6 +108,7 @@ operations: ...@@ -105,6 +108,7 @@ operations:
- auth-mode - auth-mode
- peer-identity - peer-identity
- certificate - certificate
- peername
- -
name: done name: done
doc: Handler reports handshake completion doc: Handler reports handshake completion
......
...@@ -53,6 +53,7 @@ fills in a structure that contains the parameters of the request: ...@@ -53,6 +53,7 @@ fills in a structure that contains the parameters of the request:
struct socket *ta_sock; struct socket *ta_sock;
tls_done_func_t ta_done; tls_done_func_t ta_done;
void *ta_data; void *ta_data;
const char *ta_peername;
unsigned int ta_timeout_ms; unsigned int ta_timeout_ms;
key_serial_t ta_keyring; key_serial_t ta_keyring;
key_serial_t ta_my_cert; key_serial_t ta_my_cert;
...@@ -71,6 +72,10 @@ instantiated a struct file in sock->file. ...@@ -71,6 +72,10 @@ instantiated a struct file in sock->file.
has completed. Further explanation of this function is in the "Handshake has completed. Further explanation of this function is in the "Handshake
Completion" sesction below. Completion" sesction below.
The consumer can provide a NUL-terminated hostname in the @ta_peername
field that is sent as part of ClientHello. If no peername is provided,
the DNS hostname associated with the server's IP address is used instead.
The consumer can fill in the @ta_timeout_ms field to force the servicing The consumer can fill in the @ta_timeout_ms field to force the servicing
handshake agent to exit after a number of milliseconds. This enables the handshake agent to exit after a number of milliseconds. This enables the
socket to be fully closed once both the kernel and the handshake agent socket to be fully closed once both the kernel and the handshake agent
......
...@@ -24,6 +24,7 @@ struct tls_handshake_args { ...@@ -24,6 +24,7 @@ struct tls_handshake_args {
struct socket *ta_sock; struct socket *ta_sock;
tls_done_func_t ta_done; tls_done_func_t ta_done;
void *ta_data; void *ta_data;
const char *ta_peername;
unsigned int ta_timeout_ms; unsigned int ta_timeout_ms;
key_serial_t ta_keyring; key_serial_t ta_keyring;
key_serial_t ta_my_cert; key_serial_t ta_my_cert;
......
...@@ -44,6 +44,7 @@ enum { ...@@ -44,6 +44,7 @@ enum {
HANDSHAKE_A_ACCEPT_AUTH_MODE, HANDSHAKE_A_ACCEPT_AUTH_MODE,
HANDSHAKE_A_ACCEPT_PEER_IDENTITY, HANDSHAKE_A_ACCEPT_PEER_IDENTITY,
HANDSHAKE_A_ACCEPT_CERTIFICATE, HANDSHAKE_A_ACCEPT_CERTIFICATE,
HANDSHAKE_A_ACCEPT_PEERNAME,
__HANDSHAKE_A_ACCEPT_MAX, __HANDSHAKE_A_ACCEPT_MAX,
HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1) HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1)
......
...@@ -31,6 +31,7 @@ struct handshake_req { ...@@ -31,6 +31,7 @@ struct handshake_req {
struct list_head hr_list; struct list_head hr_list;
struct rhash_head hr_rhash; struct rhash_head hr_rhash;
unsigned long hr_flags; unsigned long hr_flags;
struct file *hr_file;
const struct handshake_proto *hr_proto; const struct handshake_proto *hr_proto;
struct sock *hr_sk; struct sock *hr_sk;
void (*hr_odestruct)(struct sock *sk); void (*hr_odestruct)(struct sock *sk);
......
...@@ -48,7 +48,7 @@ int handshake_genl_notify(struct net *net, const struct handshake_proto *proto, ...@@ -48,7 +48,7 @@ int handshake_genl_notify(struct net *net, const struct handshake_proto *proto,
proto->hp_handler_class)) proto->hp_handler_class))
return -ESRCH; return -ESRCH;
msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, flags);
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
...@@ -99,9 +99,6 @@ static int handshake_dup(struct socket *sock) ...@@ -99,9 +99,6 @@ static int handshake_dup(struct socket *sock)
struct file *file; struct file *file;
int newfd; int newfd;
if (!sock->file)
return -EBADF;
file = get_file(sock->file); file = get_file(sock->file);
newfd = get_unused_fd_flags(O_CLOEXEC); newfd = get_unused_fd_flags(O_CLOEXEC);
if (newfd < 0) { if (newfd < 0) {
...@@ -142,15 +139,16 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info) ...@@ -142,15 +139,16 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
goto out_complete; goto out_complete;
} }
err = req->hr_proto->hp_accept(req, info, fd); err = req->hr_proto->hp_accept(req, info, fd);
if (err) if (err) {
fput(sock->file);
goto out_complete; goto out_complete;
}
trace_handshake_cmd_accept(net, req, req->hr_sk, fd); trace_handshake_cmd_accept(net, req, req->hr_sk, fd);
return 0; return 0;
out_complete: out_complete:
handshake_complete(req, -EIO, NULL); handshake_complete(req, -EIO, NULL);
fput(sock->file);
out_status: out_status:
trace_handshake_cmd_accept_err(net, req, NULL, err); trace_handshake_cmd_accept_err(net, req, NULL, err);
return err; return err;
...@@ -159,8 +157,8 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info) ...@@ -159,8 +157,8 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info) int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct handshake_req *req = NULL;
struct socket *sock = NULL; struct socket *sock = NULL;
struct handshake_req *req;
int fd, status, err; int fd, status, err;
if (GENL_REQ_ATTR_CHECK(info, HANDSHAKE_A_DONE_SOCKFD)) if (GENL_REQ_ATTR_CHECK(info, HANDSHAKE_A_DONE_SOCKFD))
......
...@@ -239,6 +239,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req, ...@@ -239,6 +239,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
} }
req->hr_odestruct = req->hr_sk->sk_destruct; req->hr_odestruct = req->hr_sk->sk_destruct;
req->hr_sk->sk_destruct = handshake_sk_destruct; req->hr_sk->sk_destruct = handshake_sk_destruct;
req->hr_file = sock->file;
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
net = sock_net(req->hr_sk); net = sock_net(req->hr_sk);
...@@ -334,6 +335,9 @@ bool handshake_req_cancel(struct sock *sk) ...@@ -334,6 +335,9 @@ bool handshake_req_cancel(struct sock *sk)
return false; return false;
} }
/* Request accepted and waiting for DONE */
fput(req->hr_file);
out_true: out_true:
trace_handshake_cancel(net, req, sk); trace_handshake_cancel(net, req, sk);
......
...@@ -31,6 +31,7 @@ struct tls_handshake_req { ...@@ -31,6 +31,7 @@ struct tls_handshake_req {
int th_type; int th_type;
unsigned int th_timeout_ms; unsigned int th_timeout_ms;
int th_auth_mode; int th_auth_mode;
const char *th_peername;
key_serial_t th_keyring; key_serial_t th_keyring;
key_serial_t th_certificate; key_serial_t th_certificate;
key_serial_t th_privkey; key_serial_t th_privkey;
...@@ -48,6 +49,7 @@ tls_handshake_req_init(struct handshake_req *req, ...@@ -48,6 +49,7 @@ tls_handshake_req_init(struct handshake_req *req,
treq->th_timeout_ms = args->ta_timeout_ms; treq->th_timeout_ms = args->ta_timeout_ms;
treq->th_consumer_done = args->ta_done; treq->th_consumer_done = args->ta_done;
treq->th_consumer_data = args->ta_data; treq->th_consumer_data = args->ta_data;
treq->th_peername = args->ta_peername;
treq->th_keyring = args->ta_keyring; treq->th_keyring = args->ta_keyring;
treq->th_num_peerids = 0; treq->th_num_peerids = 0;
treq->th_certificate = TLS_NO_CERT; treq->th_certificate = TLS_NO_CERT;
...@@ -214,6 +216,12 @@ static int tls_handshake_accept(struct handshake_req *req, ...@@ -214,6 +216,12 @@ static int tls_handshake_accept(struct handshake_req *req,
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type); ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type);
if (ret < 0) if (ret < 0)
goto out_cancel; goto out_cancel;
if (treq->th_peername) {
ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME,
treq->th_peername);
if (ret < 0)
goto out_cancel;
}
if (treq->th_timeout_ms) { if (treq->th_timeout_ms) {
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms); ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms);
if (ret < 0) if (ret < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment