Import of kernel-4.18.0-553.150.1.el8_10

This commit is contained in:
almalinux-bot-kernel 2026-08-03 05:18:56 +00:00
parent 22c3439a79
commit b6cd90ab03
14 changed files with 320 additions and 204 deletions

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 10
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 553.148.1
RHEL_RELEASE = 553.150.1
#
# ZSTREAM

View File

@ -162,13 +162,12 @@ static void vxcan_setup(struct net_device *dev)
/* forward declaration for rtnl_create_link() */
static struct rtnl_link_ops vxcan_link_ops;
static int vxcan_newlink(struct net *net, struct net_device *dev,
static int vxcan_newlink(struct net *peer_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct vxcan_priv *priv;
struct net_device *peer;
struct net *peer_net;
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb;
char ifname[IFNAMSIZ];
@ -178,19 +177,10 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
/* register peer device */
if (data && data[VXCAN_INFO_PEER]) {
struct nlattr *nla_peer;
struct nlattr *nla_peer = data[VXCAN_INFO_PEER];
nla_peer = data[VXCAN_INFO_PEER];
ifmp = nla_data(nla_peer);
err = rtnl_nla_parse_ifla(peer_tb,
nla_data(nla_peer) +
sizeof(struct ifinfomsg),
nla_len(nla_peer) -
sizeof(struct ifinfomsg),
NULL);
if (err < 0)
return err;
rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
tbp = peer_tb;
}
@ -202,23 +192,15 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
peer_net = rtnl_link_get_net(net, tbp);
if (IS_ERR(peer_net))
return PTR_ERR(peer_net);
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&vxcan_link_ops, tbp, extack);
if (IS_ERR(peer)) {
put_net(peer_net);
if (IS_ERR(peer))
return PTR_ERR(peer);
}
if (ifmp && dev->ifindex)
peer->ifindex = ifmp->ifi_index;
err = register_netdevice(peer);
put_net(peer_net);
peer_net = NULL;
if (err < 0) {
free_netdev(peer);
return err;
@ -297,6 +279,7 @@ static struct rtnl_link_ops vxcan_link_ops = {
.newlink = vxcan_newlink,
.dellink = vxcan_dellink,
.policy = vxcan_policy,
.peer_type = VXCAN_INFO_PEER,
.maxtype = VXCAN_INFO_MAX,
.get_link_net = vxcan_get_link_net,
};

View File

@ -1655,7 +1655,7 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[])
return 0;
}
static int veth_newlink(struct net *src_net, struct net_device *dev,
static int veth_newlink(struct net *peer_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@ -1666,27 +1666,15 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
unsigned char name_assign_type;
struct ifinfomsg *ifmp;
struct net *net;
/*
* create and register peer first
*/
if (data != NULL && data[VETH_INFO_PEER] != NULL) {
struct nlattr *nla_peer;
if (data && data[VETH_INFO_PEER]) {
struct nlattr *nla_peer = data[VETH_INFO_PEER];
nla_peer = data[VETH_INFO_PEER];
ifmp = nla_data(nla_peer);
err = rtnl_nla_parse_ifla(peer_tb,
nla_data(nla_peer) + sizeof(struct ifinfomsg),
nla_len(nla_peer) - sizeof(struct ifinfomsg),
NULL);
if (err < 0)
return err;
err = veth_validate(peer_tb, NULL, extack);
if (err < 0)
return err;
rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
tbp = peer_tb;
} else {
ifmp = NULL;
@ -1701,16 +1689,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
net = rtnl_link_get_net(src_net, tbp);
if (IS_ERR(net))
return PTR_ERR(net);
peer = rtnl_create_link(net, ifname, name_assign_type,
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&veth_link_ops, tbp, extack);
if (IS_ERR(peer)) {
put_net(net);
if (IS_ERR(peer))
return PTR_ERR(peer);
}
if (!ifmp || !tbp[IFLA_ADDRESS])
eth_hw_addr_random(peer);
@ -1721,8 +1703,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
netif_inherit_tso_max(peer, dev);
err = register_netdevice(peer);
put_net(net);
net = NULL;
if (err < 0)
goto err_register_peer;
@ -1841,6 +1821,7 @@ static struct rtnl_link_ops veth_link_ops = {
.newlink = veth_newlink,
.dellink = veth_dellink,
.policy = veth_policy,
.peer_type = VETH_INFO_PEER,
.maxtype = VETH_INFO_MAX,
.get_link_net = veth_get_link_net,
.get_num_tx_queues = veth_get_num_queues,

View File

@ -300,7 +300,7 @@ static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector
return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
}
static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
{
struct hlist_node *node = NULL;

View File

@ -299,9 +299,6 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
*/
static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark)
{
if (!mark)
return true;
if (refcount_inc_not_zero(&mark->refcnt)) {
spin_lock(&mark->lock);
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) {
@ -341,13 +338,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
int type;
fsnotify_foreach_obj_type(type) {
struct fsnotify_mark *mark = iter_info->marks[type];
/* This can fail if mark is being removed */
if (!fsnotify_get_mark_safe(iter_info->marks[type]))
goto fail;
while (mark && !fsnotify_get_mark_safe(mark)) {
if (fsnotify_iter_should_report_type(iter_info, type))
goto fail;
/* This is a mark in an unrelated group, skip */
mark = fsnotify_next_mark(mark);
iter_info->marks[type] = mark;
}
}
/*
* Now that both marks are pinned by refcount in the inode / vfsmount
* Now that all marks are pinned by refcount in the inode / vfsmount / etc
* lists, we can drop SRCU lock, and safely resume the list iteration
* once userspace returns.
*/

View File

@ -482,6 +482,7 @@ static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group
}
extern void fsnotify_get_mark(struct fsnotify_mark *mark);
extern void fsnotify_put_mark(struct fsnotify_mark *mark);
struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark);
extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);

View File

@ -79,4 +79,9 @@ void nf_conntrack_lock(spinlock_t *lock);
extern spinlock_t nf_conntrack_expect_lock;
static inline void lockdep_nfct_expect_lock_held(void)
{
lockdep_assert_held(&nf_conntrack_expect_lock);
}
#endif /* _NF_CONNTRACK_CORE_H */

View File

@ -39,6 +39,7 @@ struct rtnl_link_ops_extended_rh {
* @list: Used internally
* @kind: Identifier
* @netns_refund: Physical device, move to init_net on netns exit
* @peer_type: Peer device specific netlink attribute number (e.g. VETH_INFO_PEER)
* @maxtype: Highest device specific netlink attribute number
* @policy: Netlink policy for device specific attribute validation
* @validate: Optional validation function for netlink/changelink parameters
@ -126,7 +127,7 @@ struct rtnl_link_ops {
unsigned char name_assign_type,
unsigned int num_tx_queues,
unsigned int num_rx_queues))
RH_KABI_RESERVE(3)
RH_KABI_USE(3, const u16 peer_type)
RH_KABI_RESERVE(4)
RH_KABI_RESERVE(5)
RH_KABI_RESERVE(6)
@ -194,8 +195,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
int rtnl_delete_link(struct net_device *dev);
int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
struct netlink_ext_ack *exterr);
int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
struct netlink_ext_ack *exterr);
struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid);
#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)

View File

@ -1,2 +1,2 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.148.1.el8.x86_64,mailto:secalert@redhat.com
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.150.1.el8.x86_64,mailto:secalert@redhat.com

View File

@ -2144,17 +2144,32 @@ out_err:
return err;
}
int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
struct netlink_ext_ack *exterr)
int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
struct netlink_ext_ack *exterr)
{
return nla_parse_deprecated(tb, IFLA_MAX, head, len, ifla_policy,
const struct ifinfomsg *ifmp;
const struct nlattr *attrs;
size_t len;
ifmp = nla_data(nla_peer);
attrs = nla_data(nla_peer) + sizeof(struct ifinfomsg);
len = nla_len(nla_peer) - sizeof(struct ifinfomsg);
if (ifmp->ifi_index < 0) {
NL_SET_ERR_MSG_ATTR(exterr, nla_peer,
"ifindex can't be negative");
return -EINVAL;
}
return nla_parse_deprecated(tb, IFLA_MAX, attrs, len, ifla_policy,
exterr);
}
EXPORT_SYMBOL(rtnl_nla_parse_ifla);
EXPORT_SYMBOL(rtnl_nla_parse_ifinfomsg);
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
static struct net *rtnl_link_get_net_ifla(struct nlattr *tb[])
{
struct net *net;
struct net *net = NULL;
/* Examine the link attributes and figure out which
* network namespace we are talking about.
*/
@ -2162,8 +2177,17 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
else if (tb[IFLA_NET_NS_FD])
net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
else
return net;
}
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
{
struct net *net = rtnl_link_get_net_ifla(tb);
if (!net)
net = get_net(src_net);
return net;
}
EXPORT_SYMBOL(rtnl_link_get_net);
@ -3184,23 +3208,172 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
return 0;
}
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attr, struct netlink_ext_ack *extack)
static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
const struct rtnl_link_ops *ops,
struct net *peer_net,
struct nlattr **tb, struct nlattr **data,
struct netlink_ext_ack *extack)
{
struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
unsigned char name_assign_type = NET_NAME_USER;
struct net *net = sock_net(skb->sk);
struct net *dest_net, *link_net;
struct net_device *dev;
char ifname[IFNAMSIZ];
int err;
if (!ops->alloc && !ops->setup)
return -EOPNOTSUPP;
if (tb[IFLA_IFNAME]) {
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
} else {
snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
name_assign_type = NET_NAME_ENUM;
}
dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN);
if (IS_ERR(dest_net))
return PTR_ERR(dest_net);
if (tb[IFLA_LINK_NETNSID]) {
int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
link_net = get_net_ns_by_id(dest_net, id);
if (!link_net) {
NL_SET_ERR_MSG(extack, "Unknown network namespace id");
err = -EINVAL;
goto out;
}
err = -EPERM;
if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
goto out;
} else {
link_net = NULL;
}
dev = rtnl_create_link(link_net ? : dest_net, ifname,
name_assign_type, ops, tb, extack);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out;
}
dev->ifindex = ifm->ifi_index;
if (link_net)
net = link_net;
if (peer_net)
net = peer_net;
if (ops->newlink) {
err = ops->newlink(net, dev, tb, data, extack);
/* Drivers should call free_netdev() in ->destructor
* and unregister it on failure after registration
* so that device could be finally freed in rtnl_unlock.
*/
if (err < 0) {
/* If device is not registered at all, free it now */
if (dev->reg_state == NETREG_UNINITIALIZED)
free_netdev(dev);
goto out;
}
} else {
err = register_netdevice(dev);
if (err < 0) {
free_netdev(dev);
goto out;
}
}
err = rtnl_configure_link(dev, ifm);
if (err < 0)
goto out_unregister;
if (link_net) {
err = dev_change_net_namespace(dev, dest_net, ifname);
if (err < 0)
goto out_unregister;
}
if (tb[IFLA_MASTER]) {
err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
if (err)
goto out_unregister;
}
out:
if (link_net)
put_net(link_net);
put_net(dest_net);
return err;
out_unregister:
if (ops->newlink) {
LIST_HEAD(list_kill);
ops->dellink(dev, &list_kill);
unregister_netdevice_many(&list_kill);
} else {
unregister_netdevice(dev);
}
goto out;
}
struct rtnl_newlink_tbs {
struct nlattr *tb[IFLA_MAX + 1];
struct nlattr *attr[RTNL_MAX_TYPE + 1];
struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
};
static struct net *rtnl_get_peer_net(struct sk_buff *skb,
const struct rtnl_link_ops *ops,
struct nlattr *tbp[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct nlattr *tb[IFLA_MAX + 1], **attrs;
struct net *net;
int err;
if (!data || !data[ops->peer_type]) {
attrs = tbp;
} else {
err = rtnl_nla_parse_ifinfomsg(tb, data[ops->peer_type], extack);
if (err < 0)
return ERR_PTR(err);
if (ops->validate) {
err = ops->validate(tb, NULL, extack);
if (err < 0)
return ERR_PTR(err);
}
attrs = tb;
}
net = rtnl_link_get_net_ifla(attrs);
if (IS_ERR_OR_NULL(net))
return net;
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
put_net(net);
return ERR_PTR(-EPERM);
}
return net;
}
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_newlink_tbs *tbs,
struct netlink_ext_ack *extack)
{
struct nlattr *linkinfo[IFLA_INFO_MAX + 1];
struct nlattr ** const tb = tbs->tb;
const struct rtnl_link_ops *m_ops;
struct net_device *master_dev;
struct net *net = sock_net(skb->sk);
const struct rtnl_link_ops *ops;
struct nlattr *tb[IFLA_MAX + 1];
struct net *dest_net, *link_net;
struct net *peer_net = NULL;
struct nlattr **slave_data;
char kind[MODULE_NAME_LEN];
struct net_device *dev;
struct ifinfomsg *ifm;
char ifname[IFNAMSIZ];
struct nlattr **data;
bool link_specified;
int err;
@ -3264,86 +3437,110 @@ replay:
return -EINVAL;
if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
err = nla_parse_nested_deprecated(attr, ops->maxtype,
err = nla_parse_nested_deprecated(tbs->attr, ops->maxtype,
linkinfo[IFLA_INFO_DATA],
ops->policy, extack);
if (err < 0)
return err;
data = attr;
data = tbs->attr;
}
if (ops->validate) {
err = ops->validate(tb, data, extack);
if (err < 0)
return err;
}
if (ops->peer_type) {
peer_net = rtnl_get_peer_net(skb, ops, tb, data, extack);
if (IS_ERR(peer_net))
return PTR_ERR(peer_net);
}
}
slave_data = NULL;
if (m_ops) {
if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
return -EINVAL;
if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE) {
err = -EINVAL;
goto put_net;
}
if (m_ops->slave_maxtype &&
linkinfo[IFLA_INFO_SLAVE_DATA]) {
err = nla_parse_nested_deprecated(slave_attr,
err = nla_parse_nested_deprecated(tbs->slave_attr,
m_ops->slave_maxtype,
linkinfo[IFLA_INFO_SLAVE_DATA],
m_ops->slave_policy,
extack);
if (err < 0)
return err;
slave_data = slave_attr;
goto put_net;
slave_data = tbs->slave_attr;
}
}
if (dev) {
int status = 0;
if (nlh->nlmsg_flags & NLM_F_EXCL)
return -EEXIST;
if (nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP;
if (nlh->nlmsg_flags & NLM_F_EXCL) {
err = -EEXIST;
goto put_net;
}
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
err = -EOPNOTSUPP;
goto put_net;
}
if (linkinfo[IFLA_INFO_DATA]) {
if (!ops || ops != dev->rtnl_link_ops ||
!ops->changelink)
return -EOPNOTSUPP;
!ops->changelink) {
err = -EOPNOTSUPP;
goto put_net;
}
err = ops->changelink(dev, tb, data, extack);
if (err < 0)
return err;
goto put_net;
status |= DO_SETLINK_NOTIFY;
}
if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
if (!m_ops || !m_ops->slave_changelink)
return -EOPNOTSUPP;
if (!m_ops || !m_ops->slave_changelink) {
err = -EOPNOTSUPP;
goto put_net;
}
err = m_ops->slave_changelink(master_dev, dev, tb,
slave_data, extack);
if (err < 0)
return err;
goto put_net;
status |= DO_SETLINK_NOTIFY;
}
return do_setlink(skb, dev, ifm, extack, tb, status);
err = do_setlink(skb, dev, ifm, extack, tb, status);
goto put_net;
}
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
/* No dev found and NLM_F_CREATE not set. Requested dev does not exist,
* or it's for a group
*/
if (link_specified)
return -ENODEV;
if (tb[IFLA_GROUP])
return rtnl_group_changelink(skb, net,
nla_get_u32(tb[IFLA_GROUP]),
ifm, extack, tb);
return -ENODEV;
if (link_specified) {
err = -ENODEV;
goto put_net;
}
if (tb[IFLA_GROUP]) {
err = rtnl_group_changelink(skb, net,
nla_get_u32(tb[IFLA_GROUP]),
ifm, extack, tb);
goto put_net;
}
err = -ENODEV;
goto put_net;
}
if (tb[IFLA_MAP] || tb[IFLA_PROTINFO])
return -EOPNOTSUPP;
if (tb[IFLA_MAP] || tb[IFLA_PROTINFO]) {
err = -EOPNOTSUPP;
goto put_net;
}
if (!ops) {
#ifdef CONFIG_MODULES
@ -3357,109 +3554,31 @@ replay:
}
#endif
NL_SET_ERR_MSG(extack, "Unknown device type");
return -EOPNOTSUPP;
err = -EOPNOTSUPP;
goto put_net;
}
if (!ops->alloc && !ops->setup)
return -EOPNOTSUPP;
err = rtnl_newlink_create(skb, ifm, ops, peer_net, tb, data, extack);
if (tb[IFLA_IFNAME]) {
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
} else {
snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
name_assign_type = NET_NAME_ENUM;
}
put_net:
if (peer_net)
put_net(peer_net);
dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN);
if (IS_ERR(dest_net))
return PTR_ERR(dest_net);
if (tb[IFLA_LINK_NETNSID]) {
int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
link_net = get_net_ns_by_id(dest_net, id);
if (!link_net) {
NL_SET_ERR_MSG(extack, "Unknown network namespace id");
err = -EINVAL;
goto out;
}
err = -EPERM;
if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
goto out;
} else {
link_net = NULL;
}
dev = rtnl_create_link(link_net ? : dest_net, ifname,
name_assign_type, ops, tb, extack);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out;
}
dev->ifindex = ifm->ifi_index;
if (ops->newlink) {
err = ops->newlink(link_net ? : net, dev, tb, data, extack);
/* Drivers should call free_netdev() in ->destructor
* and unregister it on failure after registration
* so that device could be finally freed in rtnl_unlock.
*/
if (err < 0) {
/* If device is not registered at all, free it now */
if (dev->reg_state == NETREG_UNINITIALIZED)
free_netdev(dev);
goto out;
}
} else {
err = register_netdevice(dev);
if (err < 0) {
free_netdev(dev);
goto out;
}
}
err = rtnl_configure_link(dev, ifm);
if (err < 0)
goto out_unregister;
if (link_net) {
err = dev_change_net_namespace(dev, dest_net, ifname);
if (err < 0)
goto out_unregister;
}
if (tb[IFLA_MASTER]) {
err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
if (err)
goto out_unregister;
}
out:
if (link_net)
put_net(link_net);
put_net(dest_net);
return err;
out_unregister:
if (ops->newlink) {
LIST_HEAD(list_kill);
ops->dellink(dev, &list_kill);
unregister_netdevice_many(&list_kill);
} else {
unregister_netdevice(dev);
}
goto out;
}
static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct nlattr **attr;
struct rtnl_newlink_tbs *tbs;
int ret;
attr = kmalloc_array(RTNL_MAX_TYPE + 1, sizeof(*attr), GFP_KERNEL);
if (!attr)
tbs = kmalloc(sizeof(*tbs), GFP_KERNEL);
if (!tbs)
return -ENOMEM;
ret = __rtnl_newlink(skb, nlh, attr, extack);
kfree(attr);
ret = __rtnl_newlink(skb, nlh, tbs, extack);
kfree(tbs);
return ret;
}

View File

@ -239,6 +239,8 @@ void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
struct nf_exp_event_notifier *notify;
struct nf_conntrack_ecache *e;
lockdep_nfct_expect_lock_held();
rcu_read_lock();
notify = rcu_dereference(net->ct.nf_expect_event_cb);
if (!notify)

View File

@ -53,6 +53,7 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
struct nf_conn_help *master_help = nfct_help(exp->master);
struct net *net = nf_ct_exp_net(exp);
lockdep_nfct_expect_lock_held();
WARN_ON(!master_help);
WARN_ON(timer_pending(&exp->timeout));
@ -107,6 +108,8 @@ nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple,
bool nf_ct_remove_expect(struct nf_conntrack_expect *exp)
{
lockdep_nfct_expect_lock_held();
if (del_timer(&exp->timeout)) {
nf_ct_unlink_expect(exp);
nf_ct_expect_put(exp);
@ -164,6 +167,8 @@ nf_ct_find_expectation(struct net *net,
struct nf_conntrack_expect *i, *exp = NULL;
unsigned int h;
lockdep_nfct_expect_lock_held();
if (!net->ct.expect_count)
return NULL;
@ -416,6 +421,8 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
unsigned int h;
int ret = 0;
lockdep_nfct_expect_lock_held();
if (!master_help) {
ret = -ESHUTDOWN;
goto out;
@ -469,8 +476,9 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
nf_ct_expect_insert(expect);
spin_unlock_bh(&nf_conntrack_expect_lock);
nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
spin_unlock_bh(&nf_conntrack_expect_lock);
return 0;
out:
spin_unlock_bh(&nf_conntrack_expect_lock);

View File

@ -3430,33 +3430,40 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
if (err < 0)
return err;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb2)
return -ENOMEM;
spin_lock_bh(&nf_conntrack_expect_lock);
exp = nf_ct_expect_find_get(net, &zone, &tuple);
if (!exp)
if (!exp) {
spin_unlock_bh(&nf_conntrack_expect_lock);
kfree_skb(skb2);
return -ENOENT;
}
if (cda[CTA_EXPECT_ID]) {
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
if (id != nf_expect_get_id(exp)) {
nf_ct_expect_put(exp);
spin_unlock_bh(&nf_conntrack_expect_lock);
kfree_skb(skb2);
return -ENOENT;
}
}
err = -ENOMEM;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL) {
nf_ct_expect_put(exp);
goto out;
}
rcu_read_lock();
err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
rcu_read_unlock();
nf_ct_expect_put(exp);
if (err <= 0)
goto free;
spin_unlock_bh(&nf_conntrack_expect_lock);
if (err <= 0) {
kfree_skb(skb2);
return -ENOMEM;
}
err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
if (err < 0)
@ -3464,8 +3471,6 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
return 0;
free:
kfree_skb(skb2);
out:
/* this avoids a loop in nfnetlink. */
return err == -EAGAIN ? -ENOBUFS : err;
@ -3509,21 +3514,25 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
if (err < 0)
return err;
spin_lock_bh(&nf_conntrack_expect_lock);
/* bump usage count to 2 */
exp = nf_ct_expect_find_get(net, &zone, &tuple);
if (!exp)
if (!exp) {
spin_unlock_bh(&nf_conntrack_expect_lock);
return -ENOENT;
}
if (cda[CTA_EXPECT_ID]) {
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
if (ntohl(id) != (u32)(unsigned long)exp) {
nf_ct_expect_put(exp);
spin_unlock_bh(&nf_conntrack_expect_lock);
return -ENOENT;
}
}
/* after list removal, usage count == 1 */
spin_lock_bh(&nf_conntrack_expect_lock);
if (del_timer(&exp->timeout)) {
nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
nlmsg_report(nlh));

View File

@ -3938,6 +3938,9 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru
skb_do_redirect(skb);
*ret = __NET_XMIT_STOLEN;
return NULL;
case TC_ACT_CONSUMED:
*ret = __NET_XMIT_STOLEN;
return NULL;
}
return skb;