Skip to content

Conversation

@mikezhang1234567890
Copy link
Contributor

If a program is built by a 10.15 or earlier SDK is run on Big Sur (version 11)
or newer, it will run in a backwards compatibility context which will return
product version as 10.16.

Thus, when we need to get Mac OS version when running on 11+, we need to use
a workaround to get the real version string. In this case, we look at a symlink
to the SystemVersion.plist file which bypasses the backwards compatibility
context.

Signed-off-by: Mike Zhang mike.h.zhang@ibm.com

Fixes eclipse-openj9/openj9#12630

@0xdaryl
Copy link
Contributor

0xdaryl commented Jun 9, 2021

@tajila @pshipton : could one of you (or delegate) review these changes please?

* real version info.
*/
if (0 == strncmp(buffer, "10.16", 5)) {
portLibrary->mem_free_memory(portLibrary, buffer);
Copy link
Contributor

@pshipton pshipton Jun 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should first check buffer != myBuffer, or free allocatedFileBuffer instead using the same comment as below where allocatedFileBuffer is freed. Also set allocatedFileBuffer to NULL so it can't be freed twice. allocatedFileBuffer should be set to NULL above as well where it's freed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Freed allocatedFileBuffer here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer is NUL-terminated; shouldn't this use strcmp() instead?

len = resultSize + 1;
buffer = portLibrary->mem_allocate_memory(portLibrary, len,
OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
strncpy(buffer, versionString, len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer needs to be checked for NULL

portLibrary->file_close(portLibrary, plistFile);
if (rc < 0) {
/* free the buffer if it was allocated */
portLibrary->mem_free_memory(portLibrary, allocatedFileBuffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should set allocatedFileBuffer to NULL since it's freed again below.

@mikezhang1234567890
Copy link
Contributor Author

Can you please take another look @pshipton ?

if (NULL != buffer) {
strncpy(buffer, versionString, len);
} else {
rc = -1; /* error allocating memory */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the redundant code should be removed to make this easier to understand. This isn't needed.

rc = -1; /* error allocating memory */
}
} else {
rc = -1; /* parse error */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed.

}
}
portLibrary->file_close(portLibrary, plistFile);
if (rc < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block isn't needed, the memory is freed below regardless of the outcome.

portLibrary->mem_free_memory(portLibrary, allocatedFileBuffer);
allocatedFileBuffer = NULL;
}
} else { /* plistFile >= 0 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block isn't needed, rc isn't used for anything below.


intptr_t plistFile = portLibrary->file_open(portLibrary, COMPAT_PLIST_LINK, EsOpenRead, 0444);
if (plistFile >= 0) {
char myBuffer[1024]; /* the file size is ~500 bytes, 525 on a 11.3 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well remove this to save stack and use the previous definition of myBuffer, I think it's still in scope.

Copy link
Contributor Author

@mikezhang1234567890 mikezhang1234567890 Jun 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like it. The previous definition of myBuffer is bound to the previous read of the plist file that occurs if sysctl failed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya ok, I see it now.

@mikezhang1234567890
Copy link
Contributor Author

Updated the PR again @pshipton

OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
fileBuffer = allocatedFileBuffer;
}
if (NULL != fileBuffer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bug here (and the previous code). If file_length() fails then fileBuffer != NULL and len is negative and the fileBuffer[len] = '\0' below writes outside the bounds of the stack buffer. Also strstr() will be checking random data and may go outside the bounds of readable memory, or find a false hit (however unlikely) causing another write outside of the buffer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated it so we look at the return value of file_flength() first before assigning fileBuffer. If the return is an error value, fileBuffer remains NULL.

Copy link
Contributor

@pshipton pshipton Jun 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but how about assigning directly to fileLen, I don't why rc needs to be involved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of file_flength() is negative when an error occurs, and fileLen is an unsigned integer type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size_t doesn't need to be used, file_flength() returns int64_t and the code could just keep using that. I'll defer to @keithc-ca

* real version info.
*/
if (0 == strncmp(buffer, "10.16", 5)) {
portLibrary->mem_free_memory(portLibrary, buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer is NUL-terminated; shouldn't this use strcmp() instead?

while (bytesRemaining > 0) {
intptr_t result = portLibrary->file_read(portLibrary, plistFile, readPtr, bytesRemaining);
if (result > 0) {
bytesRemaining -= result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing signed and unsigned types here, suggest:

bytesRemaining -= (size_t) result;

buffer = portLibrary->mem_allocate_memory(portLibrary, len,
OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
if (NULL != buffer) {
strncpy(buffer, versionString, len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than write the NUL to readPtr above, I suggest this should use memcpy():

memcpy(buffer, versionString, resultSize);
buffer[resultSize] = '\0';

@mikezhang1234567890
Copy link
Contributor Author

Updated PR again.

} else {
rc = sysctlbyname(KERN_OSPRODUCTVERSION, buffer, &resultSize, NULL, 0);
}
buffer[resultSize] = '\0';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer may refer to freed memory here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no mem_free_memory called between when buffer was declared in L1999 and here. I don't see how.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are correct. I read the code as if the reference was to the buffer declared on line 1940 (and possibly freed on line 1988).

@pshipton
Copy link
Contributor

What's the next step for this, are all your review comments addressed @keithc-ca ?

Comment on lines 2018 to 2020
* so we check the plink symlink as that bypasses the compatibility context and returns the
* real version info.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: asterisks should line up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated PR to address this formatting issue.

@keithc-ca
Copy link
Contributor

Other than the minor formatting nit, I think this looks good.

If a program is built by a 10.15 or earlier SDK is run on Big Sur (version 11)
or newer, it will run in a backwards compatibility context which will return
product version as 10.16.

Thus, when we need to get Mac OS version when running on 11+, we need to use
a workaround to get the real version string. In this case, we look at a symlink
to the SystemVersion.plist file which bypasses the backwards compatibility
context.

Signed-off-by: Mike Zhang <mike.h.zhang@ibm.com>
@pshipton
Copy link
Contributor

@0xdaryl I think this is ready to be tested.

@0xdaryl 0xdaryl self-assigned this Jun 21, 2021
@0xdaryl
Copy link
Contributor

0xdaryl commented Jun 21, 2021

Jenkins build all

@0xdaryl 0xdaryl merged commit 708c852 into eclipse-omr:master Jun 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JDK16 MacOS jdk_lang_0_FAILED OsVersionTest - Error: 10.16 != 11.3

4 participants