mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2020-07-31 1) Fix policy matching with mark and mask on userspace interfaces. From Xin Long. 2) Several fixes for the new ESP in TCP encapsulation. From Sabrina Dubroca. 3) Fix crash when the hold queue is used. The assumption that xdst->path and dst->child are not a NULL pointer only if dst->xfrm is not a NULL pointer is true with the exception of using the hold queue. Fix this by checking for hold queue usage before dereferencing xdst->path or dst->child. 4) Validate pfkey_dump parameter before sending them. From Mark Salyzyn. 5) Fix the location of the transport header with ESP in UDPv6 encapsulation. From Sabrina Dubroca. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8d46215a1f
@ -941,7 +941,7 @@ struct xfrm_dst {
|
|||||||
static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
|
static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
if (dst->xfrm) {
|
if (dst->xfrm || (dst->flags & DST_XFRM_QUEUE)) {
|
||||||
const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
|
const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
|
||||||
|
|
||||||
return xdst->path;
|
return xdst->path;
|
||||||
@ -953,7 +953,7 @@ static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
|
|||||||
static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
|
static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
if (dst->xfrm) {
|
if (dst->xfrm || (dst->flags & DST_XFRM_QUEUE)) {
|
||||||
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
|
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
|
||||||
return xdst->child;
|
return xdst->child;
|
||||||
}
|
}
|
||||||
@ -1630,13 +1630,16 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
|
|||||||
void *);
|
void *);
|
||||||
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
|
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
|
||||||
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
|
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
|
||||||
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
|
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net,
|
||||||
u8 type, int dir,
|
const struct xfrm_mark *mark,
|
||||||
|
u32 if_id, u8 type, int dir,
|
||||||
struct xfrm_selector *sel,
|
struct xfrm_selector *sel,
|
||||||
struct xfrm_sec_ctx *ctx, int delete,
|
struct xfrm_sec_ctx *ctx, int delete,
|
||||||
int *err);
|
int *err);
|
||||||
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id, u8,
|
struct xfrm_policy *xfrm_policy_byid(struct net *net,
|
||||||
int dir, u32 id, int delete, int *err);
|
const struct xfrm_mark *mark, u32 if_id,
|
||||||
|
u8 type, int dir, u32 id, int delete,
|
||||||
|
int *err);
|
||||||
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
|
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
|
||||||
void xfrm_policy_hash_rebuild(struct net *net);
|
void xfrm_policy_hash_rebuild(struct net *net);
|
||||||
u32 xfrm_get_acqseq(void);
|
u32 xfrm_get_acqseq(void);
|
||||||
|
@ -805,10 +805,17 @@ int esp6_input_done2(struct sk_buff *skb, int err)
|
|||||||
|
|
||||||
if (x->encap) {
|
if (x->encap) {
|
||||||
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||||
|
int offset = skb_network_offset(skb) + sizeof(*ip6h);
|
||||||
struct xfrm_encap_tmpl *encap = x->encap;
|
struct xfrm_encap_tmpl *encap = x->encap;
|
||||||
struct udphdr *uh = (void *)(skb_network_header(skb) + hdr_len);
|
u8 nexthdr = ip6h->nexthdr;
|
||||||
struct tcphdr *th = (void *)(skb_network_header(skb) + hdr_len);
|
__be16 frag_off, source;
|
||||||
__be16 source;
|
struct udphdr *uh;
|
||||||
|
struct tcphdr *th;
|
||||||
|
|
||||||
|
offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
|
||||||
|
uh = (void *)(skb->data + offset);
|
||||||
|
th = (void *)(skb->data + offset);
|
||||||
|
hdr_len += offset;
|
||||||
|
|
||||||
switch (x->encap->encap_type) {
|
switch (x->encap->encap_type) {
|
||||||
case TCP_ENCAP_ESPINTCP:
|
case TCP_ENCAP_ESPINTCP:
|
||||||
|
@ -1849,6 +1849,13 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
|
|||||||
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
|
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
|
||||||
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
|
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
|
||||||
|
|
||||||
|
if ((xfilter->sadb_x_filter_splen >=
|
||||||
|
(sizeof(xfrm_address_t) << 3)) ||
|
||||||
|
(xfilter->sadb_x_filter_dplen >=
|
||||||
|
(sizeof(xfrm_address_t) << 3))) {
|
||||||
|
mutex_unlock(&pfk->dump_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
filter = kmalloc(sizeof(*filter), GFP_KERNEL);
|
filter = kmalloc(sizeof(*filter), GFP_KERNEL);
|
||||||
if (filter == NULL) {
|
if (filter == NULL) {
|
||||||
mutex_unlock(&pfk->dump_lock);
|
mutex_unlock(&pfk->dump_lock);
|
||||||
@ -2400,7 +2407,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
|
xp = xfrm_policy_bysel_ctx(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
|
||||||
pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
|
pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
|
||||||
1, &err);
|
1, &err);
|
||||||
security_xfrm_policy_free(pol_ctx);
|
security_xfrm_policy_free(pol_ctx);
|
||||||
@ -2651,7 +2658,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
|
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
|
||||||
xp = xfrm_policy_byid(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
|
xp = xfrm_policy_byid(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
|
||||||
dir, pol->sadb_x_policy_id, delete, &err);
|
dir, pol->sadb_x_policy_id, delete, &err);
|
||||||
if (xp == NULL)
|
if (xp == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -15,6 +15,7 @@ static void handle_nonesp(struct espintcp_ctx *ctx, struct sk_buff *skb,
|
|||||||
{
|
{
|
||||||
if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf ||
|
if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf ||
|
||||||
!sk_rmem_schedule(sk, skb, skb->truesize)) {
|
!sk_rmem_schedule(sk, skb, skb->truesize)) {
|
||||||
|
XFRM_INC_STATS(sock_net(sk), LINUX_MIB_XFRMINERROR);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -49,23 +50,51 @@ static void espintcp_rcv(struct strparser *strp, struct sk_buff *skb)
|
|||||||
struct espintcp_ctx *ctx = container_of(strp, struct espintcp_ctx,
|
struct espintcp_ctx *ctx = container_of(strp, struct espintcp_ctx,
|
||||||
strp);
|
strp);
|
||||||
struct strp_msg *rxm = strp_msg(skb);
|
struct strp_msg *rxm = strp_msg(skb);
|
||||||
|
int len = rxm->full_len - 2;
|
||||||
u32 nonesp_marker;
|
u32 nonesp_marker;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
/* keepalive packet? */
|
||||||
|
if (unlikely(len == 1)) {
|
||||||
|
u8 data;
|
||||||
|
|
||||||
|
err = skb_copy_bits(skb, rxm->offset + 2, &data, 1);
|
||||||
|
if (err < 0) {
|
||||||
|
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == 0xff) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* drop other short messages */
|
||||||
|
if (unlikely(len <= sizeof(nonesp_marker))) {
|
||||||
|
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
err = skb_copy_bits(skb, rxm->offset + 2, &nonesp_marker,
|
err = skb_copy_bits(skb, rxm->offset + 2, &nonesp_marker,
|
||||||
sizeof(nonesp_marker));
|
sizeof(nonesp_marker));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove header, leave non-ESP marker/SPI */
|
/* remove header, leave non-ESP marker/SPI */
|
||||||
if (!__pskb_pull(skb, rxm->offset + 2)) {
|
if (!__pskb_pull(skb, rxm->offset + 2)) {
|
||||||
|
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINERROR);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pskb_trim(skb, rxm->full_len - 2) != 0) {
|
if (pskb_trim(skb, rxm->full_len - 2) != 0) {
|
||||||
|
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINERROR);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,7 +120,7 @@ static int espintcp_parse(struct strparser *strp, struct sk_buff *skb)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
len = be16_to_cpu(blen);
|
len = be16_to_cpu(blen);
|
||||||
if (len < 6)
|
if (len < 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@ -109,8 +138,11 @@ static int espintcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|||||||
flags |= nonblock ? MSG_DONTWAIT : 0;
|
flags |= nonblock ? MSG_DONTWAIT : 0;
|
||||||
|
|
||||||
skb = __skb_recv_datagram(sk, &ctx->ike_queue, flags, &off, &err);
|
skb = __skb_recv_datagram(sk, &ctx->ike_queue, flags, &off, &err);
|
||||||
if (!skb)
|
if (!skb) {
|
||||||
|
if (err == -EAGAIN && sk->sk_shutdown & RCV_SHUTDOWN)
|
||||||
|
return 0;
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
copied = len;
|
copied = len;
|
||||||
if (copied > skb->len)
|
if (copied > skb->len)
|
||||||
@ -213,7 +245,7 @@ retry:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int espintcp_push_msgs(struct sock *sk)
|
static int espintcp_push_msgs(struct sock *sk, int flags)
|
||||||
{
|
{
|
||||||
struct espintcp_ctx *ctx = espintcp_getctx(sk);
|
struct espintcp_ctx *ctx = espintcp_getctx(sk);
|
||||||
struct espintcp_msg *emsg = &ctx->partial;
|
struct espintcp_msg *emsg = &ctx->partial;
|
||||||
@ -227,12 +259,12 @@ static int espintcp_push_msgs(struct sock *sk)
|
|||||||
ctx->tx_running = 1;
|
ctx->tx_running = 1;
|
||||||
|
|
||||||
if (emsg->skb)
|
if (emsg->skb)
|
||||||
err = espintcp_sendskb_locked(sk, emsg, 0);
|
err = espintcp_sendskb_locked(sk, emsg, flags);
|
||||||
else
|
else
|
||||||
err = espintcp_sendskmsg_locked(sk, emsg, 0);
|
err = espintcp_sendskmsg_locked(sk, emsg, flags);
|
||||||
if (err == -EAGAIN) {
|
if (err == -EAGAIN) {
|
||||||
ctx->tx_running = 0;
|
ctx->tx_running = 0;
|
||||||
return 0;
|
return flags & MSG_DONTWAIT ? -EAGAIN : 0;
|
||||||
}
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
memset(emsg, 0, sizeof(*emsg));
|
memset(emsg, 0, sizeof(*emsg));
|
||||||
@ -257,7 +289,7 @@ int espintcp_push_skb(struct sock *sk, struct sk_buff *skb)
|
|||||||
offset = skb_transport_offset(skb);
|
offset = skb_transport_offset(skb);
|
||||||
len = skb->len - offset;
|
len = skb->len - offset;
|
||||||
|
|
||||||
espintcp_push_msgs(sk);
|
espintcp_push_msgs(sk, 0);
|
||||||
|
|
||||||
if (emsg->len) {
|
if (emsg->len) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
@ -270,7 +302,7 @@ int espintcp_push_skb(struct sock *sk, struct sk_buff *skb)
|
|||||||
emsg->len = len;
|
emsg->len = len;
|
||||||
emsg->skb = skb;
|
emsg->skb = skb;
|
||||||
|
|
||||||
espintcp_push_msgs(sk);
|
espintcp_push_msgs(sk, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -287,7 +319,7 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
|
|||||||
char buf[2] = {0};
|
char buf[2] = {0};
|
||||||
int err, end;
|
int err, end;
|
||||||
|
|
||||||
if (msg->msg_flags)
|
if (msg->msg_flags & ~MSG_DONTWAIT)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (size > MAX_ESPINTCP_MSG)
|
if (size > MAX_ESPINTCP_MSG)
|
||||||
@ -298,9 +330,10 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
|
|||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
err = espintcp_push_msgs(sk);
|
err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
err = -ENOBUFS;
|
if (err != -EAGAIN || !(msg->msg_flags & MSG_DONTWAIT))
|
||||||
|
err = -ENOBUFS;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,10 +370,9 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
|
|||||||
|
|
||||||
tcp_rate_check_app_limited(sk);
|
tcp_rate_check_app_limited(sk);
|
||||||
|
|
||||||
err = espintcp_push_msgs(sk);
|
err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT);
|
||||||
/* this message could be partially sent, keep it */
|
/* this message could be partially sent, keep it */
|
||||||
if (err < 0)
|
|
||||||
goto unlock;
|
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
@ -374,7 +406,7 @@ static void espintcp_tx_work(struct work_struct *work)
|
|||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
if (!ctx->tx_running)
|
if (!ctx->tx_running)
|
||||||
espintcp_push_msgs(sk);
|
espintcp_push_msgs(sk, 0);
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#ifdef CONFIG_XFRM_STATISTICS
|
#ifdef CONFIG_XFRM_STATISTICS
|
||||||
#include <net/snmp.h>
|
#include <net/snmp.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_INET_ESPINTCP
|
#ifdef CONFIG_XFRM_ESPINTCP
|
||||||
#include <net/espintcp.h>
|
#include <net/espintcp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1433,14 +1433,10 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
|
|||||||
spin_unlock_bh(&pq->hold_queue.lock);
|
spin_unlock_bh(&pq->hold_queue.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool xfrm_policy_mark_match(struct xfrm_policy *policy,
|
static inline bool xfrm_policy_mark_match(const struct xfrm_mark *mark,
|
||||||
struct xfrm_policy *pol)
|
struct xfrm_policy *pol)
|
||||||
{
|
{
|
||||||
if (policy->mark.v == pol->mark.v &&
|
return mark->v == pol->mark.v && mark->m == pol->mark.m;
|
||||||
policy->priority == pol->priority)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 xfrm_pol_bin_key(const void *data, u32 len, u32 seed)
|
static u32 xfrm_pol_bin_key(const void *data, u32 len, u32 seed)
|
||||||
@ -1503,7 +1499,7 @@ static void xfrm_policy_insert_inexact_list(struct hlist_head *chain,
|
|||||||
if (pol->type == policy->type &&
|
if (pol->type == policy->type &&
|
||||||
pol->if_id == policy->if_id &&
|
pol->if_id == policy->if_id &&
|
||||||
!selector_cmp(&pol->selector, &policy->selector) &&
|
!selector_cmp(&pol->selector, &policy->selector) &&
|
||||||
xfrm_policy_mark_match(policy, pol) &&
|
xfrm_policy_mark_match(&policy->mark, pol) &&
|
||||||
xfrm_sec_ctx_match(pol->security, policy->security) &&
|
xfrm_sec_ctx_match(pol->security, policy->security) &&
|
||||||
!WARN_ON(delpol)) {
|
!WARN_ON(delpol)) {
|
||||||
delpol = pol;
|
delpol = pol;
|
||||||
@ -1538,7 +1534,7 @@ static struct xfrm_policy *xfrm_policy_insert_list(struct hlist_head *chain,
|
|||||||
if (pol->type == policy->type &&
|
if (pol->type == policy->type &&
|
||||||
pol->if_id == policy->if_id &&
|
pol->if_id == policy->if_id &&
|
||||||
!selector_cmp(&pol->selector, &policy->selector) &&
|
!selector_cmp(&pol->selector, &policy->selector) &&
|
||||||
xfrm_policy_mark_match(policy, pol) &&
|
xfrm_policy_mark_match(&policy->mark, pol) &&
|
||||||
xfrm_sec_ctx_match(pol->security, policy->security) &&
|
xfrm_sec_ctx_match(pol->security, policy->security) &&
|
||||||
!WARN_ON(delpol)) {
|
!WARN_ON(delpol)) {
|
||||||
if (excl)
|
if (excl)
|
||||||
@ -1610,9 +1606,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
|
|||||||
EXPORT_SYMBOL(xfrm_policy_insert);
|
EXPORT_SYMBOL(xfrm_policy_insert);
|
||||||
|
|
||||||
static struct xfrm_policy *
|
static struct xfrm_policy *
|
||||||
__xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
|
__xfrm_policy_bysel_ctx(struct hlist_head *chain, const struct xfrm_mark *mark,
|
||||||
u8 type, int dir,
|
u32 if_id, u8 type, int dir, struct xfrm_selector *sel,
|
||||||
struct xfrm_selector *sel,
|
|
||||||
struct xfrm_sec_ctx *ctx)
|
struct xfrm_sec_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct xfrm_policy *pol;
|
struct xfrm_policy *pol;
|
||||||
@ -1623,7 +1618,7 @@ __xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
|
|||||||
hlist_for_each_entry(pol, chain, bydst) {
|
hlist_for_each_entry(pol, chain, bydst) {
|
||||||
if (pol->type == type &&
|
if (pol->type == type &&
|
||||||
pol->if_id == if_id &&
|
pol->if_id == if_id &&
|
||||||
(mark & pol->mark.m) == pol->mark.v &&
|
xfrm_policy_mark_match(mark, pol) &&
|
||||||
!selector_cmp(sel, &pol->selector) &&
|
!selector_cmp(sel, &pol->selector) &&
|
||||||
xfrm_sec_ctx_match(ctx, pol->security))
|
xfrm_sec_ctx_match(ctx, pol->security))
|
||||||
return pol;
|
return pol;
|
||||||
@ -1632,11 +1627,10 @@ __xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
|
struct xfrm_policy *
|
||||||
u8 type, int dir,
|
xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, u32 if_id,
|
||||||
struct xfrm_selector *sel,
|
u8 type, int dir, struct xfrm_selector *sel,
|
||||||
struct xfrm_sec_ctx *ctx, int delete,
|
struct xfrm_sec_ctx *ctx, int delete, int *err)
|
||||||
int *err)
|
|
||||||
{
|
{
|
||||||
struct xfrm_pol_inexact_bin *bin = NULL;
|
struct xfrm_pol_inexact_bin *bin = NULL;
|
||||||
struct xfrm_policy *pol, *ret = NULL;
|
struct xfrm_policy *pol, *ret = NULL;
|
||||||
@ -1703,9 +1697,9 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
|
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
|
||||||
|
|
||||||
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
|
struct xfrm_policy *
|
||||||
u8 type, int dir, u32 id, int delete,
|
xfrm_policy_byid(struct net *net, const struct xfrm_mark *mark, u32 if_id,
|
||||||
int *err)
|
u8 type, int dir, u32 id, int delete, int *err)
|
||||||
{
|
{
|
||||||
struct xfrm_policy *pol, *ret;
|
struct xfrm_policy *pol, *ret;
|
||||||
struct hlist_head *chain;
|
struct hlist_head *chain;
|
||||||
@ -1720,8 +1714,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
|
|||||||
ret = NULL;
|
ret = NULL;
|
||||||
hlist_for_each_entry(pol, chain, byidx) {
|
hlist_for_each_entry(pol, chain, byidx) {
|
||||||
if (pol->type == type && pol->index == id &&
|
if (pol->type == type && pol->index == id &&
|
||||||
pol->if_id == if_id &&
|
pol->if_id == if_id && xfrm_policy_mark_match(mark, pol)) {
|
||||||
(mark & pol->mark.m) == pol->mark.v) {
|
|
||||||
xfrm_pol_hold(pol);
|
xfrm_pol_hold(pol);
|
||||||
if (delete) {
|
if (delete) {
|
||||||
*err = security_xfrm_policy_delete(
|
*err = security_xfrm_policy_delete(
|
||||||
@ -4156,7 +4149,7 @@ void __init xfrm_init(void)
|
|||||||
seqcount_init(&xfrm_policy_hash_generation);
|
seqcount_init(&xfrm_policy_hash_generation);
|
||||||
xfrm_input_init();
|
xfrm_input_init();
|
||||||
|
|
||||||
#ifdef CONFIG_INET_ESPINTCP
|
#ifdef CONFIG_XFRM_ESPINTCP
|
||||||
espintcp_init();
|
espintcp_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1863,7 +1863,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
struct km_event c;
|
struct km_event c;
|
||||||
int delete;
|
int delete;
|
||||||
struct xfrm_mark m;
|
struct xfrm_mark m;
|
||||||
u32 mark = xfrm_mark_get(attrs, &m);
|
|
||||||
u32 if_id = 0;
|
u32 if_id = 0;
|
||||||
|
|
||||||
p = nlmsg_data(nlh);
|
p = nlmsg_data(nlh);
|
||||||
@ -1880,8 +1879,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
if (attrs[XFRMA_IF_ID])
|
if (attrs[XFRMA_IF_ID])
|
||||||
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
|
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
|
||||||
|
|
||||||
|
xfrm_mark_get(attrs, &m);
|
||||||
|
|
||||||
if (p->index)
|
if (p->index)
|
||||||
xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, delete, &err);
|
xp = xfrm_policy_byid(net, &m, if_id, type, p->dir,
|
||||||
|
p->index, delete, &err);
|
||||||
else {
|
else {
|
||||||
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
|
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
|
||||||
struct xfrm_sec_ctx *ctx;
|
struct xfrm_sec_ctx *ctx;
|
||||||
@ -1898,8 +1900,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir, &p->sel,
|
xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir,
|
||||||
ctx, delete, &err);
|
&p->sel, ctx, delete, &err);
|
||||||
security_xfrm_policy_free(ctx);
|
security_xfrm_policy_free(ctx);
|
||||||
}
|
}
|
||||||
if (xp == NULL)
|
if (xp == NULL)
|
||||||
@ -2166,7 +2168,6 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
u8 type = XFRM_POLICY_TYPE_MAIN;
|
u8 type = XFRM_POLICY_TYPE_MAIN;
|
||||||
int err = -ENOENT;
|
int err = -ENOENT;
|
||||||
struct xfrm_mark m;
|
struct xfrm_mark m;
|
||||||
u32 mark = xfrm_mark_get(attrs, &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);
|
||||||
@ -2180,8 +2181,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
if (attrs[XFRMA_IF_ID])
|
if (attrs[XFRMA_IF_ID])
|
||||||
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
|
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
|
||||||
|
|
||||||
|
xfrm_mark_get(attrs, &m);
|
||||||
|
|
||||||
if (p->index)
|
if (p->index)
|
||||||
xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, 0, &err);
|
xp = xfrm_policy_byid(net, &m, if_id, type, p->dir, p->index,
|
||||||
|
0, &err);
|
||||||
else {
|
else {
|
||||||
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
|
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
|
||||||
struct xfrm_sec_ctx *ctx;
|
struct xfrm_sec_ctx *ctx;
|
||||||
@ -2198,7 +2202,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir,
|
xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir,
|
||||||
&p->sel, ctx, 0, &err);
|
&p->sel, ctx, 0, &err);
|
||||||
security_xfrm_policy_free(ctx);
|
security_xfrm_policy_free(ctx);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user