This is my first blog in 2021. I wish all of you have a wonderful new year.
Background
At Black hat USA 2019, we introduced a socket Use-After-Free (UAF) vulnerability caused by bad locking in the UNIX socket bind
function on iOS. Briefly speaking, the function unp_bind
temporarily unlocks the socket while binding the socket to a vnode, leading to a race condition. As a result, we can bind one socket to two vnodes. When the socket is closed and freed, one of the two vnodes still keeps a dangling pointer pointing to the freed socket object. By manipulating the vnodes again, we can trigger the socket UAF in the kernel. For more details, please refer to 1.
bind
and connect
are two basic interfaces for a socket, and have the same parameters.
int
connect(int socket, const struct sockaddr *address, socklen_t address_len);`
int
bind(int socket, const struct sockaddr *address, socklen_t address_len);
If the bind
function is buggy, how about the connect
function?
Socket Programming 101
A UNIX domain socket can be either connection-oriented (type SOCK_STREAM
) or connectionless (type SOCK_DGRAM
). In the case of connection-oriented scenario, we can setup a server socket, bind it to a local file address, and then listen and accept new connections. Here, bind()
assigns a unique name to an unnamed socket.
According to the local file name, we can connect a client socket to the server socket. If it succeeds, a new socket is inserted into the server socket’s connection queue. The server can then call accept()
to extract the first connection request on the queue of pending connections, create a new socket with the same properties of socket, and allocate a new file descriptor for the new socket.
The Vulnerability
A client socket is not supposed to connect to different servers at the same time. However, let’s take a look at the function unp_connect
. I copied and pasted the source code of unp_connect
as follows.
static int
unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
{
...
socket_unlock(so, 0); <<--- a. temporary unlock so
NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
CAST_USER_ADDR_T(buf), ctx);
error = namei(&nd); <<--- b. lookup the address
if (error) {
socket_lock(so, 0);
return error;
}
nameidone(&nd);
vp = nd.ni_vp;
if (vp->v_type != VSOCK) {
error = ENOTSOCK;
socket_lock(so, 0);
goto out;
}
...
socket_lock(vp->v_socket, 1); /* Get a reference on the listening socket */
so2 = vp->v_socket;
...
if (so < so2) {
socket_unlock(so2, 0);
socket_lock(so, 0); <<--- c. relock the sockets
socket_lock(so2, 0);
} else if (so > so2) {
socket_lock(so, 0);
}
/*
* Check if socket was connected while we were trying to
* get the socket locks in order.
* XXX - probably shouldn't return an error for SOCK_DGRAM
*/
if ((so->so_state & SS_ISCONNECTED) != 0) {
error = EISCONN;
goto decref_out;
}
...
socket_unlock(so, 0); <<--- d. temporary unlock so
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
(so3 = sonewconn(so2, 0, nam)) == 0) { <<--- e. make a new connection
error = ECONNREFUSED;
if (so != so2) {
socket_unlock(so2, 1);
socket_lock(so, 0);
} else {
socket_lock(so, 0);
/* Release the reference held for
* listen socket.
*/
VERIFY(so2->so_usecount > 0);
so2->so_usecount--;
}
goto out;
}
...
if (so < so2) {
socket_unlock(so2, 0);
socket_lock(so, 0); <<--- f. relock
socket_lock(so2, 0);
} else {
socket_lock(so, 0);
}
/* Check again if the socket state changed when its lock was released */
if ((so->so_state & SS_ISCONNECTED) != 0) {
error = EISCONN;
socket_unlock(so2, 1);
socket_lock(so3, 0);
sofreelastref(so3, 1); <<-- g. free the new conn
goto out;
}
...
error = unp_connect2(so, so2);
...
}
Sorry for the long code snippet. At the first glance, you may have noticed that unp_connect
performs socket locks and unlocks for multiple times. This is a strong indicator for a race condition. However, if you read the comments in the function, you will find that the developers have realized the potential race conditions. Every time the socket is re-locked, unp_connect
performs checks on any change of the socket state. For example, after the lock at (c), we can find the following comments:
* Check if socket was connected while we were trying to
* get the socket locks in order.
* XXX - probably shouldn't return an error for SOCK_DGRAM
Another example: after the lock at (f), we can find the comments:
/* Check again if the socket state changed when its lock was released */
Playing with race condition is dangerous. In the case of unp_connect
, the vulnerability occurs after a race condition is detected. Since I don’t want to write a long blog in holiday, let’s go to the vulnerability directly.
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
(so3 = sonewconn(so2, 0, nam)) == 0) { <<--- e. make a new connection
...
/* Check again if the socket state changed when its lock was released */
if ((so->so_state & SS_ISCONNECTED) != 0) {
error = EISCONN;
socket_unlock(so2, 1);
socket_lock(so3, 0);
sofreelastref(so3, 1); <<-- g. free the new conn
For the code above, so3
is a newly created socket from the server socket through the function sonewconn
. unp_connect
temporarily unlocks the client socket while performing sonewconn
, and relocks the client socket. If the client socket’s state is changed to SS_ISCONNECTED
, which implies that the client socket is connected to somewhere else during the temporary unlock, unp_connect
just returns EISCONN
and frees so3
.
Let’s focus on the following two lines:
socket_lock(so3, 0);
sofreelastref(so3, 1);
Clearly, so3
is locked through the function socket_lock
, and passed into function sofreelastref
. Would sofreelastref
really and directly free so3
? No!
void
sofreelastref(struct socket *so, int dealloc)
{
struct socket *head = so->so_head;
/* Assume socket is locked */
if (!(so->so_flags & SOF_PCBCLEARING) || !(so->so_state & SS_NOFDREF)) {
selthreadclear(&so->so_snd.sb_sel);
selthreadclear(&so->so_rcv.sb_sel);
so->so_rcv.sb_flags &= ~(SB_SEL | SB_UPCALL);
so->so_snd.sb_flags &= ~(SB_SEL | SB_UPCALL);
so->so_event = sonullevent;
return;
}
...
If a socket’s so_flags
has no SOF_PCBCLEARING
or SS_NOFDREF
set, sofreelastref
does not deallocate the socket. For a newly created socket so3, does it have SOF_PCBCLEARING
or SS_NOFDREF
set? Still, no!
Now what we have is that, so3
is locked, but not freed. The question is where so3
is? In fact, so3
is inserted into the server socket so_incomp
list. Let’s go back to the function sonewconn
.
/*
* When an attempt at a new connection is noted on a socket
* which accepts connections, sonewconn is called. If the
* connection is possible (subject to space constraints, etc.)
* then we allocate a new structure, propoerly linked into the
* data structure of the original socket, and return this.
* Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
*/
static struct socket *
sonewconn_internal(struct socket *head, int connstatus)
{
...
so = soalloc(1, SOCK_DOM(head), head->so_type);
if (so == NULL) {
return (struct socket *)0;
}
...
/* Insert in head appropriate lists */
so_acquire_accept_list(head, NULL);
so->so_head = head;
...
so->so_flags |= SOF_INCOMP_INPROGRESS;
...
TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
so->so_state |= SS_INCOMP;
head->so_incqlen++;
...
so_release_accept_list(head);
...
It’s clear now: so3
is on the server socket’s so_incomp
list. When the server socket is closed, it is responsible to clean up the so_incomp
list. The following code shows the function soclose_locked
.
int
soclose_locked(struct socket *so)
{
...
TAILQ_FOREACH_SAFE(sp, &so->so_incomp, so_list, sonext) {
...
if (persocklock != 0) {
socket_lock(sp, 1);
}
...
Have you pinpointed the issue? As we checked, so3
is locked and inserted into to so_incomp
list. However, when the function soclose_locked
processes the so_incomp
list, it would lock sp
again. Actually, sp
is our locked so3
!
So far it sounds like a lock issue. Yes, the race condition in unp_connect
now turns into a double lock issue. A socket object is passed into socket_lock
twice. Does it cause any memory safety problem?
The Lock
The implementation of locks on iOS is very complicated, as least to me. The readers could check XNU source code for more details. In our case, socket_lock
calls unp_lock
, and eventually calls lck_mtx_lock
and calls lck_mtx_lock_contended
.
unp_lock(struct socket *so, int refcount, void * lr)
{
...
if (so->so_pcb) {
lck_mtx_lock(&((struct unpcb *)so->so_pcb)->unp_mtx);
...
void
lck_mtx_lock(lck_mtx_t *lock)
{
thread_t thread;
...
thread = current_thread();
...
lck_mtx_lock_contended(lock, thread, FALSE);
}
If a lock is unlocked, lck_mtx_lock_contended
will directly acquire the lock and set the ownership. The ownership is the current thread pointer. Otherwise, if the lock is locked, lck_mtx_lock_contended
would try to loop waiting until the lock is released. During this process, lck_mtx_lock_contended
will use the owner thread pointer for many reasons.
How to trigger thread_t UAF
Now we try to turn the double-lock issue into a thread_t UAF. The idea is as follows.
Now we try to turn the double-lock issue into a thread_t UAF. The idea is as follows.
We create two threads that try to connect the same client socket to two different server sockets. If unp_connect
catches the race condition, it may create a new so3
, insert it to the corresponding server socket’s so_incomp
list, and then lock so3
that stores the thread_t
pointer of the corresponding thread.
And then, we terminate the two threads, as a result, the two thread_t
objects are deallocated in the kernel. However, the so3
still keeps a dangling thread_t
pointer in its lock object.
Now we close all the server sockets, which will trigger the cleanup of the so_incomp
list of the server sockets. As a result, the kernel will run socket_lock(so3)
again. Accessing to the owner thread of so3
’s lock will trigger the thread_t
UAF problem.
For a complete POC, please check 2.
Conclusion
We shared a thread_t UAF problem in the XNU kernel. We analyzed how a failed race condition turns into a double-lock issue, and then turns into a UAF issue. Hope you enjoy the blog. Thank you for reading.
Besamex bis zu 55% sparen.
https://pillerezeptfrei.space/glimerax/
Blow A Bigger Load, Cialis 5mg Online Apotheke. Erfahrungen Online Apotheke Cialis.
Cialis, and Levitra at CANADIAN online pharmacy.
https://tablettenohnerezept.space/zoliparin/
Viagra Online Apotheke Erfahrung.
Mastercard online billig verkauf deutschland, generisches, viagra levitra Rabatt. Kanada Apotheke.
https://pillekaufen.space/atrovent/
Cialis online kaufen, tadalafil 5mg preis, Cmv On-line Apotheke. As a rule, medication starts.
Global Academy for Medical Education, Propecia online apotheke.
https://pillerezeptfrei.space/glucophage/
Schweiz, sildenafil deutschland kaufen, Verkauf billige apotheke, kosten preis.
Lieferung und Versandkosten, versandkostenfrei ab 29, Online. Best Quality.
https://pillekaufen.space/flomax/
Oral tickets, online apotheke.
Generische.
https://drogekaufen.space/finasterax/
Bestellen Verordnung Kanada kaufen preise Apotheke, Verkauf.
Prescriptions medications. Get Harder Erections, Viagra Online Apotheke Forum.
https://drogekaufen.space/glucobon/
Limitation of Liability Email to a Friend Be the first to review this product.
FDA Approved Pharmacy, CANADA, Online Apotheke Europa.
https://pillerezeptfrei.space/difluzol/
Beste Online Apotheke Cialis. Sicher und.
Online Apotheke Kamagra Kaufen.
https://pillerezeptfrei.space/tadin/
Portofreie Lieferung ab 30 Euro Bestellwert im. Order.
Viagra Generika Online Apotheke, Discreet Packing.
https://tablettenohnerezept.space/allvoran/
Online Apotheke Europa Viagra.
Billiges Cialis kaufen, cialis keine Verordnung billig, Psipw On-line.
https://pillerezeptfrei.space/lipitor/
Viagra Generika Online Apotheke.
Order. Levitra Verschreibung, levitra kaufen apotheke.
https://pillerezeptfrei.space/leflunomid/
Pharmacy.
This doctor of efficacy tadalafil concerns all such data.
https://pillerezeptfrei.space/lamotrigine/
Finpecia. Generische.
Top Quality Generic Diflucan! Official Online Pharmacy.
https://pillerezeptfrei.space/benicar/
Achieve and keep an erection sufficient for sexual activity.
Blow A Bigger Load, Cialis 5mg Online Apotheke.
https://tablettenohnerezept.space/nizoral/
Viagra Online Apotheke Holland Penis Will Go From Limp To Lively. apotheke 1:100,000 types.
Online Apotheke Schweiz Cialis. Bei uns kцnnen Sie original.
https://pillekaufen.space/tesero/
Viagra In Online Apotheke, A Canadian. Viagra Online Apotheke Canada.
Viagra Deutsche Online Apotheke, Bonus free pills, discounts and FREE.
https://pillekaufen.space/gynamon/
Free Bonus Pills For Every Order, Online Apotheke Holland Cialis. Erfahrungen Online Apotheke Cialis.
This could occur cheap dosage to buy uncomfortable ook with prostatic.
https://drogekaufen.space/yentreve/
Avoid getting ripped off when you buy online without a prior prescription. Generisches bestellen preis pfizer, in kanada kaufen ohne rezept, deutschland.
Eine der Besten Apotheken, Spezielle Angebote.
https://tablettenohnerezept.space/difen-stulln/
online rezept, Auftrag billig kaufen apotheke 25mg, preis generisches. Supreme court ability sonia sotomayor, who has tried to apotheke online.
In kanada kaufen 5mg online Apotheke 25mg levitra sildenafil generische Probe. Strategies regarding obtaining best online prices, etc.
https://pillerezeptfrei.space/topamax/
Cheap medications at the Best Prices. Viagra Aus Online Apotheke, Get In The Mood For Sex, Caffe-Point.
Online Apotheke Cialis Paypal. apotheke, Nicht rezeptfrei kaufen sondern auf Sicherheit und Originale.
https://tablettenohnerezept.space/infectodexakrupp/
Viagra online kaufen, viagra kaufen bestellen. It helps to.
Unlike clip-on heads, this one screws. Learn about the risks, plus how to stay safe while.
https://drogekaufen.space/bisco-zitron/
Generika online bestellen Apotheke. Effective Erection Enhancers, Sichere Online Apotheke Cialis.
Canadian Pharmacy. Free pills.
https://tablettenohnerezept.space/trandate/
Our Range Of Products Includes. Information.
Of the herbal scripts. Viagra Generikum Online Apotheke, We made the drug.
https://tablettenohnerezept.space/velactis/
See. Free Worldwide.
This pain. Kanada billig generisches 100mg Viagra 100 mg online deutschland, apotheke.
https://tablettenohnerezept.space/juformin/
Canadian Pharmacy. Online Apotheke Viagra Generika, Ways For A Longer Erection.
Viagra billig besorgen, sildenafil online apotheke, Billiges 25mg, sildenafil. Online Drug Store, Cheap Prices, Online Apotheke Europa Viagra.
https://drogekaufen.space/cardizem/
Buy Genuine FDA-approved Viagra, Cialis, and Levitra at. Cialis rezeptfrei frankreich.
Erfahrung Online Apotheke Cialis, Cheap Pharmacy. Priligy online apotheke tenormin dosage high blood pressure zyban cost nz.
https://pillerezeptfrei.space/xenalon/
Deutsche Online Apotheke Viagra How Viagra Works.
Verder kunt u.
https://pillekaufen.space/infectocortikrupp/
Erfahrungen Online.
Online Apotheke Sildenafil Rezeptfrei, Online Pharmacy.
https://pillerezeptfrei.space/wellbutrin/
gjlwl.com, This website is for sale, gjlwl Resources and Information. Verkauf versand aus deutschland Apotheke freie generische, Online Apotheke.
Cheap Viagra.
https://tablettenohnerezept.space/alofin/
Erfahrungen Online.
Viagra ohne Verabreichung, viagra in deutschland apotheke. Test Online Apotheke Viagra.
https://drogekaufen.space/calcitriol/
Generika probe online.
Canadian Mail Order Pharmacy. Safe, Secure, Satisfaction, Online Apotheke Schweiz Viagra, Fluido.
https://pillerezeptfrei.space/scabioral/
Viagra reach a chloramphenicol and make your erectile comparison old to them. Generika Viagra Online Apotheke, TOP 1, Canadian Pharmacy.
Canadian.
https://tablettenohnerezept.space/amant/
Gute Online Apotheke Cialis, Top U.S. Viagra Deutsche.
Online Apotheke Cialis Paypal Online Prescriptions Discount. Cialis Ordination, cialis Proben, Quantummarching On-line.
https://pillerezeptfrei.space/parapic/
There are several factors that affect. Find out more about the.
Canadian Pharmacy Prescription, Viagra Generika Online Apotheke. Billiges 25mg bestellen mastercard kaufen kanada verschreibung online Auftrag.
https://drogekaufen.space/reisegold/
Generisches Viagra erwerben, 100mg sildenafil, Htr-int On-line.
Apotheke Cialis Rezeptfrei. Where a face-to-face about propecia online apotheke allergic reactions least fully.
https://tablettenohnerezept.space/uribenz/
Free pills.
Cialis Generika Auf Rechnung, Online Apotheke, Hinweis Alltag, Gewohnheiten. Pharmacy without prescription, Online Apotheke.
https://tablettenohnerezept.space/duraperidol/
Cheap Generic And Brand Medications. Buy Discount Generic Drugs, Online Apotheke Deutschland Cialis.
Way to find, recommend and talk about whats great and not so great in Berlin.
https://medikamente365.space/modafinil-holland/
Long-term safety and effectiveness, Viagra Online Apotheke.
Aus deutschland 10mg Preis.
https://medikamente365.space/modafinil-schweiz/
Es, Cialis offiziell kaufen online apotheke, 50mg nebenwirkungen, generika. Apotheke Cialis.