Pull ceph updates from Ilya Dryomov: - some messenger improvements (Eric and Max) - address an issue (also affected userspace) of incorrect permissions being granted to users who have access to multiple different CephFS instances within the same cluster (Kotresh) - a bunch of assorted CephFS fixes (Slava) * tag 'ceph-for-6.18-rc1' of https://github.com/ceph/ceph-client: ceph: add bug tracking system info to MAINTAINERS ceph: fix multifs mds auth caps issue ceph: cleanup in ceph_alloc_readdir_reply_buffer() ceph: fix potential NULL dereference issue in ceph_fill_trace() libceph: add empty check to ceph_con_get_out_msg() libceph: pass the message pointer instead of loading con->out_msg libceph: make ceph_con_get_out_msg() return the message pointer ceph: fix potential race condition on operations with CEPH_I_ODIRECT flag ceph: refactor wake_up_bit() pattern of calling ceph: fix potential race condition in ceph_ioctl_lazyio() ceph: fix overflowed constant issue in ceph_do_objects_copy() ceph: fix wrong sizeof argument issue in register_session() ceph: add checking of wait_for_completion_killable() return value ceph: make ceph_start_io_*() killable libceph: Use HMAC-SHA256 library instead of crypto_shash
Unified · Split
| @@ -5694,6 +5694,7 @@ M: Xiubo Li <xiubli@redhat.com> · 5693 unmodified lines | ||
| 5694 | 5694 | L: ceph-devel@vger.kernel.org |
| 5695 | 5695 | S: Supported |
| 5696 | 5696 | W: http://ceph.com/ |
| 5697 | +B: https://tracker.ceph.com/ | |
| 5697 | 5698 | T: git https://github.com/ceph/ceph-client.git |
| 5698 | 5699 | F: include/linux/ceph/ |
| 5699 | 5700 | F: include/linux/crush/ |
| @@ -5705,6 +5706,7 @@ M: Ilya Dryomov <idryomov@gmail.com> · 5 unmodified lines | ||
| 5705 | 5706 | L: ceph-devel@vger.kernel.org |
| 5706 | 5707 | S: Supported |
| 5707 | 5708 | W: http://ceph.com/ |
| 5709 | +B: https://tracker.ceph.com/ | |
| 5708 | 5710 | T: git https://github.com/ceph/ceph-client.git |
| 5709 | 5711 | F: Documentation/filesystems/ceph.rst |
| 5710 | 5712 | F: fs/ceph/ |
| @@ -21357,6 +21359,7 @@ R: Dongsheng Yang <dongsheng.yang@easystack.cn> · 15646 unmodified lines | ||
| 21357 | 21359 | L: ceph-devel@vger.kernel.org |
| 21358 | 21360 | S: Supported |
| 21359 | 21361 | W: http://ceph.com/ |
| 21362 | +B: https://tracker.ceph.com/ | |
| 21360 | 21363 | T: git https://github.com/ceph/ceph-client.git |
| 21361 | 21364 | F: Documentation/ABI/testing/sysfs-bus-rbd |
| 21362 | 21365 | F: drivers/block/rbd.c |
| @@ -1260,8 +1260,7 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc, · 1259 unmodified lines | ||
| 1260 | 1260 | spin_unlock(&fsc->async_unlink_conflict_lock); |
| 1261 | 1261 | |
| 1262 | 1262 | spin_lock(&dentry->d_lock); |
| 1263 | − di->flags &= ~CEPH_DENTRY_ASYNC_UNLINK; | |
| 1264 | − wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT); | |
| 1263 | + clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags); | |
| 1265 | 1264 | spin_unlock(&dentry->d_lock); |
| 1266 | 1265 | |
| 1267 | 1266 | synchronize_rcu(); |
| @@ -579,8 +579,7 @@ static void wake_async_create_waiters(struct inode *inode, · 578 unmodified lines | ||
| 579 | 579 | |
| 580 | 580 | spin_lock(&ci->i_ceph_lock); |
| 581 | 581 | if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) { |
| 582 | − ci->i_ceph_flags &= ~CEPH_I_ASYNC_CREATE; | |
| 583 | − wake_up_bit(&ci->i_ceph_flags, CEPH_ASYNC_CREATE_BIT); | |
| 582 | + clear_and_wake_up_bit(CEPH_ASYNC_CREATE_BIT, &ci->i_ceph_flags); | |
| 584 | 583 | |
| 585 | 584 | if (ci->i_ceph_flags & CEPH_I_ASYNC_CHECK_CAPS) { |
| 586 | 585 | ci->i_ceph_flags &= ~CEPH_I_ASYNC_CHECK_CAPS; |
| @@ -762,8 +761,7 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode, · 175 unmodified lines | ||
| 762 | 761 | } |
| 763 | 762 | |
| 764 | 763 | spin_lock(&dentry->d_lock); |
| 765 | − di->flags &= ~CEPH_DENTRY_ASYNC_CREATE; | |
| 766 | − wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_CREATE_BIT); | |
| 764 | + clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_CREATE_BIT, &di->flags); | |
| 767 | 765 | spin_unlock(&dentry->d_lock); |
| 768 | 766 | |
| 769 | 767 | return ret; |
| @@ -2121,10 +2119,10 @@ again: · 1351 unmodified lines | ||
| 2121 | 2119 | if (ceph_inode_is_shutdown(inode)) |
| 2122 | 2120 | return -ESTALE; |
| 2123 | 2121 | |
| 2124 | − if (direct_lock) | |
| 2125 | − ceph_start_io_direct(inode); | |
| 2126 | − else | |
| 2127 | − ceph_start_io_read(inode); | |
| 2122 | + ret = direct_lock ? ceph_start_io_direct(inode) : | |
| 2123 | + ceph_start_io_read(inode); | |
| 2124 | + if (ret) | |
| 2125 | + return ret; | |
| 2128 | 2126 | |
| 2129 | 2127 | if (!(fi->flags & CEPH_F_SYNC) && !direct_lock) |
| 2130 | 2128 | want |= CEPH_CAP_FILE_CACHE; |
| @@ -2277,7 +2275,9 @@ static ssize_t ceph_splice_read(struct file *in, loff_t *ppos, · 146 unmodified lines | ||
| 2277 | 2275 | (fi->flags & CEPH_F_SYNC)) |
| 2278 | 2276 | return copy_splice_read(in, ppos, pipe, len, flags); |
| 2279 | 2277 | |
| 2280 | − ceph_start_io_read(inode); | |
| 2278 | + ret = ceph_start_io_read(inode); | |
| 2279 | + if (ret) | |
| 2280 | + return ret; | |
| 2281 | 2281 | |
| 2282 | 2282 | want = CEPH_CAP_FILE_CACHE; |
| 2283 | 2283 | if (fi->fmode & CEPH_FILE_MODE_LAZY) |
| @@ -2356,10 +2356,10 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) · 72 unmodified lines | ||
| 2356 | 2356 | direct_lock = true; |
| 2357 | 2357 | |
| 2358 | 2358 | retry_snap: |
| 2359 | − if (direct_lock) | |
| 2360 | − ceph_start_io_direct(inode); | |
| 2361 | − else | |
| 2362 | − ceph_start_io_write(inode); | |
| 2359 | + err = direct_lock ? ceph_start_io_direct(inode) : | |
| 2360 | + ceph_start_io_write(inode); | |
| 2361 | + if (err) | |
| 2362 | + goto out_unlocked; | |
| 2363 | 2363 | |
| 2364 | 2364 | if (iocb->ki_flags & IOCB_APPEND) { |
| 2365 | 2365 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE, false); |
| @@ -2878,7 +2878,7 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off · 512 unmodified lines | ||
| 2878 | 2878 | struct ceph_object_id src_oid, dst_oid; |
| 2879 | 2879 | struct ceph_osd_client *osdc; |
| 2880 | 2880 | struct ceph_osd_request *req; |
| 2881 | − size_t bytes = 0; | |
| 2881 | + ssize_t bytes = 0; | |
| 2882 | 2882 | u64 src_objnum, src_objoff, dst_objnum, dst_objoff; |
| 2883 | 2883 | u32 src_objlen, dst_objlen; |
| 2884 | 2884 | u32 object_size = src_ci->i_layout.object_size; |
| @@ -2928,7 +2928,7 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off · 43 unmodified lines | ||
| 2928 | 2928 | "OSDs don't support copy-from2; disabling copy offload\n"); |
| 2929 | 2929 | } |
| 2930 | 2930 | doutc(cl, "returned %d\n", ret); |
| 2931 | − if (!bytes) | |
| 2931 | + if (bytes <= 0) | |
| 2932 | 2932 | bytes = ret; |
| 2933 | 2933 | goto out; |
| 2934 | 2934 | } |
| @@ -1794,6 +1794,11 @@ retry_lookup: · 1793 unmodified lines | ||
| 1794 | 1794 | goto done; |
| 1795 | 1795 | } |
| 1796 | 1796 | |
| 1797 | + if (unlikely(!in)) { | |
| 1798 | + err = -EINVAL; | |
| 1799 | + goto done; | |
| 1800 | + } | |
| 1801 | + | |
| 1797 | 1802 | /* attach proper inode */ |
| 1798 | 1803 | if (d_really_is_negative(dn)) { |
| 1799 | 1804 | ceph_dir_clear_ordered(dir); |
| @@ -1829,6 +1834,12 @@ retry_lookup: · 29 unmodified lines | ||
| 1829 | 1834 | doutc(cl, " linking snapped dir %p to dn %p\n", in, |
| 1830 | 1835 | req->r_dentry); |
| 1831 | 1836 | ceph_dir_clear_ordered(dir); |
| 1837 | + | |
| 1838 | + if (unlikely(!in)) { | |
| 1839 | + err = -EINVAL; | |
| 1840 | + goto done; | |
| 1841 | + } | |
| 1842 | + | |
| 1832 | 1843 | ihold(in); |
| 1833 | 1844 | err = splice_dentry(&req->r_dentry, in); |
| 1834 | 1845 | if (err < 0) |
| @@ -21,14 +21,23 @@ · 20 unmodified lines | ||
| 21 | 21 | /* Call with exclusively locked inode->i_rwsem */ |
| 22 | 22 | static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode) |
| 23 | 23 | { |
| 24 | + bool is_odirect; | |
| 25 | + | |
| 24 | 26 | lockdep_assert_held_write(&inode->i_rwsem); |
| 25 | 27 | |
| 26 | − if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) { | |
| 27 | − spin_lock(&ci->i_ceph_lock); | |
| 28 | − ci->i_ceph_flags &= ~CEPH_I_ODIRECT; | |
| 29 | − spin_unlock(&ci->i_ceph_lock); | |
| 30 | − inode_dio_wait(inode); | |
| 28 | + spin_lock(&ci->i_ceph_lock); | |
| 29 | + /* ensure that bit state is consistent */ | |
| 30 | + smp_mb__before_atomic(); | |
| 31 | + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; | |
| 32 | + if (is_odirect) { | |
| 33 | + clear_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags); | |
| 34 | + /* ensure modified bit is visible */ | |
| 35 | + smp_mb__after_atomic(); | |
| 31 | 36 | } |
| 37 | + spin_unlock(&ci->i_ceph_lock); | |
| 38 | + | |
| 39 | + if (is_odirect) | |
| 40 | + inode_dio_wait(inode); | |
| 32 | 41 | } |
| 33 | 42 | |
| 34 | 43 | /** |
| @@ -47,20 +56,35 @@ static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode) · 12 unmodified lines | ||
| 47 | 56 | * Note that buffered writes and truncates both take a write lock on |
| 48 | 57 | * inode->i_rwsem, meaning that those are serialised w.r.t. the reads. |
| 49 | 58 | */ |
| 50 | −void | |
| 51 | −ceph_start_io_read(struct inode *inode) | |
| 59 | +int ceph_start_io_read(struct inode *inode) | |
| 52 | 60 | { |
| 53 | 61 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 62 | + bool is_odirect; | |
| 63 | + int err; | |
| 54 | 64 | |
| 55 | 65 | /* Be an optimist! */ |
| 56 | − down_read(&inode->i_rwsem); | |
| 57 | − if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) | |
| 58 | − return; | |
| 66 | + err = down_read_killable(&inode->i_rwsem); | |
| 67 | + if (err) | |
| 68 | + return err; | |
| 69 | + | |
| 70 | + spin_lock(&ci->i_ceph_lock); | |
| 71 | + /* ensure that bit state is consistent */ | |
| 72 | + smp_mb__before_atomic(); | |
| 73 | + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; | |
| 74 | + spin_unlock(&ci->i_ceph_lock); | |
| 75 | + if (!is_odirect) | |
| 76 | + return 0; | |
| 59 | 77 | up_read(&inode->i_rwsem); |
| 78 | + | |
| 60 | 79 | /* Slow path.... */ |
| 61 | − down_write(&inode->i_rwsem); | |
| 80 | + err = down_write_killable(&inode->i_rwsem); | |
| 81 | + if (err) | |
| 82 | + return err; | |
| 83 | + | |
| 62 | 84 | ceph_block_o_direct(ci, inode); |
| 63 | 85 | downgrade_write(&inode->i_rwsem); |
| 86 | + | |
| 87 | + return 0; | |
| 64 | 88 | } |
| 65 | 89 | |
| 66 | 90 | /** |
| @@ -83,11 +107,12 @@ ceph_end_io_read(struct inode *inode) · 16 unmodified lines | ||
| 83 | 107 | * Declare that a buffered write operation is about to start, and ensure |
| 84 | 108 | * that we block all direct I/O. |
| 85 | 109 | */ |
| 86 | −void | |
| 87 | −ceph_start_io_write(struct inode *inode) | |
| 110 | +int ceph_start_io_write(struct inode *inode) | |
| 88 | 111 | { |
| 89 | − down_write(&inode->i_rwsem); | |
| 90 | − ceph_block_o_direct(ceph_inode(inode), inode); | |
| 112 | + int err = down_write_killable(&inode->i_rwsem); | |
| 113 | + if (!err) | |
| 114 | + ceph_block_o_direct(ceph_inode(inode), inode); | |
| 115 | + return err; | |
| 91 | 116 | } |
| 92 | 117 | |
| 93 | 118 | /** |
| @@ -106,12 +131,22 @@ ceph_end_io_write(struct inode *inode) · 12 unmodified lines | ||
| 106 | 131 | /* Call with exclusively locked inode->i_rwsem */ |
| 107 | 132 | static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode) |
| 108 | 133 | { |
| 134 | + bool is_odirect; | |
| 135 | + | |
| 109 | 136 | lockdep_assert_held_write(&inode->i_rwsem); |
| 110 | 137 | |
| 111 | − if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) { | |
| 112 | − spin_lock(&ci->i_ceph_lock); | |
| 113 | − ci->i_ceph_flags |= CEPH_I_ODIRECT; | |
| 114 | − spin_unlock(&ci->i_ceph_lock); | |
| 138 | + spin_lock(&ci->i_ceph_lock); | |
| 139 | + /* ensure that bit state is consistent */ | |
| 140 | + smp_mb__before_atomic(); | |
| 141 | + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; | |
| 142 | + if (!is_odirect) { | |
| 143 | + set_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags); | |
| 144 | + /* ensure modified bit is visible */ | |
| 145 | + smp_mb__after_atomic(); | |
| 146 | + } | |
| 147 | + spin_unlock(&ci->i_ceph_lock); | |
| 148 | + | |
| 149 | + if (!is_odirect) { | |
| 115 | 150 | /* FIXME: unmap_mapping_range? */ |
| 116 | 151 | filemap_write_and_wait(inode->i_mapping); |
| 117 | 152 | } |
| @@ -133,20 +168,35 @@ static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode) · 15 unmodified lines | ||
| 133 | 168 | * Note that buffered writes and truncates both take a write lock on |
| 134 | 169 | * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT. |
| 135 | 170 | */ |
| 136 | −void | |
| 137 | −ceph_start_io_direct(struct inode *inode) | |
| 171 | +int ceph_start_io_direct(struct inode *inode) | |
| 138 | 172 | { |
| 139 | 173 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 174 | + bool is_odirect; | |
| 175 | + int err; | |
| 140 | 176 | |
| 141 | 177 | /* Be an optimist! */ |
| 142 | − down_read(&inode->i_rwsem); | |
| 143 | − if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) | |
| 144 | − return; | |
| 178 | + err = down_read_killable(&inode->i_rwsem); | |
| 179 | + if (err) | |
| 180 | + return err; | |
| 181 | + | |
| 182 | + spin_lock(&ci->i_ceph_lock); | |
| 183 | + /* ensure that bit state is consistent */ | |
| 184 | + smp_mb__before_atomic(); | |
| 185 | + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; | |
| 186 | + spin_unlock(&ci->i_ceph_lock); | |
| 187 | + if (is_odirect) | |
| 188 | + return 0; | |
| 145 | 189 | up_read(&inode->i_rwsem); |
| 190 | + | |
| 146 | 191 | /* Slow path.... */ |
| 147 | − down_write(&inode->i_rwsem); | |
| 192 | + err = down_write_killable(&inode->i_rwsem); | |
| 193 | + if (err) | |
| 194 | + return err; | |
| 195 | + | |
| 148 | 196 | ceph_block_buffered(ci, inode); |
| 149 | 197 | downgrade_write(&inode->i_rwsem); |
| 198 | + | |
| 199 | + return 0; | |
| 150 | 200 | } |
| 151 | 201 | |
| 152 | 202 | /** |
| @@ -2,11 +2,13 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef _FS_CEPH_IO_H |
| 3 | 3 | #define _FS_CEPH_IO_H |
| 4 | 4 | |
| 5 | −void ceph_start_io_read(struct inode *inode); | |
| 5 | +#include <linux/compiler_attributes.h> | |
| 6 | + | |
| 7 | +int __must_check ceph_start_io_read(struct inode *inode); | |
| 6 | 8 | void ceph_end_io_read(struct inode *inode); |
| 7 | −void ceph_start_io_write(struct inode *inode); | |
| 9 | +int __must_check ceph_start_io_write(struct inode *inode); | |
| 8 | 10 | void ceph_end_io_write(struct inode *inode); |
| 9 | −void ceph_start_io_direct(struct inode *inode); | |
| 11 | +int __must_check ceph_start_io_direct(struct inode *inode); | |
| 10 | 12 | void ceph_end_io_direct(struct inode *inode); |
| 11 | 13 | |
| 12 | 14 | #endif /* FS_CEPH_IO_H */ |
| @@ -246,21 +246,28 @@ static long ceph_ioctl_lazyio(struct file *file) · 245 unmodified lines | ||
| 246 | 246 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 247 | 247 | struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; |
| 248 | 248 | struct ceph_client *cl = mdsc->fsc->client; |
| 249 | + bool is_file_already_lazy = false; | |
| 249 | 250 | |
| 251 | + spin_lock(&ci->i_ceph_lock); | |
| 250 | 252 | if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { |
| 251 | − spin_lock(&ci->i_ceph_lock); | |
| 252 | 253 | fi->fmode |= CEPH_FILE_MODE_LAZY; |
| 253 | 254 | ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++; |
| 254 | 255 | __ceph_touch_fmode(ci, mdsc, fi->fmode); |
| 255 | − spin_unlock(&ci->i_ceph_lock); | |
| 256 | + } else { | |
| 257 | + is_file_already_lazy = true; | |
| 258 | + } | |
| 259 | + spin_unlock(&ci->i_ceph_lock); | |
| 260 | + | |
| 261 | + if (is_file_already_lazy) { | |
| 262 | + doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode, | |
| 263 | + ceph_vinop(inode)); | |
| 264 | + } else { | |
| 256 | 265 | doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode, |
| 257 | 266 | ceph_vinop(inode)); |
| 258 | 267 | |
| 259 | 268 | ceph_check_caps(ci, 0); |
| 260 | − } else { | |
| 261 | − doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode, | |
| 262 | − ceph_vinop(inode)); | |
| 263 | 269 | } |
| 270 | + | |
| 264 | 271 | return 0; |
| 265 | 272 | } |
| 266 | 273 | |
| @@ -221,7 +221,10 @@ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc, · 220 unmodified lines | ||
| 221 | 221 | if (err && err != -ERESTARTSYS) |
| 222 | 222 | return err; |
| 223 | 223 | |
| 224 | − wait_for_completion_killable(&req->r_safe_completion); | |
| 224 | + err = wait_for_completion_killable(&req->r_safe_completion); | |
| 225 | + if (err) | |
| 226 | + return err; | |
| 227 | + | |
| 225 | 228 | return 0; |
| 226 | 229 | } |
| 227 | 230 | |
| @@ -979,14 +979,15 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, · 978 unmodified lines | ||
| 979 | 979 | if (mds >= mdsc->max_sessions) { |
| 980 | 980 | int newmax = 1 << get_count_order(mds + 1); |
| 981 | 981 | struct ceph_mds_session **sa; |
| 982 | + size_t ptr_size = sizeof(struct ceph_mds_session *); | |
| 982 | 983 | |
| 983 | 984 | doutc(cl, "realloc to %d\n", newmax); |
| 984 | − sa = kcalloc(newmax, sizeof(void *), GFP_NOFS); | |
| 985 | + sa = kcalloc(newmax, ptr_size, GFP_NOFS); | |
| 985 | 986 | if (!sa) |
| 986 | 987 | goto fail_realloc; |
| 987 | 988 | if (mdsc->sessions) { |
| 988 | 989 | memcpy(sa, mdsc->sessions, |
| 989 | − mdsc->max_sessions * sizeof(void *)); | |
| 990 | + mdsc->max_sessions * ptr_size); | |
| 990 | 991 | kfree(mdsc->sessions); |
| 991 | 992 | } |
| 992 | 993 | mdsc->sessions = sa; |
| @@ -2532,6 +2533,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req, · 1539 unmodified lines | ||
| 2532 | 2533 | struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options; |
| 2533 | 2534 | size_t size = sizeof(struct ceph_mds_reply_dir_entry); |
| 2534 | 2535 | unsigned int num_entries; |
| 2536 | + u64 bytes_count; | |
| 2535 | 2537 | int order; |
| 2536 | 2538 | |
| 2537 | 2539 | spin_lock(&ci->i_ceph_lock); |
| @@ -2540,7 +2542,11 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req, · 2 unmodified lines | ||
| 2540 | 2542 | num_entries = max(num_entries, 1U); |
| 2541 | 2543 | num_entries = min(num_entries, opt->max_readdir); |
| 2542 | 2544 | |
| 2543 | − order = get_order(size * num_entries); | |
| 2545 | + bytes_count = (u64)size * num_entries; | |
| 2546 | + if (unlikely(bytes_count > ULONG_MAX)) | |
| 2547 | + bytes_count = ULONG_MAX; | |
| 2548 | + | |
| 2549 | + order = get_order((unsigned long)bytes_count); | |
| 2544 | 2550 | while (order >= 0) { |
| 2545 | 2551 | rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL | |
| 2546 | 2552 | __GFP_NOWARN | |
| @@ -2550,7 +2556,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req, · 3 unmodified lines | ||
| 2550 | 2556 | break; |
| 2551 | 2557 | order--; |
| 2552 | 2558 | } |
| 2553 | − if (!rinfo->dir_entries) | |
| 2559 | + if (!rinfo->dir_entries || unlikely(order < 0)) | |
| 2554 | 2560 | return -ENOMEM; |
| 2555 | 2561 | |
| 2556 | 2562 | num_entries = (PAGE_SIZE << order) / size; |
| @@ -5649,11 +5655,19 @@ static int ceph_mds_auth_match(struct ceph_mds_client *mdsc, · 3092 unmodified lines | ||
| 5649 | 5655 | u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid); |
| 5650 | 5656 | u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid); |
| 5651 | 5657 | struct ceph_client *cl = mdsc->fsc->client; |
| 5658 | + const char *fs_name = mdsc->fsc->mount_options->mds_namespace; | |
| 5652 | 5659 | const char *spath = mdsc->fsc->mount_options->server_path; |
| 5653 | 5660 | bool gid_matched = false; |
| 5654 | 5661 | u32 gid, tlen, len; |
| 5655 | 5662 | int i, j; |
| 5656 | 5663 | |
| 5664 | + doutc(cl, "fsname check fs_name=%s match.fs_name=%s\n", | |
| 5665 | + fs_name, auth->match.fs_name ? auth->match.fs_name : ""); | |
| 5666 | + if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) { | |
| 5667 | + /* fsname mismatch, try next one */ | |
| 5668 | + return 0; | |
| 5669 | + } | |
| 5670 | + | |
| 5657 | 5671 | doutc(cl, "match.uid %lld\n", auth->match.uid); |
| 5658 | 5672 | if (auth->match.uid != MDS_AUTH_UID_ANY) { |
| 5659 | 5673 | if (auth->match.uid != caller_uid) |
| @@ -353,10 +353,22 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, · 352 unmodified lines | ||
| 353 | 353 | __decode_and_drop_type(p, end, u8, bad_ext); |
| 354 | 354 | } |
| 355 | 355 | if (mdsmap_ev >= 8) { |
| 356 | + u32 fsname_len; | |
| 356 | 357 | /* enabled */ |
| 357 | 358 | ceph_decode_8_safe(p, end, m->m_enabled, bad_ext); |
| 358 | 359 | /* fs_name */ |
| 359 | − ceph_decode_skip_string(p, end, bad_ext); | |
| 360 | + ceph_decode_32_safe(p, end, fsname_len, bad_ext); | |
| 361 | + | |
| 362 | + /* validate fsname against mds_namespace */ | |
| 363 | + if (!namespace_equals(mdsc->fsc->mount_options, *p, | |
| 364 | + fsname_len)) { | |
| 365 | + pr_warn_client(cl, "fsname %*pE doesn't match mds_namespace %s\n", | |
| 366 | + (int)fsname_len, (char *)*p, | |
| 367 | + mdsc->fsc->mount_options->mds_namespace); | |
| 368 | + goto bad; | |
| 369 | + } | |
| 370 | + /* skip fsname after validation */ | |
| 371 | + ceph_decode_skip_n(p, end, fsname_len, bad); | |
| 360 | 372 | } |
| 361 | 373 | /* damaged */ |
| 362 | 374 | if (mdsmap_ev >= 9) { |
| @@ -246,20 +246,6 @@ static void canonicalize_path(char *path) · 245 unmodified lines | ||
| 246 | 246 | path[j] = '\0'; |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | −/* | |
| 250 | − * Check if the mds namespace in ceph_mount_options matches | |
| 251 | − * the passed in namespace string. First time match (when | |
| 252 | − * ->mds_namespace is NULL) is treated specially, since | |
| 253 | − * ->mds_namespace needs to be initialized by the caller. | |
| 254 | − */ | |
| 255 | −static int namespace_equals(struct ceph_mount_options *fsopt, | |
| 256 | − const char *namespace, size_t len) | |
| 257 | −{ | |
| 258 | − return !(fsopt->mds_namespace && | |
| 259 | − (strlen(fsopt->mds_namespace) != len || | |
| 260 | − strncmp(fsopt->mds_namespace, namespace, len))); | |
| 261 | −} | |
| 262 | − | |
| 263 | 249 | static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end, |
| 264 | 250 | struct fs_context *fc) |
| 265 | 251 | { |
| @@ -104,6 +104,20 @@ struct ceph_mount_options { · 103 unmodified lines | ||
| 104 | 104 | struct fscrypt_dummy_policy dummy_enc_policy; |
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | +/* | |
| 108 | + * Check if the mds namespace in ceph_mount_options matches | |
| 109 | + * the passed in namespace string. First time match (when | |
| 110 | + * ->mds_namespace is NULL) is treated specially, since | |
| 111 | + * ->mds_namespace needs to be initialized by the caller. | |
| 112 | + */ | |
| 113 | +static inline int namespace_equals(struct ceph_mount_options *fsopt, | |
| 114 | + const char *namespace, size_t len) | |
| 115 | +{ | |
| 116 | + return !(fsopt->mds_namespace && | |
| 117 | + (strlen(fsopt->mds_namespace) != len || | |
| 118 | + strncmp(fsopt->mds_namespace, namespace, len))); | |
| 119 | +} | |
| 120 | + | |
| 107 | 121 | /* mount state */ |
| 108 | 122 | enum { |
| 109 | 123 | CEPH_MOUNT_MOUNTING, |
| @@ -639,7 +653,8 @@ static inline struct inode *ceph_find_inode(struct super_block *sb, · 529 unmodified lines | ||
| 639 | 653 | #define CEPH_I_FLUSH_SNAPS (1 << 8) /* need flush snapss */ |
| 640 | 654 | #define CEPH_I_ERROR_WRITE (1 << 9) /* have seen write errors */ |
| 641 | 655 | #define CEPH_I_ERROR_FILELOCK (1 << 10) /* have seen file lock errors */ |
| 642 | −#define CEPH_I_ODIRECT (1 << 11) /* inode in direct I/O mode */ | |
| 656 | +#define CEPH_I_ODIRECT_BIT (11) /* inode in direct I/O mode */ | |
| 657 | +#define CEPH_I_ODIRECT (1 << CEPH_I_ODIRECT_BIT) | |
| 643 | 658 | #define CEPH_ASYNC_CREATE_BIT (12) /* async create in flight for this */ |
| 644 | 659 | #define CEPH_I_ASYNC_CREATE (1 << CEPH_ASYNC_CREATE_BIT) |
| 645 | 660 | #define CEPH_I_SHUTDOWN (1 << 13) /* inode is no longer usable */ |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef __FS_CEPH_MESSENGER_H |
| 3 | 3 | #define __FS_CEPH_MESSENGER_H |
| 4 | 4 | |
| 5 | +#include <crypto/sha2.h> | |
| 5 | 6 | #include <linux/bvec.h> |
| 6 | 7 | #include <linux/crypto.h> |
| 7 | 8 | #include <linux/kref.h> |
| @@ -412,7 +413,8 @@ struct ceph_connection_v2_info { · 404 unmodified lines | ||
| 412 | 413 | struct ceph_msg_data_cursor in_cursor; |
| 413 | 414 | struct ceph_msg_data_cursor out_cursor; |
| 414 | 415 | |
| 415 | − struct crypto_shash *hmac_tfm; /* post-auth signature */ | |
| 416 | + struct hmac_sha256_key hmac_key; /* post-auth signature */ | |
| 417 | + bool hmac_key_set; | |
| 416 | 418 | struct crypto_aead *gcm_tfm; /* on-wire encryption */ |
| 417 | 419 | struct aead_request *gcm_req; |
| 418 | 420 | struct crypto_wait gcm_wait; |
| @@ -548,12 +550,12 @@ void ceph_addr_set_port(struct ceph_entity_addr *addr, int p); · 129 unmodified lines | ||
| 548 | 550 | void ceph_con_process_message(struct ceph_connection *con); |
| 549 | 551 | int ceph_con_in_msg_alloc(struct ceph_connection *con, |
| 550 | 552 | struct ceph_msg_header *hdr, int *skip); |
| 551 | −void ceph_con_get_out_msg(struct ceph_connection *con); | |
| 553 | +struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con); | |
| 552 | 554 | |
| 553 | 555 | /* messenger_v1.c */ |
| 554 | 556 | int ceph_con_v1_try_read(struct ceph_connection *con); |
| 555 | 557 | int ceph_con_v1_try_write(struct ceph_connection *con); |
| 556 | −void ceph_con_v1_revoke(struct ceph_connection *con); | |
| 558 | +void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg); | |
| 557 | 559 | void ceph_con_v1_revoke_incoming(struct ceph_connection *con); |
| 558 | 560 | bool ceph_con_v1_opened(struct ceph_connection *con); |
| 559 | 561 | void ceph_con_v1_reset_session(struct ceph_connection *con); |
| @@ -562,7 +564,7 @@ void ceph_con_v1_reset_protocol(struct ceph_connection *con); · 2 unmodified lines | ||
| 562 | 564 | /* messenger_v2.c */ |
| 563 | 565 | int ceph_con_v2_try_read(struct ceph_connection *con); |
| 564 | 566 | int ceph_con_v2_try_write(struct ceph_connection *con); |
| 565 | −void ceph_con_v2_revoke(struct ceph_connection *con); | |
| 567 | +void ceph_con_v2_revoke(struct ceph_connection *con, struct ceph_msg *msg); | |
| 566 | 568 | void ceph_con_v2_revoke_incoming(struct ceph_connection *con); |
| 567 | 569 | bool ceph_con_v2_opened(struct ceph_connection *con); |
| 568 | 570 | void ceph_con_v2_reset_session(struct ceph_connection *con); |
| @@ -6,8 +6,7 @@ config CEPH_LIB · 5 unmodified lines | ||
| 6 | 6 | select CRYPTO_AES |
| 7 | 7 | select CRYPTO_CBC |
| 8 | 8 | select CRYPTO_GCM |
| 9 | − select CRYPTO_HMAC | |
| 10 | − select CRYPTO_SHA256 | |
| 9 | + select CRYPTO_LIB_SHA256 | |
| 11 | 10 | select CRYPTO |
| 12 | 11 | select KEYS |
| 13 | 12 | default n |
| @@ -1794,9 +1794,9 @@ void ceph_msg_revoke(struct ceph_msg *msg) · 1793 unmodified lines | ||
| 1794 | 1794 | WARN_ON(con->state != CEPH_CON_S_OPEN); |
| 1795 | 1795 | dout("%s con %p msg %p was sending\n", __func__, con, msg); |
| 1796 | 1796 | if (ceph_msgr2(from_msgr(con->msgr))) |
| 1797 | − ceph_con_v2_revoke(con); | |
| 1797 | + ceph_con_v2_revoke(con, msg); | |
| 1798 | 1798 | else |
| 1799 | − ceph_con_v1_revoke(con); | |
| 1799 | + ceph_con_v1_revoke(con, msg); | |
| 1800 | 1800 | ceph_msg_put(con->out_msg); |
| 1801 | 1801 | con->out_msg = NULL; |
| 1802 | 1802 | } else { |
| @@ -2111,11 +2111,13 @@ int ceph_con_in_msg_alloc(struct ceph_connection *con, · 308 unmodified lines | ||
| 2111 | 2111 | return ret; |
| 2112 | 2112 | } |
| 2113 | 2113 | |
| 2114 | −void ceph_con_get_out_msg(struct ceph_connection *con) | |
| 2114 | +struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con) | |
| 2115 | 2115 | { |
| 2116 | 2116 | struct ceph_msg *msg; |
| 2117 | 2117 | |
| 2118 | − BUG_ON(list_empty(&con->out_queue)); | |
| 2118 | + if (list_empty(&con->out_queue)) | |
| 2119 | + return NULL; | |
| 2120 | + | |
| 2119 | 2121 | msg = list_first_entry(&con->out_queue, struct ceph_msg, list_head); |
| 2120 | 2122 | WARN_ON(msg->con != con); |
| 2121 | 2123 | |
| @@ -2142,7 +2144,7 @@ void ceph_con_get_out_msg(struct ceph_connection *con) · 20 unmodified lines | ||
| 2142 | 2144 | * message or in case of a fault. |
| 2143 | 2145 | */ |
| 2144 | 2146 | WARN_ON(con->out_msg); |
| 2145 | − con->out_msg = ceph_msg_get(msg); | |
| 2147 | + return con->out_msg = ceph_msg_get(msg); | |
| 2146 | 2148 | } |
| 2147 | 2149 | |
| 2148 | 2150 | /* |
| @@ -169,10 +169,9 @@ static void prepare_message_data(struct ceph_msg *msg, u32 data_len) · 168 unmodified lines | ||
| 169 | 169 | * Prepare footer for currently outgoing message, and finish things |
| 170 | 170 | * off. Assumes out_kvec* are already valid.. we just add on to the end. |
| 171 | 171 | */ |
| 172 | −static void prepare_write_message_footer(struct ceph_connection *con) | |
| 172 | +static void prepare_write_message_footer(struct ceph_connection *con, | |
| 173 | + struct ceph_msg *m) | |
| 173 | 174 | { |
| 174 | − struct ceph_msg *m = con->out_msg; | |
| 175 | − | |
| 176 | 175 | m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; |
| 177 | 176 | |
| 178 | 177 | dout("prepare_write_message_footer %p\n", con); |
| @@ -192,9 +191,9 @@ static void prepare_write_message_footer(struct ceph_connection *con) · 13 unmodified lines | ||
| 192 | 191 | /* |
| 193 | 192 | * Prepare headers for the next outgoing message. |
| 194 | 193 | */ |
| 195 | −static void prepare_write_message(struct ceph_connection *con) | |
| 194 | +static void prepare_write_message(struct ceph_connection *con, | |
| 195 | + struct ceph_msg *m) | |
| 196 | 196 | { |
| 197 | − struct ceph_msg *m; | |
| 198 | 197 | u32 crc; |
| 199 | 198 | |
| 200 | 199 | con_out_kvec_reset(con); |
| @@ -210,9 +209,6 @@ static void prepare_write_message(struct ceph_connection *con) · 9 unmodified lines | ||
| 210 | 209 | &con->v1.out_temp_ack); |
| 211 | 210 | } |
| 212 | 211 | |
| 213 | − ceph_con_get_out_msg(con); | |
| 214 | − m = con->out_msg; | |
| 215 | − | |
| 216 | 212 | dout("prepare_write_message %p seq %lld type %d len %d+%d+%zd\n", |
| 217 | 213 | m, con->out_seq, le16_to_cpu(m->hdr.type), |
| 218 | 214 | le32_to_cpu(m->hdr.front_len), le32_to_cpu(m->hdr.middle_len), |
| @@ -231,31 +227,31 @@ static void prepare_write_message(struct ceph_connection *con) · 12 unmodified lines | ||
| 231 | 227 | |
| 232 | 228 | /* fill in hdr crc and finalize hdr */ |
| 233 | 229 | crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); |
| 234 | − con->out_msg->hdr.crc = cpu_to_le32(crc); | |
| 235 | − memcpy(&con->v1.out_hdr, &con->out_msg->hdr, sizeof(con->v1.out_hdr)); | |
| 230 | + m->hdr.crc = cpu_to_le32(crc); | |
| 231 | + memcpy(&con->v1.out_hdr, &m->hdr, sizeof(con->v1.out_hdr)); | |
| 236 | 232 | |
| 237 | 233 | /* fill in front and middle crc, footer */ |
| 238 | 234 | crc = crc32c(0, m->front.iov_base, m->front.iov_len); |
| 239 | − con->out_msg->footer.front_crc = cpu_to_le32(crc); | |
| 235 | + m->footer.front_crc = cpu_to_le32(crc); | |
| 240 | 236 | if (m->middle) { |
| 241 | 237 | crc = crc32c(0, m->middle->vec.iov_base, |
| 242 | 238 | m->middle->vec.iov_len); |
| 243 | − con->out_msg->footer.middle_crc = cpu_to_le32(crc); | |
| 239 | + m->footer.middle_crc = cpu_to_le32(crc); | |
| 244 | 240 | } else |
| 245 | − con->out_msg->footer.middle_crc = 0; | |
| 241 | + m->footer.middle_crc = 0; | |
| 246 | 242 | dout("%s front_crc %u middle_crc %u\n", __func__, |
| 247 | − le32_to_cpu(con->out_msg->footer.front_crc), | |
| 248 | − le32_to_cpu(con->out_msg->footer.middle_crc)); | |
| 249 | − con->out_msg->footer.flags = 0; | |
| 243 | + le32_to_cpu(m->footer.front_crc), | |
| 244 | + le32_to_cpu(m->footer.middle_crc)); | |
| 245 | + m->footer.flags = 0; | |
| 250 | 246 | |
| 251 | 247 | /* is there a data payload? */ |
| 252 | − con->out_msg->footer.data_crc = 0; | |
| 248 | + m->footer.data_crc = 0; | |
| 253 | 249 | if (m->data_length) { |
| 254 | − prepare_message_data(con->out_msg, m->data_length); | |
| 250 | + prepare_message_data(m, m->data_length); | |
| 255 | 251 | con->v1.out_more = 1; /* data + footer will follow */ |
| 256 | 252 | } else { |
| 257 | 253 | /* no, queue up footer too and be done */ |
| 258 | − prepare_write_message_footer(con); | |
| 254 | + prepare_write_message_footer(con, m); | |
| 259 | 255 | } |
| 260 | 256 | |
| 261 | 257 | ceph_con_flag_set(con, CEPH_CON_F_WRITE_PENDING); |
| @@ -462,9 +458,9 @@ out: · 200 unmodified lines | ||
| 462 | 458 | * 0 -> socket full, but more to do |
| 463 | 459 | * <0 -> error |
| 464 | 460 | */ |
| 465 | −static int write_partial_message_data(struct ceph_connection *con) | |
| 461 | +static int write_partial_message_data(struct ceph_connection *con, | |
| 462 | + struct ceph_msg *msg) | |
| 466 | 463 | { |
| 467 | − struct ceph_msg *msg = con->out_msg; | |
| 468 | 464 | struct ceph_msg_data_cursor *cursor = &msg->cursor; |
| 469 | 465 | bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); |
| 470 | 466 | u32 crc; |
| @@ -516,7 +512,7 @@ static int write_partial_message_data(struct ceph_connection *con) · 45 unmodified lines | ||
| 516 | 512 | else |
| 517 | 513 | msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; |
| 518 | 514 | con_out_kvec_reset(con); |
| 519 | − prepare_write_message_footer(con); | |
| 515 | + prepare_write_message_footer(con, msg); | |
| 520 | 516 | |
| 521 | 517 | return 1; /* must return > 0 to indicate success */ |
| 522 | 518 | } |
| @@ -1472,6 +1468,7 @@ bad_tag: · 949 unmodified lines | ||
| 1472 | 1468 | */ |
| 1473 | 1469 | int ceph_con_v1_try_write(struct ceph_connection *con) |
| 1474 | 1470 | { |
| 1471 | + struct ceph_msg *msg; | |
| 1475 | 1472 | int ret = 1; |
| 1476 | 1473 | |
| 1477 | 1474 | dout("try_write start %p state %d\n", con, con->state); |
| @@ -1518,14 +1515,15 @@ more: · 40 unmodified lines | ||
| 1518 | 1515 | } |
| 1519 | 1516 | |
| 1520 | 1517 | /* msg pages? */ |
| 1521 | − if (con->out_msg) { | |
| 1518 | + msg = con->out_msg; | |
| 1519 | + if (msg) { | |
| 1522 | 1520 | if (con->v1.out_msg_done) { |
| 1523 | − ceph_msg_put(con->out_msg); | |
| 1521 | + ceph_msg_put(msg); | |
| 1524 | 1522 | con->out_msg = NULL; /* we're done with this one */ |
| 1525 | 1523 | goto do_next; |
| 1526 | 1524 | } |
| 1527 | 1525 | |
| 1528 | − ret = write_partial_message_data(con); | |
| 1526 | + ret = write_partial_message_data(con, msg); | |
| 1529 | 1527 | if (ret == 1) |
| 1530 | 1528 | goto more; /* we need to send the footer, too! */ |
| 1531 | 1529 | if (ret == 0) |
| @@ -1545,8 +1543,8 @@ do_next: · 13 unmodified lines | ||
| 1545 | 1543 | goto more; |
| 1546 | 1544 | } |
| 1547 | 1545 | /* is anything else pending? */ |
| 1548 | − if (!list_empty(&con->out_queue)) { | |
| 1549 | − prepare_write_message(con); | |
| 1546 | + if ((msg = ceph_con_get_out_msg(con)) != NULL) { | |
| 1547 | + prepare_write_message(con, msg); | |
| 1550 | 1548 | goto more; |
| 1551 | 1549 | } |
| 1552 | 1550 | if (con->in_seq > con->in_seq_acked) { |
| @@ -1564,10 +1562,8 @@ out: · 11 unmodified lines | ||
| 1564 | 1562 | return ret; |
| 1565 | 1563 | } |
| 1566 | 1564 | |
| 1567 | −void ceph_con_v1_revoke(struct ceph_connection *con) | |
| 1565 | +void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg) | |
| 1568 | 1566 | { |
| 1569 | − struct ceph_msg *msg = con->out_msg; | |
| 1570 | − | |
| 1571 | 1567 | WARN_ON(con->v1.out_skip); |
| 1572 | 1568 | /* footer */ |
| 1573 | 1569 | if (con->v1.out_msg_done) { |
| @@ -709,7 +709,7 @@ static int setup_crypto(struct ceph_connection *con, · 708 unmodified lines | ||
| 709 | 709 | |
| 710 | 710 | dout("%s con %p con_mode %d session_key_len %d con_secret_len %d\n", |
| 711 | 711 | __func__, con, con->v2.con_mode, session_key_len, con_secret_len); |
| 712 | − WARN_ON(con->v2.hmac_tfm || con->v2.gcm_tfm || con->v2.gcm_req); | |
| 712 | + WARN_ON(con->v2.hmac_key_set || con->v2.gcm_tfm || con->v2.gcm_req); | |
| 713 | 713 | |
| 714 | 714 | if (con->v2.con_mode != CEPH_CON_MODE_CRC && |
| 715 | 715 | con->v2.con_mode != CEPH_CON_MODE_SECURE) { |
| @@ -723,22 +723,8 @@ static int setup_crypto(struct ceph_connection *con, · 7 unmodified lines | ||
| 723 | 723 | return 0; /* auth_none */ |
| 724 | 724 | } |
| 725 | 725 | |
| 726 | − noio_flag = memalloc_noio_save(); | |
| 727 | − con->v2.hmac_tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); | |
| 728 | − memalloc_noio_restore(noio_flag); | |
| 729 | − if (IS_ERR(con->v2.hmac_tfm)) { | |
| 730 | − ret = PTR_ERR(con->v2.hmac_tfm); | |
| 731 | − con->v2.hmac_tfm = NULL; | |
| 732 | − pr_err("failed to allocate hmac tfm context: %d\n", ret); | |
| 733 | − return ret; | |
| 734 | − } | |
| 735 | − | |
| 736 | − ret = crypto_shash_setkey(con->v2.hmac_tfm, session_key, | |
| 737 | − session_key_len); | |
| 738 | − if (ret) { | |
| 739 | − pr_err("failed to set hmac key: %d\n", ret); | |
| 740 | − return ret; | |
| 741 | − } | |
| 726 | + hmac_sha256_preparekey(&con->v2.hmac_key, session_key, session_key_len); | |
| 727 | + con->v2.hmac_key_set = true; | |
| 742 | 728 | |
| 743 | 729 | if (con->v2.con_mode == CEPH_CON_MODE_CRC) { |
| 744 | 730 | WARN_ON(con_secret_len); |
| @@ -793,38 +779,26 @@ static int setup_crypto(struct ceph_connection *con, · 48 unmodified lines | ||
| 793 | 779 | return 0; /* auth_x, secure mode */ |
| 794 | 780 | } |
| 795 | 781 | |
| 796 | −static int ceph_hmac_sha256(struct ceph_connection *con, | |
| 797 | − const struct kvec *kvecs, int kvec_cnt, u8 *hmac) | |
| 782 | +static void ceph_hmac_sha256(struct ceph_connection *con, | |
| 783 | + const struct kvec *kvecs, int kvec_cnt, | |
| 784 | + u8 hmac[SHA256_DIGEST_SIZE]) | |
| 798 | 785 | { |
| 799 | − SHASH_DESC_ON_STACK(desc, con->v2.hmac_tfm); /* tfm arg is ignored */ | |
| 800 | − int ret; | |
| 786 | + struct hmac_sha256_ctx ctx; | |
| 801 | 787 | int i; |
| 802 | 788 | |
| 803 | − dout("%s con %p hmac_tfm %p kvec_cnt %d\n", __func__, con, | |
| 804 | − con->v2.hmac_tfm, kvec_cnt); | |
| 789 | + dout("%s con %p hmac_key_set %d kvec_cnt %d\n", __func__, con, | |
| 790 | + con->v2.hmac_key_set, kvec_cnt); | |
| 805 | 791 | |
| 806 | − if (!con->v2.hmac_tfm) { | |
| 792 | + if (!con->v2.hmac_key_set) { | |
| 807 | 793 | memset(hmac, 0, SHA256_DIGEST_SIZE); |
| 808 | − return 0; /* auth_none */ | |
| 794 | + return; /* auth_none */ | |
| 809 | 795 | } |
| 810 | 796 | |
| 811 | − desc->tfm = con->v2.hmac_tfm; | |
| 812 | − ret = crypto_shash_init(desc); | |
| 813 | − if (ret) | |
| 814 | − goto out; | |
| 815 | − | |
| 816 | − for (i = 0; i < kvec_cnt; i++) { | |
| 817 | − ret = crypto_shash_update(desc, kvecs[i].iov_base, | |
| 818 | − kvecs[i].iov_len); | |
| 819 | − if (ret) | |
| 820 | − goto out; | |
| 821 | − } | |
| 822 | − | |
| 823 | − ret = crypto_shash_final(desc, hmac); | |
| 824 | − | |
| 825 | −out: | |
| 826 | − shash_desc_zero(desc); | |
| 827 | − return ret; /* auth_x, both plain and secure modes */ | |
| 797 | + /* auth_x, both plain and secure modes */ | |
| 798 | + hmac_sha256_init(&ctx, &con->v2.hmac_key); | |
| 799 | + for (i = 0; i < kvec_cnt; i++) | |
| 800 | + hmac_sha256_update(&ctx, kvecs[i].iov_base, kvecs[i].iov_len); | |
| 801 | + hmac_sha256_final(&ctx, hmac); | |
| 828 | 802 | } |
| 829 | 803 | |
| 830 | 804 | static void gcm_inc_nonce(struct ceph_gcm_nonce *nonce) |
| @@ -1455,17 +1429,14 @@ static int prepare_auth_request_more(struct ceph_connection *con, · 624 unmodified lines | ||
| 1455 | 1429 | static int prepare_auth_signature(struct ceph_connection *con) |
| 1456 | 1430 | { |
| 1457 | 1431 | void *buf; |
| 1458 | − int ret; | |
| 1459 | 1432 | |
| 1460 | 1433 | buf = alloc_conn_buf(con, head_onwire_len(SHA256_DIGEST_SIZE, |
| 1461 | 1434 | con_secure(con))); |
| 1462 | 1435 | if (!buf) |
| 1463 | 1436 | return -ENOMEM; |
| 1464 | 1437 | |
| 1465 | − ret = ceph_hmac_sha256(con, con->v2.in_sign_kvecs, | |
| 1466 | − con->v2.in_sign_kvec_cnt, CTRL_BODY(buf)); | |
| 1467 | − if (ret) | |
| 1468 | − return ret; | |
| 1438 | + ceph_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, | |
| 1439 | + CTRL_BODY(buf)); | |
| 1469 | 1440 | |
| 1470 | 1441 | return prepare_control(con, FRAME_TAG_AUTH_SIGNATURE, buf, |
| 1471 | 1442 | SHA256_DIGEST_SIZE); |
| @@ -1589,10 +1560,11 @@ static int prepare_ack(struct ceph_connection *con) · 117 unmodified lines | ||
| 1589 | 1560 | return prepare_control(con, FRAME_TAG_ACK, con->v2.out_buf, 8); |
| 1590 | 1561 | } |
| 1591 | 1562 | |
| 1592 | −static void prepare_epilogue_plain(struct ceph_connection *con, bool aborted) | |
| 1563 | +static void prepare_epilogue_plain(struct ceph_connection *con, | |
| 1564 | + struct ceph_msg *msg, bool aborted) | |
| 1593 | 1565 | { |
| 1594 | 1566 | dout("%s con %p msg %p aborted %d crcs %u %u %u\n", __func__, con, |
| 1595 | − con->out_msg, aborted, con->v2.out_epil.front_crc, | |
| 1567 | + msg, aborted, con->v2.out_epil.front_crc, | |
| 1596 | 1568 | con->v2.out_epil.middle_crc, con->v2.out_epil.data_crc); |
| 1597 | 1569 | |
| 1598 | 1570 | encode_epilogue_plain(con, aborted); |
| @@ -1603,10 +1575,9 @@ static void prepare_epilogue_plain(struct ceph_connection *con, bool aborted) · 4 unmodified lines | ||
| 1603 | 1575 | * For "used" empty segments, crc is -1. For unused (trailing) |
| 1604 | 1576 | * segments, crc is 0. |
| 1605 | 1577 | */ |
| 1606 | −static void prepare_message_plain(struct ceph_connection *con) | |
| 1578 | +static void prepare_message_plain(struct ceph_connection *con, | |
| 1579 | + struct ceph_msg *msg) | |
| 1607 | 1580 | { |
| 1608 | − struct ceph_msg *msg = con->out_msg; | |
| 1609 | − | |
| 1610 | 1581 | prepare_head_plain(con, con->v2.out_buf, |
| 1611 | 1582 | sizeof(struct ceph_msg_header2), NULL, 0, false); |
| 1612 | 1583 | |
| @@ -1647,7 +1618,7 @@ static void prepare_message_plain(struct ceph_connection *con) · 34 unmodified lines | ||
| 1647 | 1618 | con->v2.out_state = OUT_S_QUEUE_DATA; |
| 1648 | 1619 | } else { |
| 1649 | 1620 | con->v2.out_epil.data_crc = 0; |
| 1650 | − prepare_epilogue_plain(con, false); | |
| 1621 | + prepare_epilogue_plain(con, msg, false); | |
| 1651 | 1622 | con->v2.out_state = OUT_S_FINISH_MESSAGE; |
| 1652 | 1623 | } |
| 1653 | 1624 | } |
| @@ -1659,7 +1630,8 @@ static void prepare_message_plain(struct ceph_connection *con) · 5 unmodified lines | ||
| 1659 | 1630 | * allocate pages for the entire tail of the message (currently up |
| 1660 | 1631 | * to ~32M) and two sgs arrays (up to ~256K each)... |
| 1661 | 1632 | */ |
| 1662 | −static int prepare_message_secure(struct ceph_connection *con) | |
| 1633 | +static int prepare_message_secure(struct ceph_connection *con, | |
| 1634 | + struct ceph_msg *msg) | |
| 1663 | 1635 | { |
| 1664 | 1636 | void *zerop = page_address(ceph_zero_page); |
| 1665 | 1637 | struct sg_table enc_sgt = {}; |
| @@ -1674,7 +1646,7 @@ static int prepare_message_secure(struct ceph_connection *con) · 8 unmodified lines | ||
| 1674 | 1646 | if (ret) |
| 1675 | 1647 | return ret; |
| 1676 | 1648 | |
| 1677 | − tail_len = tail_onwire_len(con->out_msg, true); | |
| 1649 | + tail_len = tail_onwire_len(msg, true); | |
| 1678 | 1650 | if (!tail_len) { |
| 1679 | 1651 | /* |
| 1680 | 1652 | * Empty message: once the head is written, |
| @@ -1685,7 +1657,7 @@ static int prepare_message_secure(struct ceph_connection *con) · 4 unmodified lines | ||
| 1685 | 1657 | } |
| 1686 | 1658 | |
| 1687 | 1659 | encode_epilogue_secure(con, false); |
| 1688 | − ret = setup_message_sgs(&sgt, con->out_msg, zerop, zerop, zerop, | |
| 1660 | + ret = setup_message_sgs(&sgt, msg, zerop, zerop, zerop, | |
| 1689 | 1661 | &con->v2.out_epil, NULL, 0, false); |
| 1690 | 1662 | if (ret) |
| 1691 | 1663 | goto out; |
| @@ -1714,7 +1686,7 @@ static int prepare_message_secure(struct ceph_connection *con) · 22 unmodified lines | ||
| 1714 | 1686 | goto out; |
| 1715 | 1687 | |
| 1716 | 1688 | dout("%s con %p msg %p sg_cnt %d enc_page_cnt %d\n", __func__, con, |
| 1717 | − con->out_msg, sgt.orig_nents, enc_page_cnt); | |
| 1689 | + msg, sgt.orig_nents, enc_page_cnt); | |
| 1718 | 1690 | con->v2.out_state = OUT_S_QUEUE_ENC_PAGE; |
| 1719 | 1691 | |
| 1720 | 1692 | out: |
| @@ -1723,19 +1695,19 @@ out: · 2 unmodified lines | ||
| 1723 | 1695 | return ret; |
| 1724 | 1696 | } |
| 1725 | 1697 | |
| 1726 | −static int prepare_message(struct ceph_connection *con) | |
| 1698 | +static int prepare_message(struct ceph_connection *con, struct ceph_msg *msg) | |
| 1727 | 1699 | { |
| 1728 | 1700 | int lens[] = { |
| 1729 | 1701 | sizeof(struct ceph_msg_header2), |
| 1730 | − front_len(con->out_msg), | |
| 1731 | − middle_len(con->out_msg), | |
| 1732 | − data_len(con->out_msg) | |
| 1702 | + front_len(msg), | |
| 1703 | + middle_len(msg), | |
| 1704 | + data_len(msg) | |
| 1733 | 1705 | }; |
| 1734 | 1706 | struct ceph_frame_desc desc; |
| 1735 | 1707 | int ret; |
| 1736 | 1708 | |
| 1737 | 1709 | dout("%s con %p msg %p logical %d+%d+%d+%d\n", __func__, con, |
| 1738 | − con->out_msg, lens[0], lens[1], lens[2], lens[3]); | |
| 1710 | + msg, lens[0], lens[1], lens[2], lens[3]); | |
| 1739 | 1711 | |
| 1740 | 1712 | if (con->in_seq > con->in_seq_acked) { |
| 1741 | 1713 | dout("%s con %p in_seq_acked %llu -> %llu\n", __func__, con, |
| @@ -1746,15 +1718,15 @@ static int prepare_message(struct ceph_connection *con) · 4 unmodified lines | ||
| 1746 | 1718 | reset_out_kvecs(con); |
| 1747 | 1719 | init_frame_desc(&desc, FRAME_TAG_MESSAGE, lens, 4); |
| 1748 | 1720 | encode_preamble(&desc, con->v2.out_buf); |
| 1749 | − fill_header2(CTRL_BODY(con->v2.out_buf), &con->out_msg->hdr, | |
| 1721 | + fill_header2(CTRL_BODY(con->v2.out_buf), &msg->hdr, | |
| 1750 | 1722 | con->in_seq_acked); |
| 1751 | 1723 | |
| 1752 | 1724 | if (con_secure(con)) { |
| 1753 | − ret = prepare_message_secure(con); | |
| 1725 | + ret = prepare_message_secure(con, msg); | |
| 1754 | 1726 | if (ret) |
| 1755 | 1727 | return ret; |
| 1756 | 1728 | } else { |
| 1757 | − prepare_message_plain(con); | |
| 1729 | + prepare_message_plain(con, msg); | |
| 1758 | 1730 | } |
| 1759 | 1731 | |
| 1760 | 1732 | ceph_con_flag_set(con, CEPH_CON_F_WRITE_PENDING); |
| @@ -2460,10 +2432,8 @@ static int process_auth_signature(struct ceph_connection *con, · 699 unmodified lines | ||
| 2460 | 2432 | return -EINVAL; |
| 2461 | 2433 | } |
| 2462 | 2434 | |
| 2463 | − ret = ceph_hmac_sha256(con, con->v2.out_sign_kvecs, | |
| 2464 | − con->v2.out_sign_kvec_cnt, hmac); | |
| 2465 | − if (ret) | |
| 2466 | − return ret; | |
| 2435 | + ceph_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, | |
| 2436 | + hmac); | |
| 2467 | 2437 | |
| 2468 | 2438 | ceph_decode_need(&p, end, SHA256_DIGEST_SIZE, bad); |
| 2469 | 2439 | if (crypto_memneq(p, hmac, SHA256_DIGEST_SIZE)) { |
| @@ -3184,20 +3154,20 @@ int ceph_con_v2_try_read(struct ceph_connection *con) · 714 unmodified lines | ||
| 3184 | 3154 | } |
| 3185 | 3155 | } |
| 3186 | 3156 | |
| 3187 | −static void queue_data(struct ceph_connection *con) | |
| 3157 | +static void queue_data(struct ceph_connection *con, struct ceph_msg *msg) | |
| 3188 | 3158 | { |
| 3189 | 3159 | struct bio_vec bv; |
| 3190 | 3160 | |
| 3191 | 3161 | con->v2.out_epil.data_crc = -1; |
| 3192 | − ceph_msg_data_cursor_init(&con->v2.out_cursor, con->out_msg, | |
| 3193 | − data_len(con->out_msg)); | |
| 3162 | + ceph_msg_data_cursor_init(&con->v2.out_cursor, msg, | |
| 3163 | + data_len(msg)); | |
| 3194 | 3164 | |
| 3195 | 3165 | get_bvec_at(&con->v2.out_cursor, &bv); |
| 3196 | 3166 | set_out_bvec(con, &bv, true); |
| 3197 | 3167 | con->v2.out_state = OUT_S_QUEUE_DATA_CONT; |
| 3198 | 3168 | } |
| 3199 | 3169 | |
| 3200 | −static void queue_data_cont(struct ceph_connection *con) | |
| 3170 | +static void queue_data_cont(struct ceph_connection *con, struct ceph_msg *msg) | |
| 3201 | 3171 | { |
| 3202 | 3172 | struct bio_vec bv; |
| 3203 | 3173 | |
| @@ -3218,7 +3188,7 @@ static void queue_data_cont(struct ceph_connection *con) · 14 unmodified lines | ||
| 3218 | 3188 | * we are done. |
| 3219 | 3189 | */ |
| 3220 | 3190 | reset_out_kvecs(con); |
| 3221 | − prepare_epilogue_plain(con, false); | |
| 3191 | + prepare_epilogue_plain(con, msg, false); | |
| 3222 | 3192 | con->v2.out_state = OUT_S_FINISH_MESSAGE; |
| 3223 | 3193 | } |
| 3224 | 3194 | |
| @@ -3250,7 +3220,7 @@ static void queue_enc_page(struct ceph_connection *con) · 25 unmodified lines | ||
| 3250 | 3220 | con->v2.out_state = OUT_S_FINISH_MESSAGE; |
| 3251 | 3221 | } |
| 3252 | 3222 | |
| 3253 | −static void queue_zeros(struct ceph_connection *con) | |
| 3223 | +static void queue_zeros(struct ceph_connection *con, struct ceph_msg *msg) | |
| 3254 | 3224 | { |
| 3255 | 3225 | dout("%s con %p out_zero %d\n", __func__, con, con->v2.out_zero); |
| 3256 | 3226 | |
| @@ -3267,7 +3237,7 @@ static void queue_zeros(struct ceph_connection *con) · 10 unmodified lines | ||
| 3267 | 3237 | * Once it's written, we are done patching up for the revoke. |
| 3268 | 3238 | */ |
| 3269 | 3239 | reset_out_kvecs(con); |
| 3270 | − prepare_epilogue_plain(con, true); | |
| 3240 | + prepare_epilogue_plain(con, msg, true); | |
| 3271 | 3241 | con->v2.out_state = OUT_S_FINISH_MESSAGE; |
| 3272 | 3242 | } |
| 3273 | 3243 | |
| @@ -3294,6 +3264,7 @@ static void finish_message(struct ceph_connection *con) · 20 unmodified lines | ||
| 3294 | 3264 | |
| 3295 | 3265 | static int populate_out_iter(struct ceph_connection *con) |
| 3296 | 3266 | { |
| 3267 | + struct ceph_msg *msg; | |
| 3297 | 3268 | int ret; |
| 3298 | 3269 | |
| 3299 | 3270 | dout("%s con %p state %d out_state %d\n", __func__, con, con->state, |
| @@ -3309,18 +3280,18 @@ static int populate_out_iter(struct ceph_connection *con) · 9 unmodified lines | ||
| 3309 | 3280 | switch (con->v2.out_state) { |
| 3310 | 3281 | case OUT_S_QUEUE_DATA: |
| 3311 | 3282 | WARN_ON(!con->out_msg); |
| 3312 | − queue_data(con); | |
| 3283 | + queue_data(con, con->out_msg); | |
| 3313 | 3284 | goto populated; |
| 3314 | 3285 | case OUT_S_QUEUE_DATA_CONT: |
| 3315 | 3286 | WARN_ON(!con->out_msg); |
| 3316 | − queue_data_cont(con); | |
| 3287 | + queue_data_cont(con, con->out_msg); | |
| 3317 | 3288 | goto populated; |
| 3318 | 3289 | case OUT_S_QUEUE_ENC_PAGE: |
| 3319 | 3290 | queue_enc_page(con); |
| 3320 | 3291 | goto populated; |
| 3321 | 3292 | case OUT_S_QUEUE_ZEROS: |
| 3322 | 3293 | WARN_ON(con->out_msg); /* revoked */ |
| 3323 | − queue_zeros(con); | |
| 3294 | + queue_zeros(con, con->out_msg); | |
| 3324 | 3295 | goto populated; |
| 3325 | 3296 | case OUT_S_FINISH_MESSAGE: |
| 3326 | 3297 | finish_message(con); |
| @@ -3339,9 +3310,8 @@ static int populate_out_iter(struct ceph_connection *con) · 12 unmodified lines | ||
| 3339 | 3310 | pr_err("prepare_keepalive2 failed: %d\n", ret); |
| 3340 | 3311 | return ret; |
| 3341 | 3312 | } |
| 3342 | − } else if (!list_empty(&con->out_queue)) { | |
| 3343 | − ceph_con_get_out_msg(con); | |
| 3344 | − ret = prepare_message(con); | |
| 3313 | + } else if ((msg = ceph_con_get_out_msg(con)) != NULL) { | |
| 3314 | + ret = prepare_message(con, msg); | |
| 3345 | 3315 | if (ret) { |
| 3346 | 3316 | pr_err("prepare_message failed: %d\n", ret); |
| 3347 | 3317 | return ret; |
| @@ -3453,17 +3423,18 @@ static u32 crc32c_zeros(u32 crc, int zero_len) · 105 unmodified lines | ||
| 3453 | 3423 | return crc; |
| 3454 | 3424 | } |
| 3455 | 3425 | |
| 3456 | −static void prepare_zero_front(struct ceph_connection *con, int resid) | |
| 3426 | +static void prepare_zero_front(struct ceph_connection *con, | |
| 3427 | + struct ceph_msg *msg, int resid) | |
| 3457 | 3428 | { |
| 3458 | 3429 | int sent; |
| 3459 | 3430 | |
| 3460 | − WARN_ON(!resid || resid > front_len(con->out_msg)); | |
| 3461 | − sent = front_len(con->out_msg) - resid; | |
| 3431 | + WARN_ON(!resid || resid > front_len(msg)); | |
| 3432 | + sent = front_len(msg) - resid; | |
| 3462 | 3433 | dout("%s con %p sent %d resid %d\n", __func__, con, sent, resid); |
| 3463 | 3434 | |
| 3464 | 3435 | if (sent) { |
| 3465 | 3436 | con->v2.out_epil.front_crc = |
| 3466 | − crc32c(-1, con->out_msg->front.iov_base, sent); | |
| 3437 | + crc32c(-1, msg->front.iov_base, sent); | |
| 3467 | 3438 | con->v2.out_epil.front_crc = |
| 3468 | 3439 | crc32c_zeros(con->v2.out_epil.front_crc, resid); |
| 3469 | 3440 | } else { |
| @@ -3474,17 +3445,18 @@ static void prepare_zero_front(struct ceph_connection *con, int resid) · 4 unmodified lines | ||
| 3474 | 3445 | out_zero_add(con, resid); |
| 3475 | 3446 | } |
| 3476 | 3447 | |
| 3477 | −static void prepare_zero_middle(struct ceph_connection *con, int resid) | |
| 3448 | +static void prepare_zero_middle(struct ceph_connection *con, | |
| 3449 | + struct ceph_msg *msg, int resid) | |
| 3478 | 3450 | { |
| 3479 | 3451 | int sent; |
| 3480 | 3452 | |
| 3481 | − WARN_ON(!resid || resid > middle_len(con->out_msg)); | |
| 3482 | − sent = middle_len(con->out_msg) - resid; | |
| 3453 | + WARN_ON(!resid || resid > middle_len(msg)); | |
| 3454 | + sent = middle_len(msg) - resid; | |
| 3483 | 3455 | dout("%s con %p sent %d resid %d\n", __func__, con, sent, resid); |
| 3484 | 3456 | |
| 3485 | 3457 | if (sent) { |
| 3486 | 3458 | con->v2.out_epil.middle_crc = |
| 3487 | − crc32c(-1, con->out_msg->middle->vec.iov_base, sent); | |
| 3459 | + crc32c(-1, msg->middle->vec.iov_base, sent); | |
| 3488 | 3460 | con->v2.out_epil.middle_crc = |
| 3489 | 3461 | crc32c_zeros(con->v2.out_epil.middle_crc, resid); |
| 3490 | 3462 | } else { |
| @@ -3495,61 +3467,64 @@ static void prepare_zero_middle(struct ceph_connection *con, int resid) · 4 unmodified lines | ||
| 3495 | 3467 | out_zero_add(con, resid); |
| 3496 | 3468 | } |
| 3497 | 3469 | |
| 3498 | −static void prepare_zero_data(struct ceph_connection *con) | |
| 3470 | +static void prepare_zero_data(struct ceph_connection *con, | |
| 3471 | + struct ceph_msg *msg) | |
| 3499 | 3472 | { |
| 3500 | 3473 | dout("%s con %p\n", __func__, con); |
| 3501 | − con->v2.out_epil.data_crc = crc32c_zeros(-1, data_len(con->out_msg)); | |
| 3502 | − out_zero_add(con, data_len(con->out_msg)); | |
| 3474 | + con->v2.out_epil.data_crc = crc32c_zeros(-1, data_len(msg)); | |
| 3475 | + out_zero_add(con, data_len(msg)); | |
| 3503 | 3476 | } |
| 3504 | 3477 | |
| 3505 | −static void revoke_at_queue_data(struct ceph_connection *con) | |
| 3478 | +static void revoke_at_queue_data(struct ceph_connection *con, | |
| 3479 | + struct ceph_msg *msg) | |
| 3506 | 3480 | { |
| 3507 | 3481 | int boundary; |
| 3508 | 3482 | int resid; |
| 3509 | 3483 | |
| 3510 | − WARN_ON(!data_len(con->out_msg)); | |
| 3484 | + WARN_ON(!data_len(msg)); | |
| 3511 | 3485 | WARN_ON(!iov_iter_is_kvec(&con->v2.out_iter)); |
| 3512 | 3486 | resid = iov_iter_count(&con->v2.out_iter); |
| 3513 | 3487 | |
| 3514 | − boundary = front_len(con->out_msg) + middle_len(con->out_msg); | |
| 3488 | + boundary = front_len(msg) + middle_len(msg); | |
| 3515 | 3489 | if (resid > boundary) { |
| 3516 | 3490 | resid -= boundary; |
| 3517 | 3491 | WARN_ON(resid > MESSAGE_HEAD_PLAIN_LEN); |
| 3518 | 3492 | dout("%s con %p was sending head\n", __func__, con); |
| 3519 | − if (front_len(con->out_msg)) | |
| 3520 | − prepare_zero_front(con, front_len(con->out_msg)); | |
| 3521 | − if (middle_len(con->out_msg)) | |
| 3522 | − prepare_zero_middle(con, middle_len(con->out_msg)); | |
| 3523 | − prepare_zero_data(con); | |
| 3493 | + if (front_len(msg)) | |
| 3494 | + prepare_zero_front(con, msg, front_len(msg)); | |
| 3495 | + if (middle_len(msg)) | |
| 3496 | + prepare_zero_middle(con, msg, middle_len(msg)); | |
| 3497 | + prepare_zero_data(con, msg); | |
| 3524 | 3498 | WARN_ON(iov_iter_count(&con->v2.out_iter) != resid); |
| 3525 | 3499 | con->v2.out_state = OUT_S_QUEUE_ZEROS; |
| 3526 | 3500 | return; |
| 3527 | 3501 | } |
| 3528 | 3502 | |
| 3529 | − boundary = middle_len(con->out_msg); | |
| 3503 | + boundary = middle_len(msg); | |
| 3530 | 3504 | if (resid > boundary) { |
| 3531 | 3505 | resid -= boundary; |
| 3532 | 3506 | dout("%s con %p was sending front\n", __func__, con); |
| 3533 | − prepare_zero_front(con, resid); | |
| 3534 | − if (middle_len(con->out_msg)) | |
| 3535 | − prepare_zero_middle(con, middle_len(con->out_msg)); | |
| 3536 | − prepare_zero_data(con); | |
| 3537 | − queue_zeros(con); | |
| 3507 | + prepare_zero_front(con, msg, resid); | |
| 3508 | + if (middle_len(msg)) | |
| 3509 | + prepare_zero_middle(con, msg, middle_len(msg)); | |
| 3510 | + prepare_zero_data(con, msg); | |
| 3511 | + queue_zeros(con, msg); | |
| 3538 | 3512 | return; |
| 3539 | 3513 | } |
| 3540 | 3514 | |
| 3541 | 3515 | WARN_ON(!resid); |
| 3542 | 3516 | dout("%s con %p was sending middle\n", __func__, con); |
| 3543 | − prepare_zero_middle(con, resid); | |
| 3544 | − prepare_zero_data(con); | |
| 3545 | − queue_zeros(con); | |
| 3517 | + prepare_zero_middle(con, msg, resid); | |
| 3518 | + prepare_zero_data(con, msg); | |
| 3519 | + queue_zeros(con, msg); | |
| 3546 | 3520 | } |
| 3547 | 3521 | |
| 3548 | −static void revoke_at_queue_data_cont(struct ceph_connection *con) | |
| 3522 | +static void revoke_at_queue_data_cont(struct ceph_connection *con, | |
| 3523 | + struct ceph_msg *msg) | |
| 3549 | 3524 | { |
| 3550 | 3525 | int sent, resid; /* current piece of data */ |
| 3551 | 3526 | |
| 3552 | − WARN_ON(!data_len(con->out_msg)); | |
| 3527 | + WARN_ON(!data_len(msg)); | |
| 3553 | 3528 | WARN_ON(!iov_iter_is_bvec(&con->v2.out_iter)); |
| 3554 | 3529 | resid = iov_iter_count(&con->v2.out_iter); |
| 3555 | 3530 | WARN_ON(!resid || resid > con->v2.out_bvec.bv_len); |
| @@ -3568,10 +3543,11 @@ static void revoke_at_queue_data_cont(struct ceph_connection *con) · 12 unmodified lines | ||
| 3568 | 3543 | |
| 3569 | 3544 | con->v2.out_iter.count -= resid; |
| 3570 | 3545 | out_zero_add(con, con->v2.out_cursor.total_resid); |
| 3571 | − queue_zeros(con); | |
| 3546 | + queue_zeros(con, msg); | |
| 3572 | 3547 | } |
| 3573 | 3548 | |
| 3574 | −static void revoke_at_finish_message(struct ceph_connection *con) | |
| 3549 | +static void revoke_at_finish_message(struct ceph_connection *con, | |
| 3550 | + struct ceph_msg *msg) | |
| 3575 | 3551 | { |
| 3576 | 3552 | int boundary; |
| 3577 | 3553 | int resid; |
| @@ -3579,39 +3555,39 @@ static void revoke_at_finish_message(struct ceph_connection *con) · 1 unmodified line | ||
| 3579 | 3555 | WARN_ON(!iov_iter_is_kvec(&con->v2.out_iter)); |
| 3580 | 3556 | resid = iov_iter_count(&con->v2.out_iter); |
| 3581 | 3557 | |
| 3582 | − if (!front_len(con->out_msg) && !middle_len(con->out_msg) && | |
| 3583 | − !data_len(con->out_msg)) { | |
| 3558 | + if (!front_len(msg) && !middle_len(msg) && | |
| 3559 | + !data_len(msg)) { | |
| 3584 | 3560 | WARN_ON(!resid || resid > MESSAGE_HEAD_PLAIN_LEN); |
| 3585 | 3561 | dout("%s con %p was sending head (empty message) - noop\n", |
| 3586 | 3562 | __func__, con); |
| 3587 | 3563 | return; |
| 3588 | 3564 | } |
| 3589 | 3565 | |
| 3590 | − boundary = front_len(con->out_msg) + middle_len(con->out_msg) + | |
| 3566 | + boundary = front_len(msg) + middle_len(msg) + | |
| 3591 | 3567 | CEPH_EPILOGUE_PLAIN_LEN; |
| 3592 | 3568 | if (resid > boundary) { |
| 3593 | 3569 | resid -= boundary; |
| 3594 | 3570 | WARN_ON(resid > MESSAGE_HEAD_PLAIN_LEN); |
| 3595 | 3571 | dout("%s con %p was sending head\n", __func__, con); |
| 3596 | − if (front_len(con->out_msg)) | |
| 3597 | − prepare_zero_front(con, front_len(con->out_msg)); | |
| 3598 | − if (middle_len(con->out_msg)) | |
| 3599 | − prepare_zero_middle(con, middle_len(con->out_msg)); | |
| 3572 | + if (front_len(msg)) | |
| 3573 | + prepare_zero_front(con, msg, front_len(msg)); | |
| 3574 | + if (middle_len(msg)) | |
| 3575 | + prepare_zero_middle(con, msg, middle_len(msg)); | |
| 3600 | 3576 | con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; |
| 3601 | 3577 | WARN_ON(iov_iter_count(&con->v2.out_iter) != resid); |
| 3602 | 3578 | con->v2.out_state = OUT_S_QUEUE_ZEROS; |
| 3603 | 3579 | return; |
| 3604 | 3580 | } |
| 3605 | 3581 | |
| 3606 | − boundary = middle_len(con->out_msg) + CEPH_EPILOGUE_PLAIN_LEN; | |
| 3582 | + boundary = middle_len(msg) + CEPH_EPILOGUE_PLAIN_LEN; | |
| 3607 | 3583 | if (resid > boundary) { |
| 3608 | 3584 | resid -= boundary; |
| 3609 | 3585 | dout("%s con %p was sending front\n", __func__, con); |
| 3610 | − prepare_zero_front(con, resid); | |
| 3611 | − if (middle_len(con->out_msg)) | |
| 3612 | − prepare_zero_middle(con, middle_len(con->out_msg)); | |
| 3586 | + prepare_zero_front(con, msg, resid); | |
| 3587 | + if (middle_len(msg)) | |
| 3588 | + prepare_zero_middle(con, msg, middle_len(msg)); | |
| 3613 | 3589 | con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; |
| 3614 | − queue_zeros(con); | |
| 3590 | + queue_zeros(con, msg); | |
| 3615 | 3591 | return; |
| 3616 | 3592 | } |
| 3617 | 3593 | |
| @@ -3619,9 +3595,9 @@ static void revoke_at_finish_message(struct ceph_connection *con) · 1 unmodified line | ||
| 3619 | 3595 | if (resid > boundary) { |
| 3620 | 3596 | resid -= boundary; |
| 3621 | 3597 | dout("%s con %p was sending middle\n", __func__, con); |
| 3622 | − prepare_zero_middle(con, resid); | |
| 3598 | + prepare_zero_middle(con, msg, resid); | |
| 3623 | 3599 | con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; |
| 3624 | − queue_zeros(con); | |
| 3600 | + queue_zeros(con, msg); | |
| 3625 | 3601 | return; |
| 3626 | 3602 | } |
| 3627 | 3603 | |
| @@ -3629,7 +3605,7 @@ static void revoke_at_finish_message(struct ceph_connection *con) · 1 unmodified line | ||
| 3629 | 3605 | dout("%s con %p was sending epilogue - noop\n", __func__, con); |
| 3630 | 3606 | } |
| 3631 | 3607 | |
| 3632 | −void ceph_con_v2_revoke(struct ceph_connection *con) | |
| 3608 | +void ceph_con_v2_revoke(struct ceph_connection *con, struct ceph_msg *msg) | |
| 3633 | 3609 | { |
| 3634 | 3610 | WARN_ON(con->v2.out_zero); |
| 3635 | 3611 | |
| @@ -3642,13 +3618,13 @@ void ceph_con_v2_revoke(struct ceph_connection *con) · 6 unmodified lines | ||
| 3642 | 3618 | |
| 3643 | 3619 | switch (con->v2.out_state) { |
| 3644 | 3620 | case OUT_S_QUEUE_DATA: |
| 3645 | − revoke_at_queue_data(con); | |
| 3621 | + revoke_at_queue_data(con, msg); | |
| 3646 | 3622 | break; |
| 3647 | 3623 | case OUT_S_QUEUE_DATA_CONT: |
| 3648 | − revoke_at_queue_data_cont(con); | |
| 3624 | + revoke_at_queue_data_cont(con, msg); | |
| 3649 | 3625 | break; |
| 3650 | 3626 | case OUT_S_FINISH_MESSAGE: |
| 3651 | − revoke_at_finish_message(con); | |
| 3627 | + revoke_at_finish_message(con, msg); | |
| 3652 | 3628 | break; |
| 3653 | 3629 | default: |
| 3654 | 3630 | WARN(1, "bad out_state %d", con->v2.out_state); |
| @@ -3814,10 +3790,8 @@ void ceph_con_v2_reset_protocol(struct ceph_connection *con) · 159 unmodified lines | ||
| 3814 | 3790 | memzero_explicit(&con->v2.in_gcm_nonce, CEPH_GCM_IV_LEN); |
| 3815 | 3791 | memzero_explicit(&con->v2.out_gcm_nonce, CEPH_GCM_IV_LEN); |
| 3816 | 3792 | |
| 3817 | − if (con->v2.hmac_tfm) { | |
| 3818 | − crypto_free_shash(con->v2.hmac_tfm); | |
| 3819 | − con->v2.hmac_tfm = NULL; | |
| 3820 | − } | |
| 3793 | + memzero_explicit(&con->v2.hmac_key, sizeof(con->v2.hmac_key)); | |
| 3794 | + con->v2.hmac_key_set = false; | |
| 3821 | 3795 | if (con->v2.gcm_req) { |
| 3822 | 3796 | aead_request_free(con->v2.gcm_req); |
| 3823 | 3797 | con->v2.gcm_req = NULL; |