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:
36
check.c
36
check.c
@@ -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
22
env.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
5
parse.c
5
parse.c
@@ -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)
|
||||||
|
@@ -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
19
sudo.c
@@ -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';
|
||||||
|
@@ -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++) {
|
||||||
*to++ = ' ';
|
n = strlcpy(to, *from, size - (to - user_args));
|
||||||
(void) strcpy(to, *from);
|
if (n >= size) {
|
||||||
to += strlen(*from);
|
(void) fprintf(stderr,
|
||||||
|
"%s: internal error, init_vars() overflow\n", Argv[0]);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
to += n;
|
||||||
|
*to++ = ' ';
|
||||||
|
}
|
||||||
|
*--to = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize default values. */
|
/* Initialize default values. */
|
||||||
|
Reference in New Issue
Block a user