Skip to content
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

d.mon: Fix Unbounded Source Buffer in main.c file of d.mon module #4260

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

ShubhamDesai
Copy link
Contributor

This Pull Request addresses the unbounded source buffer issue identified by Coverity Scan (CID: 1270265).

Changes Implemented:

  • Monitor Name Length Check:

  • Defined a maximum length for the monitor name (mon) as 256 characters using the MONITOR_NAME_LIMIT macro.

  • Introduced checks to ensure that the mon variable, which stores the monitor name, does not exceed this defined length.

  • The check if (mon && strlen(mon) < MONITOR_NAME_LIMIT) ensures that mon is not NULL and that its length does not exceed MONITOR_NAME_LIMIT.

@github-actions github-actions bot added C Related code is in C module display labels Aug 30, 2024
Copy link
Member

@wenzeslaus wenzeslaus left a comment

Choose a reason for hiding this comment

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

While this may address the unbounded source buffer issue, it seems to me that it will just lead to another warning. The mon string goes into functions like list_cmd and somewhere there it is put to another buffer which may or may not be large enough. Maybe the issue needs to be addressed there. I checked this issue in Coverity Scan and it seems to be able to take you there.

@ShubhamDesai ShubhamDesai changed the title display: Fix Unbounded Source Buffer in main.c file of d.mon module d.mon: Fix Unbounded Source Buffer in main.c file of d.mon module Sep 1, 2024
@ShubhamDesai
Copy link
Contributor Author

While this may address the unbounded source buffer issue, it seems to me that it will just lead to another warning. The mon string goes into functions like list_cmd and somewhere there it is put to another buffer which may or may not be large enough. Maybe the issue needs to be addressed there. I checked this issue in Coverity Scan and it seems to be able to take you there.

To address this, I have now added two checks:

Primary Check in the Main File: I implemented a length check for mon directly in the main file to ensure it is within safe limits before being passed to other functions.

Additional Checks in Individual Functions: In each of the individual functions, the length of name is also checked to provide an extra layer of safety.

For these checks, instead of using a random number, I used GPATH_MAX as the baseline. The MONITOR_NAME_LIMIT is specifically calculated as GPATH_MAX - strlen("/MONITORS/") - 1 because the "/MONITORS/" directory path is used in one of the functions to create a temporary directory. This calculation ensures that the actual monitor name length is within safe limits, considering the directory structure.

So if the checks pass in the main file still there will be additional checks inside the functions

Comment on lines 17 to 20
if (strlen(name) >= GPATH_MAX) {
G_fatal_error(_("Monitor name <%s> is too long."), name);
}

Copy link
Member

Choose a reason for hiding this comment

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

Here, it is not constructing any strings, so a check is not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed. Done

@@ -176,7 +178,7 @@ int main(int argc, char *argv[])
if (list_flag->answer)
G_warning(_("Flag -%c ignored"), list_flag->key);
mon = G_getenv_nofatal("MONITOR");
if (mon) {
if (mon && strlen(mon) < MONITOR_NAME_LIMIT) {
Copy link
Member

Choose a reason for hiding this comment

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

There is actually GNAME_MAX, so you that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 108 to 110
if (strlen(name) >= GPATH_MAX) {
G_fatal_error(_("Monitor name <%s> is too long."), name);
}
Copy link
Member

Choose a reason for hiding this comment

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

The check should be done in get_path where the strings are concatenated. See also below for the issue with the check itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I initialized the available_space variable with GPATH_MAX - strlen(tmpdir) - 1, ensuring that it accounts for the initial size of tmpdir and the null terminator.
After each concatenation (such as "/", "MONITORS", and the monitor name), I subtracted the length of the appended string from available_space and checked whether there was enough space for the next operation.
This ensures that each part of the path can be appended safely without overflowing the buffer.

Comment on lines 142 to 144
if (strlen(tmpdir) >= GPATH_MAX) {
G_fatal_error(_("The path for monitor <%s> is too long."), name);
}
Copy link
Member

Choose a reason for hiding this comment

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

This type of check actually does not work. The point is not to limit the length of the string just because. The point is to not overflow the allocated buffer. You need to compute the length before using strcat, for strings which are too long, the behavior is undefined (see strcat doc).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same usage of variable available_space for calculating the buffer availability

display/d.mon/list.c Outdated Show resolved Hide resolved
display/d.mon/list.c Outdated Show resolved Hide resolved
ShubhamDesai and others added 4 commits September 5, 2024 20:45
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Copy link
Contributor

@nilason nilason left a comment

Choose a reason for hiding this comment

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

I have planned to create a new G_strlcat() (local wrapper/implementation of strlcat(), to accompany G_strlcpy()), but have not got the time for that yet.
That would make this fix much less complicated. Please hold on for that (or implement for the time being with posix strlcat() if possible).

@nilason nilason added this to the 8.5.0 milestone Sep 11, 2024
@nilason
Copy link
Contributor

nilason commented Sep 11, 2024

I have planned to create a new G_strlcat() (local wrapper/implementation of strlcat(), to accompany G_strlcpy())

Addressed by #4304.

@ShubhamDesai
Copy link
Contributor Author

I have planned to create a new G_strlcat() (local wrapper/implementation of strlcat(), to accompany G_strlcpy())

Addressed by #4304.

Thanks. I will use it

@nilason
Copy link
Contributor

nilason commented Sep 16, 2024

G_strlcat is now in place.

@ShubhamDesai
Copy link
Contributor Author

G_strlcat is now in place.

Done.

@nilason
Copy link
Contributor

nilason commented Sep 17, 2024

G_temp_element() + "/" + "MONITORS" + "/" is guaranteed to fit into a buffer of size GPATH_MAX, so you can (void) the return value of the three first G_strlcat (in both get_path and list_files). The name variable is coming from user, so this should be checked (and G_fatal_error if truncated).
I don't see the need for the change of main.c.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C Related code is in C display module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants