Hi all,
Today's linux-next merge of the ipvs-next tree got a conflict in:
net/bluetooth/l2cap_sock.c
between commits:
2ff1a41a912de ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_state_change_cb()")
78a88d43dab8d ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_get_sndtimeo_cb()")
0a120d9616630 ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_new_connection_cb()")
ab1513597c6cf ("Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()")
from the origin tree and commits:
da5bd8be1bd5a ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_state_change_cb()")
11bc757180ef5 ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_get_sndtimeo_cb()")
91fa64f09e55b ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_new_connection_cb()")
0b580042a1a54 ("Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()")
75780ca4c6a87 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()")
from the ipvs-next tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
Commits that are in other trees, especially in Linus' tree, *really*
shouldn't be getting rebased or cherry picked.
diff --combined net/bluetooth/l2cap_sock.c
index b34e7da8d9067,025329636353d..0000000000000
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@@ -31,6 -31,7 +31,7 @@@
#include <linux/export.h>
#include <linux/filter.h>
#include <linux/sched/signal.h>
+ #include <linux/uio.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@@ -438,7 -439,7 +439,7 @@@ static int l2cap_get_mode(struct l2cap_
}
static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *sopt)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@@ -450,8 -451,7 +451,7 @@@
BT_DBG("sk %p", sk);
- if (get_user(len, optlen))
- return -EFAULT;
+ len = sopt->optlen;
lock_sock(sk);
@@@ -493,7 -493,7 +493,7 @@@
BT_DBG("mode 0x%2.2x", chan->mode);
len = min(len, sizeof(opts));
- if (copy_to_user(optval, (char *) &opts, len))
+ if (copy_to_iter(&opts, len, &sopt->iter_out) != len)
err = -EFAULT;
break;
@@@ -525,7 -525,8 +525,8 @@@
if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
opt |= L2CAP_LM_RELIABLE;
- if (put_user(opt, (u32 __user *) optval))
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;
@@@ -543,7 -544,7 +544,7 @@@
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
len = min(len, sizeof(cinfo));
- if (copy_to_user(optval, (char *) &cinfo, len))
+ if (copy_to_iter(&cinfo, len, &sopt->iter_out) != len)
err = -EFAULT;
break;
@@@ -558,25 -559,26 +559,26 @@@
}
static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *sopt)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
struct bt_power pwr;
- u32 phys;
int len, mode, err = 0;
+ u32 opt;
+ u16 mtu;
+ u8 mval;
BT_DBG("sk %p", sk);
if (level == SOL_L2CAP)
- return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
+ return l2cap_sock_getsockopt_old(sock, optname, sopt);
if (level != SOL_BLUETOOTH)
return -ENOPROTOOPT;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = sopt->optlen;
lock_sock(sk);
@@@ -600,7 -602,7 +602,7 @@@
}
len = min_t(unsigned int, len, sizeof(sec));
- if (copy_to_user(optval, (char *) &sec, len))
+ if (copy_to_iter(&sec, len, &sopt->iter_out) != len)
err = -EFAULT;
break;
@@@ -611,15 -613,17 +613,17 @@@
break;
}
- if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
- (u32 __user *) optval))
+ opt = test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;
case BT_FLUSHABLE:
- if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
- (u32 __user *) optval))
+ opt = test_bit(FLAG_FLUSHABLE, &chan->flags);
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;
@@@ -634,13 -638,15 +638,15 @@@
pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
len = min_t(unsigned int, len, sizeof(pwr));
- if (copy_to_user(optval, (char *) &pwr, len))
+ if (copy_to_iter(&pwr, len, &sopt->iter_out) != len)
err = -EFAULT;
break;
case BT_CHANNEL_POLICY:
- if (put_user(chan->chan_policy, (u32 __user *) optval))
+ opt = chan->chan_policy;
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;
@@@ -655,7 -661,9 +661,9 @@@
break;
}
- if (put_user(chan->omtu, (u16 __user *) optval))
+ mtu = chan->omtu;
+ if (copy_to_iter(&mtu, sizeof(mtu), &sopt->iter_out) !=
+ sizeof(mtu))
err = -EFAULT;
break;
@@@ -665,7 -673,9 +673,9 @@@
break;
}
- if (put_user(chan->imtu, (u16 __user *) optval))
+ mtu = chan->imtu;
+ if (copy_to_iter(&mtu, sizeof(mtu), &sopt->iter_out) !=
+ sizeof(mtu))
err = -EFAULT;
break;
@@@ -675,9 -685,10 +685,10 @@@
break;
}
- phys = hci_conn_get_phy(chan->conn->hcon);
+ opt = hci_conn_get_phy(chan->conn->hcon);
- if (put_user(phys, (u32 __user *) optval))
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;
@@@ -698,7 -709,9 +709,9 @@@
break;
}
- if (put_user(mode, (u8 __user *) optval))
+ mval = mode;
+ if (copy_to_iter(&mval, sizeof(mval), &sopt->iter_out) !=
+ sizeof(mval))
err = -EFAULT;
break;
@@@ -1499,6 -1512,10 +1512,10 @@@ static void l2cap_sock_cleanup_listen(s
* pin it (hold_unless_zero() additionally skips a chan already past
* its last reference). We then drop the sk lock before taking
* chan->lock, so sk and chan locks are never held together.
+ *
+ * Since we cannot call l2cap_chan_close() without conn->lock,
+ * schedule l2cap_chan_timeout to close the channel; it already
+ * acquires conn->lock -> chan->lock in the correct order.
*/
while ((sk = bt_accept_dequeue(parent, NULL))) {
struct l2cap_chan *chan;
@@@ -1516,14 -1533,12 +1533,12 @@@
state_to_string(chan->state));
l2cap_chan_lock(chan);
- __clear_chan_timer(chan);
- l2cap_chan_close(chan, ECONNRESET);
- /* l2cap_conn_del() may already have killed this socket
- * (it sets SOCK_DEAD); skip the duplicate to avoid a
- * double sock_put()/l2cap_chan_put().
+ /* Since we cannot call l2cap_chan_close() without
+ * conn->lock, schedule its timer to trigger the close
+ * and cleanup of this channel.
*/
- if (!sock_flag(sk, SOCK_DEAD))
- l2cap_sock_kill(sk);
+ if (chan->conn)
+ __set_chan_timer(chan, 0);
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
@@@ -2037,7 -2052,7 +2052,7 @@@ static const struct proto_ops l2cap_soc
.socketpair = sock_no_socketpair,
.shutdown = l2cap_sock_shutdown,
.setsockopt = l2cap_sock_setsockopt,
- .getsockopt = l2cap_sock_getsockopt
+ .getsockopt_iter = l2cap_sock_getsockopt
};
static const struct net_proto_family l2cap_sock_family_ops = {
© 2016 - 2026 Red Hat, Inc.