diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2016-01-29 14:37:40 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2016-02-25 02:41:01 -0500 |
commit | 03c05355543149bf610f4375e8382ee4fc0aaade (patch) | |
tree | 6173ee32c1628a3973ec9305611895434ad121e7 /net/nfc | |
parent | 81ca7835f2cb0c3ba4236e3bcf31d997c6f5d71a (diff) |
NFC: Close a race condition in llcp_sock_getname()
llcp_sock_getname() checks llcp_sock->dev to make sure
llcp_sock is already connected or bound, however, we could
be in the middle of llcp_sock_bind() where llcp_sock->dev
is bound and llcp_sock->service_name_len is set,
but llcp_sock->service_name is not, in this case we would
lead to copy some bytes from a NULL pointer.
Just lock the sock since this is not a hot path anyway.
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/llcp_sock.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index ecf0a0196f18..b9edf5fae6ae 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c | |||
@@ -509,6 +509,11 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, | |||
509 | memset(llcp_addr, 0, sizeof(*llcp_addr)); | 509 | memset(llcp_addr, 0, sizeof(*llcp_addr)); |
510 | *len = sizeof(struct sockaddr_nfc_llcp); | 510 | *len = sizeof(struct sockaddr_nfc_llcp); |
511 | 511 | ||
512 | lock_sock(sk); | ||
513 | if (!llcp_sock->dev) { | ||
514 | release_sock(sk); | ||
515 | return -EBADFD; | ||
516 | } | ||
512 | llcp_addr->sa_family = AF_NFC; | 517 | llcp_addr->sa_family = AF_NFC; |
513 | llcp_addr->dev_idx = llcp_sock->dev->idx; | 518 | llcp_addr->dev_idx = llcp_sock->dev->idx; |
514 | llcp_addr->target_idx = llcp_sock->target_idx; | 519 | llcp_addr->target_idx = llcp_sock->target_idx; |
@@ -518,6 +523,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, | |||
518 | llcp_addr->service_name_len = llcp_sock->service_name_len; | 523 | llcp_addr->service_name_len = llcp_sock->service_name_len; |
519 | memcpy(llcp_addr->service_name, llcp_sock->service_name, | 524 | memcpy(llcp_addr->service_name, llcp_sock->service_name, |
520 | llcp_addr->service_name_len); | 525 | llcp_addr->service_name_len); |
526 | release_sock(sk); | ||
521 | 527 | ||
522 | return 0; | 528 | return 0; |
523 | } | 529 | } |