Skip to content

Commit e1e3f53

Browse files
committed
Merge tag 'ceph-for-6.8-rc4' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: "Some fscrypt-related fixups (sparse reads are used only for encrypted files) and two cap handling fixes from Xiubo and Rishabh" * tag 'ceph-for-6.8-rc4' of https://github.com/ceph/ceph-client: ceph: always check dir caps asynchronously ceph: prevent use-after-free in encode_cap_msg() ceph: always set initial i_blkbits to CEPH_FSCRYPT_BLOCK_SHIFT libceph: just wait for more data to be available on the socket libceph: rename read_sparse_msg_*() to read_partial_sparse_msg_*() libceph: fail sparse-read if the data length doesn't match
2 parents a2343df + 0704564 commit e1e3f53

File tree

10 files changed

+49
-44
lines changed

10 files changed

+49
-44
lines changed

fs/ceph/caps.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,7 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
14521452
if (flushing & CEPH_CAP_XATTR_EXCL) {
14531453
arg->old_xattr_buf = __ceph_build_xattrs_blob(ci);
14541454
arg->xattr_version = ci->i_xattrs.version;
1455-
arg->xattr_buf = ci->i_xattrs.blob;
1455+
arg->xattr_buf = ceph_buffer_get(ci->i_xattrs.blob);
14561456
} else {
14571457
arg->xattr_buf = NULL;
14581458
arg->old_xattr_buf = NULL;
@@ -1553,6 +1553,7 @@ static void __send_cap(struct cap_msg_args *arg, struct ceph_inode_info *ci)
15531553
encode_cap_msg(msg, arg);
15541554
ceph_con_send(&arg->session->s_con, msg);
15551555
ceph_buffer_put(arg->old_xattr_buf);
1556+
ceph_buffer_put(arg->xattr_buf);
15561557
if (arg->wake)
15571558
wake_up_all(&ci->i_cap_wq);
15581559
}
@@ -3215,7 +3216,6 @@ static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
32153216

32163217
enum put_cap_refs_mode {
32173218
PUT_CAP_REFS_SYNC = 0,
3218-
PUT_CAP_REFS_NO_CHECK,
32193219
PUT_CAP_REFS_ASYNC,
32203220
};
32213221

@@ -3331,11 +3331,6 @@ void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had)
33313331
__ceph_put_cap_refs(ci, had, PUT_CAP_REFS_ASYNC);
33323332
}
33333333

3334-
void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, int had)
3335-
{
3336-
__ceph_put_cap_refs(ci, had, PUT_CAP_REFS_NO_CHECK);
3337-
}
3338-
33393334
/*
33403335
* Release @nr WRBUFFER refs on dirty pages for the given @snapc snap
33413336
* context. Adjust per-snap dirty page accounting as appropriate.

fs/ceph/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry,
7878
if (!inode)
7979
return ERR_PTR(-ENOMEM);
8080

81+
inode->i_blkbits = CEPH_FSCRYPT_BLOCK_SHIFT;
82+
8183
if (!S_ISLNK(*mode)) {
8284
err = ceph_pre_init_acls(dir, mode, as_ctx);
8385
if (err < 0)

fs/ceph/mds_client.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@ void ceph_mdsc_release_request(struct kref *kref)
10891089
struct ceph_mds_request *req = container_of(kref,
10901090
struct ceph_mds_request,
10911091
r_kref);
1092-
ceph_mdsc_release_dir_caps_no_check(req);
1092+
ceph_mdsc_release_dir_caps_async(req);
10931093
destroy_reply_info(&req->r_reply_info);
10941094
if (req->r_request)
10951095
ceph_msg_put(req->r_request);
@@ -4261,16 +4261,15 @@ void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req)
42614261
}
42624262
}
42634263

4264-
void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req)
4264+
void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req)
42654265
{
42664266
struct ceph_client *cl = req->r_mdsc->fsc->client;
42674267
int dcaps;
42684268

42694269
dcaps = xchg(&req->r_dir_caps, 0);
42704270
if (dcaps) {
42714271
doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
4272-
ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent),
4273-
dcaps);
4272+
ceph_put_cap_refs_async(ceph_inode(req->r_parent), dcaps);
42744273
}
42754274
}
42764275

@@ -4306,7 +4305,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
43064305
if (req->r_session->s_mds != session->s_mds)
43074306
continue;
43084307

4309-
ceph_mdsc_release_dir_caps_no_check(req);
4308+
ceph_mdsc_release_dir_caps_async(req);
43104309

43114310
__send_request(session, req, true);
43124311
}

fs/ceph/mds_client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ extern int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
552552
struct inode *dir,
553553
struct ceph_mds_request *req);
554554
extern void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req);
555-
extern void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req);
555+
extern void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req);
556556
static inline void ceph_mdsc_get_request(struct ceph_mds_request *req)
557557
{
558558
kref_get(&req->r_kref);

fs/ceph/super.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,8 +1255,6 @@ extern void ceph_take_cap_refs(struct ceph_inode_info *ci, int caps,
12551255
extern void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps);
12561256
extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
12571257
extern void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had);
1258-
extern void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci,
1259-
int had);
12601258
extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
12611259
struct ceph_snap_context *snapc);
12621260
extern void __ceph_remove_capsnap(struct inode *inode,

include/linux/ceph/messenger.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ struct ceph_msg {
283283
struct kref kref;
284284
bool more_to_follow;
285285
bool needs_out_seq;
286-
bool sparse_read;
286+
u64 sparse_read_total;
287287
int front_alloc_len;
288288

289289
struct ceph_msgpool *pool;

include/linux/ceph/osd_client.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum ceph_sparse_read_state {
4545
CEPH_SPARSE_READ_HDR = 0,
4646
CEPH_SPARSE_READ_EXTENTS,
4747
CEPH_SPARSE_READ_DATA_LEN,
48+
CEPH_SPARSE_READ_DATA_PRE,
4849
CEPH_SPARSE_READ_DATA,
4950
};
5051

@@ -64,7 +65,7 @@ struct ceph_sparse_read {
6465
u64 sr_req_len; /* orig request length */
6566
u64 sr_pos; /* current pos in buffer */
6667
int sr_index; /* current extent index */
67-
__le32 sr_datalen; /* length of actual data */
68+
u32 sr_datalen; /* length of actual data */
6869
u32 sr_count; /* extent count in reply */
6970
int sr_ext_len; /* length of extent array */
7071
struct ceph_sparse_extent *sr_extent; /* extent array */

net/ceph/messenger_v1.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ static size_t sizeof_footer(struct ceph_connection *con)
160160
static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
161161
{
162162
/* Initialize data cursor if it's not a sparse read */
163-
if (!msg->sparse_read)
164-
ceph_msg_data_cursor_init(&msg->cursor, msg, data_len);
163+
u64 len = msg->sparse_read_total ? : data_len;
164+
165+
ceph_msg_data_cursor_init(&msg->cursor, msg, len);
165166
}
166167

167168
/*
@@ -991,7 +992,7 @@ static inline int read_partial_message_section(struct ceph_connection *con,
991992
return read_partial_message_chunk(con, section, sec_len, crc);
992993
}
993994

994-
static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
995+
static int read_partial_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
995996
{
996997
struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor;
997998
bool do_bounce = ceph_test_opt(from_msgr(con->msgr), RXBOUNCE);
@@ -1026,7 +1027,7 @@ static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc)
10261027
return 1;
10271028
}
10281029

1029-
static int read_sparse_msg_data(struct ceph_connection *con)
1030+
static int read_partial_sparse_msg_data(struct ceph_connection *con)
10301031
{
10311032
struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor;
10321033
bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
@@ -1036,31 +1037,31 @@ static int read_sparse_msg_data(struct ceph_connection *con)
10361037
if (do_datacrc)
10371038
crc = con->in_data_crc;
10381039

1039-
do {
1040+
while (cursor->total_resid) {
10401041
if (con->v1.in_sr_kvec.iov_base)
10411042
ret = read_partial_message_chunk(con,
10421043
&con->v1.in_sr_kvec,
10431044
con->v1.in_sr_len,
10441045
&crc);
10451046
else if (cursor->sr_resid > 0)
1046-
ret = read_sparse_msg_extent(con, &crc);
1047-
1048-
if (ret <= 0) {
1049-
if (do_datacrc)
1050-
con->in_data_crc = crc;
1051-
return ret;
1052-
}
1047+
ret = read_partial_sparse_msg_extent(con, &crc);
1048+
if (ret <= 0)
1049+
break;
10531050

10541051
memset(&con->v1.in_sr_kvec, 0, sizeof(con->v1.in_sr_kvec));
10551052
ret = con->ops->sparse_read(con, cursor,
10561053
(char **)&con->v1.in_sr_kvec.iov_base);
1054+
if (ret <= 0) {
1055+
ret = ret ? ret : 1; /* must return > 0 to indicate success */
1056+
break;
1057+
}
10571058
con->v1.in_sr_len = ret;
1058-
} while (ret > 0);
1059+
}
10591060

10601061
if (do_datacrc)
10611062
con->in_data_crc = crc;
10621063

1063-
return ret < 0 ? ret : 1; /* must return > 0 to indicate success */
1064+
return ret;
10641065
}
10651066

10661067
static int read_partial_msg_data(struct ceph_connection *con)
@@ -1253,8 +1254,8 @@ static int read_partial_message(struct ceph_connection *con)
12531254
if (!m->num_data_items)
12541255
return -EIO;
12551256

1256-
if (m->sparse_read)
1257-
ret = read_sparse_msg_data(con);
1257+
if (m->sparse_read_total)
1258+
ret = read_partial_sparse_msg_data(con);
12581259
else if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE))
12591260
ret = read_partial_msg_data_bounce(con);
12601261
else

net/ceph/messenger_v2.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ static int decrypt_tail(struct ceph_connection *con)
11281128
struct sg_table enc_sgt = {};
11291129
struct sg_table sgt = {};
11301130
struct page **pages = NULL;
1131-
bool sparse = con->in_msg->sparse_read;
1131+
bool sparse = !!con->in_msg->sparse_read_total;
11321132
int dpos = 0;
11331133
int tail_len;
11341134
int ret;
@@ -2060,7 +2060,7 @@ static int prepare_read_tail_plain(struct ceph_connection *con)
20602060
}
20612061

20622062
if (data_len(msg)) {
2063-
if (msg->sparse_read)
2063+
if (msg->sparse_read_total)
20642064
con->v2.in_state = IN_S_PREPARE_SPARSE_DATA;
20652065
else
20662066
con->v2.in_state = IN_S_PREPARE_READ_DATA;

net/ceph/osd_client.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5510,7 +5510,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
55105510
}
55115511

55125512
m = ceph_msg_get(req->r_reply);
5513-
m->sparse_read = (bool)srlen;
5513+
m->sparse_read_total = srlen;
55145514

55155515
dout("get_reply tid %lld %p\n", tid, m);
55165516

@@ -5777,11 +5777,8 @@ static int prep_next_sparse_read(struct ceph_connection *con,
57775777
}
57785778

57795779
if (o->o_sparse_op_idx < 0) {
5780-
u64 srlen = sparse_data_requested(req);
5781-
5782-
dout("%s: [%d] starting new sparse read req. srlen=0x%llx\n",
5783-
__func__, o->o_osd, srlen);
5784-
ceph_msg_data_cursor_init(cursor, con->in_msg, srlen);
5780+
dout("%s: [%d] starting new sparse read req\n",
5781+
__func__, o->o_osd);
57855782
} else {
57865783
u64 end;
57875784

@@ -5857,8 +5854,8 @@ static int osd_sparse_read(struct ceph_connection *con,
58575854
struct ceph_osd *o = con->private;
58585855
struct ceph_sparse_read *sr = &o->o_sparse_read;
58595856
u32 count = sr->sr_count;
5860-
u64 eoff, elen;
5861-
int ret;
5857+
u64 eoff, elen, len = 0;
5858+
int i, ret;
58625859

58635860
switch (sr->sr_state) {
58645861
case CEPH_SPARSE_READ_HDR:
@@ -5903,8 +5900,20 @@ static int osd_sparse_read(struct ceph_connection *con,
59035900
convert_extent_map(sr);
59045901
ret = sizeof(sr->sr_datalen);
59055902
*pbuf = (char *)&sr->sr_datalen;
5906-
sr->sr_state = CEPH_SPARSE_READ_DATA;
5903+
sr->sr_state = CEPH_SPARSE_READ_DATA_PRE;
59075904
break;
5905+
case CEPH_SPARSE_READ_DATA_PRE:
5906+
/* Convert sr_datalen to host-endian */
5907+
sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen);
5908+
for (i = 0; i < count; i++)
5909+
len += sr->sr_extent[i].len;
5910+
if (sr->sr_datalen != len) {
5911+
pr_warn_ratelimited("data len %u != extent len %llu\n",
5912+
sr->sr_datalen, len);
5913+
return -EREMOTEIO;
5914+
}
5915+
sr->sr_state = CEPH_SPARSE_READ_DATA;
5916+
fallthrough;
59085917
case CEPH_SPARSE_READ_DATA:
59095918
if (sr->sr_index >= count) {
59105919
sr->sr_state = CEPH_SPARSE_READ_HDR;

0 commit comments

Comments
 (0)