Closed
Bug 334448
Opened 18 years ago
Closed 18 years ago
oom Crash in crmf_copy_cert_req_msg
Categories
(NSS :: Libraries, defect, P2)
Tracking
(Not tracked)
RESOLVED
FIXED
3.11.2
People
(Reporter: timeless, Assigned: alvolkov.bgs)
References
()
Details
(4 keywords, Whiteboard: CID 212)
Attachments
(2 files, 2 obsolete files)
2.11 KB,
patch
|
nelson
:
review-
|
Details | Diff | Splinter Review |
9.51 KB,
patch
|
nelson
:
review+
|
Details | Diff | Splinter Review |
found by coverity
Attachment #218791 -
Flags: review?(nelson)
Comment 2•18 years ago
|
||
Comment on attachment 218791 [details] [diff] [review] free arena if object isn't constructed > newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg); > newReqMsg->poolp = poolp; > if (newReqMsg == NULL) { > goto loser; As long as you're here, check for null /before/ dereferencing newReqMsg->poolp. > newReqMsg->pop = crmf_copy_pop(poolp, srcReqMsg->pop); > if (newReqMsg->pop == NULL) { > goto loser; This is fine here, but looking in crmf_copy_pop it looks like it leaks newPOP if it hits any of the three "goto loser" cases.
Updated•18 years ago
|
Target Milestone: --- → 3.11.1
Updated•18 years ago
|
Priority: -- → P2
Hardware: PC → All
Comment 3•18 years ago
|
||
Comment on attachment 218791 [details] [diff] [review] free arena if object isn't constructed > newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg); > newReqMsg->poolp = poolp; > if (newReqMsg == NULL) { Dan's right. That crash has to be fixed. This patch didn't address that. > loser: > if (newReqMsg != NULL) { >- CRMF_DestroyCertReqMsg(newReqMsg); >+ if (newReqMsg->certReq) { >+ CRMF_DestroyCertReqMsg(newReqMsg); >+ } else { >+ PORT_FreeArena(poolp, PR_TRUE); >+ } The right way to destroy a CertReqMsg is to call CRMF_DestroyCertReqMsg, even if the CertReqMsg is incomplete. If CRMF_DestroyCertReqMsg crashes when the CertReqMsg is incomplete, then the patch should fix THAT, rather than incorporate some of the logic that belongs in CRMF_DestroyCertReqMsg into every one of its callers.
Attachment #218791 -
Flags: review?(nelson) → review-
Assignee | ||
Comment 4•18 years ago
|
||
> > newReqMsg->pop = crmf_copy_pop(poolp, srcReqMsg->pop);
> > if (newReqMsg->pop == NULL) {
> > goto loser;
>
> This is fine here, but looking in crmf_copy_pop it looks like it leaks newPOP
> if it hits any of the three "goto loser" cases.
>
Yes, the newPOP object leaks in crmf_copy_pop.
PORT_ArenaMark, PORT_ArenaUnmark, PORT_ArenaRelease should be used in the function.
Assignee | ||
Comment 5•18 years ago
|
||
Assignee: nobody → alexei.volkov.bugs
Status: NEW → ASSIGNED
Attachment #219376 -
Flags: review?(nelson)
Comment 6•18 years ago
|
||
Comment on attachment 219376 [details] [diff] [review] fix for crash and some leaks r- I see no calls to PORT_ArenaUnmark here. Every ArenaMark has to be either Released or Unmarked. On some platforms, in some builds, a Mark acquires a lock. That lock is release by calling either Release or Unmark. Unmark removes the mark, and leaves the arena intact, and clears the lock. Release frees anything allocating since the mark was made, removes the mark, and clears the lock.
Attachment #219376 -
Flags: review?(nelson) → review-
Assignee | ||
Comment 7•18 years ago
|
||
Modification to the previous patch: PORT_ArenaUnmark is added.
Attachment #219376 -
Attachment is obsolete: true
Attachment #219767 -
Flags: review?(nelson)
Comment 8•18 years ago
|
||
Comment on attachment 219767 [details] [diff] [review] Be more conservative with pool. This patch is fine, as far as it goes, but it doesn't address the original OOM crash. Here's the change that's needed for that. > newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg); >- newReqMsg->poolp = poolp; > if (newReqMsg == NULL) { > goto loser; >+ newReqMsg->poolp = poolp;
Attachment #219767 -
Attachment description: fix → Be more conservative with pool.
Comment 9•18 years ago
|
||
Comment on attachment 219767 [details] [diff] [review] Be more conservative with pool. r- because it doesn't prevent the oom crash. Otherwise it's OK.
Attachment #219767 -
Flags: review?(nelson) → review-
Assignee | ||
Comment 10•18 years ago
|
||
I think moving pool assignment below "if" is not enough. When failure occures at 517, we still have crash in CRMF_DestroyCertReqMsg function. 517 newReqMsg->certReq = crmf_copy_cert_request(poolp, srcReqMsg->certReq); 518 if (newReqMsg->certReq == NULL) { 519 goto loser; 520 } This is why the third patch has changes to CRMF_DestroyCertReqMsg function.
Assignee | ||
Comment 11•18 years ago
|
||
Attachment #219767 -
Attachment is obsolete: true
Attachment #220067 -
Flags: review?(nelson)
Comment 12•18 years ago
|
||
Comment on attachment 220067 [details] [diff] [review] address the root issue of the bug r=nelson for the 3.11 branch (not 3.11.1 branch) and the trunk. I think this patch is no less correct than the old code in all respects, but as I review the patched code, there are still a few areas where the original code seems, uh, suspicious. So, IMO, it's ok to check in these changes (on the branches indicated above), but before marking the bug resolved/fixed there might be a few more changes worth consideration. >Index: crmfreq.c > SECStatus > CRMF_DestroyCertReqMsg(CRMFCertReqMsg *inCertReqMsg) > { > PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->poolp != NULL); That assertion should be followed by an if statement that detects those conditions and deal with them gracefully in non-debug builds, e.g. set an error code and return SECFailure. >- if (!inCertReqMsg->isDecoded) { >+ if (!inCertReqMsg->isDecoded && inCertReqMsg->certReq) { > if (inCertReqMsg->certReq->certTemplate.extensions != NULL) { > PORT_Free(inCertReqMsg->certReq->certTemplate.extensions); > } > if (inCertReqMsg->certReq->controls != NULL) { > PORT_Free(inCertReqMsg->certReq->controls); > } > } > PORT_FreeArena(inCertReqMsg->poolp, PR_TRUE); > return SECSuccess; > } The above block is a part that seems suspicious. Cert request messages can be either (a) locally generated (to be DER encoded and then sent off to a remote server) or (b) received in the server from a remote client and then DER decoded. IOW, the message can be either input to encoder or output of decoder. The "isDecoded" flag serves to tell us which case we're dealing with on this stack. The decoded case always implies that the decoded parts are in an arena pool (because the decoder always decodes into a pool). The code here seems to be saying: if we're in a pool, and we're decoded, then explicitly free the extensions (rather than implicitly freeing them when the pool is freed). That's suspicious. It might be right (in which case it must be that the extensions and controls were not allocated from the pool), but there should be some comments explaining that, if so.
Attachment #220067 -
Flags: review?(nelson) → review+
Updated•18 years ago
|
Target Milestone: 3.11.1 → 3.11.2
Assignee | ||
Updated•18 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Comment 14•17 years ago
|
||
should this be considered for fixing in firefox 2.0.0.4?
Flags: blocking1.8.1.4?
Updated•17 years ago
|
Flags: blocking1.8.1.4?
Keywords: fixed1.8.0.10,
fixed1.8.1.1
Updated•17 years ago
|
Group: security
You need to log in
before you can comment on or make changes to this bug.
Description
•