diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-28 11:51:05 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-28 11:51:05 -0700 |
| commit | 548e7bcd0c5460ddcbca9600cea603ebeebf4da7 (patch) | |
| tree | f6c9495617263ee073c84c9735afa173a3686a3b /net | |
| parent | ce727a090be04dc7c51edd5c0da2a41d2fb6e106 (diff) | |
| parent | 8fdf946445732c2bcd685abc8bd0e509d2ebc158 (diff) | |
| download | linux-548e7bcd0c5460ddcbca9600cea603ebeebf4da7.tar.gz linux-548e7bcd0c5460ddcbca9600cea603ebeebf4da7.zip | |
Merge tag 'ceph-for-7.3-rc1' of https://github.com/ceph/ceph-client
Pull ceph updates from Ilya Dryomov:
"A wide variety of mostly CephFS fixes and cleanups, split between
changes that address edge cases (Sam, Xiubo, Matthew), efficiency
improvements (Max) and AI-assisted hardening (Michael, Jeremy).
One thing that stands out is Alex's change to how CephFS behaves in
NEARFULL scenarios: the long-standing "make all writes synchronous"
behavior has become opt-in. It was always somewhat controversial and
doesn't make much sense for modern deployments; the new default is to
continue normal operation (i.e. buffer writes as MDS allows, etc). The
behavior in case the cluster reaches any FULL state remains the same
as before"
* tag 'ceph-for-7.3-rc1' of https://github.com/ceph/ceph-client: (32 commits)
ceph: force a cap message when a deferred revoke can't be acked immediately
libceph: reject buckets with mismatched CRUSH ids
ceph: reject export_targets ranks >= CEPH_MAX_MDS in mdsmap decode
ceph: fix leaked inode reference on writeback abort at umount
libceph: remove ceph_put_page_vector()
libceph: validate banner payload length
ceph: make nearfull sync writes opt-in
ceph: do not repeat ceph_trim_dentries() if no progress possible
ceph: drop mdsc->mutex before decoding the MDS reply
ceph: fix UAF in check_new_map() on session freed during unlock
ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock
ceph: pass inode pointer around instead of reloading it
ceph: mark cap remove with RB_CLEAR_NODE() instead of setting ci=NULL
ceph: add helper function ceph_cap_is_removed()
ceph: make __ceph_remove_cap() static
ceph: cap delegated inode count in ceph_parse_deleg_inos()
ceph: bound num_export_targets array for mds info v2/v3
ceph: bound MDSCapAuth path and fs_name decode in handle_session()
ceph: bound xattr value length in __build_xattrs()
ceph: bound copied dentry name length in NFS export get_name
...
Diffstat (limited to 'net')
| -rw-r--r-- | net/ceph/messenger_v2.c | 5 | ||||
| -rw-r--r-- | net/ceph/osd_client.c | 30 | ||||
| -rw-r--r-- | net/ceph/osdmap.c | 2 | ||||
| -rw-r--r-- | net/ceph/pagevec.c | 13 |
4 files changed, 37 insertions, 13 deletions
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c index 05f6eea299fc..b323b61e7023 100644 --- a/net/ceph/messenger_v2.c +++ b/net/ceph/messenger_v2.c @@ -2142,6 +2142,11 @@ static int process_banner_prefix(struct ceph_connection *con) payload_len = ceph_decode_16(&p); dout("%s con %p payload_len %d\n", __func__, con, payload_len); + if (payload_len < sizeof(u64) + sizeof(u64)) { + con->error_msg = "protocol error, bad banner payload len"; + return -EINVAL; + } + return prepare_read_banner_payload(con, payload_len); } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 28d76c2f6b3e..f36ce5ae7568 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -6,6 +6,7 @@ #include <linux/err.h> #include <linux/highmem.h> #include <linux/mm.h> +#include <linux/overflow.h> #include <linux/pagemap.h> #include <linux/slab.h> #include <linux/uaccess.h> @@ -5802,6 +5803,31 @@ static inline void convert_extent_map(struct ceph_sparse_read *sr) } #endif +static bool sparse_extent_map_valid(struct ceph_sparse_read *sr) +{ + u64 req_end, pos; + int i; + + if (check_add_overflow(sr->sr_req_off, sr->sr_req_len, &req_end)) + return false; + + pos = sr->sr_req_off; + for (i = 0; i < sr->sr_count; i++) { + struct ceph_sparse_extent *ext = &sr->sr_extent[i]; + u64 end; + + if (ext->off < pos) + return false; + if (check_add_overflow(ext->off, ext->len, &end)) + return false; + if (end > req_end) + return false; + pos = end; + } + + return true; +} + static int osd_sparse_read(struct ceph_connection *con, struct ceph_msg_data_cursor *cursor, char **pbuf) @@ -5852,6 +5878,10 @@ next_op: fallthrough; case CEPH_SPARSE_READ_DATA_LEN: convert_extent_map(sr); + if (!sparse_extent_map_valid(sr)) { + pr_warn_ratelimited("invalid sparse extent map\n"); + return -EREMOTEIO; + } ret = sizeof(sr->sr_datalen); *pbuf = (char *)&sr->sr_datalen; sr->sr_state = CEPH_SPARSE_READ_DATA_PRE; diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index d6282f0bcff8..cf34b35c9a90 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -517,6 +517,8 @@ static struct crush_map *crush_decode(void *pbyval, void *end) ceph_decode_need(p, end, 4*sizeof(u32), bad); b->id = ceph_decode_32(p); + if (b->id != -1 - i) + goto bad; b->type = ceph_decode_16(p); if (b->type == 0) goto bad; diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 858359873c4d..a6aa5b3b7a1e 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -10,19 +10,6 @@ #include <linux/ceph/libceph.h> -void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty) -{ - int i; - - for (i = 0; i < num_pages; i++) { - if (dirty) - set_page_dirty_lock(pages[i]); - put_page(pages[i]); - } - kvfree(pages); -} -EXPORT_SYMBOL(ceph_put_page_vector); - void ceph_release_page_vector(struct page **pages, int num_pages) { int i; |
