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

Merge tag 'ceph-for-6.18-rc8' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
"A patch to make sparse read handling work in msgr2 secure mode from
Slava and a couple of fixes from Ziming and myself to avoid operating
on potentially invalid memory, all marked for stable"

* tag 'ceph-for-6.18-rc8' of https://github.com/ceph/ceph-client:
libceph: prevent potential out-of-bounds writes in handle_auth_session_key()
libceph: replace BUG_ON with bounds check for map->max_osd
ceph: fix crash in process_v2_sparse_read() for encrypted directories
libceph: drop started parameter of __ceph_open_session()
libceph: fix potential use-after-free in have_mon_and_osd_map()

+67 -43
+1 -1
fs/ceph/super.c
··· 1149 1149 const char *path = fsc->mount_options->server_path ? 1150 1150 fsc->mount_options->server_path + 1 : ""; 1151 1151 1152 - err = __ceph_open_session(fsc->client, started); 1152 + err = __ceph_open_session(fsc->client); 1153 1153 if (err < 0) 1154 1154 goto out; 1155 1155
+1 -2
include/linux/ceph/libceph.h
··· 306 306 u64 ceph_client_gid(struct ceph_client *client); 307 307 extern void ceph_destroy_client(struct ceph_client *client); 308 308 extern void ceph_reset_client_addr(struct ceph_client *client); 309 - extern int __ceph_open_session(struct ceph_client *client, 310 - unsigned long started); 309 + extern int __ceph_open_session(struct ceph_client *client); 311 310 extern int ceph_open_session(struct ceph_client *client); 312 311 int ceph_wait_for_latest_osdmap(struct ceph_client *client, 313 312 unsigned long timeout);
+2
net/ceph/auth_x.c
··· 631 631 632 632 /* connection secret */ 633 633 ceph_decode_32_safe(p, end, len, e_inval); 634 + ceph_decode_need(p, end, len, e_inval); 634 635 dout("%s connection secret blob len %d\n", __func__, len); 635 636 if (len > 0) { 636 637 dp = *p + ceph_x_encrypt_offset(); ··· 649 648 650 649 /* service tickets */ 651 650 ceph_decode_32_safe(p, end, len, e_inval); 651 + ceph_decode_need(p, end, len, e_inval); 652 652 dout("%s service tickets blob len %d\n", __func__, len); 653 653 if (len > 0) { 654 654 ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
+34 -24
net/ceph/ceph_common.c
··· 786 786 EXPORT_SYMBOL(ceph_reset_client_addr); 787 787 788 788 /* 789 - * true if we have the mon map (and have thus joined the cluster) 790 - */ 791 - static bool have_mon_and_osd_map(struct ceph_client *client) 792 - { 793 - return client->monc.monmap && client->monc.monmap->epoch && 794 - client->osdc.osdmap && client->osdc.osdmap->epoch; 795 - } 796 - 797 - /* 798 789 * mount: join the ceph cluster, and open root directory. 799 790 */ 800 - int __ceph_open_session(struct ceph_client *client, unsigned long started) 791 + int __ceph_open_session(struct ceph_client *client) 801 792 { 802 - unsigned long timeout = client->options->mount_timeout; 803 - long err; 793 + DEFINE_WAIT_FUNC(wait, woken_wake_function); 794 + long timeout = ceph_timeout_jiffies(client->options->mount_timeout); 795 + bool have_monmap, have_osdmap; 796 + int err; 804 797 805 798 /* open session, and wait for mon and osd maps */ 806 799 err = ceph_monc_open_session(&client->monc); 807 800 if (err < 0) 808 801 return err; 809 802 810 - while (!have_mon_and_osd_map(client)) { 811 - if (timeout && time_after_eq(jiffies, started + timeout)) 812 - return -ETIMEDOUT; 803 + add_wait_queue(&client->auth_wq, &wait); 804 + for (;;) { 805 + mutex_lock(&client->monc.mutex); 806 + err = client->auth_err; 807 + have_monmap = client->monc.monmap && client->monc.monmap->epoch; 808 + mutex_unlock(&client->monc.mutex); 809 + 810 + down_read(&client->osdc.lock); 811 + have_osdmap = client->osdc.osdmap && client->osdc.osdmap->epoch; 812 + up_read(&client->osdc.lock); 813 + 814 + if (err || (have_monmap && have_osdmap)) 815 + break; 816 + 817 + if (signal_pending(current)) { 818 + err = -ERESTARTSYS; 819 + break; 820 + } 821 + 822 + if (!timeout) { 823 + err = -ETIMEDOUT; 824 + break; 825 + } 813 826 814 827 /* wait */ 815 828 dout("mount waiting for mon_map\n"); 816 - err = wait_event_interruptible_timeout(client->auth_wq, 817 - have_mon_and_osd_map(client) || (client->auth_err < 0), 818 - ceph_timeout_jiffies(timeout)); 819 - if (err < 0) 820 - return err; 821 - if (client->auth_err < 0) 822 - return client->auth_err; 829 + timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout); 823 830 } 831 + remove_wait_queue(&client->auth_wq, &wait); 832 + 833 + if (err) 834 + return err; 824 835 825 836 pr_info("client%llu fsid %pU\n", ceph_client_gid(client), 826 837 &client->fsid); ··· 844 833 int ceph_open_session(struct ceph_client *client) 845 834 { 846 835 int ret; 847 - unsigned long started = jiffies; /* note the start time */ 848 836 849 837 dout("open_session start\n"); 850 838 mutex_lock(&client->mount_mutex); 851 839 852 - ret = __ceph_open_session(client, started); 840 + ret = __ceph_open_session(client); 853 841 854 842 mutex_unlock(&client->mount_mutex); 855 843 return ret;
+11 -5
net/ceph/debugfs.c
··· 36 36 int i; 37 37 struct ceph_client *client = s->private; 38 38 39 + mutex_lock(&client->monc.mutex); 39 40 if (client->monc.monmap == NULL) 40 - return 0; 41 + goto out_unlock; 41 42 42 43 seq_printf(s, "epoch %d\n", client->monc.monmap->epoch); 43 44 for (i = 0; i < client->monc.monmap->num_mon; i++) { ··· 49 48 ENTITY_NAME(inst->name), 50 49 ceph_pr_addr(&inst->addr)); 51 50 } 51 + 52 + out_unlock: 53 + mutex_unlock(&client->monc.mutex); 52 54 return 0; 53 55 } 54 56 ··· 60 56 int i; 61 57 struct ceph_client *client = s->private; 62 58 struct ceph_osd_client *osdc = &client->osdc; 63 - struct ceph_osdmap *map = osdc->osdmap; 59 + struct ceph_osdmap *map; 64 60 struct rb_node *n; 65 61 66 - if (map == NULL) 67 - return 0; 68 - 69 62 down_read(&osdc->lock); 63 + map = osdc->osdmap; 64 + if (map == NULL) 65 + goto out_unlock; 66 + 70 67 seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch, 71 68 osdc->epoch_barrier, map->flags); 72 69 ··· 136 131 seq_printf(s, "]\n"); 137 132 } 138 133 134 + out_unlock: 139 135 up_read(&osdc->lock); 140 136 return 0; 141 137 }
+7 -4
net/ceph/messenger_v2.c
··· 1061 1061 static int process_v2_sparse_read(struct ceph_connection *con, 1062 1062 struct page **pages, int spos) 1063 1063 { 1064 - struct ceph_msg_data_cursor *cursor = &con->v2.in_cursor; 1064 + struct ceph_msg_data_cursor cursor; 1065 1065 int ret; 1066 + 1067 + ceph_msg_data_cursor_init(&cursor, con->in_msg, 1068 + con->in_msg->sparse_read_total); 1066 1069 1067 1070 for (;;) { 1068 1071 char *buf = NULL; 1069 1072 1070 - ret = con->ops->sparse_read(con, cursor, &buf); 1073 + ret = con->ops->sparse_read(con, &cursor, &buf); 1071 1074 if (ret <= 0) 1072 1075 return ret; 1073 1076 ··· 1088 1085 } else { 1089 1086 struct bio_vec bv; 1090 1087 1091 - get_bvec_at(cursor, &bv); 1088 + get_bvec_at(&cursor, &bv); 1092 1089 len = min_t(int, len, bv.bv_len); 1093 1090 memcpy_page(bv.bv_page, bv.bv_offset, 1094 1091 spage, soff, len); 1095 - ceph_msg_data_advance(cursor, len); 1092 + ceph_msg_data_advance(&cursor, len); 1096 1093 } 1097 1094 spos += len; 1098 1095 ret -= len;
+11 -7
net/ceph/osdmap.c
··· 1504 1504 1505 1505 u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd) 1506 1506 { 1507 - BUG_ON(osd >= map->max_osd); 1508 - 1509 1507 if (!map->osd_primary_affinity) 1510 1508 return CEPH_OSD_DEFAULT_PRIMARY_AFFINITY; 1511 1509 ··· 1512 1514 1513 1515 static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff) 1514 1516 { 1515 - BUG_ON(osd >= map->max_osd); 1516 - 1517 1517 if (!map->osd_primary_affinity) { 1518 1518 int i; 1519 1519 ··· 1573 1577 1574 1578 ceph_decode_32_safe(p, end, osd, e_inval); 1575 1579 ceph_decode_32_safe(p, end, aff, e_inval); 1580 + if (osd >= map->max_osd) 1581 + goto e_inval; 1576 1582 1577 1583 ret = set_primary_affinity(map, osd, aff); 1578 1584 if (ret) ··· 1877 1879 ceph_decode_need(p, end, 2*sizeof(u32), e_inval); 1878 1880 osd = ceph_decode_32(p); 1879 1881 w = ceph_decode_32(p); 1880 - BUG_ON(osd >= map->max_osd); 1882 + if (osd >= map->max_osd) 1883 + goto e_inval; 1884 + 1881 1885 osdmap_info(map, "osd%d weight 0x%x %s\n", osd, w, 1882 1886 w == CEPH_OSD_IN ? "(in)" : 1883 1887 (w == CEPH_OSD_OUT ? "(out)" : "")); ··· 1905 1905 u32 xorstate; 1906 1906 1907 1907 osd = ceph_decode_32(p); 1908 + if (osd >= map->max_osd) 1909 + goto e_inval; 1910 + 1908 1911 if (struct_v >= 5) 1909 1912 xorstate = ceph_decode_32(p); 1910 1913 else 1911 1914 xorstate = ceph_decode_8(p); 1912 1915 if (xorstate == 0) 1913 1916 xorstate = CEPH_OSD_UP; 1914 - BUG_ON(osd >= map->max_osd); 1915 1917 if ((map->osd_state[osd] & CEPH_OSD_UP) && 1916 1918 (xorstate & CEPH_OSD_UP)) 1917 1919 osdmap_info(map, "osd%d down\n", osd); ··· 1939 1937 struct ceph_entity_addr addr; 1940 1938 1941 1939 osd = ceph_decode_32(p); 1942 - BUG_ON(osd >= map->max_osd); 1940 + if (osd >= map->max_osd) 1941 + goto e_inval; 1942 + 1943 1943 if (struct_v >= 7) 1944 1944 ret = ceph_decode_entity_addrvec(p, end, msgr2, &addr); 1945 1945 else