-
Notifications
You must be signed in to change notification settings - Fork 802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed AudioMediaPort use after free #4200
Conversation
To be honest, the existing port warning confused me. If I just comment I'm not sure if my proposed fix is right though, so please correct it if it's inaccurate. Please also help check for the other media ports in pjsua2 |
Right, it sounds a bit confusing indeed. Let me try to clarify it, and then help me clarify it for port developers :) To avoid premature destroy, port must use its own pool, never use app's pool (as app may call Note that the port's group lock, while being needed to properly time the port's pool release, is actually optional, because the bridge can check and install one automatically if there is none. If the port already has a group lock, implicitly it means that it is already aware of possible premature destroy, it should have its own pool & the pool release timing should have been managed using the group lock. If the port does not have group lock, the bridge will call |
pjsip/src/pjsua2/media.cpp
Outdated
@@ -321,7 +326,8 @@ static pj_status_t get_frame(pjmedia_port *port, pjmedia_frame *frame) | |||
|
|||
static pj_status_t put_frame(pjmedia_port *port, pjmedia_frame *frame) | |||
{ | |||
AudioMediaPort *mport = (AudioMediaPort *) port->port_data.pdata; | |||
struct port_data *pdata = (struct port_data *)port->port_data.pdata; | |||
AudioMediaPort *mport = pdata->mport; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that get/put_frame()
may be called after the AudioMediaPort
instance is destroyed, so perhaps mport
field need to be reset in AudioMediaPort
destructor. Even perhaps better to protect all access to the field with (group) lock.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ouch, this is more complicated than I anticipated and never seems to be mentioned anywhere.
Perhaps need to add this in the PR desc: Due to the async nature of conf port removal, media port must be prepared to receive further get/put_frame() callbacks until the removal completes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to backward compatibility issue in PR & 2.15 release note.
I would suggest: (b) Warning, port %s on_destroy() not found. To avoid premature destroy, media port must manage its own pool, which can only be released in on_destroy() or in its grp lock handler. (c) Warning, port %s on_destroy() not found. To avoid premature destroy, media port must control its own lifetime. See PR #3928. |
I'd vote for (b), with "see PR #3928 for more info" perhaps? |
pjmedia/src/pjmedia/port.c
Outdated
* and then destroys the pool immediately, it may cause crash as the port | ||
* may have not really been destroyed and may still be accessed. | ||
* When port has a pool, it usually implements on_destroy() for releasing | ||
* If port uses app's pool, it needs to implement on_destroy() for releasing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"If port uses app's pool" implies that port may still use app's pool, while it must not. Even perhaps we should clarify somewhere here that port must create & use its own pool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did quick check on the code, Tonegen & AudioMedia seems okay. Also done a quick test for Tonegen using pjsua2_demo.cpp, while AudioMedia should already have been tested when testing Android.
As described in #3928 point 1, due to the now async nature of the conference bridge, we need to make sure that the port is not prematurely destroyed.