switch (nlh_src->nlmsg_type) { /* Compat message has the same layout as native */ case XFRM_MSG_DELSA: case XFRM_MSG_DELPOLICY: case XFRM_MSG_FLUSHSA: case XFRM_MSG_FLUSHPOLICY: case XFRM_MSG_NEWAE: case XFRM_MSG_REPORT: case XFRM_MSG_MIGRATE: case XFRM_MSG_NEWSADINFO: case XFRM_MSG_NEWSPDINFO: case XFRM_MSG_MAPPING:
WARN_ON_ONCE(src_len != payload);
memcpy(nlmsg_data(nlh_dst), nlmsg_data(nlh_src), src_len); break; /* 4 byte alignment for trailing u64 on native, but not on compat */ case XFRM_MSG_NEWSA: case XFRM_MSG_NEWPOLICY: case XFRM_MSG_UPDSA: case XFRM_MSG_UPDPOLICY:
WARN_ON_ONCE(src_len != payload + 4);
memcpy(nlmsg_data(nlh_dst), nlmsg_data(nlh_src), payload); break; case XFRM_MSG_EXPIRE: { conststruct xfrm_user_expire *src_ue = nlmsg_data(nlh_src); struct compat_xfrm_user_expire *dst_ue = nlmsg_data(nlh_dst);
/* compat_xfrm_user_expire has 4-byte smaller state */
memcpy(dst_ue, src_ue, sizeof(dst_ue->state));
dst_ue->hard = src_ue->hard; break;
} case XFRM_MSG_ACQUIRE: { conststruct xfrm_user_acquire *src_ua = nlmsg_data(nlh_src); struct compat_xfrm_user_acquire *dst_ua = nlmsg_data(nlh_dst);
/* compat_xfrm_user_polexpire has 4-byte smaller state */
memcpy(dst_upe, src_upe, sizeof(dst_upe->pol));
dst_upe->hard = src_upe->hard; break;
} case XFRM_MSG_ALLOCSPI: { conststruct xfrm_userspi_info *src_usi = nlmsg_data(nlh_src); struct compat_xfrm_userspi_info *dst_usi = nlmsg_data(nlh_dst);
/* compat_xfrm_user_polexpire has 4-byte smaller state */
memcpy(dst_usi, src_usi, sizeof(src_usi->info));
dst_usi->min = src_usi->min;
dst_usi->max = src_usi->max; break;
} /* Not being sent by kernel */ case XFRM_MSG_GETSA: case XFRM_MSG_GETPOLICY: case XFRM_MSG_GETAE: case XFRM_MSG_GETSADINFO: case XFRM_MSG_GETSPDINFO: default:
pr_warn_once("unsupported nlmsg_type %d\n", nlh_src->nlmsg_type); return ERR_PTR(-EOPNOTSUPP);
}
staticint xfrm_xlate64_attr(struct sk_buff *dst, conststruct nlattr *src)
{ switch (src->nla_type) { case XFRMA_PAD: /* Ignore */ return 0; case XFRMA_UNSPEC: case XFRMA_ALG_AUTH: case XFRMA_ALG_CRYPT: case XFRMA_ALG_COMP: case XFRMA_ENCAP: case XFRMA_TMPL: return xfrm_nla_cpy(dst, src, nla_len(src)); case XFRMA_SA: return xfrm_nla_cpy(dst, src, XMSGSIZE(compat_xfrm_usersa_info)); case XFRMA_POLICY: return xfrm_nla_cpy(dst, src, XMSGSIZE(compat_xfrm_userpolicy_info)); case XFRMA_SEC_CTX: return xfrm_nla_cpy(dst, src, nla_len(src)); case XFRMA_LTIME_VAL: return nla_put_64bit(dst, src->nla_type, nla_len(src),
nla_data(src), XFRMA_PAD); case XFRMA_REPLAY_VAL: case XFRMA_REPLAY_THRESH: case XFRMA_ETIMER_THRESH: case XFRMA_SRCADDR: case XFRMA_COADDR: return xfrm_nla_cpy(dst, src, nla_len(src)); case XFRMA_LASTUSED: return nla_put_64bit(dst, src->nla_type, nla_len(src),
nla_data(src), XFRMA_PAD); case XFRMA_POLICY_TYPE: case XFRMA_MIGRATE: case XFRMA_ALG_AEAD: case XFRMA_KMADDRESS: case XFRMA_ALG_AUTH_TRUNC: case XFRMA_MARK: case XFRMA_TFCPAD: case XFRMA_REPLAY_ESN_VAL: case XFRMA_SA_EXTRA_FLAGS: case XFRMA_PROTO: case XFRMA_ADDRESS_FILTER: case XFRMA_OFFLOAD_DEV: case XFRMA_SET_MARK: case XFRMA_SET_MARK_MASK: case XFRMA_IF_ID: case XFRMA_MTIMER_THRESH: case XFRMA_SA_DIR: case XFRMA_NAT_KEEPALIVE_INTERVAL: case XFRMA_SA_PCPU: case XFRMA_IPTFS_DROP_TIME: case XFRMA_IPTFS_REORDER_WINDOW: case XFRMA_IPTFS_DONT_FRAG: case XFRMA_IPTFS_INIT_DELAY: case XFRMA_IPTFS_MAX_QSIZE: case XFRMA_IPTFS_PKT_SIZE: return xfrm_nla_cpy(dst, src, nla_len(src)); default:
BUILD_BUG_ON(XFRMA_MAX != XFRMA_IPTFS_PKT_SIZE);
pr_warn_once("unsupported nla_type %d\n", src->nla_type); return -EOPNOTSUPP;
}
}
/* Take kernel-built (64bit layout) and create 32bit layout for userspace */ staticint xfrm_xlate64(struct sk_buff *dst, conststruct nlmsghdr *nlh_src)
{
u16 type = nlh_src->nlmsg_type - XFRM_MSG_BASE; conststruct nlattr *nla, *attrs; struct nlmsghdr *nlh_dst; int len, remaining;
nlh_dst = xfrm_nlmsg_put_compat(dst, nlh_src, type); if (IS_ERR(nlh_dst)) return PTR_ERR(nlh_dst);
attrs = nlmsg_attrdata(nlh_src, xfrm_msg_min[type]);
len = nlmsg_attrlen(nlh_src, xfrm_msg_min[type]);
nla_for_each_attr(nla, attrs, len, remaining) { int err;
if (skb_shinfo(skb)->frag_list == NULL) { new = alloc_skb(skb->len + skb_tailroom(skb), GFP_ATOMIC); if (!new) return -ENOMEM;
skb_shinfo(skb)->frag_list = new;
}
err = xfrm_xlate64(skb_shinfo(skb)->frag_list, nlh_src); if (err) { if (new) {
kfree_skb(new);
skb_shinfo(skb)->frag_list = NULL;
} return err;
}
return 0;
}
/* Calculates len of translated 64-bit message. */ static size_t xfrm_user_rcv_calculate_len64(conststruct nlmsghdr *src, struct nlattr *attrs[XFRMA_MAX + 1], int maxtype)
{
size_t len = nlmsg_len(src);
switch (src->nlmsg_type) { case XFRM_MSG_NEWSA: case XFRM_MSG_NEWPOLICY: case XFRM_MSG_ALLOCSPI: case XFRM_MSG_ACQUIRE: case XFRM_MSG_UPDPOLICY: case XFRM_MSG_UPDSA:
len += 4; break; case XFRM_MSG_EXPIRE: case XFRM_MSG_POLEXPIRE:
len += 8; break; case XFRM_MSG_NEWSPDINFO: /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */ return len; default: break;
}
/* Unexpected for anything, but XFRM_MSG_NEWSPDINFO, please * correct both 64=>32-bit and 32=>64-bit translators to copy * new attributes.
*/ if (WARN_ON_ONCE(maxtype)) return len;
if (attrs[XFRMA_SA])
len += 4; if (attrs[XFRMA_POLICY])
len += 4;
/* XXX: some attrs may need to be realigned * if !CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
*/
/* xfrm_user_rcv_msg_compat() relies on fact that 32-bit messages * have the same len or shorted than 64-bit ones. * 32-bit translation that is bigger than 64-bit original is unexpected.
*/ if (WARN_ON_ONCE(copy_len > payload))
copy_len = payload;
if (size - *pos < nla_attr_size(payload)) return -ENOBUFS;
switch (src->nlmsg_type) { /* Compat message has the same layout as native */ case XFRM_MSG_DELSA: case XFRM_MSG_GETSA: case XFRM_MSG_DELPOLICY: case XFRM_MSG_GETPOLICY: case XFRM_MSG_FLUSHSA: case XFRM_MSG_FLUSHPOLICY: case XFRM_MSG_NEWAE: case XFRM_MSG_GETAE: case XFRM_MSG_REPORT: case XFRM_MSG_MIGRATE: case XFRM_MSG_NEWSADINFO: case XFRM_MSG_GETSADINFO: case XFRM_MSG_NEWSPDINFO: case XFRM_MSG_GETSPDINFO: case XFRM_MSG_MAPPING:
memcpy(nlmsg_data(dst), nlmsg_data(src), compat_msg_min[type]); break; /* 4 byte alignment for trailing u64 on native, but not on compat */ case XFRM_MSG_NEWSA: case XFRM_MSG_NEWPOLICY: case XFRM_MSG_UPDSA: case XFRM_MSG_UPDPOLICY:
memcpy(nlmsg_data(dst), nlmsg_data(src), compat_msg_min[type]); break; case XFRM_MSG_EXPIRE: { conststruct compat_xfrm_user_expire *src_ue = nlmsg_data(src); struct xfrm_user_expire *dst_ue = nlmsg_data(dst);
/* compat_xfrm_user_expire has 4-byte smaller state */
memcpy(dst_ue, src_ue, sizeof(src_ue->state));
dst_ue->hard = src_ue->hard; break;
} case XFRM_MSG_ACQUIRE: { conststruct compat_xfrm_user_acquire *src_ua = nlmsg_data(src); struct xfrm_user_acquire *dst_ua = nlmsg_data(dst);
if (maxtype) { /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */
WARN_ON_ONCE(src->nlmsg_type != XFRM_MSG_NEWSPDINFO);
for (i = 1; i <= maxtype; i++) { int err;
if (!attrs[i]) continue;
/* just copy - no need for translation */
err = xfrm_attr_cpy32(dst, &pos, attrs[i], size,
nla_len(attrs[i]), nla_len(attrs[i])); if (err) return err;
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.