mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
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()
This commit is contained in:
@@ -1149,7 +1149,7 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
|
|||||||
const char *path = fsc->mount_options->server_path ?
|
const char *path = fsc->mount_options->server_path ?
|
||||||
fsc->mount_options->server_path + 1 : "";
|
fsc->mount_options->server_path + 1 : "";
|
||||||
|
|
||||||
err = __ceph_open_session(fsc->client, started);
|
err = __ceph_open_session(fsc->client);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|||||||
@@ -306,8 +306,7 @@ struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client);
|
|||||||
u64 ceph_client_gid(struct ceph_client *client);
|
u64 ceph_client_gid(struct ceph_client *client);
|
||||||
extern void ceph_destroy_client(struct ceph_client *client);
|
extern void ceph_destroy_client(struct ceph_client *client);
|
||||||
extern void ceph_reset_client_addr(struct ceph_client *client);
|
extern void ceph_reset_client_addr(struct ceph_client *client);
|
||||||
extern int __ceph_open_session(struct ceph_client *client,
|
extern int __ceph_open_session(struct ceph_client *client);
|
||||||
unsigned long started);
|
|
||||||
extern int ceph_open_session(struct ceph_client *client);
|
extern int ceph_open_session(struct ceph_client *client);
|
||||||
int ceph_wait_for_latest_osdmap(struct ceph_client *client,
|
int ceph_wait_for_latest_osdmap(struct ceph_client *client,
|
||||||
unsigned long timeout);
|
unsigned long timeout);
|
||||||
|
|||||||
@@ -631,6 +631,7 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
|
|||||||
|
|
||||||
/* connection secret */
|
/* connection secret */
|
||||||
ceph_decode_32_safe(p, end, len, e_inval);
|
ceph_decode_32_safe(p, end, len, e_inval);
|
||||||
|
ceph_decode_need(p, end, len, e_inval);
|
||||||
dout("%s connection secret blob len %d\n", __func__, len);
|
dout("%s connection secret blob len %d\n", __func__, len);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
dp = *p + ceph_x_encrypt_offset();
|
dp = *p + ceph_x_encrypt_offset();
|
||||||
@@ -648,6 +649,7 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
|
|||||||
|
|
||||||
/* service tickets */
|
/* service tickets */
|
||||||
ceph_decode_32_safe(p, end, len, e_inval);
|
ceph_decode_32_safe(p, end, len, e_inval);
|
||||||
|
ceph_decode_need(p, end, len, e_inval);
|
||||||
dout("%s service tickets blob len %d\n", __func__, len);
|
dout("%s service tickets blob len %d\n", __func__, len);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
|
ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
|
||||||
|
|||||||
@@ -785,42 +785,53 @@ void ceph_reset_client_addr(struct ceph_client *client)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ceph_reset_client_addr);
|
EXPORT_SYMBOL(ceph_reset_client_addr);
|
||||||
|
|
||||||
/*
|
|
||||||
* true if we have the mon map (and have thus joined the cluster)
|
|
||||||
*/
|
|
||||||
static bool have_mon_and_osd_map(struct ceph_client *client)
|
|
||||||
{
|
|
||||||
return client->monc.monmap && client->monc.monmap->epoch &&
|
|
||||||
client->osdc.osdmap && client->osdc.osdmap->epoch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mount: join the ceph cluster, and open root directory.
|
* mount: join the ceph cluster, and open root directory.
|
||||||
*/
|
*/
|
||||||
int __ceph_open_session(struct ceph_client *client, unsigned long started)
|
int __ceph_open_session(struct ceph_client *client)
|
||||||
{
|
{
|
||||||
unsigned long timeout = client->options->mount_timeout;
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
long err;
|
long timeout = ceph_timeout_jiffies(client->options->mount_timeout);
|
||||||
|
bool have_monmap, have_osdmap;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* open session, and wait for mon and osd maps */
|
/* open session, and wait for mon and osd maps */
|
||||||
err = ceph_monc_open_session(&client->monc);
|
err = ceph_monc_open_session(&client->monc);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
while (!have_mon_and_osd_map(client)) {
|
add_wait_queue(&client->auth_wq, &wait);
|
||||||
if (timeout && time_after_eq(jiffies, started + timeout))
|
for (;;) {
|
||||||
return -ETIMEDOUT;
|
mutex_lock(&client->monc.mutex);
|
||||||
|
err = client->auth_err;
|
||||||
|
have_monmap = client->monc.monmap && client->monc.monmap->epoch;
|
||||||
|
mutex_unlock(&client->monc.mutex);
|
||||||
|
|
||||||
|
down_read(&client->osdc.lock);
|
||||||
|
have_osdmap = client->osdc.osdmap && client->osdc.osdmap->epoch;
|
||||||
|
up_read(&client->osdc.lock);
|
||||||
|
|
||||||
|
if (err || (have_monmap && have_osdmap))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
err = -ERESTARTSYS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
err = -ETIMEDOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* wait */
|
/* wait */
|
||||||
dout("mount waiting for mon_map\n");
|
dout("mount waiting for mon_map\n");
|
||||||
err = wait_event_interruptible_timeout(client->auth_wq,
|
timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
|
||||||
have_mon_and_osd_map(client) || (client->auth_err < 0),
|
|
||||||
ceph_timeout_jiffies(timeout));
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
if (client->auth_err < 0)
|
|
||||||
return client->auth_err;
|
|
||||||
}
|
}
|
||||||
|
remove_wait_queue(&client->auth_wq, &wait);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
|
pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
|
||||||
&client->fsid);
|
&client->fsid);
|
||||||
@@ -833,12 +844,11 @@ EXPORT_SYMBOL(__ceph_open_session);
|
|||||||
int ceph_open_session(struct ceph_client *client)
|
int ceph_open_session(struct ceph_client *client)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long started = jiffies; /* note the start time */
|
|
||||||
|
|
||||||
dout("open_session start\n");
|
dout("open_session start\n");
|
||||||
mutex_lock(&client->mount_mutex);
|
mutex_lock(&client->mount_mutex);
|
||||||
|
|
||||||
ret = __ceph_open_session(client, started);
|
ret = __ceph_open_session(client);
|
||||||
|
|
||||||
mutex_unlock(&client->mount_mutex);
|
mutex_unlock(&client->mount_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ static int monmap_show(struct seq_file *s, void *p)
|
|||||||
int i;
|
int i;
|
||||||
struct ceph_client *client = s->private;
|
struct ceph_client *client = s->private;
|
||||||
|
|
||||||
|
mutex_lock(&client->monc.mutex);
|
||||||
if (client->monc.monmap == NULL)
|
if (client->monc.monmap == NULL)
|
||||||
return 0;
|
goto out_unlock;
|
||||||
|
|
||||||
seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
|
seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
|
||||||
for (i = 0; i < client->monc.monmap->num_mon; i++) {
|
for (i = 0; i < client->monc.monmap->num_mon; i++) {
|
||||||
@@ -48,6 +49,9 @@ static int monmap_show(struct seq_file *s, void *p)
|
|||||||
ENTITY_NAME(inst->name),
|
ENTITY_NAME(inst->name),
|
||||||
ceph_pr_addr(&inst->addr));
|
ceph_pr_addr(&inst->addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&client->monc.mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,13 +60,14 @@ static int osdmap_show(struct seq_file *s, void *p)
|
|||||||
int i;
|
int i;
|
||||||
struct ceph_client *client = s->private;
|
struct ceph_client *client = s->private;
|
||||||
struct ceph_osd_client *osdc = &client->osdc;
|
struct ceph_osd_client *osdc = &client->osdc;
|
||||||
struct ceph_osdmap *map = osdc->osdmap;
|
struct ceph_osdmap *map;
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
|
|
||||||
if (map == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
down_read(&osdc->lock);
|
down_read(&osdc->lock);
|
||||||
|
map = osdc->osdmap;
|
||||||
|
if (map == NULL)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
|
seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
|
||||||
osdc->epoch_barrier, map->flags);
|
osdc->epoch_barrier, map->flags);
|
||||||
|
|
||||||
@@ -131,6 +136,7 @@ static int osdmap_show(struct seq_file *s, void *p)
|
|||||||
seq_printf(s, "]\n");
|
seq_printf(s, "]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
up_read(&osdc->lock);
|
up_read(&osdc->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1061,13 +1061,16 @@ static int decrypt_control_remainder(struct ceph_connection *con)
|
|||||||
static int process_v2_sparse_read(struct ceph_connection *con,
|
static int process_v2_sparse_read(struct ceph_connection *con,
|
||||||
struct page **pages, int spos)
|
struct page **pages, int spos)
|
||||||
{
|
{
|
||||||
struct ceph_msg_data_cursor *cursor = &con->v2.in_cursor;
|
struct ceph_msg_data_cursor cursor;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ceph_msg_data_cursor_init(&cursor, con->in_msg,
|
||||||
|
con->in_msg->sparse_read_total);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
ret = con->ops->sparse_read(con, cursor, &buf);
|
ret = con->ops->sparse_read(con, &cursor, &buf);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -1085,11 +1088,11 @@ static int process_v2_sparse_read(struct ceph_connection *con,
|
|||||||
} else {
|
} else {
|
||||||
struct bio_vec bv;
|
struct bio_vec bv;
|
||||||
|
|
||||||
get_bvec_at(cursor, &bv);
|
get_bvec_at(&cursor, &bv);
|
||||||
len = min_t(int, len, bv.bv_len);
|
len = min_t(int, len, bv.bv_len);
|
||||||
memcpy_page(bv.bv_page, bv.bv_offset,
|
memcpy_page(bv.bv_page, bv.bv_offset,
|
||||||
spage, soff, len);
|
spage, soff, len);
|
||||||
ceph_msg_data_advance(cursor, len);
|
ceph_msg_data_advance(&cursor, len);
|
||||||
}
|
}
|
||||||
spos += len;
|
spos += len;
|
||||||
ret -= len;
|
ret -= len;
|
||||||
|
|||||||
@@ -1504,8 +1504,6 @@ static int decode_new_primary_temp(void **p, void *end,
|
|||||||
|
|
||||||
u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd)
|
u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd)
|
||||||
{
|
{
|
||||||
BUG_ON(osd >= map->max_osd);
|
|
||||||
|
|
||||||
if (!map->osd_primary_affinity)
|
if (!map->osd_primary_affinity)
|
||||||
return CEPH_OSD_DEFAULT_PRIMARY_AFFINITY;
|
return CEPH_OSD_DEFAULT_PRIMARY_AFFINITY;
|
||||||
|
|
||||||
@@ -1514,8 +1512,6 @@ u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd)
|
|||||||
|
|
||||||
static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff)
|
static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff)
|
||||||
{
|
{
|
||||||
BUG_ON(osd >= map->max_osd);
|
|
||||||
|
|
||||||
if (!map->osd_primary_affinity) {
|
if (!map->osd_primary_affinity) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -1577,6 +1573,8 @@ static int decode_new_primary_affinity(void **p, void *end,
|
|||||||
|
|
||||||
ceph_decode_32_safe(p, end, osd, e_inval);
|
ceph_decode_32_safe(p, end, osd, e_inval);
|
||||||
ceph_decode_32_safe(p, end, aff, e_inval);
|
ceph_decode_32_safe(p, end, aff, e_inval);
|
||||||
|
if (osd >= map->max_osd)
|
||||||
|
goto e_inval;
|
||||||
|
|
||||||
ret = set_primary_affinity(map, osd, aff);
|
ret = set_primary_affinity(map, osd, aff);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -1879,7 +1877,9 @@ static int decode_new_up_state_weight(void **p, void *end, u8 struct_v,
|
|||||||
ceph_decode_need(p, end, 2*sizeof(u32), e_inval);
|
ceph_decode_need(p, end, 2*sizeof(u32), e_inval);
|
||||||
osd = ceph_decode_32(p);
|
osd = ceph_decode_32(p);
|
||||||
w = ceph_decode_32(p);
|
w = ceph_decode_32(p);
|
||||||
BUG_ON(osd >= map->max_osd);
|
if (osd >= map->max_osd)
|
||||||
|
goto e_inval;
|
||||||
|
|
||||||
osdmap_info(map, "osd%d weight 0x%x %s\n", osd, w,
|
osdmap_info(map, "osd%d weight 0x%x %s\n", osd, w,
|
||||||
w == CEPH_OSD_IN ? "(in)" :
|
w == CEPH_OSD_IN ? "(in)" :
|
||||||
(w == CEPH_OSD_OUT ? "(out)" : ""));
|
(w == CEPH_OSD_OUT ? "(out)" : ""));
|
||||||
@@ -1905,13 +1905,15 @@ static int decode_new_up_state_weight(void **p, void *end, u8 struct_v,
|
|||||||
u32 xorstate;
|
u32 xorstate;
|
||||||
|
|
||||||
osd = ceph_decode_32(p);
|
osd = ceph_decode_32(p);
|
||||||
|
if (osd >= map->max_osd)
|
||||||
|
goto e_inval;
|
||||||
|
|
||||||
if (struct_v >= 5)
|
if (struct_v >= 5)
|
||||||
xorstate = ceph_decode_32(p);
|
xorstate = ceph_decode_32(p);
|
||||||
else
|
else
|
||||||
xorstate = ceph_decode_8(p);
|
xorstate = ceph_decode_8(p);
|
||||||
if (xorstate == 0)
|
if (xorstate == 0)
|
||||||
xorstate = CEPH_OSD_UP;
|
xorstate = CEPH_OSD_UP;
|
||||||
BUG_ON(osd >= map->max_osd);
|
|
||||||
if ((map->osd_state[osd] & CEPH_OSD_UP) &&
|
if ((map->osd_state[osd] & CEPH_OSD_UP) &&
|
||||||
(xorstate & CEPH_OSD_UP))
|
(xorstate & CEPH_OSD_UP))
|
||||||
osdmap_info(map, "osd%d down\n", osd);
|
osdmap_info(map, "osd%d down\n", osd);
|
||||||
@@ -1937,7 +1939,9 @@ static int decode_new_up_state_weight(void **p, void *end, u8 struct_v,
|
|||||||
struct ceph_entity_addr addr;
|
struct ceph_entity_addr addr;
|
||||||
|
|
||||||
osd = ceph_decode_32(p);
|
osd = ceph_decode_32(p);
|
||||||
BUG_ON(osd >= map->max_osd);
|
if (osd >= map->max_osd)
|
||||||
|
goto e_inval;
|
||||||
|
|
||||||
if (struct_v >= 7)
|
if (struct_v >= 7)
|
||||||
ret = ceph_decode_entity_addrvec(p, end, msgr2, &addr);
|
ret = ceph_decode_entity_addrvec(p, end, msgr2, &addr);
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user