Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions crypto/algif_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,6 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags,
return err;

err = crypto_ahash_import(&ctx2->req, state);
if (err) {
sock_orphan(sk2);
sock_put(sk2);
}

return err;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/realtek/rtw88/coex.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
u8 para[2] = {0};
u8 para[6] = {};
u8 times;
u16 tbtt_interval = coex_stat->wl_beacon_interval;

Expand Down
2 changes: 1 addition & 1 deletion fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
locks_wake_up_blocks(left);
}
out:
trace_posix_lock_inode(inode, request, error);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you pointed out on Slack, this leaves the trace_posix_lock_inode() call at the bottom of the function.

I want to add though: leaving the trace_posix_lock_inode() outside of the spin lock is the cause of the CVE. So this not only results in a duplicate trace call, but also results in the CVE not getting fixed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For posterity: this was an incorrect merge resolution by git cherry-pick because it does a 3-way merge, which is why this commit cherry-picked cleanly. Because to git, it looked like the deletion of the old trace_posix_lock_inode() had already been done in this tree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous commit is the precoditional fix which is pretty easy to see that it moved twice and without it we get a clean pick where this now has two trace_psix_loc_indoe calls. 893c028.

While we don't have the exact example we can likely simulate it for internal and public facing docs in the GH wiki.

spin_unlock(&ctx->flc_lock);
percpu_up_read(&file_rwsem);
/*
Expand All @@ -1237,7 +1238,6 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
if (new_fl2)
locks_free_lock(new_fl2);
locks_dispose_list(&dispose);
trace_posix_lock_inode(inode, request, error);

return error;
}
Expand Down
6 changes: 6 additions & 0 deletions kernel/padata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,12 @@ void padata_free_shell(struct padata_shell *ps)
if (!ps)
return;

/*
* Wait for all _do_serial calls to finish to avoid touching
* freed pd's and ps's.
*/
synchronize_rcu();

mutex_lock(&ps->pinst->lock);
list_del(&ps->list);
padata_free_pd(rcu_dereference_protected(ps->pd, 1));
Expand Down
13 changes: 10 additions & 3 deletions net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,15 @@ DEFINE_COOKIE(net_cookie);

static struct net_generic *net_alloc_generic(void)
{
unsigned int gen_ptrs = READ_ONCE(max_gen_ptrs);
unsigned int generic_size;
struct net_generic *ng;
unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);

generic_size = offsetof(struct net_generic, ptr[gen_ptrs]);

ng = kzalloc(generic_size, GFP_KERNEL);
if (ng)
ng->s.len = max_gen_ptrs;
ng->s.len = gen_ptrs;

return ng;
}
Expand Down Expand Up @@ -1210,7 +1213,11 @@ static int register_pernet_operations(struct list_head *list,
if (error < 0)
return error;
*ops->id = error;
max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
/* This does not require READ_ONCE as writers already hold
* pernet_ops_rwsem. But WRITE_ONCE is needed to protect
* net_alloc_generic.
*/
WRITE_ONCE(max_gen_ptrs, max(max_gen_ptrs, *ops->id + 1));
}
error = __register_pernet_operations(list, ops);
if (error) {
Expand Down
8 changes: 7 additions & 1 deletion net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
if (tcptw->tw_ts_recent_stamp &&
(!twp || (reuse && time_after32(ktime_get_seconds(),
tcptw->tw_ts_recent_stamp)))) {
/* inet_twsk_hashdance() sets sk_refcnt after putting twsk
* and releasing the bucket lock.
*/
if (unlikely(!refcount_inc_not_zero(&sktw->sk_refcnt)))
return 0;

/* In case of repair and re-using TIME-WAIT sockets we still
* want to be sure that it is safe as above but honor the
* sequence numbers and time stamps set as part of the repair
Expand All @@ -171,7 +177,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
}
sock_hold(sktw);

return 1;
}

Expand Down
21 changes: 7 additions & 14 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -5355,26 +5355,20 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
err_nh = NULL;
list_for_each_entry(nh, &rt6_nh_list, next) {
err = __ip6_ins_rt(nh->fib6_info, info, extack);
fib6_info_release(nh->fib6_info);

if (!err) {
/* save reference to last route successfully inserted */
rt_last = nh->fib6_info;

/* save reference to first route for notification */
if (!rt_notif)
rt_notif = nh->fib6_info;
}

/* nh->fib6_info is used or freed at this point, reset to NULL*/
nh->fib6_info = NULL;
if (err) {
if (replace && nhn)
NL_SET_ERR_MSG_MOD(extack,
"multipath route replace failed (check consistency of installed routes)");
err_nh = nh;
goto add_errout;
}
/* save reference to last route successfully inserted */
rt_last = nh->fib6_info;

/* save reference to first route for notification */
if (!rt_notif)
rt_notif = nh->fib6_info;

/* Because each route is added like a single route we remove
* these flags after the first nexthop: if there is a collision,
Expand Down Expand Up @@ -5435,8 +5429,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,

cleanup:
list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
if (nh->fib6_info)
fib6_info_release(nh->fib6_info);
fib6_info_release(nh->fib6_info);
list_del(&nh->next);
kfree(nh);
}
Expand Down
13 changes: 9 additions & 4 deletions net/mptcp/pm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,21 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
{
struct mptcp_pm_add_entry *entry;
struct sock *sk = (struct sock *)msk;
struct timer_list *add_timer = NULL;

spin_lock_bh(&msk->pm.lock);
entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
if (entry && (!check_id || entry->addr.id == addr->id))
if (entry && (!check_id || entry->addr.id == addr->id)) {
entry->retrans_times = ADD_ADDR_RETRANS_MAX;
add_timer = &entry->add_timer;
}
if (!check_id && entry)
list_del(&entry->list);
spin_unlock_bh(&msk->pm.lock);

if (entry && (!check_id || entry->addr.id == addr->id))
sk_stop_timer_sync(sk, &entry->add_timer);
/* no lock, because sk_stop_timer_sync() is calling del_timer_sync() */
if (add_timer)
sk_stop_timer_sync(sk, add_timer);

return entry;
}
Expand Down Expand Up @@ -1392,7 +1398,6 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,

entry = mptcp_pm_del_add_timer(msk, addr, false);
if (entry) {
list_del(&entry->list);
kfree(entry);
return true;
}
Expand Down
22 changes: 14 additions & 8 deletions net/netfilter/nft_exthdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ static unsigned int optlen(const u8 *opt, unsigned int offset)
return opt[offset + 1];
}

static int nft_skb_copy_to_reg(const struct sk_buff *skb, int offset, u32 *dest, unsigned int len)
{
if (len % NFT_REG32_SIZE)
dest[len / NFT_REG32_SIZE] = 0;

return skb_copy_bits(skb, offset, dest, len);
}

static void nft_exthdr_ipv6_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
Expand All @@ -56,8 +64,7 @@ static void nft_exthdr_ipv6_eval(const struct nft_expr *expr,
}
offset += priv->offset;

dest[priv->len / NFT_REG32_SIZE] = 0;
if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0)
if (nft_skb_copy_to_reg(pkt->skb, offset, dest, priv->len) < 0)
goto err;
return;
err:
Expand Down Expand Up @@ -153,8 +160,7 @@ static void nft_exthdr_ipv4_eval(const struct nft_expr *expr,
}
offset += priv->offset;

dest[priv->len / NFT_REG32_SIZE] = 0;
if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0)
if (nft_skb_copy_to_reg(pkt->skb, offset, dest, priv->len) < 0)
goto err;
return;
err:
Expand Down Expand Up @@ -210,7 +216,8 @@ static void nft_exthdr_tcp_eval(const struct nft_expr *expr,
if (priv->flags & NFT_EXTHDR_F_PRESENT) {
*dest = 1;
} else {
dest[priv->len / NFT_REG32_SIZE] = 0;
if (priv->len % NFT_REG32_SIZE)
dest[priv->len / NFT_REG32_SIZE] = 0;
memcpy(dest, opt + offset, priv->len);
}

Expand Down Expand Up @@ -335,9 +342,8 @@ static void nft_exthdr_sctp_eval(const struct nft_expr *expr,
offset + ntohs(sch->length) > pkt->skb->len)
break;

dest[priv->len / NFT_REG32_SIZE] = 0;
if (skb_copy_bits(pkt->skb, offset + priv->offset,
dest, priv->len) < 0)
if (nft_skb_copy_to_reg(pkt->skb, offset + priv->offset,
dest, priv->len) < 0)
break;
return;
}
Expand Down
8 changes: 6 additions & 2 deletions net/sched/sch_hfsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,10 @@ eltree_insert(struct hfsc_class *cl)
static inline void
eltree_remove(struct hfsc_class *cl)
{
rb_erase(&cl->el_node, &cl->sched->eligible);
if (!RB_EMPTY_NODE(&cl->el_node)) {
rb_erase(&cl->el_node, &cl->sched->eligible);
RB_CLEAR_NODE(&cl->el_node);
}
}

static inline void
Expand Down Expand Up @@ -1229,7 +1232,8 @@ hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
/* vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
* needs to be called explicitly to remove a class from vttree.
*/
update_vf(cl, 0, 0);
if (cl->cl_nactive)
update_vf(cl, 0, 0);
if (cl->cl_flags & HFSC_RSC)
eltree_remove(cl);
}
Expand Down
2 changes: 1 addition & 1 deletion net/sched/sch_multiq.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,

qopt->bands = qdisc_dev(sch)->real_num_tx_queues;

removed = kmalloc(sizeof(*removed) * (q->max_bands - q->bands),
removed = kmalloc(sizeof(*removed) * (q->max_bands - qopt->bands),
GFP_KERNEL);
if (!removed)
return -ENOMEM;
Expand Down
2 changes: 2 additions & 0 deletions net/tipc/topsrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,10 @@ static void tipc_topsrv_stop(struct net *net)
for (id = 0; srv->idr_in_use; id++) {
con = idr_find(&srv->conn_idr, id);
if (con) {
conn_get(con);
spin_unlock_bh(&srv->idr_lock);
tipc_conn_close(con);
conn_put(con);
spin_lock_bh(&srv->idr_lock);
}
}
Expand Down