cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

decode.c (4744B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/ceph/ceph_debug.h>
      3
      4#include <linux/inet.h>
      5
      6#include <linux/ceph/decode.h>
      7#include <linux/ceph/messenger.h>  /* for ceph_pr_addr() */
      8
      9static int
     10ceph_decode_entity_addr_versioned(void **p, void *end,
     11				  struct ceph_entity_addr *addr)
     12{
     13	int ret;
     14	u8 struct_v;
     15	u32 struct_len, addr_len;
     16	void *struct_end;
     17
     18	ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v,
     19				  &struct_len);
     20	if (ret)
     21		goto bad;
     22
     23	ret = -EINVAL;
     24	struct_end = *p + struct_len;
     25
     26	ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad);
     27
     28	ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
     29
     30	ceph_decode_32_safe(p, end, addr_len, bad);
     31	if (addr_len > sizeof(addr->in_addr))
     32		goto bad;
     33
     34	memset(&addr->in_addr, 0, sizeof(addr->in_addr));
     35	if (addr_len) {
     36		ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad);
     37
     38		addr->in_addr.ss_family =
     39			le16_to_cpu((__force __le16)addr->in_addr.ss_family);
     40	}
     41
     42	/* Advance past anything the client doesn't yet understand */
     43	*p = struct_end;
     44	ret = 0;
     45bad:
     46	return ret;
     47}
     48
     49static int
     50ceph_decode_entity_addr_legacy(void **p, void *end,
     51			       struct ceph_entity_addr *addr)
     52{
     53	int ret = -EINVAL;
     54
     55	/* Skip rest of type field */
     56	ceph_decode_skip_n(p, end, 3, bad);
     57
     58	/*
     59	 * Clients that don't support ADDR2 always send TYPE_NONE, change it
     60	 * to TYPE_LEGACY for forward compatibility.
     61	 */
     62	addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
     63	ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
     64	memset(&addr->in_addr, 0, sizeof(addr->in_addr));
     65	ceph_decode_copy_safe(p, end, &addr->in_addr,
     66			      sizeof(addr->in_addr), bad);
     67	addr->in_addr.ss_family =
     68			be16_to_cpu((__force __be16)addr->in_addr.ss_family);
     69	ret = 0;
     70bad:
     71	return ret;
     72}
     73
     74int
     75ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
     76{
     77	u8 marker;
     78
     79	ceph_decode_8_safe(p, end, marker, bad);
     80	if (marker == 1)
     81		return ceph_decode_entity_addr_versioned(p, end, addr);
     82	else if (marker == 0)
     83		return ceph_decode_entity_addr_legacy(p, end, addr);
     84bad:
     85	return -EINVAL;
     86}
     87EXPORT_SYMBOL(ceph_decode_entity_addr);
     88
     89/*
     90 * Return addr of desired type (MSGR2 or LEGACY) or error.
     91 * Make sure there is only one match.
     92 *
     93 * Assume encoding with MSG_ADDR2.
     94 */
     95int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
     96			       struct ceph_entity_addr *addr)
     97{
     98	__le32 my_type = msgr2 ? CEPH_ENTITY_ADDR_TYPE_MSGR2 :
     99				 CEPH_ENTITY_ADDR_TYPE_LEGACY;
    100	struct ceph_entity_addr tmp_addr;
    101	int addr_cnt;
    102	bool found;
    103	u8 marker;
    104	int ret;
    105	int i;
    106
    107	ceph_decode_8_safe(p, end, marker, e_inval);
    108	if (marker != 2) {
    109		pr_err("bad addrvec marker %d\n", marker);
    110		return -EINVAL;
    111	}
    112
    113	ceph_decode_32_safe(p, end, addr_cnt, e_inval);
    114	dout("%s addr_cnt %d\n", __func__, addr_cnt);
    115
    116	found = false;
    117	for (i = 0; i < addr_cnt; i++) {
    118		ret = ceph_decode_entity_addr(p, end, &tmp_addr);
    119		if (ret)
    120			return ret;
    121
    122		dout("%s i %d addr %s\n", __func__, i, ceph_pr_addr(&tmp_addr));
    123		if (tmp_addr.type == my_type) {
    124			if (found) {
    125				pr_err("another match of type %d in addrvec\n",
    126				       le32_to_cpu(my_type));
    127				return -EINVAL;
    128			}
    129
    130			memcpy(addr, &tmp_addr, sizeof(*addr));
    131			found = true;
    132		}
    133	}
    134
    135	if (found)
    136		return 0;
    137
    138	if (!addr_cnt)
    139		return 0;  /* normal -- e.g. unused OSD id/slot */
    140
    141	if (addr_cnt == 1 && !memchr_inv(&tmp_addr, 0, sizeof(tmp_addr)))
    142		return 0;  /* weird but effectively the same as !addr_cnt */
    143
    144	pr_err("no match of type %d in addrvec\n", le32_to_cpu(my_type));
    145	return -ENOENT;
    146
    147e_inval:
    148	return -EINVAL;
    149}
    150EXPORT_SYMBOL(ceph_decode_entity_addrvec);
    151
    152static int get_sockaddr_encoding_len(sa_family_t family)
    153{
    154	union {
    155		struct sockaddr sa;
    156		struct sockaddr_in sin;
    157		struct sockaddr_in6 sin6;
    158	} u;
    159
    160	switch (family) {
    161	case AF_INET:
    162		return sizeof(u.sin);
    163	case AF_INET6:
    164		return sizeof(u.sin6);
    165	default:
    166		return sizeof(u);
    167	}
    168}
    169
    170int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr)
    171{
    172	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
    173	int addr_len = get_sockaddr_encoding_len(family);
    174
    175	return 1 + CEPH_ENCODING_START_BLK_LEN + 4 + 4 + 4 + addr_len;
    176}
    177
    178void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr)
    179{
    180	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
    181	int addr_len = get_sockaddr_encoding_len(family);
    182
    183	ceph_encode_8(p, 1);  /* marker */
    184	ceph_start_encoding(p, 1, 1, sizeof(addr->type) +
    185				     sizeof(addr->nonce) +
    186				     sizeof(u32) + addr_len);
    187	ceph_encode_copy(p, &addr->type, sizeof(addr->type));
    188	ceph_encode_copy(p, &addr->nonce, sizeof(addr->nonce));
    189
    190	ceph_encode_32(p, addr_len);
    191	ceph_encode_16(p, family);
    192	ceph_encode_copy(p, addr->in_addr.__data, addr_len - sizeof(family));
    193}