libc: check name in getvent()/putenv()
passing "", "." or ".." as name caused a crash in getenv() as it would open the directory; then seek() to determine the file size would fail and return -1. now checking for these special names and set error string when its bad. doing a single read() will not work when /env has a 9p fileserver mounted onto it and the file size is bigger than the i/o unit. so doing incremental reads until we get eof.
This commit is contained in:
parent
21570a4719
commit
8b57e59ea9
|
@ -4,33 +4,42 @@
|
||||||
char*
|
char*
|
||||||
getenv(char *name)
|
getenv(char *name)
|
||||||
{
|
{
|
||||||
int r, f;
|
enum { HUNK = 100, };
|
||||||
long s;
|
char *s, *p;
|
||||||
char *ans;
|
int f, r, n;
|
||||||
char *p, *ep, ename[100];
|
|
||||||
|
|
||||||
if(strchr(name, '/') != nil)
|
if(name[0]=='\0' || strcmp(name, ".")==0 || strcmp(name, "..")==0 || strchr(name, '/')!=nil
|
||||||
|
|| strlen(name) >= HUNK-5){
|
||||||
|
werrstr("bad env name: %s", name);
|
||||||
return nil;
|
return nil;
|
||||||
snprint(ename, sizeof ename, "/env/%s", name);
|
|
||||||
if(strcmp(ename+5, name) != 0)
|
|
||||||
return nil;
|
|
||||||
f = open(ename, OREAD);
|
|
||||||
if(f < 0)
|
|
||||||
return 0;
|
|
||||||
s = seek(f, 0, 2);
|
|
||||||
ans = malloc(s+1);
|
|
||||||
if(ans) {
|
|
||||||
setmalloctag(ans, getcallerpc(&name));
|
|
||||||
seek(f, 0, 0);
|
|
||||||
r = read(f, ans, s);
|
|
||||||
if(r >= 0) {
|
|
||||||
ep = ans + s - 1;
|
|
||||||
for(p = ans; p < ep; p++)
|
|
||||||
if(*p == '\0')
|
|
||||||
*p = ' ';
|
|
||||||
ans[s] = '\0';
|
|
||||||
}
|
}
|
||||||
|
if((s = malloc(HUNK)) == nil)
|
||||||
|
return nil;
|
||||||
|
snprint(s, HUNK, "/env/%s", name);
|
||||||
|
n = 0;
|
||||||
|
r = -1;
|
||||||
|
if((f = open(s, OREAD)) >= 0){
|
||||||
|
while((r = read(f, s+n, HUNK)) > 0){
|
||||||
|
n += r;
|
||||||
|
r = -1;
|
||||||
|
if((p = realloc(s, n+HUNK)) == nil)
|
||||||
|
break;
|
||||||
|
s = p;
|
||||||
}
|
}
|
||||||
close(f);
|
close(f);
|
||||||
return ans;
|
}
|
||||||
|
if(r < 0 || (p = realloc(s, n+1)) == nil){
|
||||||
|
free(s);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
s = p;
|
||||||
|
setmalloctag(s, getcallerpc(&name));
|
||||||
|
while(n > 0 && s[n-1] == '\0')
|
||||||
|
n--;
|
||||||
|
s[n] = '\0';
|
||||||
|
while(--n >= 0){
|
||||||
|
if(s[n] == '\0')
|
||||||
|
s[n] = ' ';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
int
|
int
|
||||||
putenv(char *name, char *val)
|
putenv(char *name, char *val)
|
||||||
{
|
{
|
||||||
int f;
|
|
||||||
char ename[100];
|
char ename[100];
|
||||||
long s;
|
int f, n;
|
||||||
|
|
||||||
if(strchr(name, '/') != nil)
|
if(name[0]=='\0' || strcmp(name, ".")==0 || strcmp(name, "..")==0 || strchr(name, '/')!=nil
|
||||||
return -1;
|
|| strlen(name) >= sizeof(ename)-5){
|
||||||
snprint(ename, sizeof ename, "/env/%s", name);
|
werrstr("bad env name: %s", name);
|
||||||
if(strcmp(ename+5, name) != 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
snprint(ename, sizeof(ename), "/env/%s", name);
|
||||||
f = create(ename, OWRITE, 0664);
|
f = create(ename, OWRITE, 0664);
|
||||||
if(f < 0)
|
if(f < 0)
|
||||||
return -1;
|
return -1;
|
||||||
s = strlen(val);
|
n = strlen(val);
|
||||||
if(write(f, val, s) != s){
|
if(write(f, val, n) != n){
|
||||||
close(f);
|
close(f);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue