--- /dev/null
+From a5739435b5a3b8c449f8844ecd71a3b1e89f0a33 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@ZenIV.linux.org.uk>
+Date: Tue, 5 Dec 2017 23:27:57 +0000
+Subject: fix kcm_clone()
+
+From: Al Viro <viro@ZenIV.linux.org.uk>
+
+commit a5739435b5a3b8c449f8844ecd71a3b1e89f0a33 upstream.
+
+1) it's fput() or sock_release(), not both
+2) don't do fd_install() until the last failure exit.
+3) not a bug per se, but... don't attach socket to struct file
+ until it's set up.
+
+Take reserving descriptor into the caller, move fd_install() to the
+caller, sanitize failure exits and calling conventions.
+
+Acked-by: Tom Herbert <tom@herbertland.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/kcm/kcmsock.c | 73 +++++++++++++++++++-----------------------------------
+ 1 file changed, 26 insertions(+), 47 deletions(-)
+
+--- a/net/kcm/kcmsock.c
++++ b/net/kcm/kcmsock.c
+@@ -1624,60 +1624,35 @@ static struct proto kcm_proto = {
+ };
+
+ /* Clone a kcm socket. */
+-static int kcm_clone(struct socket *osock, struct kcm_clone *info,
+- struct socket **newsockp)
++static struct file *kcm_clone(struct socket *osock)
+ {
+ struct socket *newsock;
+ struct sock *newsk;
+- struct file *newfile;
+- int err, newfd;
++ struct file *file;
+
+- err = -ENFILE;
+ newsock = sock_alloc();
+ if (!newsock)
+- goto out;
++ return ERR_PTR(-ENFILE);
+
+ newsock->type = osock->type;
+ newsock->ops = osock->ops;
+
+ __module_get(newsock->ops->owner);
+
+- newfd = get_unused_fd_flags(0);
+- if (unlikely(newfd < 0)) {
+- err = newfd;
+- goto out_fd_fail;
+- }
+-
+- newfile = sock_alloc_file(newsock, 0, osock->sk->sk_prot_creator->name);
+- if (unlikely(IS_ERR(newfile))) {
+- err = PTR_ERR(newfile);
+- goto out_sock_alloc_fail;
+- }
+-
+ newsk = sk_alloc(sock_net(osock->sk), PF_KCM, GFP_KERNEL,
+ &kcm_proto, true);
+ if (!newsk) {
+- err = -ENOMEM;
+- goto out_sk_alloc_fail;
++ sock_release(newsock);
++ return ERR_PTR(-ENOMEM);
+ }
+-
+ sock_init_data(newsock, newsk);
+ init_kcm_sock(kcm_sk(newsk), kcm_sk(osock->sk)->mux);
+
+- fd_install(newfd, newfile);
+- *newsockp = newsock;
+- info->fd = newfd;
+-
+- return 0;
+-
+-out_sk_alloc_fail:
+- fput(newfile);
+-out_sock_alloc_fail:
+- put_unused_fd(newfd);
+-out_fd_fail:
+- sock_release(newsock);
+-out:
+- return err;
++ file = sock_alloc_file(newsock, 0, osock->sk->sk_prot_creator->name);
++ if (IS_ERR(file))
++ sock_release(newsock);
++
++ return file;
+ }
+
+ static int kcm_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+@@ -1707,21 +1682,25 @@ static int kcm_ioctl(struct socket *sock
+ }
+ case SIOCKCMCLONE: {
+ struct kcm_clone info;
+- struct socket *newsock = NULL;
++ struct file *file;
+
+- if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
++ info.fd = get_unused_fd_flags(0);
++ if (unlikely(info.fd < 0))
++ return info.fd;
++
++ file = kcm_clone(sock);
++ if (IS_ERR(file)) {
++ put_unused_fd(info.fd);
++ return PTR_ERR(file);
++ }
++ if (copy_to_user((void __user *)arg, &info,
++ sizeof(info))) {
++ put_unused_fd(info.fd);
++ fput(file);
+ return -EFAULT;
+-
+- err = kcm_clone(sock, &info, &newsock);
+-
+- if (!err) {
+- if (copy_to_user((void __user *)arg, &info,
+- sizeof(info))) {
+- err = -EFAULT;
+- sys_close(info.fd);
+- }
+ }
+-
++ fd_install(info.fd, file);
++ err = 0;
+ break;
+ }
+ default: