]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jan 2017 15:35:01 +0000 (16:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jan 2017 15:35:01 +0000 (16:35 +0100)
added patches:
input-alps-fix-trackstick-support-for-ss5-hardware.patch
libceph-ceph_x_encrypt_buflen-takes-in_len.patch
libceph-introduce-ceph_crypt-for-in-place-en-decryption.patch
libceph-introduce-ceph_x_encrypt_offset.patch
libceph-old_key-in-process_one_ticket-is-redundant.patch
libceph-remove-now-unused-ceph_-en-de-crypt-functions.patch
libceph-rename-and-align-ceph_x_authorizer-reply_buf.patch
libceph-switch-ceph_x_decrypt-to-ceph_crypt.patch
libceph-switch-ceph_x_encrypt-to-ceph_crypt.patch
libceph-tweak-calcu_signature-a-little.patch

queue-4.9/input-alps-fix-trackstick-support-for-ss5-hardware.patch [new file with mode: 0644]
queue-4.9/libceph-ceph_x_encrypt_buflen-takes-in_len.patch [new file with mode: 0644]
queue-4.9/libceph-introduce-ceph_crypt-for-in-place-en-decryption.patch [new file with mode: 0644]
queue-4.9/libceph-introduce-ceph_x_encrypt_offset.patch [new file with mode: 0644]
queue-4.9/libceph-old_key-in-process_one_ticket-is-redundant.patch [new file with mode: 0644]
queue-4.9/libceph-remove-now-unused-ceph_-en-de-crypt-functions.patch [new file with mode: 0644]
queue-4.9/libceph-rename-and-align-ceph_x_authorizer-reply_buf.patch [new file with mode: 0644]
queue-4.9/libceph-switch-ceph_x_decrypt-to-ceph_crypt.patch [new file with mode: 0644]
queue-4.9/libceph-switch-ceph_x_encrypt-to-ceph_crypt.patch [new file with mode: 0644]
queue-4.9/libceph-tweak-calcu_signature-a-little.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/input-alps-fix-trackstick-support-for-ss5-hardware.patch b/queue-4.9/input-alps-fix-trackstick-support-for-ss5-hardware.patch
new file mode 100644 (file)
index 0000000..8bf04ec
--- /dev/null
@@ -0,0 +1,70 @@
+From 864db9295b06837d11a260e5dacf99a3fdf6bce2 Mon Sep 17 00:00:00 2001
+From: Paul Donohue <linux-kernel@PaulSD.com>
+Date: Mon, 28 Nov 2016 20:11:25 -0800
+Subject: Input: ALPS - fix TrackStick support for SS5 hardware
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paul Donohue <linux-kernel@PaulSD.com>
+
+commit 864db9295b06837d11a260e5dacf99a3fdf6bce2 upstream.
+
+The current Alps SS5 (SS4 v2) code generates bogus TouchPad events when
+TrackStick packets are processed.
+
+This causes the xorg synaptics driver to print
+"unable to find touch point 0" and
+"BUG: triggered 'if (priv->num_active_touches > priv->num_slots)'"
+messages.  It also causes unexpected TouchPad button release and re-click
+event sequences if the TrackStick is moved while holding a TouchPad
+button.
+
+This commit corrects the problem by adjusting alps_process_packet_ss4_v2()
+so that it only sends TrackStick reports when processing TrackStick
+packets.
+
+Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
+Signed-off-by: Paul Donohue <linux-kernel@PaulSD.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/mouse/alps.c |   19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/input/mouse/alps.c
++++ b/drivers/input/mouse/alps.c
+@@ -1346,6 +1346,18 @@ static void alps_process_packet_ss4_v2(s
+       priv->multi_packet = 0;
++      /* Report trackstick */
++      if (alps_get_pkt_id_ss4_v2(packet) == SS4_PACKET_ID_STICK) {
++              if (priv->flags & ALPS_DUALPOINT) {
++                      input_report_key(dev2, BTN_LEFT, f->ts_left);
++                      input_report_key(dev2, BTN_RIGHT, f->ts_right);
++                      input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
++                      input_sync(dev2);
++              }
++              return;
++      }
++
++      /* Report touchpad */
+       alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
+       input_mt_report_finger_count(dev, f->fingers);
+@@ -1356,13 +1368,6 @@ static void alps_process_packet_ss4_v2(s
+       input_report_abs(dev, ABS_PRESSURE, f->pressure);
+       input_sync(dev);
+-
+-      if (priv->flags & ALPS_DUALPOINT) {
+-              input_report_key(dev2, BTN_LEFT, f->ts_left);
+-              input_report_key(dev2, BTN_RIGHT, f->ts_right);
+-              input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
+-              input_sync(dev2);
+-      }
+ }
+ static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
diff --git a/queue-4.9/libceph-ceph_x_encrypt_buflen-takes-in_len.patch b/queue-4.9/libceph-ceph_x_encrypt_buflen-takes-in_len.patch
new file mode 100644 (file)
index 0000000..ed61573
--- /dev/null
@@ -0,0 +1,48 @@
+From 36721ece1e84a25130c4befb930509b3f96de020 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:06 +0100
+Subject: libceph: ceph_x_encrypt_buflen() takes in_len
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 36721ece1e84a25130c4befb930509b3f96de020 upstream.
+
+Pass what's going to be encrypted - that's msg_b, not ticket_blob.
+ceph_x_encrypt_buflen() returns the upper bound, so this doesn't change
+the maxlen calculation, but makes it a bit clearer.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -308,8 +308,8 @@ static int ceph_x_build_authorizer(struc
+       if (ret)
+               goto out_au;
+-      maxlen = sizeof(*msg_a) + sizeof(msg_b) +
+-              ceph_x_encrypt_buflen(ticket_blob_len);
++      maxlen = sizeof(*msg_a) + ticket_blob_len +
++              ceph_x_encrypt_buflen(sizeof(msg_b));
+       dout("  need len %d\n", maxlen);
+       if (au->buf && au->buf->alloc_len < maxlen) {
+               ceph_buffer_put(au->buf);
+@@ -350,11 +350,12 @@ static int ceph_x_build_authorizer(struc
+                            p, end - p);
+       if (ret < 0)
+               goto out_au;
++
+       p += ret;
++      WARN_ON(p > end);
+       au->buf->vec.iov_len = p - au->buf->vec.iov_base;
+       dout(" built authorizer nonce %llx len %d\n", au->nonce,
+            (int)au->buf->vec.iov_len);
+-      BUG_ON(au->buf->vec.iov_len > maxlen);
+       return 0;
+ out_au:
diff --git a/queue-4.9/libceph-introduce-ceph_crypt-for-in-place-en-decryption.patch b/queue-4.9/libceph-introduce-ceph_crypt-for-in-place-en-decryption.patch
new file mode 100644 (file)
index 0000000..63dc6da
--- /dev/null
@@ -0,0 +1,143 @@
+From a45f795c65b479b4ba107b6ccde29b896d51ee98 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:07 +0100
+Subject: libceph: introduce ceph_crypt() for in-place en/decryption
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit a45f795c65b479b4ba107b6ccde29b896d51ee98 upstream.
+
+Starting with 4.9, kernel stacks may be vmalloced and therefore not
+guaranteed to be physically contiguous; the new CONFIG_VMAP_STACK
+option is enabled by default on x86.  This makes it invalid to use
+on-stack buffers with the crypto scatterlist API, as sg_set_buf()
+expects a logical address and won't work with vmalloced addresses.
+
+There isn't a different (e.g. kvec-based) crypto API we could switch
+net/ceph/crypto.c to and the current scatterlist.h API isn't getting
+updated to accommodate this use case.  Allocating a new header and
+padding for each operation is a non-starter, so do the en/decryption
+in-place on a single pre-assembled (header + data + padding) heap
+buffer.  This is explicitly supported by the crypto API:
+
+    "... the caller may provide the same scatter/gather list for the
+     plaintext and cipher text. After the completion of the cipher
+     operation, the plaintext data is replaced with the ciphertext data
+     in case of an encryption and vice versa for a decryption."
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/crypto.c |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ net/ceph/crypto.h |    2 +
+ 2 files changed, 89 insertions(+)
+
+--- a/net/ceph/crypto.c
++++ b/net/ceph/crypto.c
+@@ -526,6 +526,93 @@ int ceph_encrypt2(struct ceph_crypto_key
+       }
+ }
++static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt,
++                        void *buf, int buf_len, int in_len, int *pout_len)
++{
++      struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher();
++      SKCIPHER_REQUEST_ON_STACK(req, tfm);
++      struct sg_table sgt;
++      struct scatterlist prealloc_sg;
++      char iv[AES_BLOCK_SIZE];
++      int pad_byte = AES_BLOCK_SIZE - (in_len & (AES_BLOCK_SIZE - 1));
++      int crypt_len = encrypt ? in_len + pad_byte : in_len;
++      int ret;
++
++      if (IS_ERR(tfm))
++              return PTR_ERR(tfm);
++
++      WARN_ON(crypt_len > buf_len);
++      if (encrypt)
++              memset(buf + in_len, pad_byte, pad_byte);
++      ret = setup_sgtable(&sgt, &prealloc_sg, buf, crypt_len);
++      if (ret)
++              goto out_tfm;
++
++      crypto_skcipher_setkey((void *)tfm, key->key, key->len);
++      memcpy(iv, aes_iv, AES_BLOCK_SIZE);
++
++      skcipher_request_set_tfm(req, tfm);
++      skcipher_request_set_callback(req, 0, NULL, NULL);
++      skcipher_request_set_crypt(req, sgt.sgl, sgt.sgl, crypt_len, iv);
++
++      /*
++      print_hex_dump(KERN_ERR, "key: ", DUMP_PREFIX_NONE, 16, 1,
++                     key->key, key->len, 1);
++      print_hex_dump(KERN_ERR, " in: ", DUMP_PREFIX_NONE, 16, 1,
++                     buf, crypt_len, 1);
++      */
++      if (encrypt)
++              ret = crypto_skcipher_encrypt(req);
++      else
++              ret = crypto_skcipher_decrypt(req);
++      skcipher_request_zero(req);
++      if (ret) {
++              pr_err("%s %scrypt failed: %d\n", __func__,
++                     encrypt ? "en" : "de", ret);
++              goto out_sgt;
++      }
++      /*
++      print_hex_dump(KERN_ERR, "out: ", DUMP_PREFIX_NONE, 16, 1,
++                     buf, crypt_len, 1);
++      */
++
++      if (encrypt) {
++              *pout_len = crypt_len;
++      } else {
++              pad_byte = *(char *)(buf + in_len - 1);
++              if (pad_byte > 0 && pad_byte <= AES_BLOCK_SIZE &&
++                  in_len >= pad_byte) {
++                      *pout_len = in_len - pad_byte;
++              } else {
++                      pr_err("%s got bad padding %d on in_len %d\n",
++                             __func__, pad_byte, in_len);
++                      ret = -EPERM;
++                      goto out_sgt;
++              }
++      }
++
++out_sgt:
++      teardown_sgtable(&sgt);
++out_tfm:
++      crypto_free_skcipher(tfm);
++      return ret;
++}
++
++int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
++             void *buf, int buf_len, int in_len, int *pout_len)
++{
++      switch (key->type) {
++      case CEPH_CRYPTO_NONE:
++              *pout_len = in_len;
++              return 0;
++      case CEPH_CRYPTO_AES:
++              return ceph_aes_crypt(key, encrypt, buf, buf_len, in_len,
++                                    pout_len);
++      default:
++              return -ENOTSUPP;
++      }
++}
++
+ static int ceph_key_preparse(struct key_preparsed_payload *prep)
+ {
+       struct ceph_crypto_key *ckey;
+--- a/net/ceph/crypto.h
++++ b/net/ceph/crypto.h
+@@ -43,6 +43,8 @@ int ceph_encrypt2(struct ceph_crypto_key
+                 void *dst, size_t *dst_len,
+                 const void *src1, size_t src1_len,
+                 const void *src2, size_t src2_len);
++int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
++             void *buf, int buf_len, int in_len, int *pout_len);
+ int ceph_crypto_init(void);
+ void ceph_crypto_shutdown(void);
diff --git a/queue-4.9/libceph-introduce-ceph_x_encrypt_offset.patch b/queue-4.9/libceph-introduce-ceph_x_encrypt_offset.patch
new file mode 100644 (file)
index 0000000..47473c1
--- /dev/null
@@ -0,0 +1,36 @@
+From 55d9cc834f933698fc864f0d36f3cca533d30a8d Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:07 +0100
+Subject: libceph: introduce ceph_x_encrypt_offset()
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 55d9cc834f933698fc864f0d36f3cca533d30a8d upstream.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -39,10 +39,14 @@ static int ceph_x_should_authenticate(st
+       return need != 0;
+ }
++static int ceph_x_encrypt_offset(void)
++{
++      return sizeof(u32) + sizeof(struct ceph_x_encrypt_header);
++}
++
+ static int ceph_x_encrypt_buflen(int ilen)
+ {
+-      return sizeof(struct ceph_x_encrypt_header) + ilen + 16 +
+-              sizeof(u32);
++      return ceph_x_encrypt_offset() + ilen + 16;
+ }
+ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
diff --git a/queue-4.9/libceph-old_key-in-process_one_ticket-is-redundant.patch b/queue-4.9/libceph-old_key-in-process_one_ticket-is-redundant.patch
new file mode 100644 (file)
index 0000000..9b3d7e9
--- /dev/null
@@ -0,0 +1,47 @@
+From 462e650451c577d15eeb4d883d70fa9e4e529fad Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:06 +0100
+Subject: libceph: old_key in process_one_ticket() is redundant
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 462e650451c577d15eeb4d883d70fa9e4e529fad upstream.
+
+Since commit 0a990e709356 ("ceph: clean up service ticket decoding"),
+th->session_key isn't assigned until everything is decoded.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -148,7 +148,6 @@ static int process_one_ticket(struct cep
+       int dlen;
+       char is_enc;
+       struct timespec validity;
+-      struct ceph_crypto_key old_key;
+       void *ticket_buf = NULL;
+       void *tp, *tpend;
+       void **ptp;
+@@ -187,7 +186,6 @@ static int process_one_ticket(struct cep
+       if (tkt_struct_v != 1)
+               goto bad;
+-      memcpy(&old_key, &th->session_key, sizeof(old_key));
+       ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
+       if (ret)
+               goto out;
+@@ -204,7 +202,7 @@ static int process_one_ticket(struct cep
+       if (is_enc) {
+               /* encrypted */
+               dout(" encrypted ticket\n");
+-              dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
++              dlen = ceph_x_decrypt(&th->session_key, p, end, &ticket_buf, 0);
+               if (dlen < 0) {
+                       ret = dlen;
+                       goto out;
diff --git a/queue-4.9/libceph-remove-now-unused-ceph_-en-de-crypt-functions.patch b/queue-4.9/libceph-remove-now-unused-ceph_-en-de-crypt-functions.patch
new file mode 100644 (file)
index 0000000..b702eb0
--- /dev/null
@@ -0,0 +1,419 @@
+From 2b1e1a7cd0a615d57455567a549f9965023321b5 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:08 +0100
+Subject: libceph: remove now unused ceph_*{en,de}crypt*() functions
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 2b1e1a7cd0a615d57455567a549f9965023321b5 upstream.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/crypto.c |  369 ------------------------------------------------------
+ net/ceph/crypto.h |   14 --
+ 2 files changed, 383 deletions(-)
+
+--- a/net/ceph/crypto.c
++++ b/net/ceph/crypto.c
+@@ -157,375 +157,6 @@ static void teardown_sgtable(struct sg_t
+               sg_free_table(sgt);
+ }
+-static int ceph_aes_encrypt(const void *key, int key_len,
+-                          void *dst, size_t *dst_len,
+-                          const void *src, size_t src_len)
+-{
+-      struct scatterlist sg_in[2], prealloc_sg;
+-      struct sg_table sg_out;
+-      struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher();
+-      SKCIPHER_REQUEST_ON_STACK(req, tfm);
+-      int ret;
+-      char iv[AES_BLOCK_SIZE];
+-      size_t zero_padding = (0x10 - (src_len & 0x0f));
+-      char pad[16];
+-
+-      if (IS_ERR(tfm))
+-              return PTR_ERR(tfm);
+-
+-      memset(pad, zero_padding, zero_padding);
+-
+-      *dst_len = src_len + zero_padding;
+-
+-      sg_init_table(sg_in, 2);
+-      sg_set_buf(&sg_in[0], src, src_len);
+-      sg_set_buf(&sg_in[1], pad, zero_padding);
+-      ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
+-      if (ret)
+-              goto out_tfm;
+-
+-      crypto_skcipher_setkey((void *)tfm, key, key_len);
+-      memcpy(iv, aes_iv, AES_BLOCK_SIZE);
+-
+-      skcipher_request_set_tfm(req, tfm);
+-      skcipher_request_set_callback(req, 0, NULL, NULL);
+-      skcipher_request_set_crypt(req, sg_in, sg_out.sgl,
+-                                 src_len + zero_padding, iv);
+-
+-      /*
+-      print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
+-                     key, key_len, 1);
+-      print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1,
+-                      src, src_len, 1);
+-      print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
+-                      pad, zero_padding, 1);
+-      */
+-      ret = crypto_skcipher_encrypt(req);
+-      skcipher_request_zero(req);
+-      if (ret < 0) {
+-              pr_err("ceph_aes_crypt failed %d\n", ret);
+-              goto out_sg;
+-      }
+-      /*
+-      print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
+-                     dst, *dst_len, 1);
+-      */
+-
+-out_sg:
+-      teardown_sgtable(&sg_out);
+-out_tfm:
+-      crypto_free_skcipher(tfm);
+-      return ret;
+-}
+-
+-static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
+-                           size_t *dst_len,
+-                           const void *src1, size_t src1_len,
+-                           const void *src2, size_t src2_len)
+-{
+-      struct scatterlist sg_in[3], prealloc_sg;
+-      struct sg_table sg_out;
+-      struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher();
+-      SKCIPHER_REQUEST_ON_STACK(req, tfm);
+-      int ret;
+-      char iv[AES_BLOCK_SIZE];
+-      size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f));
+-      char pad[16];
+-
+-      if (IS_ERR(tfm))
+-              return PTR_ERR(tfm);
+-
+-      memset(pad, zero_padding, zero_padding);
+-
+-      *dst_len = src1_len + src2_len + zero_padding;
+-
+-      sg_init_table(sg_in, 3);
+-      sg_set_buf(&sg_in[0], src1, src1_len);
+-      sg_set_buf(&sg_in[1], src2, src2_len);
+-      sg_set_buf(&sg_in[2], pad, zero_padding);
+-      ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
+-      if (ret)
+-              goto out_tfm;
+-
+-      crypto_skcipher_setkey((void *)tfm, key, key_len);
+-      memcpy(iv, aes_iv, AES_BLOCK_SIZE);
+-
+-      skcipher_request_set_tfm(req, tfm);
+-      skcipher_request_set_callback(req, 0, NULL, NULL);
+-      skcipher_request_set_crypt(req, sg_in, sg_out.sgl,
+-                                 src1_len + src2_len + zero_padding, iv);
+-
+-      /*
+-      print_hex_dump(KERN_ERR, "enc  key: ", DUMP_PREFIX_NONE, 16, 1,
+-                     key, key_len, 1);
+-      print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1,
+-                      src1, src1_len, 1);
+-      print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1,
+-                      src2, src2_len, 1);
+-      print_hex_dump(KERN_ERR, "enc  pad: ", DUMP_PREFIX_NONE, 16, 1,
+-                      pad, zero_padding, 1);
+-      */
+-      ret = crypto_skcipher_encrypt(req);
+-      skcipher_request_zero(req);
+-      if (ret < 0) {
+-              pr_err("ceph_aes_crypt2 failed %d\n", ret);
+-              goto out_sg;
+-      }
+-      /*
+-      print_hex_dump(KERN_ERR, "enc  out: ", DUMP_PREFIX_NONE, 16, 1,
+-                     dst, *dst_len, 1);
+-      */
+-
+-out_sg:
+-      teardown_sgtable(&sg_out);
+-out_tfm:
+-      crypto_free_skcipher(tfm);
+-      return ret;
+-}
+-
+-static int ceph_aes_decrypt(const void *key, int key_len,
+-                          void *dst, size_t *dst_len,
+-                          const void *src, size_t src_len)
+-{
+-      struct sg_table sg_in;
+-      struct scatterlist sg_out[2], prealloc_sg;
+-      struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher();
+-      SKCIPHER_REQUEST_ON_STACK(req, tfm);
+-      char pad[16];
+-      char iv[AES_BLOCK_SIZE];
+-      int ret;
+-      int last_byte;
+-
+-      if (IS_ERR(tfm))
+-              return PTR_ERR(tfm);
+-
+-      sg_init_table(sg_out, 2);
+-      sg_set_buf(&sg_out[0], dst, *dst_len);
+-      sg_set_buf(&sg_out[1], pad, sizeof(pad));
+-      ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
+-      if (ret)
+-              goto out_tfm;
+-
+-      crypto_skcipher_setkey((void *)tfm, key, key_len);
+-      memcpy(iv, aes_iv, AES_BLOCK_SIZE);
+-
+-      skcipher_request_set_tfm(req, tfm);
+-      skcipher_request_set_callback(req, 0, NULL, NULL);
+-      skcipher_request_set_crypt(req, sg_in.sgl, sg_out,
+-                                 src_len, iv);
+-
+-      /*
+-      print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
+-                     key, key_len, 1);
+-      print_hex_dump(KERN_ERR, "dec  in: ", DUMP_PREFIX_NONE, 16, 1,
+-                     src, src_len, 1);
+-      */
+-      ret = crypto_skcipher_decrypt(req);
+-      skcipher_request_zero(req);
+-      if (ret < 0) {
+-              pr_err("ceph_aes_decrypt failed %d\n", ret);
+-              goto out_sg;
+-      }
+-
+-      if (src_len <= *dst_len)
+-              last_byte = ((char *)dst)[src_len - 1];
+-      else
+-              last_byte = pad[src_len - *dst_len - 1];
+-      if (last_byte <= 16 && src_len >= last_byte) {
+-              *dst_len = src_len - last_byte;
+-      } else {
+-              pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
+-                     last_byte, (int)src_len);
+-              return -EPERM;  /* bad padding */
+-      }
+-      /*
+-      print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
+-                     dst, *dst_len, 1);
+-      */
+-
+-out_sg:
+-      teardown_sgtable(&sg_in);
+-out_tfm:
+-      crypto_free_skcipher(tfm);
+-      return ret;
+-}
+-
+-static int ceph_aes_decrypt2(const void *key, int key_len,
+-                           void *dst1, size_t *dst1_len,
+-                           void *dst2, size_t *dst2_len,
+-                           const void *src, size_t src_len)
+-{
+-      struct sg_table sg_in;
+-      struct scatterlist sg_out[3], prealloc_sg;
+-      struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher();
+-      SKCIPHER_REQUEST_ON_STACK(req, tfm);
+-      char pad[16];
+-      char iv[AES_BLOCK_SIZE];
+-      int ret;
+-      int last_byte;
+-
+-      if (IS_ERR(tfm))
+-              return PTR_ERR(tfm);
+-
+-      sg_init_table(sg_out, 3);
+-      sg_set_buf(&sg_out[0], dst1, *dst1_len);
+-      sg_set_buf(&sg_out[1], dst2, *dst2_len);
+-      sg_set_buf(&sg_out[2], pad, sizeof(pad));
+-      ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
+-      if (ret)
+-              goto out_tfm;
+-
+-      crypto_skcipher_setkey((void *)tfm, key, key_len);
+-      memcpy(iv, aes_iv, AES_BLOCK_SIZE);
+-
+-      skcipher_request_set_tfm(req, tfm);
+-      skcipher_request_set_callback(req, 0, NULL, NULL);
+-      skcipher_request_set_crypt(req, sg_in.sgl, sg_out,
+-                                 src_len, iv);
+-
+-      /*
+-      print_hex_dump(KERN_ERR, "dec  key: ", DUMP_PREFIX_NONE, 16, 1,
+-                     key, key_len, 1);
+-      print_hex_dump(KERN_ERR, "dec   in: ", DUMP_PREFIX_NONE, 16, 1,
+-                     src, src_len, 1);
+-      */
+-      ret = crypto_skcipher_decrypt(req);
+-      skcipher_request_zero(req);
+-      if (ret < 0) {
+-              pr_err("ceph_aes_decrypt failed %d\n", ret);
+-              goto out_sg;
+-      }
+-
+-      if (src_len <= *dst1_len)
+-              last_byte = ((char *)dst1)[src_len - 1];
+-      else if (src_len <= *dst1_len + *dst2_len)
+-              last_byte = ((char *)dst2)[src_len - *dst1_len - 1];
+-      else
+-              last_byte = pad[src_len - *dst1_len - *dst2_len - 1];
+-      if (last_byte <= 16 && src_len >= last_byte) {
+-              src_len -= last_byte;
+-      } else {
+-              pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
+-                     last_byte, (int)src_len);
+-              return -EPERM;  /* bad padding */
+-      }
+-
+-      if (src_len < *dst1_len) {
+-              *dst1_len = src_len;
+-              *dst2_len = 0;
+-      } else {
+-              *dst2_len = src_len - *dst1_len;
+-      }
+-      /*
+-      print_hex_dump(KERN_ERR, "dec  out1: ", DUMP_PREFIX_NONE, 16, 1,
+-                     dst1, *dst1_len, 1);
+-      print_hex_dump(KERN_ERR, "dec  out2: ", DUMP_PREFIX_NONE, 16, 1,
+-                     dst2, *dst2_len, 1);
+-      */
+-
+-out_sg:
+-      teardown_sgtable(&sg_in);
+-out_tfm:
+-      crypto_free_skcipher(tfm);
+-      return ret;
+-}
+-
+-
+-int ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+-               const void *src, size_t src_len)
+-{
+-      switch (secret->type) {
+-      case CEPH_CRYPTO_NONE:
+-              if (*dst_len < src_len)
+-                      return -ERANGE;
+-              memcpy(dst, src, src_len);
+-              *dst_len = src_len;
+-              return 0;
+-
+-      case CEPH_CRYPTO_AES:
+-              return ceph_aes_decrypt(secret->key, secret->len, dst,
+-                                      dst_len, src, src_len);
+-
+-      default:
+-              return -EINVAL;
+-      }
+-}
+-
+-int ceph_decrypt2(struct ceph_crypto_key *secret,
+-                      void *dst1, size_t *dst1_len,
+-                      void *dst2, size_t *dst2_len,
+-                      const void *src, size_t src_len)
+-{
+-      size_t t;
+-
+-      switch (secret->type) {
+-      case CEPH_CRYPTO_NONE:
+-              if (*dst1_len + *dst2_len < src_len)
+-                      return -ERANGE;
+-              t = min(*dst1_len, src_len);
+-              memcpy(dst1, src, t);
+-              *dst1_len = t;
+-              src += t;
+-              src_len -= t;
+-              if (src_len) {
+-                      t = min(*dst2_len, src_len);
+-                      memcpy(dst2, src, t);
+-                      *dst2_len = t;
+-              }
+-              return 0;
+-
+-      case CEPH_CRYPTO_AES:
+-              return ceph_aes_decrypt2(secret->key, secret->len,
+-                                       dst1, dst1_len, dst2, dst2_len,
+-                                       src, src_len);
+-
+-      default:
+-              return -EINVAL;
+-      }
+-}
+-
+-int ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+-               const void *src, size_t src_len)
+-{
+-      switch (secret->type) {
+-      case CEPH_CRYPTO_NONE:
+-              if (*dst_len < src_len)
+-                      return -ERANGE;
+-              memcpy(dst, src, src_len);
+-              *dst_len = src_len;
+-              return 0;
+-
+-      case CEPH_CRYPTO_AES:
+-              return ceph_aes_encrypt(secret->key, secret->len, dst,
+-                                      dst_len, src, src_len);
+-
+-      default:
+-              return -EINVAL;
+-      }
+-}
+-
+-int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+-                const void *src1, size_t src1_len,
+-                const void *src2, size_t src2_len)
+-{
+-      switch (secret->type) {
+-      case CEPH_CRYPTO_NONE:
+-              if (*dst_len < src1_len + src2_len)
+-                      return -ERANGE;
+-              memcpy(dst, src1, src1_len);
+-              memcpy(dst + src1_len, src2, src2_len);
+-              *dst_len = src1_len + src2_len;
+-              return 0;
+-
+-      case CEPH_CRYPTO_AES:
+-              return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len,
+-                                       src1, src1_len, src2, src2_len);
+-
+-      default:
+-              return -EINVAL;
+-      }
+-}
+-
+ static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt,
+                         void *buf, int buf_len, int in_len, int *pout_len)
+ {
+--- a/net/ceph/crypto.h
++++ b/net/ceph/crypto.h
+@@ -29,20 +29,6 @@ int ceph_crypto_key_decode(struct ceph_c
+ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *in);
+ /* crypto.c */
+-int ceph_decrypt(struct ceph_crypto_key *secret,
+-               void *dst, size_t *dst_len,
+-               const void *src, size_t src_len);
+-int ceph_encrypt(struct ceph_crypto_key *secret,
+-               void *dst, size_t *dst_len,
+-               const void *src, size_t src_len);
+-int ceph_decrypt2(struct ceph_crypto_key *secret,
+-                void *dst1, size_t *dst1_len,
+-                void *dst2, size_t *dst2_len,
+-                const void *src, size_t src_len);
+-int ceph_encrypt2(struct ceph_crypto_key *secret,
+-                void *dst, size_t *dst_len,
+-                const void *src1, size_t src1_len,
+-                const void *src2, size_t src2_len);
+ int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
+              void *buf, int buf_len, int in_len, int *pout_len);
+ int ceph_crypto_init(void);
diff --git a/queue-4.9/libceph-rename-and-align-ceph_x_authorizer-reply_buf.patch b/queue-4.9/libceph-rename-and-align-ceph_x_authorizer-reply_buf.patch
new file mode 100644 (file)
index 0000000..758cf44
--- /dev/null
@@ -0,0 +1,68 @@
+From 7882a26d2e2e520099e2961d5e2e870f8e4172dc Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:07 +0100
+Subject: libceph: rename and align ceph_x_authorizer::reply_buf
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 7882a26d2e2e520099e2961d5e2e870f8e4172dc upstream.
+
+It's going to be used as a temporary buffer for in-place en/decryption
+with ceph_crypt() instead of on-stack buffers, so rename to enc_buf.
+Ensure alignment to avoid GFP_ATOMIC allocations in the crypto stack.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |   10 +++++-----
+ net/ceph/auth_x.h |    3 ++-
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -603,8 +603,8 @@ static int ceph_x_create_authorizer(
+       auth->authorizer = (struct ceph_authorizer *) au;
+       auth->authorizer_buf = au->buf->vec.iov_base;
+       auth->authorizer_buf_len = au->buf->vec.iov_len;
+-      auth->authorizer_reply_buf = au->reply_buf;
+-      auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
++      auth->authorizer_reply_buf = au->enc_buf;
++      auth->authorizer_reply_buf_len = CEPHX_AU_ENC_BUF_LEN;
+       auth->sign_message = ac->ops->sign_message;
+       auth->check_message_signature = ac->ops->check_message_signature;
+@@ -638,10 +638,10 @@ static int ceph_x_verify_authorizer_repl
+       int ret = 0;
+       struct ceph_x_authorize_reply reply;
+       void *preply = &reply;
+-      void *p = au->reply_buf;
+-      void *end = p + sizeof(au->reply_buf);
++      void *p = au->enc_buf;
+-      ret = ceph_x_decrypt(&au->session_key, &p, end, &preply, sizeof(reply));
++      ret = ceph_x_decrypt(&au->session_key, &p, p + CEPHX_AU_ENC_BUF_LEN,
++                           &preply, sizeof(reply));
+       if (ret < 0)
+               return ret;
+       if (ret != sizeof(reply))
+--- a/net/ceph/auth_x.h
++++ b/net/ceph/auth_x.h
+@@ -24,6 +24,7 @@ struct ceph_x_ticket_handler {
+       unsigned long renew_after, expires;
+ };
++#define CEPHX_AU_ENC_BUF_LEN  128  /* big enough for encrypted blob */
+ struct ceph_x_authorizer {
+       struct ceph_authorizer base;
+@@ -32,7 +33,7 @@ struct ceph_x_authorizer {
+       unsigned int service;
+       u64 nonce;
+       u64 secret_id;
+-      char reply_buf[128];  /* big enough for encrypted blob */
++      char enc_buf[CEPHX_AU_ENC_BUF_LEN] __aligned(8);
+ };
+ struct ceph_x_info {
diff --git a/queue-4.9/libceph-switch-ceph_x_decrypt-to-ceph_crypt.patch b/queue-4.9/libceph-switch-ceph_x_decrypt-to-ceph_crypt.patch
new file mode 100644 (file)
index 0000000..a3e1f3b
--- /dev/null
@@ -0,0 +1,162 @@
+From e15fd0a11db00fc7f470a9fc804657ec3f6d04a5 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:08 +0100
+Subject: libceph: switch ceph_x_decrypt() to ceph_crypt()
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit e15fd0a11db00fc7f470a9fc804657ec3f6d04a5 upstream.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |   78 ++++++++++++++++++++++--------------------------------
+ 1 file changed, 32 insertions(+), 46 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -69,32 +69,28 @@ static int ceph_x_encrypt(struct ceph_cr
+       return sizeof(u32) + ciphertext_len;
+ }
+-static int ceph_x_decrypt(struct ceph_crypto_key *secret,
+-                        void **p, void *end, void **obuf, size_t olen)
++static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end)
+ {
+-      struct ceph_x_encrypt_header head;
+-      size_t head_len = sizeof(head);
+-      int len, ret;
+-
+-      len = ceph_decode_32(p);
+-      if (*p + len > end)
+-              return -EINVAL;
++      struct ceph_x_encrypt_header *hdr = *p + sizeof(u32);
++      int ciphertext_len, plaintext_len;
++      int ret;
+-      dout("ceph_x_decrypt len %d\n", len);
+-      if (*obuf == NULL) {
+-              *obuf = kmalloc(len, GFP_NOFS);
+-              if (!*obuf)
+-                      return -ENOMEM;
+-              olen = len;
+-      }
++      ceph_decode_32_safe(p, end, ciphertext_len, e_inval);
++      ceph_decode_need(p, end, ciphertext_len, e_inval);
+-      ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
++      ret = ceph_crypt(secret, false, *p, end - *p, ciphertext_len,
++                       &plaintext_len);
+       if (ret)
+               return ret;
+-      if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
++
++      if (hdr->struct_v != 1 || le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC)
+               return -EPERM;
+-      *p += len;
+-      return olen;
++
++      *p += ciphertext_len;
++      return plaintext_len - sizeof(struct ceph_x_encrypt_header);
++
++e_inval:
++      return -EINVAL;
+ }
+ /*
+@@ -149,12 +145,10 @@ static int process_one_ticket(struct cep
+       int type;
+       u8 tkt_struct_v, blob_struct_v;
+       struct ceph_x_ticket_handler *th;
+-      void *dbuf = NULL;
+       void *dp, *dend;
+       int dlen;
+       char is_enc;
+       struct timespec validity;
+-      void *ticket_buf = NULL;
+       void *tp, *tpend;
+       void **ptp;
+       struct ceph_crypto_key new_session_key;
+@@ -179,14 +173,12 @@ static int process_one_ticket(struct cep
+       }
+       /* blob for me */
+-      dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
+-      if (dlen <= 0) {
+-              ret = dlen;
++      dp = *p + ceph_x_encrypt_offset();
++      ret = ceph_x_decrypt(secret, p, end);
++      if (ret < 0)
+               goto out;
+-      }
+-      dout(" decrypted %d bytes\n", dlen);
+-      dp = dbuf;
+-      dend = dp + dlen;
++      dout(" decrypted %d bytes\n", ret);
++      dend = dp + ret;
+       tkt_struct_v = ceph_decode_8(&dp);
+       if (tkt_struct_v != 1)
+@@ -207,15 +199,13 @@ static int process_one_ticket(struct cep
+       ceph_decode_8_safe(p, end, is_enc, bad);
+       if (is_enc) {
+               /* encrypted */
+-              dout(" encrypted ticket\n");
+-              dlen = ceph_x_decrypt(&th->session_key, p, end, &ticket_buf, 0);
+-              if (dlen < 0) {
+-                      ret = dlen;
++              tp = *p + ceph_x_encrypt_offset();
++              ret = ceph_x_decrypt(&th->session_key, p, end);
++              if (ret < 0)
+                       goto out;
+-              }
+-              tp = ticket_buf;
++              dout(" encrypted ticket, decrypted %d bytes\n", ret);
+               ptp = &tp;
+-              tpend = *ptp + dlen;
++              tpend = tp + ret;
+       } else {
+               /* unencrypted */
+               ptp = p;
+@@ -246,8 +236,6 @@ static int process_one_ticket(struct cep
+       xi->have_keys |= th->service;
+ out:
+-      kfree(ticket_buf);
+-      kfree(dbuf);
+       return ret;
+ bad:
+@@ -638,24 +626,22 @@ static int ceph_x_verify_authorizer_repl
+                                         struct ceph_authorizer *a, size_t len)
+ {
+       struct ceph_x_authorizer *au = (void *)a;
+-      int ret = 0;
+-      struct ceph_x_authorize_reply reply;
+-      void *preply = &reply;
+       void *p = au->enc_buf;
++      struct ceph_x_authorize_reply *reply = p + ceph_x_encrypt_offset();
++      int ret;
+-      ret = ceph_x_decrypt(&au->session_key, &p, p + CEPHX_AU_ENC_BUF_LEN,
+-                           &preply, sizeof(reply));
++      ret = ceph_x_decrypt(&au->session_key, &p, p + CEPHX_AU_ENC_BUF_LEN);
+       if (ret < 0)
+               return ret;
+-      if (ret != sizeof(reply))
++      if (ret != sizeof(*reply))
+               return -EPERM;
+-      if (au->nonce + 1 != le64_to_cpu(reply.nonce_plus_one))
++      if (au->nonce + 1 != le64_to_cpu(reply->nonce_plus_one))
+               ret = -EPERM;
+       else
+               ret = 0;
+       dout("verify_authorizer_reply nonce %llx got %llx ret %d\n",
+-           au->nonce, le64_to_cpu(reply.nonce_plus_one), ret);
++           au->nonce, le64_to_cpu(reply->nonce_plus_one), ret);
+       return ret;
+ }
diff --git a/queue-4.9/libceph-switch-ceph_x_encrypt-to-ceph_crypt.patch b/queue-4.9/libceph-switch-ceph_x_encrypt-to-ceph_crypt.patch
new file mode 100644 (file)
index 0000000..bd71510
--- /dev/null
@@ -0,0 +1,161 @@
+From d03857c63bb036edff0aa7a107276360173aca4e Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:07 +0100
+Subject: libceph: switch ceph_x_encrypt() to ceph_crypt()
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit d03857c63bb036edff0aa7a107276360173aca4e upstream.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |   71 ++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 37 insertions(+), 34 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -49,22 +49,24 @@ static int ceph_x_encrypt_buflen(int ile
+       return ceph_x_encrypt_offset() + ilen + 16;
+ }
+-static int ceph_x_encrypt(struct ceph_crypto_key *secret,
+-                        void *ibuf, int ilen, void *obuf, size_t olen)
++static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
++                        int buf_len, int plaintext_len)
+ {
+-      struct ceph_x_encrypt_header head = {
+-              .struct_v = 1,
+-              .magic = cpu_to_le64(CEPHX_ENC_MAGIC)
+-      };
+-      size_t len = olen - sizeof(u32);
++      struct ceph_x_encrypt_header *hdr = buf + sizeof(u32);
++      int ciphertext_len;
+       int ret;
+-      ret = ceph_encrypt2(secret, obuf + sizeof(u32), &len,
+-                          &head, sizeof(head), ibuf, ilen);
++      hdr->struct_v = 1;
++      hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC);
++
++      ret = ceph_crypt(secret, true, buf + sizeof(u32), buf_len - sizeof(u32),
++                       plaintext_len + sizeof(struct ceph_x_encrypt_header),
++                       &ciphertext_len);
+       if (ret)
+               return ret;
+-      ceph_encode_32(&obuf, len);
+-      return len + sizeof(u32);
++
++      ceph_encode_32(&buf, ciphertext_len);
++      return sizeof(u32) + ciphertext_len;
+ }
+ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
+@@ -296,7 +298,7 @@ static int ceph_x_build_authorizer(struc
+ {
+       int maxlen;
+       struct ceph_x_authorize_a *msg_a;
+-      struct ceph_x_authorize_b msg_b;
++      struct ceph_x_authorize_b *msg_b;
+       void *p, *end;
+       int ret;
+       int ticket_blob_len =
+@@ -311,7 +313,7 @@ static int ceph_x_build_authorizer(struc
+               goto out_au;
+       maxlen = sizeof(*msg_a) + ticket_blob_len +
+-              ceph_x_encrypt_buflen(sizeof(msg_b));
++              ceph_x_encrypt_buflen(sizeof(*msg_b));
+       dout("  need len %d\n", maxlen);
+       if (au->buf && au->buf->alloc_len < maxlen) {
+               ceph_buffer_put(au->buf);
+@@ -345,11 +347,11 @@ static int ceph_x_build_authorizer(struc
+       p += ticket_blob_len;
+       end = au->buf->vec.iov_base + au->buf->vec.iov_len;
++      msg_b = p + ceph_x_encrypt_offset();
++      msg_b->struct_v = 1;
+       get_random_bytes(&au->nonce, sizeof(au->nonce));
+-      msg_b.struct_v = 1;
+-      msg_b.nonce = cpu_to_le64(au->nonce);
+-      ret = ceph_x_encrypt(&au->session_key, &msg_b, sizeof(msg_b),
+-                           p, end - p);
++      msg_b->nonce = cpu_to_le64(au->nonce);
++      ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b));
+       if (ret < 0)
+               goto out_au;
+@@ -455,8 +457,9 @@ static int ceph_x_build_request(struct c
+       if (need & CEPH_ENTITY_TYPE_AUTH) {
+               struct ceph_x_authenticate *auth = (void *)(head + 1);
+               void *p = auth + 1;
+-              struct ceph_x_challenge_blob tmp;
+-              char tmp_enc[40];
++              void *enc_buf = xi->auth_authorizer.enc_buf;
++              struct ceph_x_challenge_blob *blob = enc_buf +
++                                                      ceph_x_encrypt_offset();
+               u64 *u;
+               if (p > end)
+@@ -467,16 +470,16 @@ static int ceph_x_build_request(struct c
+               /* encrypt and hash */
+               get_random_bytes(&auth->client_challenge, sizeof(u64));
+-              tmp.client_challenge = auth->client_challenge;
+-              tmp.server_challenge = cpu_to_le64(xi->server_challenge);
+-              ret = ceph_x_encrypt(&xi->secret, &tmp, sizeof(tmp),
+-                                   tmp_enc, sizeof(tmp_enc));
++              blob->client_challenge = auth->client_challenge;
++              blob->server_challenge = cpu_to_le64(xi->server_challenge);
++              ret = ceph_x_encrypt(&xi->secret, enc_buf, CEPHX_AU_ENC_BUF_LEN,
++                                   sizeof(*blob));
+               if (ret < 0)
+                       return ret;
+               auth->struct_v = 1;
+               auth->key = 0;
+-              for (u = (u64 *)tmp_enc; u + 1 <= (u64 *)(tmp_enc + ret); u++)
++              for (u = (u64 *)enc_buf; u + 1 <= (u64 *)(enc_buf + ret); u++)
+                       auth->key ^= *(__le64 *)u;
+               dout(" server_challenge %llx client_challenge %llx key %llx\n",
+                    xi->server_challenge, le64_to_cpu(auth->client_challenge),
+@@ -710,27 +713,27 @@ static void ceph_x_invalidate_authorizer
+ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
+                         __le64 *psig)
+ {
+-      char tmp_enc[40];
++      void *enc_buf = au->enc_buf;
+       struct {
+               __le32 len;
+               __le32 header_crc;
+               __le32 front_crc;
+               __le32 middle_crc;
+               __le32 data_crc;
+-      } __packed sigblock;
++      } __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
+       int ret;
+-      sigblock.len = cpu_to_le32(4*sizeof(u32));
+-      sigblock.header_crc = msg->hdr.crc;
+-      sigblock.front_crc = msg->footer.front_crc;
+-      sigblock.middle_crc = msg->footer.middle_crc;
+-      sigblock.data_crc =  msg->footer.data_crc;
+-      ret = ceph_x_encrypt(&au->session_key, &sigblock, sizeof(sigblock),
+-                           tmp_enc, sizeof(tmp_enc));
++      sigblock->len = cpu_to_le32(4*sizeof(u32));
++      sigblock->header_crc = msg->hdr.crc;
++      sigblock->front_crc = msg->footer.front_crc;
++      sigblock->middle_crc = msg->footer.middle_crc;
++      sigblock->data_crc =  msg->footer.data_crc;
++      ret = ceph_x_encrypt(&au->session_key, enc_buf, CEPHX_AU_ENC_BUF_LEN,
++                           sizeof(*sigblock));
+       if (ret < 0)
+               return ret;
+-      *psig = *(__le64 *)(tmp_enc + sizeof(u32));
++      *psig = *(__le64 *)(enc_buf + sizeof(u32));
+       return 0;
+ }
diff --git a/queue-4.9/libceph-tweak-calcu_signature-a-little.patch b/queue-4.9/libceph-tweak-calcu_signature-a-little.patch
new file mode 100644 (file)
index 0000000..1215c55
--- /dev/null
@@ -0,0 +1,96 @@
+From 4eb4517ce7c9c573b6c823de403aeccb40018cfc Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Fri, 2 Dec 2016 16:35:07 +0100
+Subject: libceph: tweak calcu_signature() a little
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 4eb4517ce7c9c573b6c823de403aeccb40018cfc upstream.
+
+- replace an ad-hoc array with a struct
+- rename to calc_signature() for consistency
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |   43 ++++++++++++++++++++++++++++---------------
+ 1 file changed, 28 insertions(+), 15 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -707,35 +707,48 @@ static void ceph_x_invalidate_authorizer
+       invalidate_ticket(ac, CEPH_ENTITY_TYPE_AUTH);
+ }
+-static int calcu_signature(struct ceph_x_authorizer *au,
+-                         struct ceph_msg *msg, __le64 *sig)
++static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
++                        __le64 *psig)
+ {
+-      int ret;
+       char tmp_enc[40];
+-      __le32 tmp[5] = {
+-              cpu_to_le32(16), msg->hdr.crc, msg->footer.front_crc,
+-              msg->footer.middle_crc, msg->footer.data_crc,
+-      };
+-      ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp),
++      struct {
++              __le32 len;
++              __le32 header_crc;
++              __le32 front_crc;
++              __le32 middle_crc;
++              __le32 data_crc;
++      } __packed sigblock;
++      int ret;
++
++      sigblock.len = cpu_to_le32(4*sizeof(u32));
++      sigblock.header_crc = msg->hdr.crc;
++      sigblock.front_crc = msg->footer.front_crc;
++      sigblock.middle_crc = msg->footer.middle_crc;
++      sigblock.data_crc =  msg->footer.data_crc;
++      ret = ceph_x_encrypt(&au->session_key, &sigblock, sizeof(sigblock),
+                            tmp_enc, sizeof(tmp_enc));
+       if (ret < 0)
+               return ret;
+-      *sig = *(__le64*)(tmp_enc + 4);
++
++      *psig = *(__le64 *)(tmp_enc + sizeof(u32));
+       return 0;
+ }
+ static int ceph_x_sign_message(struct ceph_auth_handshake *auth,
+                              struct ceph_msg *msg)
+ {
++      __le64 sig;
+       int ret;
+       if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
+               return 0;
+-      ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
+-                            msg, &msg->footer.sig);
+-      if (ret < 0)
++      ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer,
++                           msg, &sig);
++      if (ret)
+               return ret;
++
++      msg->footer.sig = sig;
+       msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED;
+       return 0;
+ }
+@@ -749,9 +762,9 @@ static int ceph_x_check_message_signatur
+       if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
+               return 0;
+-      ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
+-                            msg, &sig_check);
+-      if (ret < 0)
++      ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer,
++                           msg, &sig_check);
++      if (ret)
+               return ret;
+       if (sig_check == msg->footer.sig)
+               return 0;
index 78983c6ad0094c4f1fe364e12378aa442860a3b5..0d7c60ab699f69e59678f7bb68f9e658bb0a06f1 100644 (file)
@@ -72,3 +72,13 @@ arm64-ptrace-preserve-previous-registers-for-short-regset-write-2.patch
 arm64-ptrace-preserve-previous-registers-for-short-regset-write-3.patch
 arm64-ptrace-avoid-uninitialised-struct-padding-in-fpr_set.patch
 arm64-ptrace-reject-attempts-to-set-incomplete-hardware-breakpoint-fields.patch
+input-alps-fix-trackstick-support-for-ss5-hardware.patch
+libceph-ceph_x_encrypt_buflen-takes-in_len.patch
+libceph-old_key-in-process_one_ticket-is-redundant.patch
+libceph-introduce-ceph_x_encrypt_offset.patch
+libceph-introduce-ceph_crypt-for-in-place-en-decryption.patch
+libceph-rename-and-align-ceph_x_authorizer-reply_buf.patch
+libceph-tweak-calcu_signature-a-little.patch
+libceph-switch-ceph_x_encrypt-to-ceph_crypt.patch
+libceph-switch-ceph_x_decrypt-to-ceph_crypt.patch
+libceph-remove-now-unused-ceph_-en-de-crypt-functions.patch