Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a601af0 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Alistair Delva
Browse files

UPSTREAM: xfrm/compat: Attach xfrm dumps to 64=>32 bit translator



Currently nlmsg_unicast() is used by functions that dump structures that
can be different in size for compat tasks, see dump_one_state() and
dump_one_policy().

The following nlmsg_unicast() users exist today in xfrm:

         Function                          |    Message can be different
                                           |       in size on compat
-------------------------------------------|------------------------------
    xfrm_get_spdinfo()                     |               N
    xfrm_get_sadinfo()                     |               N
    xfrm_get_sa()                          |               Y
    xfrm_alloc_userspi()                   |               Y
    xfrm_get_policy()                      |               Y
    xfrm_get_ae()                          |               N

Besides, dump_one_state() and dump_one_policy() can be used by filtered
netlink dump for XFRM_MSG_GETSA, XFRM_MSG_GETPOLICY.

Just as for xfrm multicast, allocate frag_list for compat skb journey
down to recvmsg() which will give user the desired skb according to
syscall bitness.

Signed-off-by: default avatarDmitry Safonov <dima@arista.com>

Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
(cherry picked from commit 5f3eea6b7e8f58cf5c8a9d4b9679dc19e9e67ba3)
Bug: 163141236
Signed-off-by: default avatarAlistair Delva <adelva@google.com>
Change-Id: Id1a606ddd9d7dfe73a448eeb252b1bfd8dbd2fcb
parent 00260df4
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -974,6 +974,7 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
	struct xfrm_dump_info *sp = ptr;
	struct sk_buff *in_skb = sp->in_skb;
	struct sk_buff *skb = sp->out_skb;
	struct xfrm_translator *xtr;
	struct xfrm_usersa_info *p;
	struct nlmsghdr *nlh;
	int err;
@@ -991,6 +992,18 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
		return err;
	}
	nlmsg_end(skb, nlh);

	xtr = xfrm_get_translator();
	if (xtr) {
		err = xtr->alloc_compat(skb, nlh);

		xfrm_put_translator(xtr);
		if (err) {
			nlmsg_cancel(skb, nlh);
			return err;
		}
	}

	return 0;
}

@@ -1319,6 +1332,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
	struct net *net = sock_net(skb->sk);
	struct xfrm_state *x;
	struct xfrm_userspi_info *p;
	struct xfrm_translator *xtr;
	struct sk_buff *resp_skb;
	xfrm_address_t *daddr;
	int family;
@@ -1369,6 +1383,17 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
		goto out;
	}

	xtr = xfrm_get_translator();
	if (xtr) {
		err = xtr->alloc_compat(skb, nlmsg_hdr(skb));

		xfrm_put_translator(xtr);
		if (err) {
			kfree_skb(resp_skb);
			goto out;
		}
	}

	err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);

out:
@@ -1775,6 +1800,7 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
	struct xfrm_userpolicy_info *p;
	struct sk_buff *in_skb = sp->in_skb;
	struct sk_buff *skb = sp->out_skb;
	struct xfrm_translator *xtr;
	struct nlmsghdr *nlh;
	int err;

@@ -1799,6 +1825,18 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
		return err;
	}
	nlmsg_end(skb, nlh);

	xtr = xfrm_get_translator();
	if (xtr) {
		err = xtr->alloc_compat(skb, nlh);

		xfrm_put_translator(xtr);
		if (err) {
			nlmsg_cancel(skb, nlh);
			return err;
		}
	}

	return 0;
}