sshfs: fix -r / retulting in "//foo" paths, memory leaks, use estrdup9p()

just use cleanname() to implement pathcat(), which
handles double slashes and ".." elements already.

have to free the partial dir structue on error in
parsedir().

use estrdup9p() instead of strdup().
This commit is contained in:
cinap_lenrek 2017-04-30 18:28:06 +02:00
parent 607e651c06
commit c00c60d327

View file

@ -172,7 +172,7 @@ idlookup(IDEnt **tab, int id)
for(p = tab[(ulong)id % HASH]; p != nil; p = p->next)
if(p->id == id)
return strdup(p->name);
return estrdup9p(p->name);
return smprint("%d", id);
}
@ -367,19 +367,22 @@ recvpkt(void)
return rxpkt[0];
}
void
freedir1(Dir *d)
{
free(d->name);
free(d->uid);
free(d->gid);
free(d->muid);
}
void
freedir(SFid *s)
{
int i;
Dir *d;
for(i = 0; i < s->ndirent; i++){
d = &s->dirent[i];
free(d->name);
free(d->uid);
free(d->gid);
free(d->muid);
}
for(i = 0; i < s->ndirent; i++)
freedir1(&s->dirent[i]);
free(s->dirent);
s->dirent = nil;
s->ndirent = 0;
@ -436,23 +439,13 @@ submitreq(Req *r)
char *
pathcat(char *p, char *c)
{
if(strcmp(p, ".") == 0)
return strdup(c);
return smprint("%s/%s", p, c);
return cleanname(smprint("%s/%s", p, c));
}
char *
parentdir(char *p)
{
char *q, *r;
if(strcmp(p, ".") == 0) return strdup(".");
if(strcmp(p, "/") == 0) return strdup("/");
q = strdup(p);
r = strrchr(q, '/');
if(r != nil) *r = 0;
else strcpy(q, ".");
return q;
return pathcat(p, "..");
}
char *
@ -461,8 +454,8 @@ finalelem(char *p)
char *q;
q = strrchr(p, '/');
if(q == nil) return strdup(p);
return strdup(q+1);
if(q == nil) return estrdup9p(p);
return estrdup9p(q+1);
}
u64int
@ -524,10 +517,10 @@ attrib2dir(uchar *p0, uchar *ep, Dir *d)
d->uid = idlookup(uidtab, uid);
d->gid = idlookup(gidtab, gid);
}else{
d->uid = strdup("sshfs");
d->gid = strdup("sshfs");
d->uid = estrdup9p("sshfs");
d->gid = estrdup9p("sshfs");
}
d->muid = strdup(d->uid);
d->muid = estrdup9p(d->uid);
if((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0){
rc = unpack(p, ep - p, "u", &perm); if(rc < 0) return -1; p += rc;
d->mode = perm & 0777;
@ -632,17 +625,16 @@ parsedir(SFid *sf)
p = rxpkt + 9;
ep = rxpkt + rxlen;
for(i = 0; i < c; i++){
rc = unpack(p, ep - p, "ss", &fn, &fns, &ln, &lns); if(rc < 0) goto err; p += rc;
memset(d, 0, sizeof(Dir));
rc = unpack(p, ep - p, "ss", &fn, &fns, &ln, &lns); if(rc < 0) goto err; p += rc;
rc = attrib2dir(p, ep, d); if(rc < 0) goto err; p += rc;
if(fn[0] == '.' && (fns == 1 || fns == 2 && fn[1] == '.')){
free(d->uid);
free(d->gid);
free(d->muid);
freedir1(d);
continue;
}
d->name = emalloc9p(fns + 1);
memcpy(d->name, fn, fns);
d->name[fns] = 0;
s = pathcat(sf->fn, d->name);
d->qid.path = qidcalc(s);
free(s);
@ -652,6 +644,7 @@ parsedir(SFid *sf)
wunlock(sf);
return 0;
err:
freedir1(d);
wunlock(sf);
return -1;
}
@ -731,9 +724,9 @@ sshfsattach(Req *r)
}
sf = emalloc9p(sizeof(SFid));
if(r->ifcall.aname != nil && *r->ifcall.aname != 0)
sf->fn = strdup(r->ifcall.aname);
sf->fn = estrdup9p(r->ifcall.aname);
else
sf->fn = strdup(root);
sf->fn = estrdup9p(root);
root = ".";
sf->qid = (Qid){qidcalc(sf->fn), 0, QTDIR};
r->ofcall.qid = sf->qid;
@ -855,8 +848,8 @@ sendproc(void *)
}else if(r->req->aux == (void*)-2){
sendpkt("bus", SSH_FXP_OPENDIR, r->reqid, sf->fn, strlen(sf->fn));
}else{
sendpkt("bus", SSH_FXP_READDIR, r->reqid, sf->hand, sf->handn);
sf->dirreads++;
sendpkt("bus", SSH_FXP_READDIR, r->reqid, sf->hand, sf->handn);
}
wunlock(sf);
}else{
@ -892,9 +885,9 @@ sendproc(void *)
rlock(sf);
s = parentdir(sf->fn);
t = pathcat(s, r->req->d.name);
sendpkt("buss", SSH_FXP_RENAME, r->reqid, sf->fn, strlen(sf->fn), t, strlen(t));
free(s);
r->req->aux = t;
sendpkt("buss", SSH_FXP_RENAME, r->reqid, sf->fn, strlen(sf->fn), t, strlen(t));
runlock(sf);
break;
}
@ -1137,7 +1130,7 @@ sshfswalk(Req *r)
r->newfid->qid = r->fid->qid;
s = r->fid->aux;
t = emalloc9p(sizeof(SFid));
t->fn = strdup(s->fn);
t->fn = estrdup9p(s->fn);
t->qid = s->qid;
r->newfid->aux = t;
}else
@ -1146,12 +1139,9 @@ sshfswalk(Req *r)
respond(r, nil);
return;
}
p = strdup(t->fn);
p = estrdup9p(t->fn);
for(i = 0; i < r->ifcall.nwname; i++){
if(strcmp(r->ifcall.wname[i], "..") == 0)
q = parentdir(p);
else
q = pathcat(p, r->ifcall.wname[i]);
q = pathcat(p, r->ifcall.wname[i]);
free(p);
p = q;
r->ofcall.wqid[i] = (Qid){qidcalc(p), 0, QTDIR};
@ -1271,7 +1261,7 @@ passwdparse(IDEnt **tab, char *s)
if(p == nil) break;
p++;
e = emalloc9p(sizeof(IDEnt));
e->name = strdup(n);
e->name = estrdup9p(n);
e->id = id;
b = &tab[((ulong)e->id) % HASH];
e->next = *b;