Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: ipv6: Fix OOPS in ip6_dst_lookup_tail(). ipsec: Restore larval states and socket policies in dump [Bluetooth] Reject L2CAP connections on an insecure ACL link [Bluetooth] Enforce correct authentication requirements [Bluetooth] Fix reference counting during ACL config stage
This commit is contained in:
commit
91cd99f677
|
@ -325,7 +325,8 @@ int hci_conn_del(struct hci_conn *conn);
|
|||
void hci_conn_hash_flush(struct hci_dev *hdev);
|
||||
void hci_conn_check_pending(struct hci_dev *hdev);
|
||||
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
int hci_conn_auth(struct hci_conn *conn);
|
||||
int hci_conn_encrypt(struct hci_conn *conn);
|
||||
int hci_conn_change_link_key(struct hci_conn *conn);
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.12"
|
||||
#define VERSION "2.13"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
|
|
|
@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);
|
|||
|
||||
/* Create SCO or ACL connection.
|
||||
* Device _must_ be locked */
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
|
||||
{
|
||||
struct hci_conn *acl;
|
||||
struct hci_conn *sco;
|
||||
|
@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
|||
|
||||
hci_conn_hold(acl);
|
||||
|
||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
|
||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
|
||||
acl->auth_type = auth_type;
|
||||
hci_acl_connect(acl);
|
||||
}
|
||||
|
||||
if (type == ACL_LINK)
|
||||
return acl;
|
||||
|
@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
|||
}
|
||||
EXPORT_SYMBOL(hci_connect);
|
||||
|
||||
/* Check link security requirement */
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
|
||||
!(conn->link_mode & HCI_LM_ENCRYPT))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_conn_check_link_mode);
|
||||
|
||||
/* Authenticate remote device */
|
||||
int hci_conn_auth(struct hci_conn *conn)
|
||||
{
|
||||
|
@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)
|
|||
|
||||
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
|
||||
if (!(conn->auth_type & 0x01)) {
|
||||
conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
|
||||
conn->auth_type |= 0x01;
|
||||
conn->link_mode &= ~HCI_LM_AUTH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
|
|||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status && hdev->ssp_mode > 0 &&
|
||||
conn->ssp_mode > 0) {
|
||||
if (conn->out) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
cp.handle = ev->handle;
|
||||
hci_send_cmd(hdev,
|
||||
HCI_OP_AUTH_REQUESTED,
|
||||
conn->ssp_mode > 0 && conn->out) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
cp.handle = ev->handle;
|
||||
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
} else {
|
||||
conn->state = BT_CONNECTED;
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.10"
|
||||
#define VERSION "2.11"
|
||||
|
||||
static u32 l2cap_feat_mask = 0x0000;
|
||||
|
||||
|
@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
|
|||
struct l2cap_conn *conn;
|
||||
struct hci_conn *hcon;
|
||||
struct hci_dev *hdev;
|
||||
__u8 auth_type;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
|
||||
|
@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
|
|||
|
||||
err = -ENOMEM;
|
||||
|
||||
hcon = hci_connect(hdev, ACL_LINK, dst);
|
||||
if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
|
||||
l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
|
||||
l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
|
||||
if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
|
||||
auth_type = HCI_AT_NO_BONDING_MITM;
|
||||
else
|
||||
auth_type = HCI_AT_GENERAL_BONDING_MITM;
|
||||
} else {
|
||||
if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
|
||||
auth_type = HCI_AT_NO_BONDING;
|
||||
else
|
||||
auth_type = HCI_AT_GENERAL_BONDING;
|
||||
}
|
||||
|
||||
hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
|
||||
if (!hcon)
|
||||
goto done;
|
||||
|
||||
|
@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
||||
struct l2cap_conn_rsp rsp;
|
||||
struct sock *sk, *parent;
|
||||
int result, status = 0;
|
||||
int result, status = L2CAP_CS_NO_INFO;
|
||||
|
||||
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
||||
__le16 psm = req->psm;
|
||||
__le16 psm = req->psm;
|
||||
|
||||
BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
|
||||
|
||||
|
@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
goto sendresp;
|
||||
}
|
||||
|
||||
/* Check if the ACL is secure enough (if not SDP) */
|
||||
if (psm != cpu_to_le16(0x0001) &&
|
||||
!hci_conn_check_link_mode(conn->hcon)) {
|
||||
result = L2CAP_CR_SEC_BLOCK;
|
||||
goto response;
|
||||
}
|
||||
|
||||
result = L2CAP_CR_NO_MEM;
|
||||
|
||||
/* Check for backlog size */
|
||||
|
@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
|
|||
else
|
||||
type = SCO_LINK;
|
||||
|
||||
hcon = hci_connect(hdev, type, dst);
|
||||
hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
|
||||
if (!hcon)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -943,39 +943,39 @@ static int ip6_dst_lookup_tail(struct sock *sk,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
||||
/*
|
||||
* Here if the dst entry we've looked up
|
||||
* has a neighbour entry that is in the INCOMPLETE
|
||||
* state and the src address from the flow is
|
||||
* marked as OPTIMISTIC, we release the found
|
||||
* dst entry and replace it instead with the
|
||||
* dst entry of the nexthop router
|
||||
*/
|
||||
if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
|
||||
struct inet6_ifaddr *ifp;
|
||||
struct flowi fl_gw;
|
||||
int redirect;
|
||||
/*
|
||||
* Here if the dst entry we've looked up
|
||||
* has a neighbour entry that is in the INCOMPLETE
|
||||
* state and the src address from the flow is
|
||||
* marked as OPTIMISTIC, we release the found
|
||||
* dst entry and replace it instead with the
|
||||
* dst entry of the nexthop router
|
||||
*/
|
||||
if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
|
||||
struct inet6_ifaddr *ifp;
|
||||
struct flowi fl_gw;
|
||||
int redirect;
|
||||
|
||||
ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
|
||||
(*dst)->dev, 1);
|
||||
ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
|
||||
(*dst)->dev, 1);
|
||||
|
||||
redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
|
||||
if (ifp)
|
||||
in6_ifa_put(ifp);
|
||||
redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
|
||||
if (ifp)
|
||||
in6_ifa_put(ifp);
|
||||
|
||||
if (redirect) {
|
||||
/*
|
||||
* We need to get the dst entry for the
|
||||
* default router instead
|
||||
*/
|
||||
dst_release(*dst);
|
||||
memcpy(&fl_gw, fl, sizeof(struct flowi));
|
||||
memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
|
||||
*dst = ip6_route_output(net, sk, &fl_gw);
|
||||
if ((err = (*dst)->error))
|
||||
goto out_err_release;
|
||||
}
|
||||
if (redirect) {
|
||||
/*
|
||||
* We need to get the dst entry for the
|
||||
* default router instead
|
||||
*/
|
||||
dst_release(*dst);
|
||||
memcpy(&fl_gw, fl, sizeof(struct flowi));
|
||||
memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
|
||||
*dst = ip6_route_output(net, sk, &fl_gw);
|
||||
if ((err = (*dst)->error))
|
||||
goto out_err_release;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1077,6 +1077,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
|
|||
struct hlist_head *chain = policy_hash_bysel(&pol->selector,
|
||||
pol->family, dir);
|
||||
|
||||
list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]);
|
||||
hlist_add_head(&pol->bydst, chain);
|
||||
hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index));
|
||||
xfrm_policy_count[dir]++;
|
||||
|
|
|
@ -858,6 +858,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
|
|||
|
||||
if (km_query(x, tmpl, pol) == 0) {
|
||||
x->km.state = XFRM_STATE_ACQ;
|
||||
list_add_tail(&x->all, &xfrm_state_all);
|
||||
hlist_add_head(&x->bydst, xfrm_state_bydst+h);
|
||||
h = xfrm_src_hash(daddr, saddr, family);
|
||||
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
|
||||
|
@ -1055,6 +1056,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
|
|||
xfrm_state_hold(x);
|
||||
x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
|
||||
add_timer(&x->timer);
|
||||
list_add_tail(&x->all, &xfrm_state_all);
|
||||
hlist_add_head(&x->bydst, xfrm_state_bydst+h);
|
||||
h = xfrm_src_hash(daddr, saddr, family);
|
||||
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
|
||||
|
|
Loading…
Reference in New Issue