mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
BACKPORT: xfrm/compat: Translate 32-bit user_policy from sockptr
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>
(cherry picked from commit 96392ee5a1)
[adelva: Edited around removed compat check in Android kernels]
Bug: 163141236
Signed-off-by: Alistair Delva <adelva@google.com>
Change-Id: I32a6495cd92fa13c956fca88aa5d80716155b8ae
This commit is contained in:
@@ -1833,6 +1833,9 @@ struct xfrm_translator {
|
||||
struct nlmsghdr *(*rcv_msg_compat)(const struct nlmsghdr *nlh,
|
||||
int maxtype, const struct nla_policy *policy);
|
||||
|
||||
/* Translate 32-bit user_policy from sockptr */
|
||||
int (*xlate_user_policy_sockptr)(u8 **pdata32, int optlen);
|
||||
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1974,6 +1974,20 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
|
||||
if (copy_from_user(data, optval, optlen))
|
||||
goto out;
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user