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

Fix coverity unbounded source buffer issues #989

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

MarcinDigitic
Copy link

During coverity scan, there is reported an issue
with unbounded source buffer for each usage of input arg directly with syslog function.
This commit is to limit the names of users and groups passed as input args to a fixed value of 256.
The max length 256 is a typical POSIX login name length. This should improve also security.

During coverity scan, there is reported an issue
with unbounded source buffer for each usage of input arg
directly with syslog function.
This commit is to limit the names of users and groups
passed as input args to a fixed value of 256.
The max length 256 is a typical POSIX login name length.
This should improve also security.

char *
xstrndup(const char *s, size_t max_length) {
size_t length = strlen(s);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think strndup(3) is not allowed to read more than n bytes in the source string.

Comment on lines +89 to +90
strncpy(p, s, length);
p[length] = '\0';
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is an antipattern that I've blown away from this project. Please have a look at the functions in lib/string/ to find something suitable.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can check that there are no direct calls to strncpy(3) at all:

$ grep -rn '\<strncpy *(' lib* src/
lib/string/strncpy.h:18:#define STRNCPY(dst, src)  strncpy(dst, src, NITEMS(dst))

And that macro is only used for other very specific purposes:

$ grep -rn 'STRNCPY *(' lib* src/
lib/utmp.c:279:	STRNCPY(utent->ut_line, line);
lib/utmp.c:281:		STRNCPY(utent->ut_id, ut->ut_id);
lib/utmp.c:284:		STRNCPY(utent->ut_id, line + 3);
lib/utmp.c:287:	STRNCPY(utent->ut_name, name);
lib/utmp.c:289:	STRNCPY(utent->ut_user, name);
lib/utmp.c:293:		STRNCPY(utent->ut_host, hostname);
lib/string/strncpy.h:18:#define STRNCPY(dst, src)  strncpy(dst, src, NITEMS(dst))
lib/log.c:86:	STRNCPY(newlog.ll_host, host);

user = argv[optind];
user = xstrndup(argv[optind], USER_ENTRY_MAX_LENGTH);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't you free(3) the memory?

* to syslog function.
* Typical POSIX login name max length is 256.
*/
#define USER_ENTRY_MAX_LENGTH 256
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is LOGIN_NAME_MAX, defined by POSIX in <limits.h>.

However, we support unlimited user-name lengths. See this commit:

commit 6a1f45d932c859725bc175f96f7c42b9ccc20ea4
Author: Tobias Stoeckmann <[email protected]>
Date:   Sat Feb 3 01:10:22 2024 +0100

    lib/chkname.c: Support unlimited user name lengths
    
    If the system does not have a user name length limit, support it
    accordingly. If the system has no _SC_LOGIN_NAME_MAX, use
    LOGIN_NAME_MAX constant instead.
    
    Signed-off-by: Tobias Stoeckmann <[email protected]>

You should probably use a run-time-variable user-name length.

You'll need to write this function (extracted from the current code in is_valid_user_name() from <lib/chkname.c>):

size_t
username_maxlen(void)
{
	long  maxlen;

	errno = 0;
	maxlen = sysconf(_SC_LOGIN_NAME_MAX);
	if (maxlen == -1 && errno != 0)
		return LOGIN_NAME_MAX;

	return maxlen;
}

and use it in your cases.

Copy link
Collaborator

Choose a reason for hiding this comment

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

BTW, now I remember we use the term size, not len, since it includes the NUL byte.

Comment on lines +77 to +86
size_t length = strlen(s);
if (length > max_length) {
length = max_length;
}

char *p = malloc(length + 1);
if (!p) {
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Isn't this simpler as the following?:

{
        char  *dup;

        dup = strndup(s, n);
        if (dup == NULL) { ... }

        return dup;
}

Or am I missing something?

length = max_length;
}

char *p = malloc(length + 1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't call malloc(3) directly. Have a look at <lib/alloc.h>, and the MALLOC() macro.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And you'll also want to check XMALLOC().

@alejandro-colomar
Copy link
Collaborator

alejandro-colomar commented May 10, 2024

During coverity scan, there is reported an issue with unbounded source buffer for each usage of input arg directly with syslog function.

Please paste such a Coverity scan report in the commit message. It would be helpful when reviewing.

alejandro-colomar added a commit to alejandro-colomar/shadow that referenced this pull request May 10, 2024
It encapsulates some logic that we may want to reuse elsewhere.

Link: <shadow-maint#989>
Signed-off-by: Alejandro Colomar <[email protected]>
alejandro-colomar added a commit to alejandro-colomar/shadow that referenced this pull request May 10, 2024
It encapsulates some logic that we may want to reuse elsewhere.

Link: <shadow-maint#989>
Signed-off-by: Alejandro Colomar <[email protected]>
alejandro-colomar added a commit to alejandro-colomar/shadow that referenced this pull request May 10, 2024
It encapsulates some logic that we may want to reuse elsewhere.

Link: <shadow-maint#989>
Signed-off-by: Alejandro Colomar <[email protected]>
@@ -498,7 +498,7 @@ int main (int argc, char **argv)
* name, or the name getlogin() returns.
*/
if (optind < argc) {
user = argv[optind];
user = xstrndup(argv[optind], USER_ENTRY_MAX_LENGTH);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why truncate it silently? If the input is invalid, we should just fail, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants