ref: b2cd4959fe3695d317b6b75956da55a7f77ed858
parent: b37238edb8f86809cdb395c235f9f2cc3f24d388
author: Ori Bernstein <ori@eigenstate.org>
date: Sat May 18 14:26:38 EDT 2024
gefs: check name lengths before packing them
--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -42,8 +42,9 @@
Ndtab = 1024, /* number of dir tab entries */
Max9p = 32*KiB, /* biggest message size we're willing to negotiate */
Nsec = 1000LL*1000*1000, /* nanoseconds to the second */
- Maxname = 256, /* maximum size of a name element */
- Maxent = 9+Maxname+1, /* maximum size of ent key, with terminator */
+ Maxent = 256, /* maximum size of ent key, with terminator */
+ Maxname = Maxent-1-9-1, /* maximum size of a name element */
+ Maxuname= 64, /* maximum length of a username */
Maxtag = 1<<16, /* maximum tag in 9p */
/*
@@ -51,7 +52,7 @@
* there is no way to get a valid split of a
* maximally filled tree.
*/
- Keymax = 128, /* key data limit */
+ Keymax = Maxent, /* key data limit */
Inlmax = 512, /* inline data limit */
Ptrsz = 24, /* off, hash, gen */
Pptrsz = 26, /* off, hash, gen, fill */
@@ -128,7 +129,8 @@
#define Zb (Bptr){-1, -1, -1}
/* internal errors */
-#define Efs (abort(), "fs broke")
+//#define Efs (abort(), "fs broke")
+extern char Efs[];
extern char Ecorrupt[];
extern char Efsvers[];
extern char Eimpl[];
--- a/sys/src/cmd/gefs/error.c
+++ b/sys/src/cmd/gefs/error.c
@@ -4,6 +4,7 @@
#include <fcall.h>
#include "dat.h"
+char Efs[] = "internal error";
char Ecorrupt[] = "block contents corrupted";
char Efsvers[] = "unknown fs version";
char Eimpl[] = "not implemented";
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -253,22 +253,22 @@
d->muid = -1;
}
-static int
+static char*
okname(char *name)
{
int i;
if(name[0] == 0)
- return -1;
+ return Ename;
if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
- return -1;
+ return Ename;
for(i = 0; i < Maxname; i++){
if(name[i] == 0)
- return 0;
+ return nil;
if((name[i]&0xff) < 0x20 || name[i] == '/')
- return -1;
+ return Ename;
}
- return -1;
+ return Elength;
}
Chan*
@@ -1230,9 +1230,11 @@
dmode = d.mode;
r.type = Rwalk;
for(i = 0; i < m->nwname; i++){
+ name = m->wname[i];
+ if(strlen(name) > Maxname)
+ error(Elength);
if(fsaccess(o, d.mode, d.uid, d.gid, DMEXEC) != 0)
error(Eperm);
- name = m->wname[i];
if(d.qid.path == Qdump){
if((mnt = getmount(m->wname[i])) == nil)
error(Esrch);
@@ -1345,7 +1347,7 @@
fswstat(Fmsg *m, int id, Amsg **ao)
{
char rnbuf[Kvmax], opbuf[Kvmax], upbuf[Upksz];
- char *p, strs[65535];
+ char *p, *e, strs[65535];
int op, nm, rename;
vlong oldlen;
Qid old;
@@ -1395,10 +1397,12 @@
error(Ewstatv);
}
if(*d.name != '\0'){
+ if(strlen(d.name) > Maxname)
+ error(Elength);
if(strcmp(d.name, de->name) != 0){
rename = 1;
- if(okname(d.name) == -1)
- error(Ename);
+ if((e = okname(d.name)) != nil)
+ error(e);
if(walk1(t, f->dent->up, d.name, &old, &oldlen) == 0)
error(Eexist);
n.name = d.name;
@@ -1452,6 +1456,8 @@
}
}
if(*d.uid != '\0'){
+ if(strlen(d.uid) > Maxuname)
+ error(Elength);
rlock(&fs->userlk);
u = name2user(d.uid);
if(u == nil){
@@ -1467,6 +1473,8 @@
}
}
if(*d.gid != '\0'){
+ if(strlen(d.gid) > Maxuname)
+ error(Elength);
rlock(&fs->userlk);
u = name2user(d.gid);
if(u == nil){
@@ -1573,7 +1581,7 @@
static void
fscreate(Fmsg *m)
{
- char *p, buf[Kvmax], upkbuf[Keymax], upvbuf[Inlmax];
+ char *p, *e, buf[Kvmax], upkbuf[Keymax], upvbuf[Inlmax];
Dent *de;
vlong oldlen;
Qid old;
@@ -1583,8 +1591,8 @@
Xdir d;
int nm;
- if(okname(m->name) == -1){
- rerror(m, Ename);
+ if((e = okname(m->name)) != nil){
+ rerror(m, e);
return;
}
if(m->perm & (DMMOUNT|DMAUTH)){
--- a/sys/src/cmd/gefs/pack.c
+++ b/sys/src/cmd/gefs/pack.c
@@ -12,8 +12,7 @@
{
int n;
- if (e - p < 3)
- error(Elength);
+ assert(e - p >= 3);
n = UNPACK16(p);
if(e - p < n + 3 || p[n+2] != 0)
broke(Efs);
@@ -28,8 +27,7 @@
int n;
n = strlen(s);
- if (e - p < n+3)
- error(Elength);
+ assert(e - p >= n+3);
PACK16(p, n); p += 2;
memmove(p, s, n); p += n;
*p = 0; p += 1;
--- a/sys/src/cmd/gefs/snap.c
+++ b/sys/src/cmd/gefs/snap.c
@@ -377,12 +377,12 @@
i = 0;
n = nil;
- if(waserror()){
- free(n);
- nexterror();
- }
if(flg & Lmut){
n = emalloc(sizeof(Tree), 1);
+ if(waserror()){
+ free(n);
+ nexterror();
+ }
n->memref = 1;
n->dirty = 0;
n->nlbl = 1;
@@ -405,6 +405,7 @@
m[i].op = Oinsert;
tree2kv(n, &m[i], buf[i], sizeof(buf[i]));
i++;
+ poperror();
}else{
t->nlbl++;
m[i].op = Orelink;
@@ -418,7 +419,6 @@
i++;
}
btupsert(&fs->snap, m, i);
- poperror();
free(n);
}