Use strlc{at,py} for paranoia's sake and exit on overflow. In all

cases the strings were either pre-allocated to the correct size of
length checks were done before the copy but a little paranoia can
go a long way.
This commit is contained in:
Todd C. Miller
2003-03-13 20:00:45 +00:00
parent a54c8e66fa
commit eebc763bd3
7 changed files with 72 additions and 44 deletions

36
check.c
View File

@@ -174,9 +174,9 @@ expand_prompt(old_prompt, user, host)
char *user; char *user;
char *host; char *host;
{ {
size_t len; size_t len, n;
int subst; int subst;
char *p, *np, *new_prompt; char *p, *np, *new_prompt, *endp;
/* How much space do we need to malloc for the prompt? */ /* How much space do we need to malloc for the prompt? */
subst = 0; subst = 0;
@@ -215,29 +215,35 @@ expand_prompt(old_prompt, user, host)
} }
if (subst) { if (subst) {
new_prompt = (char *) emalloc(len + 1); new_prompt = (char *) emalloc(++len);
*new_prompt = '\0';
endp = new_prompt + len - 1;
for (p = old_prompt, np = new_prompt; *p; p++) { for (p = old_prompt, np = new_prompt; *p; p++) {
if (p[0] =='%') { if (p[0] =='%') {
switch (p[1]) { switch (p[1]) {
case 'h': case 'h':
p++; p++;
strcpy(np, user_shost); if ((n = strlcat(new_prompt, user_shost, len)) >= len)
np += strlen(user_shost); goto oflow;
np += n;
continue; continue;
case 'H': case 'H':
p++; p++;
strcpy(np, user_host); if ((n = strlcat(new_prompt, user_host, len)) >= len)
np += strlen(user_host); goto oflow;
np += n;
continue; continue;
case 'u': case 'u':
p++; p++;
strcpy(np, user_name); if ((n = strlcat(new_prompt, user_name, len)) >= len)
np += strlen(user_name); goto oflow;
np += n;
continue; continue;
case 'U': case 'U':
p++; p++;
strcpy(np, *user_runas); if ((n = strlcat(new_prompt, *user_runas, len)) >= len)
np += strlen(*user_runas); goto oflow;
np += n;
continue; continue;
case '%': case '%':
/* convert %% -> % */ /* convert %% -> % */
@@ -248,6 +254,8 @@ expand_prompt(old_prompt, user, host)
break; break;
} }
} }
if (np >= endp)
goto oflow;
*np++ = *p; *np++ = *p;
} }
*np = '\0'; *np = '\0';
@@ -255,6 +263,12 @@ expand_prompt(old_prompt, user, host)
new_prompt = old_prompt; new_prompt = old_prompt;
return(new_prompt); return(new_prompt);
oflow:
/* We pre-allocate enough space, so this should never happen. */
(void) fprintf(stderr, "%s: internal error, expand_prompt() overflow\n",
Argv[0]);
exit(1);
} }
/* /*

22
env.c
View File

@@ -213,16 +213,20 @@ format_env(var, val)
char *var; char *var;
char *val; char *val;
{ {
char *estring, *p; char *estring;
size_t varlen, vallen; size_t esize;
varlen = strlen(var); esize = strlen(var) + 1 + strlen(val) + 1;
vallen = strlen(val); estring = (char *) emalloc(esize);
p = estring = (char *) emalloc(varlen + vallen + 2);
strcpy(p, var); /* We pre-allocate enough space, so this should never overflow. */
p += varlen; if (strlcpy(estring, var, esize) >= esize ||
*p++ = '='; strlcat(estring, "=", esize) >= esize ||
strcpy(p, val); strlcat(estring, val, esize) >= esize) {
(void) fprintf(stderr, "%s: internal error, format_env() overflow\n",
Argv[0]);
exit(1);
}
return(estring); return(estring);
} }

View File

@@ -82,6 +82,7 @@ find_path(infile, outfile, path)
char *origpath; /* so we can free path later */ char *origpath; /* so we can free path later */
char *result = NULL; /* result of path/file lookup */ char *result = NULL; /* result of path/file lookup */
int checkdot = 0; /* check current dir? */ int checkdot = 0; /* check current dir? */
int len; /* length parameter */
if (strlen(infile) >= MAXPATHLEN) { if (strlen(infile) >= MAXPATHLEN) {
(void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile); (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
@@ -93,7 +94,7 @@ find_path(infile, outfile, path)
* there is no need to look at $PATH. * there is no need to look at $PATH.
*/ */
if (strchr(infile, '/')) { if (strchr(infile, '/')) {
(void) strcpy(command, infile); strlcpy(command, infile, sizeof(command)); /* paranoia */
if (sudo_goodpath(command)) { if (sudo_goodpath(command)) {
*outfile = command; *outfile = command;
return(FOUND); return(FOUND);
@@ -128,11 +129,11 @@ find_path(infile, outfile, path)
/* /*
* Resolve the path and exit the loop if found. * Resolve the path and exit the loop if found.
*/ */
if (strlen(path) + strlen(infile) + 1 >= MAXPATHLEN) { len = snprintf(command, sizeof(command), "%s/%s", path, infile);
if (len <= 0 || len >= sizeof(command)) {
(void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile); (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
exit(1); exit(1);
} }
(void) sprintf(command, "%s/%s", path, infile);
if ((result = sudo_goodpath(command))) if ((result = sudo_goodpath(command)))
break; break;

View File

@@ -343,10 +343,9 @@ command_matches(cmnd, cmnd_args, path, sudoers_args)
while ((dent = readdir(dirp)) != NULL) { while ((dent = readdir(dirp)) != NULL) {
/* ignore paths > MAXPATHLEN (XXX - log) */ /* ignore paths > MAXPATHLEN (XXX - log) */
if (plen + NAMLEN(dent) >= sizeof(buf)) if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf) ||
strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf))
continue; continue;
strcpy(buf, path);
strcat(buf, dent->d_name);
/* only stat if basenames are the same */ /* only stat if basenames are the same */
if (strcmp(cmnd_base, dent->d_name) != 0 || stat(buf, &pst) == -1) if (strcmp(cmnd_base, dent->d_name) != 0 || stat(buf, &pst) == -1)

View File

@@ -1109,6 +1109,7 @@ append(src, dstp, dst_len, dst_size, separator)
/* Assumes dst will be NULL if not set. */ /* Assumes dst will be NULL if not set. */
if (dst == NULL) { if (dst == NULL) {
dst = (char *) emalloc(BUFSIZ); dst = (char *) emalloc(BUFSIZ);
*dst = '\0';
*dst_size = BUFSIZ; *dst_size = BUFSIZ;
*dst_len = 0; *dst_len = 0;
*dstp = dst; *dstp = dst;
@@ -1124,12 +1125,10 @@ append(src, dstp, dst_len, dst_size, separator)
} }
/* Copy src -> dst adding a separator if appropriate and adjust len. */ /* Copy src -> dst adding a separator if appropriate and adjust len. */
dst += *dst_len;
*dst_len += src_len;
*dst = '\0';
if (separator) if (separator)
(void) strcat(dst, separator); (void) strlcat(dst, separator, *dst_size);
(void) strcat(dst, src); (void) strlcat(dst, src, *dst_size);
*dst_len += src_len;
} }
/* /*

19
sudo.c
View File

@@ -480,7 +480,7 @@ init_vars(sudo_mode)
/* Default value for cmnd and cwd, overridden later. */ /* Default value for cmnd and cwd, overridden later. */
if (user_cmnd == NULL) if (user_cmnd == NULL)
user_cmnd = NewArgv[0]; user_cmnd = NewArgv[0];
(void) strcpy(user_cwd, "unknown"); (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
/* /*
* We avoid gethostbyname() if possible since we don't want * We avoid gethostbyname() if possible since we don't want
@@ -556,7 +556,7 @@ init_vars(sudo_mode)
if (!getcwd(user_cwd, sizeof(user_cwd))) { if (!getcwd(user_cwd, sizeof(user_cwd))) {
(void) fprintf(stderr, "%s: Can't get working directory!\n", (void) fprintf(stderr, "%s: Can't get working directory!\n",
Argv[0]); Argv[0]);
(void) strcpy(user_cwd, "unknown"); (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
} }
} else } else
set_perms(PERM_ROOT); set_perms(PERM_ROOT);
@@ -598,7 +598,7 @@ init_vars(sudo_mode)
/* set user_args */ /* set user_args */
if (NewArgc > 1) { if (NewArgc > 1) {
char *to, **from; char *to, **from;
size_t size; size_t size, n;
/* If MODE_SHELL not set then NewArgv is contiguous so just count */ /* If MODE_SHELL not set then NewArgv is contiguous so just count */
if (!(sudo_mode & MODE_SHELL)) { if (!(sudo_mode & MODE_SHELL)) {
@@ -610,10 +610,15 @@ init_vars(sudo_mode)
} }
/* alloc and copy. */ /* alloc and copy. */
to = user_args = (char *) emalloc(size); user_args = (char *) emalloc(size);
for (from = NewArgv + 1; *from; from++) { for (to = user_args, from = NewArgv + 1; *from; from++) {
(void) strcpy(to, *from); n = strlcpy(to, *from, size - (to - user_args));
to += strlen(*from); if (n >= size) {
(void) fprintf(stderr,
"%s: internal error, init_vars() overflow\n", Argv[0]);
exit(1);
}
to += n;
*to++ = ' '; *to++ = ' ';
} }
*--to = '\0'; *--to = '\0';

View File

@@ -377,17 +377,23 @@ main(argc, argv)
/* Fill in cmnd_args from NewArgv. */ /* Fill in cmnd_args from NewArgv. */
if (NewArgc > 1) { if (NewArgc > 1) {
size_t size;
char *to, **from; char *to, **from;
size_t size, n;
size = (size_t) NewArgv[NewArgc-1] + strlen(NewArgv[NewArgc-1]) - size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
(size_t) NewArgv[1] + 1; strlen(NewArgv[NewArgc-1]) + 1;
user_args = (char *) emalloc(size); user_args = (char *) emalloc(size);
for (to = user_args, from = &NewArgv[1]; *from; from++) { for (to = user_args, from = NewArgv + 1; *from; from++) {
n = strlcpy(to, *from, size - (to - user_args));
if (n >= size) {
(void) fprintf(stderr,
"%s: internal error, init_vars() overflow\n", Argv[0]);
exit(1);
}
to += n;
*to++ = ' '; *to++ = ' ';
(void) strcpy(to, *from);
to += strlen(*from);
} }
*--to = '\0';
} }
/* Initialize default values. */ /* Initialize default values. */