Skip to content

Commit

Permalink
xfrm/compat: Translate 32-bit user_policy from sockptr
Browse files Browse the repository at this point in the history
Provide compat_xfrm_userpolicy_info translation for xfrm setsocketopt().
Reallocate buffer and put the missing padding for 64-bit message.

Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
  • Loading branch information
Dmitry Safonov authored and Steffen Klassert committed Sep 24, 2020
1 parent 5106f4a commit 96392ee
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2012,6 +2012,9 @@ struct xfrm_translator {
int maxtype, const struct nla_policy *policy,
struct netlink_ext_ack *extack);

/* Translate 32-bit user_policy from sockptr */
int (*xlate_user_policy_sockptr)(u8 **pdata32, int optlen);

struct module *owner;
};

Expand Down
26 changes: 26 additions & 0 deletions net/xfrm/xfrm_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,36 @@ static struct nlmsghdr *xfrm_user_rcv_msg_compat(const struct nlmsghdr *h32,
return h64;
}

static int xfrm_user_policy_compat(u8 **pdata32, int optlen)
{
struct compat_xfrm_userpolicy_info *p = (void *)*pdata32;
u8 *src_templates, *dst_templates;
u8 *data64;

if (optlen < sizeof(*p))
return -EINVAL;

data64 = kmalloc_track_caller(optlen + 4, GFP_USER | __GFP_NOWARN);
if (!data64)
return -ENOMEM;

memcpy(data64, *pdata32, sizeof(*p));
memset(data64 + sizeof(*p), 0, 4);

src_templates = *pdata32 + sizeof(*p);
dst_templates = data64 + sizeof(*p) + 4;
memcpy(dst_templates, src_templates, optlen - sizeof(*p));

kfree(*pdata32);
*pdata32 = data64;
return 0;
}

static struct xfrm_translator xfrm_translator = {
.owner = THIS_MODULE,
.alloc_compat = xfrm_alloc_compat,
.rcv_msg_compat = xfrm_user_rcv_msg_compat,
.xlate_user_policy_sockptr = xfrm_user_policy_compat,
};

static int __init xfrm_compat_init(void)
Expand Down
17 changes: 14 additions & 3 deletions net/xfrm/xfrm_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2331,9 +2331,6 @@ int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen)
struct xfrm_mgr *km;
struct xfrm_policy *pol = NULL;

if (in_compat_syscall())
return -EOPNOTSUPP;

if (sockptr_is_null(optval) && !optlen) {
xfrm_sk_policy_insert(sk, XFRM_POLICY_IN, NULL);
xfrm_sk_policy_insert(sk, XFRM_POLICY_OUT, NULL);
Expand All @@ -2348,6 +2345,20 @@ int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen)
if (IS_ERR(data))
return PTR_ERR(data);

if (in_compat_syscall()) {
struct xfrm_translator *xtr = xfrm_get_translator();

if (!xtr)
return -EOPNOTSUPP;

err = xtr->xlate_user_policy_sockptr(&data, optlen);
xfrm_put_translator(xtr);
if (err) {
kfree(data);
return err;
}
}

err = -EINVAL;
rcu_read_lock();
list_for_each_entry_rcu(km, &xfrm_km_list, list) {
Expand Down

0 comments on commit 96392ee

Please sign in to comment.