Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ceph-for-7.0-rc4' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
"A small pile of CephFS and messenger bug fixes, all marked for stable"

* tag 'ceph-for-7.0-rc4' of https://github.com/ceph/ceph-client:
libceph: Fix potential out-of-bounds access in ceph_handle_auth_reply()
libceph: Use u32 for non-negative values in ceph_monmap_decode()
MAINTAINERS: update email address of Dongsheng Yang
libceph: reject preamble if control segment is empty
libceph: admit message frames only in CEPH_CON_S_OPEN state
libceph: prevent potential out-of-bounds reads in process_message_header()
ceph: do not skip the first folio of the next object in writeback
ceph: fix memory leaks in ceph_mdsc_build_path()
ceph: add a bunch of missing ceph_path_info initializers
ceph: fix i_nlink underrun during async unlink

+52 -24
+1 -1
MAINTAINERS
··· 21937 21937 21938 21938 RADOS BLOCK DEVICE (RBD) 21939 21939 M: Ilya Dryomov <idryomov@gmail.com> 21940 - R: Dongsheng Yang <dongsheng.yang@easystack.cn> 21940 + R: Dongsheng Yang <dongsheng.yang@linux.dev> 21941 21941 L: ceph-devel@vger.kernel.org 21942 21942 S: Supported 21943 21943 W: http://ceph.com/
-1
fs/ceph/addr.c
··· 1326 1326 continue; 1327 1327 } else if (rc == -E2BIG) { 1328 1328 folio_unlock(folio); 1329 - ceph_wbc->fbatch.folios[i] = NULL; 1330 1329 break; 1331 1330 } 1332 1331
+2 -2
fs/ceph/debugfs.c
··· 79 79 if (req->r_inode) { 80 80 seq_printf(s, " #%llx", ceph_ino(req->r_inode)); 81 81 } else if (req->r_dentry) { 82 - struct ceph_path_info path_info; 82 + struct ceph_path_info path_info = {0}; 83 83 path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); 84 84 if (IS_ERR(path)) 85 85 path = NULL; ··· 98 98 } 99 99 100 100 if (req->r_old_dentry) { 101 - struct ceph_path_info path_info; 101 + struct ceph_path_info path_info = {0}; 102 102 path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &path_info, 0); 103 103 if (IS_ERR(path)) 104 104 path = NULL;
+15 -2
fs/ceph/dir.c
··· 1339 1339 struct ceph_client *cl = fsc->client; 1340 1340 struct ceph_mds_client *mdsc = fsc->mdsc; 1341 1341 struct inode *inode = d_inode(dentry); 1342 + struct ceph_inode_info *ci = ceph_inode(inode); 1342 1343 struct ceph_mds_request *req; 1343 1344 bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS); 1344 1345 struct dentry *dn; ··· 1364 1363 if (!dn) { 1365 1364 try_async = false; 1366 1365 } else { 1367 - struct ceph_path_info path_info; 1366 + struct ceph_path_info path_info = {0}; 1368 1367 path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); 1369 1368 if (IS_ERR(path)) { 1370 1369 try_async = false; ··· 1425 1424 * We have enough caps, so we assume that the unlink 1426 1425 * will succeed. Fix up the target inode and dcache. 1427 1426 */ 1428 - drop_nlink(inode); 1427 + 1428 + /* 1429 + * Protect the i_nlink update with i_ceph_lock 1430 + * to precent racing against ceph_fill_inode() 1431 + * handling our completion on a worker thread 1432 + * and don't decrement if i_nlink has already 1433 + * been updated to zero by this completion. 1434 + */ 1435 + spin_lock(&ci->i_ceph_lock); 1436 + if (inode->i_nlink > 0) 1437 + drop_nlink(inode); 1438 + spin_unlock(&ci->i_ceph_lock); 1439 + 1429 1440 d_delete(dentry); 1430 1441 } else { 1431 1442 spin_lock(&fsc->async_unlink_conflict_lock);
+2 -2
fs/ceph/file.c
··· 397 397 if (!dentry) { 398 398 do_sync = true; 399 399 } else { 400 - struct ceph_path_info path_info; 400 + struct ceph_path_info path_info = {0}; 401 401 path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); 402 402 if (IS_ERR(path)) { 403 403 do_sync = true; ··· 807 807 if (!dn) { 808 808 try_async = false; 809 809 } else { 810 - struct ceph_path_info path_info; 810 + struct ceph_path_info path_info = {0}; 811 811 path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); 812 812 if (IS_ERR(path)) { 813 813 try_async = false;
+1 -1
fs/ceph/inode.c
··· 2551 2551 if (!dentry) { 2552 2552 do_sync = true; 2553 2553 } else { 2554 - struct ceph_path_info path_info; 2554 + struct ceph_path_info path_info = {0}; 2555 2555 path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); 2556 2556 if (IS_ERR(path)) { 2557 2557 do_sync = true;
+3
fs/ceph/mds_client.c
··· 2768 2768 if (ret < 0) { 2769 2769 dput(parent); 2770 2770 dput(cur); 2771 + __putname(path); 2771 2772 return ERR_PTR(ret); 2772 2773 } 2773 2774 ··· 2778 2777 if (len < 0) { 2779 2778 dput(parent); 2780 2779 dput(cur); 2780 + __putname(path); 2781 2781 return ERR_PTR(len); 2782 2782 } 2783 2783 } ··· 2815 2813 * cannot ever succeed. Creating paths that long is 2816 2814 * possible with Ceph, but Linux cannot use them. 2817 2815 */ 2816 + __putname(path); 2818 2817 return ERR_PTR(-ENAMETOOLONG); 2819 2818 } 2820 2819
+4 -2
net/ceph/auth.c
··· 205 205 s32 result; 206 206 u64 global_id; 207 207 void *payload, *payload_end; 208 - int payload_len; 208 + u32 payload_len; 209 209 char *result_msg; 210 - int result_msg_len; 210 + u32 result_msg_len; 211 211 int ret = -EINVAL; 212 212 213 213 mutex_lock(&ac->mutex); ··· 217 217 result = ceph_decode_32(&p); 218 218 global_id = ceph_decode_64(&p); 219 219 payload_len = ceph_decode_32(&p); 220 + ceph_decode_need(&p, end, payload_len, bad); 220 221 payload = p; 221 222 p += payload_len; 222 223 ceph_decode_need(&p, end, sizeof(u32), bad); 223 224 result_msg_len = ceph_decode_32(&p); 225 + ceph_decode_need(&p, end, result_msg_len, bad); 224 226 result_msg = p; 225 227 p += result_msg_len; 226 228 if (p != end)
+21 -10
net/ceph/messenger_v2.c
··· 392 392 int head_len; 393 393 int rem_len; 394 394 395 - BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN); 395 + BUG_ON(ctrl_len < 1 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN); 396 396 397 397 if (secure) { 398 398 head_len = CEPH_PREAMBLE_SECURE_LEN; ··· 401 401 head_len += padded_len(rem_len) + CEPH_GCM_TAG_LEN; 402 402 } 403 403 } else { 404 - head_len = CEPH_PREAMBLE_PLAIN_LEN; 405 - if (ctrl_len) 406 - head_len += ctrl_len + CEPH_CRC_LEN; 404 + head_len = CEPH_PREAMBLE_PLAIN_LEN + ctrl_len + CEPH_CRC_LEN; 407 405 } 408 406 return head_len; 409 407 } ··· 526 528 desc->fd_aligns[i] = ceph_decode_16(&p); 527 529 } 528 530 529 - if (desc->fd_lens[0] < 0 || 531 + /* 532 + * This would fire for FRAME_TAG_WAIT (it has one empty 533 + * segment), but we should never get it as client. 534 + */ 535 + if (desc->fd_lens[0] < 1 || 530 536 desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) { 531 537 pr_err("bad control segment length %d\n", desc->fd_lens[0]); 532 538 return -EINVAL; 533 539 } 540 + 534 541 if (desc->fd_lens[1] < 0 || 535 542 desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) { 536 543 pr_err("bad front segment length %d\n", desc->fd_lens[1]); ··· 552 549 return -EINVAL; 553 550 } 554 551 555 - /* 556 - * This would fire for FRAME_TAG_WAIT (it has one empty 557 - * segment), but we should never get it as client. 558 - */ 559 552 if (!desc->fd_lens[desc->fd_seg_cnt - 1]) { 560 553 pr_err("last segment empty, segment count %d\n", 561 554 desc->fd_seg_cnt); ··· 2832 2833 void *p, void *end) 2833 2834 { 2834 2835 struct ceph_frame_desc *desc = &con->v2.in_desc; 2835 - struct ceph_msg_header2 *hdr2 = p; 2836 + struct ceph_msg_header2 *hdr2; 2836 2837 struct ceph_msg_header hdr; 2837 2838 int skip; 2838 2839 int ret; 2839 2840 u64 seq; 2841 + 2842 + ceph_decode_need(&p, end, sizeof(*hdr2), bad); 2843 + hdr2 = p; 2840 2844 2841 2845 /* verify seq# */ 2842 2846 seq = le64_to_cpu(hdr2->seq); ··· 2871 2869 WARN_ON(!con->in_msg); 2872 2870 WARN_ON(con->in_msg->con != con); 2873 2871 return 1; 2872 + 2873 + bad: 2874 + pr_err("failed to decode message header\n"); 2875 + return -EINVAL; 2874 2876 } 2875 2877 2876 2878 static int process_message(struct ceph_connection *con) ··· 2903 2897 2904 2898 if (con->v2.in_desc.fd_tag != FRAME_TAG_MESSAGE) 2905 2899 return process_control(con, p, end); 2900 + 2901 + if (con->state != CEPH_CON_S_OPEN) { 2902 + con->error_msg = "protocol error, unexpected message"; 2903 + return -EINVAL; 2904 + } 2906 2905 2907 2906 ret = process_message_header(con, p, end); 2908 2907 if (ret < 0)
+3 -3
net/ceph/mon_client.c
··· 72 72 struct ceph_monmap *monmap = NULL; 73 73 struct ceph_fsid fsid; 74 74 u32 struct_len; 75 - int blob_len; 76 - int num_mon; 75 + u32 blob_len; 76 + u32 num_mon; 77 77 u8 struct_v; 78 78 u32 epoch; 79 79 int ret; ··· 112 112 } 113 113 ceph_decode_32_safe(p, end, num_mon, e_inval); 114 114 115 - dout("%s fsid %pU epoch %u num_mon %d\n", __func__, &fsid, epoch, 115 + dout("%s fsid %pU epoch %u num_mon %u\n", __func__, &fsid, epoch, 116 116 num_mon); 117 117 if (num_mon > CEPH_MAX_MON) 118 118 goto e_inval;