Commit 50c448bb authored by Steffen Klassert's avatar Steffen Klassert

Merge remote-tracking branch 'xfrm: start adding netlink extack support'

Sabrina Dubroca says:

============
XFRM states and policies are complex objects, and there are many
reasons why the kernel can reject userspace's request to create
one. This series makes it a bit clearer by providing extended ack
messages for policy creation.

A few other operations that reuse the same helper functions are also
getting partial extack support in this series. More patches will
follow to complete extack support, in particular for state creation.

Note: The policy->share attribute seems to be entirely ignored in the
kernel outside of checking its value in verify_newpolicy_info(). There
are some (very) old comments in copy_from_user_policy and
copy_to_user_policy suggesting that it should at least be copied
to/from userspace. I don't know what it was intended for.
============
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parents 2c2493b9 08a717e4
...@@ -102,7 +102,7 @@ static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, ...@@ -102,7 +102,7 @@ static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type,
*addrp = nla_data(rt); *addrp = nla_data(rt);
} }
static inline int verify_sec_ctx_len(struct nlattr **attrs) static inline int verify_sec_ctx_len(struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_user_sec_ctx *uctx; struct xfrm_user_sec_ctx *uctx;
...@@ -112,8 +112,10 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs) ...@@ -112,8 +112,10 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
uctx = nla_data(rt); uctx = nla_data(rt);
if (uctx->len > nla_len(rt) || if (uctx->len > nla_len(rt) ||
uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) {
NL_SET_ERR_MSG(extack, "Invalid security context length");
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
...@@ -264,7 +266,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, ...@@ -264,7 +266,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
goto out; goto out;
if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP))) if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
goto out; goto out;
if ((err = verify_sec_ctx_len(attrs))) if ((err = verify_sec_ctx_len(attrs, NULL)))
goto out; goto out;
if ((err = verify_replay(p, attrs))) if ((err = verify_replay(p, attrs)))
goto out; goto out;
...@@ -678,7 +680,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -678,7 +680,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
} }
static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_usersa_info *p = nlmsg_data(nlh); struct xfrm_usersa_info *p = nlmsg_data(nlh);
...@@ -757,7 +759,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, ...@@ -757,7 +759,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
} }
static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
...@@ -1254,7 +1256,8 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, ...@@ -1254,7 +1256,8 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net,
} }
static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrmu_spdhthresh *thresh4 = NULL; struct xfrmu_spdhthresh *thresh4 = NULL;
...@@ -1299,7 +1302,8 @@ static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1299,7 +1302,8 @@ static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct sk_buff *r_skb; struct sk_buff *r_skb;
...@@ -1358,7 +1362,8 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, ...@@ -1358,7 +1362,8 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net,
} }
static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct sk_buff *r_skb; struct sk_buff *r_skb;
...@@ -1378,7 +1383,7 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1378,7 +1383,7 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_usersa_id *p = nlmsg_data(nlh); struct xfrm_usersa_id *p = nlmsg_data(nlh);
...@@ -1402,7 +1407,8 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1402,7 +1407,8 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
...@@ -1477,7 +1483,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1477,7 +1483,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
return err; return err;
} }
static int verify_policy_dir(u8 dir) static int verify_policy_dir(u8 dir, struct netlink_ext_ack *extack)
{ {
switch (dir) { switch (dir) {
case XFRM_POLICY_IN: case XFRM_POLICY_IN:
...@@ -1486,13 +1492,14 @@ static int verify_policy_dir(u8 dir) ...@@ -1486,13 +1492,14 @@ static int verify_policy_dir(u8 dir)
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid policy direction");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
static int verify_policy_type(u8 type) static int verify_policy_type(u8 type, struct netlink_ext_ack *extack)
{ {
switch (type) { switch (type) {
case XFRM_POLICY_TYPE_MAIN: case XFRM_POLICY_TYPE_MAIN:
...@@ -1502,13 +1509,15 @@ static int verify_policy_type(u8 type) ...@@ -1502,13 +1509,15 @@ static int verify_policy_type(u8 type)
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid policy type");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) static int verify_newpolicy_info(struct xfrm_userpolicy_info *p,
struct netlink_ext_ack *extack)
{ {
int ret; int ret;
...@@ -1520,6 +1529,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) ...@@ -1520,6 +1529,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid policy share");
return -EINVAL; return -EINVAL;
} }
...@@ -1529,35 +1539,44 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) ...@@ -1529,35 +1539,44 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid policy action");
return -EINVAL; return -EINVAL;
} }
switch (p->sel.family) { switch (p->sel.family) {
case AF_INET: case AF_INET:
if (p->sel.prefixlen_d > 32 || p->sel.prefixlen_s > 32) if (p->sel.prefixlen_d > 32 || p->sel.prefixlen_s > 32) {
NL_SET_ERR_MSG(extack, "Invalid prefix length in selector (must be <= 32 for IPv4)");
return -EINVAL; return -EINVAL;
}
break; break;
case AF_INET6: case AF_INET6:
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (p->sel.prefixlen_d > 128 || p->sel.prefixlen_s > 128) if (p->sel.prefixlen_d > 128 || p->sel.prefixlen_s > 128) {
NL_SET_ERR_MSG(extack, "Invalid prefix length in selector (must be <= 128 for IPv6)");
return -EINVAL; return -EINVAL;
}
break; break;
#else #else
NL_SET_ERR_MSG(extack, "IPv6 support disabled");
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
#endif #endif
default: default:
NL_SET_ERR_MSG(extack, "Invalid selector family");
return -EINVAL; return -EINVAL;
} }
ret = verify_policy_dir(p->dir); ret = verify_policy_dir(p->dir, extack);
if (ret) if (ret)
return ret; return ret;
if (p->index && (xfrm_policy_id2dir(p->index) != p->dir)) if (p->index && (xfrm_policy_id2dir(p->index) != p->dir)) {
NL_SET_ERR_MSG(extack, "Policy index doesn't match direction");
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
...@@ -1599,13 +1618,16 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, ...@@ -1599,13 +1618,16 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
} }
} }
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
struct netlink_ext_ack *extack)
{ {
u16 prev_family; u16 prev_family;
int i; int i;
if (nr > XFRM_MAX_DEPTH) if (nr > XFRM_MAX_DEPTH) {
NL_SET_ERR_MSG(extack, "Template count must be <= XFRM_MAX_DEPTH (" __stringify(XFRM_MAX_DEPTH) ")");
return -EINVAL; return -EINVAL;
}
prev_family = family; prev_family = family;
...@@ -1625,12 +1647,16 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) ...@@ -1625,12 +1647,16 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
case XFRM_MODE_BEET: case XFRM_MODE_BEET:
break; break;
default: default:
if (ut[i].family != prev_family) if (ut[i].family != prev_family) {
NL_SET_ERR_MSG(extack, "Mode in template doesn't support a family change");
return -EINVAL; return -EINVAL;
}
break; break;
} }
if (ut[i].mode >= XFRM_MODE_MAX) if (ut[i].mode >= XFRM_MODE_MAX) {
NL_SET_ERR_MSG(extack, "Mode in template must be < XFRM_MODE_MAX (" __stringify(XFRM_MODE_MAX) ")");
return -EINVAL; return -EINVAL;
}
prev_family = ut[i].family; prev_family = ut[i].family;
...@@ -1642,17 +1668,21 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) ...@@ -1642,17 +1668,21 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
break; break;
#endif #endif
default: default:
NL_SET_ERR_MSG(extack, "Invalid family in template");
return -EINVAL; return -EINVAL;
} }
if (!xfrm_id_proto_valid(ut[i].id.proto)) if (!xfrm_id_proto_valid(ut[i].id.proto)) {
NL_SET_ERR_MSG(extack, "Invalid XFRM protocol in template");
return -EINVAL; return -EINVAL;
}
} }
return 0; return 0;
} }
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct nlattr *rt = attrs[XFRMA_TMPL]; struct nlattr *rt = attrs[XFRMA_TMPL];
...@@ -1663,7 +1693,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) ...@@ -1663,7 +1693,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
int nr = nla_len(rt) / sizeof(*utmpl); int nr = nla_len(rt) / sizeof(*utmpl);
int err; int err;
err = validate_tmpl(nr, utmpl, pol->family); err = validate_tmpl(nr, utmpl, pol->family, extack);
if (err) if (err)
return err; return err;
...@@ -1672,7 +1702,8 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) ...@@ -1672,7 +1702,8 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
return 0; return 0;
} }
static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs) static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct nlattr *rt = attrs[XFRMA_POLICY_TYPE]; struct nlattr *rt = attrs[XFRMA_POLICY_TYPE];
struct xfrm_userpolicy_type *upt; struct xfrm_userpolicy_type *upt;
...@@ -1684,7 +1715,7 @@ static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs) ...@@ -1684,7 +1715,7 @@ static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs)
type = upt->type; type = upt->type;
} }
err = verify_policy_type(type); err = verify_policy_type(type, extack);
if (err) if (err)
return err; return err;
...@@ -1719,7 +1750,11 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i ...@@ -1719,7 +1750,11 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i
p->share = XFRM_SHARE_ANY; /* XXX xp->share */ p->share = XFRM_SHARE_ANY; /* XXX xp->share */
} }
static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) static struct xfrm_policy *xfrm_policy_construct(struct net *net,
struct xfrm_userpolicy_info *p,
struct nlattr **attrs,
int *errp,
struct netlink_ext_ack *extack)
{ {
struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL);
int err; int err;
...@@ -1731,11 +1766,11 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us ...@@ -1731,11 +1766,11 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us
copy_from_user_policy(xp, p); copy_from_user_policy(xp, p);
err = copy_from_user_policy_type(&xp->type, attrs); err = copy_from_user_policy_type(&xp->type, attrs, extack);
if (err) if (err)
goto error; goto error;
if (!(err = copy_from_user_tmpl(xp, attrs))) if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
err = copy_from_user_sec_ctx(xp, attrs); err = copy_from_user_sec_ctx(xp, attrs);
if (err) if (err)
goto error; goto error;
...@@ -1754,7 +1789,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us ...@@ -1754,7 +1789,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us
} }
static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_userpolicy_info *p = nlmsg_data(nlh); struct xfrm_userpolicy_info *p = nlmsg_data(nlh);
...@@ -1763,14 +1799,14 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1763,14 +1799,14 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
int err; int err;
int excl; int excl;
err = verify_newpolicy_info(p); err = verify_newpolicy_info(p, extack);
if (err) if (err)
return err; return err;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs, extack);
if (err) if (err)
return err; return err;
xp = xfrm_policy_construct(net, p, attrs, &err); xp = xfrm_policy_construct(net, p, attrs, &err, extack);
if (!xp) if (!xp)
return err; return err;
...@@ -2015,7 +2051,7 @@ static bool xfrm_userpolicy_is_valid(__u8 policy) ...@@ -2015,7 +2051,7 @@ static bool xfrm_userpolicy_is_valid(__u8 policy)
} }
static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_userpolicy_default *up = nlmsg_data(nlh); struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
...@@ -2036,7 +2072,7 @@ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2036,7 +2072,7 @@ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct sk_buff *r_skb; struct sk_buff *r_skb;
struct nlmsghdr *r_nlh; struct nlmsghdr *r_nlh;
...@@ -2066,7 +2102,8 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2066,7 +2102,8 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_policy *xp; struct xfrm_policy *xp;
...@@ -2081,11 +2118,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2081,11 +2118,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
p = nlmsg_data(nlh); p = nlmsg_data(nlh);
delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
err = copy_from_user_policy_type(&type, attrs); err = copy_from_user_policy_type(&type, attrs, extack);
if (err) if (err)
return err; return err;
err = verify_policy_dir(p->dir); err = verify_policy_dir(p->dir, extack);
if (err) if (err)
return err; return err;
...@@ -2101,7 +2138,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2101,7 +2138,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx; struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs, extack);
if (err) if (err)
return err; return err;
...@@ -2149,7 +2186,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2149,7 +2186,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct km_event c; struct km_event c;
...@@ -2249,7 +2287,7 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct ...@@ -2249,7 +2287,7 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct
} }
static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
...@@ -2293,7 +2331,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2293,7 +2331,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
...@@ -2344,14 +2382,15 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2344,14 +2382,15 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct km_event c; struct km_event c;
u8 type = XFRM_POLICY_TYPE_MAIN; u8 type = XFRM_POLICY_TYPE_MAIN;
int err; int err;
err = copy_from_user_policy_type(&type, attrs); err = copy_from_user_policy_type(&type, attrs, extack);
if (err) if (err)
return err; return err;
...@@ -2372,7 +2411,8 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2372,7 +2411,8 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_policy *xp; struct xfrm_policy *xp;
...@@ -2383,11 +2423,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2383,11 +2423,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_mark m; struct xfrm_mark m;
u32 if_id = 0; u32 if_id = 0;
err = copy_from_user_policy_type(&type, attrs); err = copy_from_user_policy_type(&type, attrs, extack);
if (err) if (err)
return err; return err;
err = verify_policy_dir(p->dir); err = verify_policy_dir(p->dir, extack);
if (err) if (err)
return err; return err;
...@@ -2403,7 +2443,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2403,7 +2443,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_sec_ctx *ctx; struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs, extack);
if (err) if (err)
return err; return err;
...@@ -2438,7 +2478,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2438,7 +2478,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_state *x; struct xfrm_state *x;
...@@ -2472,7 +2513,8 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2472,7 +2513,8 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_policy *xp; struct xfrm_policy *xp;
...@@ -2490,15 +2532,15 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2490,15 +2532,15 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
xfrm_mark_get(attrs, &mark); xfrm_mark_get(attrs, &mark);
err = verify_newpolicy_info(&ua->policy); err = verify_newpolicy_info(&ua->policy, extack);
if (err) if (err)
goto free_state; goto free_state;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs, extack);
if (err) if (err)
goto free_state; goto free_state;
/* build an XP */ /* build an XP */
xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); xp = xfrm_policy_construct(net, &ua->policy, attrs, &err, extack);
if (!xp) if (!xp)
goto free_state; goto free_state;
...@@ -2577,7 +2619,7 @@ static int copy_from_user_migrate(struct xfrm_migrate *ma, ...@@ -2577,7 +2619,7 @@ static int copy_from_user_migrate(struct xfrm_migrate *ma,
} }
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);
struct xfrm_migrate m[XFRM_MAX_DEPTH]; struct xfrm_migrate m[XFRM_MAX_DEPTH];
...@@ -2594,7 +2636,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2594,7 +2636,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;
err = copy_from_user_policy_type(&type, attrs); err = copy_from_user_policy_type(&type, attrs, extack);
if (err) if (err)
return err; return err;
...@@ -2623,7 +2665,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2623,7 +2665,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
#else #else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs, struct netlink_ext_ack *extack)
{ {
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
...@@ -2819,7 +2861,8 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { ...@@ -2819,7 +2861,8 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
}; };
static const struct xfrm_link { static const struct xfrm_link {
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **,
struct netlink_ext_ack *);
int (*start)(struct netlink_callback *); int (*start)(struct netlink_callback *);
int (*dump)(struct sk_buff *, struct netlink_callback *); int (*dump)(struct sk_buff *, struct netlink_callback *);
int (*done)(struct netlink_callback *); int (*done)(struct netlink_callback *);
...@@ -2921,7 +2964,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2921,7 +2964,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
goto err; goto err;
} }
err = link->doit(skb, nlh, attrs); err = link->doit(skb, nlh, attrs, extack);
/* We need to free skb allocated in xfrm_alloc_compat() before /* We need to free skb allocated in xfrm_alloc_compat() before
* returning from this function, because consume_skb() won't take * returning from this function, because consume_skb() won't take
...@@ -3272,11 +3315,11 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, ...@@ -3272,11 +3315,11 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
*dir = -EINVAL; *dir = -EINVAL;
if (len < sizeof(*p) || if (len < sizeof(*p) ||
verify_newpolicy_info(p)) verify_newpolicy_info(p, NULL))
return NULL; return NULL;
nr = ((len - sizeof(*p)) / sizeof(*ut)); nr = ((len - sizeof(*p)) / sizeof(*ut));
if (validate_tmpl(nr, ut, p->sel.family)) if (validate_tmpl(nr, ut, p->sel.family, NULL))
return NULL; return NULL;
if (p->dir > XFRM_POLICY_OUT) if (p->dir > XFRM_POLICY_OUT)
......
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