Commit 5f3eea6b authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Steffen Klassert

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>
parent 5461fc0c
...@@ -975,6 +975,7 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) ...@@ -975,6 +975,7 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
struct xfrm_dump_info *sp = ptr; struct xfrm_dump_info *sp = ptr;
struct sk_buff *in_skb = sp->in_skb; struct sk_buff *in_skb = sp->in_skb;
struct sk_buff *skb = sp->out_skb; struct sk_buff *skb = sp->out_skb;
struct xfrm_translator *xtr;
struct xfrm_usersa_info *p; struct xfrm_usersa_info *p;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
int err; int err;
...@@ -992,6 +993,18 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) ...@@ -992,6 +993,18 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
return err; return err;
} }
nlmsg_end(skb, nlh); 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; return 0;
} }
...@@ -1320,6 +1333,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1320,6 +1333,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_userspi_info *p; struct xfrm_userspi_info *p;
struct xfrm_translator *xtr;
struct sk_buff *resp_skb; struct sk_buff *resp_skb;
xfrm_address_t *daddr; xfrm_address_t *daddr;
int family; int family;
...@@ -1370,6 +1384,17 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1370,6 +1384,17 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out; 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); err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
out: out:
...@@ -1776,6 +1801,7 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr ...@@ -1776,6 +1801,7 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
struct xfrm_userpolicy_info *p; struct xfrm_userpolicy_info *p;
struct sk_buff *in_skb = sp->in_skb; struct sk_buff *in_skb = sp->in_skb;
struct sk_buff *skb = sp->out_skb; struct sk_buff *skb = sp->out_skb;
struct xfrm_translator *xtr;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
int err; int err;
...@@ -1800,6 +1826,18 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr ...@@ -1800,6 +1826,18 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
return err; return err;
} }
nlmsg_end(skb, nlh); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment