Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/klassert/ipsec-next

Steffen Klassert says:

====================
1) Refactor selftests to use an array of structs in xfrm_fill_key().
   From Gautam Menghani.

2) Drop an unused argument from xfrm_policy_match.
   From Hongbin Wang.

3) Support collect metadata mode for xfrm interfaces.
   From Eyal Birger.

4) Add netlink extack support to xfrm.
   From Sabrina Dubroca.

Please note, there is a merge conflict in:

include/net/dst_metadata.h

between commit:

0a28bfd ("net/macsec: Add MACsec skb_metadata_dst Tx Data path support")

from the net-next tree and commit:

5182a5d ("net: allow storing xfrm interface metadata in metadata_dst")

from the ipsec-next tree.

Can be solved as done in linux-next.

Please pull or let me know if there are problems.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 3, 2022
2 parents 9d43507 + c39596f commit 42e8e6d
Show file tree
Hide file tree
Showing 24 changed files with 738 additions and 323 deletions.
31 changes: 31 additions & 0 deletions include/net/dst_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum metadata_type {
METADATA_IP_TUNNEL,
METADATA_HW_PORT_MUX,
METADATA_MACSEC,
METADATA_XFRM,
};

struct hw_port_info {
Expand All @@ -22,13 +23,19 @@ struct macsec_info {
sci_t sci;
};

struct xfrm_md_info {
u32 if_id;
int link;
};

struct metadata_dst {
struct dst_entry dst;
enum metadata_type type;
union {
struct ip_tunnel_info tun_info;
struct hw_port_info port_info;
struct macsec_info macsec_info;
struct xfrm_md_info xfrm_info;
} u;
};

Expand Down Expand Up @@ -60,6 +67,27 @@ skb_tunnel_info(const struct sk_buff *skb)
return NULL;
}

static inline struct xfrm_md_info *lwt_xfrm_info(struct lwtunnel_state *lwt)
{
return (struct xfrm_md_info *)lwt->data;
}

static inline struct xfrm_md_info *skb_xfrm_md_info(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
struct dst_entry *dst;

if (md_dst && md_dst->type == METADATA_XFRM)
return &md_dst->u.xfrm_info;

dst = skb_dst(skb);
if (dst && dst->lwtstate &&
dst->lwtstate->type == LWTUNNEL_ENCAP_XFRM)
return lwt_xfrm_info(dst->lwtstate);

return NULL;
}

static inline bool skb_valid_dst(const struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
Expand Down Expand Up @@ -92,6 +120,9 @@ static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
case METADATA_MACSEC:
return memcmp(&a->u.macsec_info, &b->u.macsec_info,
sizeof(a->u.macsec_info));
case METADATA_XFRM:
return memcmp(&a->u.xfrm_info, &b->u.xfrm_info,
sizeof(a->u.xfrm_info));
default:
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion include/net/ipcomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct xfrm_state;
int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
void ipcomp_destroy(struct xfrm_state *x);
int ipcomp_init_state(struct xfrm_state *x);
int ipcomp_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack);

static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
{
Expand Down
24 changes: 17 additions & 7 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,15 @@ struct km_event {
struct net *net;
};

struct xfrm_if_decode_session_result {
struct net *net;
u32 if_id;
};

struct xfrm_if_cb {
struct xfrm_if *(*decode_session)(struct sk_buff *skb,
unsigned short family);
bool (*decode_session)(struct sk_buff *skb,
unsigned short family,
struct xfrm_if_decode_session_result *res);
};

void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
Expand Down Expand Up @@ -399,7 +405,8 @@ struct xfrm_type {
#define XFRM_TYPE_LOCAL_COADDR 4
#define XFRM_TYPE_REMOTE_COADDR 8

int (*init_state)(struct xfrm_state *x);
int (*init_state)(struct xfrm_state *x,
struct netlink_ext_ack *extack);
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
Expand Down Expand Up @@ -985,6 +992,7 @@ void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
struct xfrm_if_parms {
int link; /* ifindex of underlying L2 interface */
u32 if_id; /* interface identifyer */
bool collect_md;
};

struct xfrm_if {
Expand Down Expand Up @@ -1573,9 +1581,10 @@ int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_vali
void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
int xfrm_init_replay(struct xfrm_state *x);
int xfrm_init_replay(struct xfrm_state *x, struct netlink_ext_ack *extack);
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu);
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
struct netlink_ext_ack *extack);
int xfrm_init_state(struct xfrm_state *x);
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
Expand Down Expand Up @@ -1879,7 +1888,8 @@ void xfrm_dev_resume(struct sk_buff *skb);
void xfrm_dev_backlog(struct softnet_data *sd);
struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again);
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
struct xfrm_user_offload *xuo);
struct xfrm_user_offload *xuo,
struct netlink_ext_ack *extack);
bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);

static inline void xfrm_dev_state_advance_esn(struct xfrm_state *x)
Expand Down Expand Up @@ -1942,7 +1952,7 @@ static inline struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_fea
return skb;
}

static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo)
static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo, struct netlink_ext_ack *extack)
{
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ enum {
IFLA_XFRM_UNSPEC,
IFLA_XFRM_LINK,
IFLA_XFRM_IF_ID,
IFLA_XFRM_COLLECT_METADATA,
__IFLA_XFRM_MAX
};

Expand Down
10 changes: 10 additions & 0 deletions include/uapi/linux/lwtunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_SEG6_LOCAL,
LWTUNNEL_ENCAP_RPL,
LWTUNNEL_ENCAP_IOAM6,
LWTUNNEL_ENCAP_XFRM,
__LWTUNNEL_ENCAP_MAX,
};

Expand Down Expand Up @@ -111,4 +112,13 @@ enum {

#define LWT_BPF_MAX_HEADROOM 256

enum {
LWT_XFRM_UNSPEC,
LWT_XFRM_IF_ID,
LWT_XFRM_LINK,
__LWT_XFRM_MAX,
};

#define LWT_XFRM_MAX (__LWT_XFRM_MAX - 1)

#endif /* _UAPI_LWTUNNEL_H_ */
1 change: 1 addition & 0 deletions net/core/lwtunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
return "IOAM6";
case LWTUNNEL_ENCAP_IP6:
case LWTUNNEL_ENCAP_IP:
case LWTUNNEL_ENCAP_XFRM:
case LWTUNNEL_ENCAP_NONE:
case __LWTUNNEL_ENCAP_MAX:
/* should not have got here */
Expand Down
23 changes: 14 additions & 9 deletions net/ipv4/ah4.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,30 +471,38 @@ static int ah4_err(struct sk_buff *skb, u32 info)
return 0;
}

static int ah_init_state(struct xfrm_state *x)
static int ah_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
struct crypto_ahash *ahash;

if (!x->aalg)
if (!x->aalg) {
NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm");
goto error;
}

if (x->encap)
if (x->encap) {
NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation");
goto error;
}

ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
if (!ahp)
return -ENOMEM;

ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
if (IS_ERR(ahash))
if (IS_ERR(ahash)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error;
}

ahp->ahash = ahash;
if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
(x->aalg->alg_key_len + 7) / 8))
(x->aalg->alg_key_len + 7) / 8)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error;
}

/*
* Lookup the algorithm description maintained by xfrm_algo,
Expand All @@ -507,10 +515,7 @@ static int ah_init_state(struct xfrm_state *x)

if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_ahash_digestsize(ahash)) {
pr_info("%s: %s digestsize %u != %u\n",
__func__, x->aalg->alg_name,
crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits / 8);
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error;
}

Expand Down
55 changes: 33 additions & 22 deletions net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1008,16 +1008,17 @@ static void esp_destroy(struct xfrm_state *x)
crypto_free_aead(aead);
}

static int esp_init_aead(struct xfrm_state *x)
static int esp_init_aead(struct xfrm_state *x, struct netlink_ext_ack *extack)
{
char aead_name[CRYPTO_MAX_ALG_NAME];
struct crypto_aead *aead;
int err;

err = -ENAMETOOLONG;
if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME)
goto error;
x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
return -ENAMETOOLONG;
}

aead = crypto_alloc_aead(aead_name, 0, 0);
err = PTR_ERR(aead);
Expand All @@ -1035,11 +1036,15 @@ static int esp_init_aead(struct xfrm_state *x)
if (err)
goto error;

return 0;

error:
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
return err;
}

static int esp_init_authenc(struct xfrm_state *x)
static int esp_init_authenc(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{
struct crypto_aead *aead;
struct crypto_authenc_key_param *param;
Expand All @@ -1050,10 +1055,6 @@ static int esp_init_authenc(struct xfrm_state *x)
unsigned int keylen;
int err;

err = -EINVAL;
if (!x->ealg)
goto error;

err = -ENAMETOOLONG;

if ((x->props.flags & XFRM_STATE_ESN)) {
Expand All @@ -1062,22 +1063,28 @@ static int esp_init_authenc(struct xfrm_state *x)
x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error;
}
} else {
if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
"%s%sauthenc(%s,%s)%s",
x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error;
}
}

aead = crypto_alloc_aead(authenc_name, 0, 0);
err = PTR_ERR(aead);
if (IS_ERR(aead))
if (IS_ERR(aead)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error;
}

x->data = aead;

Expand Down Expand Up @@ -1107,17 +1114,16 @@ static int esp_init_authenc(struct xfrm_state *x)
err = -EINVAL;
if (aalg_desc->uinfo.auth.icv_fullbits / 8 !=
crypto_aead_authsize(aead)) {
pr_info("ESP: %s digestsize %u != %u\n",
x->aalg->alg_name,
crypto_aead_authsize(aead),
aalg_desc->uinfo.auth.icv_fullbits / 8);
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto free_key;
}

err = crypto_aead_setauthsize(
aead, x->aalg->alg_trunc_len / 8);
if (err)
if (err) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto free_key;
}
}

param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
Expand All @@ -1132,18 +1138,22 @@ static int esp_init_authenc(struct xfrm_state *x)
return err;
}

static int esp_init_state(struct xfrm_state *x)
static int esp_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{
struct crypto_aead *aead;
u32 align;
int err;

x->data = NULL;

if (x->aead)
err = esp_init_aead(x);
else
err = esp_init_authenc(x);
if (x->aead) {
err = esp_init_aead(x, extack);
} else if (x->ealg) {
err = esp_init_authenc(x, extack);
} else {
NL_SET_ERR_MSG(extack, "ESP: AEAD or CRYPT must be provided");
err = -EINVAL;
}

if (err)
goto error;
Expand All @@ -1161,6 +1171,7 @@ static int esp_init_state(struct xfrm_state *x)

switch (encap->encap_type) {
default:
NL_SET_ERR_MSG(extack, "Unsupported encapsulation type for ESP");
err = -EINVAL;
goto error;
case UDP_ENCAP_ESPINUDP:
Expand Down
Loading

0 comments on commit 42e8e6d

Please sign in to comment.