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:
cinap_lenrek 2015-02-11 23:54:28 +01:00
parent 21570a4719
commit 8b57e59ea9
2 changed files with 43 additions and 34 deletions

View file

@ -4,33 +4,42 @@
char*
getenv(char *name)
{
int r, f;
long s;
char *ans;
char *p, *ep, ename[100];
enum { HUNK = 100, };
char *s, *p;
int f, r, n;
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;
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';
}
}
close(f);
return ans;
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);
}
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;
}

View file

@ -4,20 +4,20 @@
int
putenv(char *name, char *val)
{
int f;
char ename[100];
long s;
int f, n;
if(strchr(name, '/') != nil)
return -1;
snprint(ename, sizeof ename, "/env/%s", name);
if(strcmp(ename+5, name) != 0)
if(name[0]=='\0' || strcmp(name, ".")==0 || strcmp(name, "..")==0 || strchr(name, '/')!=nil
|| strlen(name) >= sizeof(ename)-5){
werrstr("bad env name: %s", name);
return -1;
}
snprint(ename, sizeof(ename), "/env/%s", name);
f = create(ename, OWRITE, 0664);
if(f < 0)
return -1;
s = strlen(val);
if(write(f, val, s) != s){
n = strlen(val);
if(write(f, val, n) != n){
close(f);
return -1;
}