ref: ffa663fec1eec67cf8f81fe2882e7393076ff235
parent: eed6e68174a13a4b7c0b39acdcfa911a302f96c2
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Jan 21 00:01:34 EST 2022
fs: add auth support
--- a/TODO
+++ b/TODO
@@ -1,8 +1,4 @@
-*** must have before usable for testing ***
-- auth against authservers
-- implement special file modes: ORCLOSE, OEXCL, etc
-
-*** must have before full release ***
+*** major issues, need to fix ***
- live alloc log recompression
- Reserve blocks for deletion
- transient exec snapshots
@@ -11,7 +7,7 @@
- reduce io ops per update
- async page writeback: currently, every write to device is sync.
-*** nice to have, can get testing without ***
+*** nice to have, can go without ***
- add missing management commands in console
- performance optimization:
- bulk block frees
--- a/blk.c
+++ b/blk.c
@@ -135,7 +135,7 @@
{
int n;
- n = hint+ainc(&fs->roundrobin)/1024;
+ n = hint+ainc(&fs->roundrobin)/(64*1024);
return &fs->arenas[n%fs->narena];
}
@@ -865,7 +865,7 @@
lock(&fs->activelk);
allquiesced = 1;
fs->active[tid]++;
- for(i = 0; i < fs->nproc; i++){
+ for(i = 0; i < fs->nquiesce; i++){
/*
* Odd parity on quiescence implies
* that we're between the exit from
@@ -879,7 +879,7 @@
allquiesced = 0;
}
if(allquiesced)
- for(i = 0; i < fs->nproc; i++)
+ for(i = 0; i < fs->nquiesce; i++)
fs->lastactive[i] = fs->active[i];
unlock(&fs->activelk);
if(!allquiesced)
--- a/dat.h
+++ b/dat.h
@@ -40,7 +40,6 @@
Nsec = 1000*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 */
- Maxproc = 8, /* maximum number of worker procs */
/*
* Kpmax must be no more than 1/4 of pivspc, or
@@ -125,6 +124,11 @@
#define Ebadu "attach -- unknown user or failed authentication"
#define Erdonly "file system read only"
#define Elocked "open/create -- file is locked"
+#define Eauthp "authread -- auth protocol not finished"
+#define Eauthd "authread -- not enough data"
+#define Ephase "auth phase error"
+#define Enone "auth -- user 'none' requires no authentication"
+#define Enoauth "auth -- authentication disabled"
#define Ewstatb "wstat -- unknown bits in qid.type/mode"
#define Ewstatd "wstat -- attempt to change directory"
@@ -407,11 +411,11 @@
Chan *wrchan;
Chan *rdchan;
- int nproc;
+ int nquiesce;
Lock activelk;
- int active[Maxproc];
- int lastactive[Maxproc];
+ int active[32];
+ int lastactive[32];
Lock freelk;
Bfree *freep;
Bfree *freehd;
@@ -419,6 +423,7 @@
int fd;
long broken;
long rdonly;
+ int noauth;
/* root snapshot tree */
Tree snap;
@@ -522,7 +527,6 @@
Mount *next;
long ref;
vlong gen;
- int uid;
char *name;
Tree *root;
};
@@ -537,7 +541,8 @@
*/
Mount *mnt;
Scan *scan; /* in progres scan */
- Dent *dent; /* (pqid, name) ref, modified on rename */
+ Dent *dent; /* (pqid, name) ref, modified on rename */
+ void *auth;
u32int fid;
vlong qpath;
@@ -546,6 +551,7 @@
int mode;
int iounit;
+ int uid;
int duid;
int dgid;
int dmode;
--- a/dump.c
+++ b/dump.c
@@ -20,6 +20,8 @@
* ptr: off[8] hash[8] -- a key for an Dir block.
* dir: fixed statbuf header, user ids
*/
+ if(k->nk == 0)
+ return fmtprint(fmt, "\"\"");
switch(k->k[0]){
case Kdat: /* qid[8] off[8] => ptr[16]: pointer to data page */
n = fmtprint(fmt, "dat qid:%llx off:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
--- a/fs.c
+++ b/fs.c
@@ -1,5 +1,6 @@
#include <u.h>
#include <libc.h>
+#include <auth.h>
#include <fcall.h>
#include <avl.h>
#include <bio.h>
@@ -165,8 +166,10 @@
r->tag = m->tag;
dprint("→ %F\n", r);
- if((n = convS2M(r, buf, sizeof(buf))) == 0)
+ if((n = convS2M(r, buf, sizeof(buf))) == 0){
+ fprint(2, "wut: %r\n");
abort();
+ }
w = write(m->fd, buf, n);
if(w != n)
fshangup(m->fd, Eio);
@@ -339,11 +342,10 @@
de->ref = 1;
de->qid = d->qid;
de->length = d->length;
- de->k = de->buf;
- de->nk = 9 + strlen(d->name) + 1;
if((e = packdkey(de->buf, sizeof(de->buf), pqid, d->name)) == nil)
return nil;
+ de->k = de->buf;
de->nk = e - de->buf;
de->next = fs->dtab[h];
fs->dtab[h] = de;
@@ -529,13 +531,83 @@
respond(m, &r);
}
+void
+authfree(AuthRpc *auth)
+{
+ AuthRpc *rpc;
+
+ if(rpc = auth){
+ close(rpc->afd);
+ auth_freerpc(rpc);
+ }
+}
+
+AuthRpc*
+authnew(void)
+{
+ static char *keyspec = "proto=p9any role=server";
+ AuthRpc *rpc;
+ int fd;
+
+ if(access("/mnt/factotum", 0) < 0)
+ if((fd = open("/srv/factotum", ORDWR)) >= 0)
+ mount(fd, -1, "/mnt", MBEFORE, "");
+ if((fd = open("/mnt/factotum/rpc", ORDWR)) < 0)
+ return nil;
+ if((rpc = auth_allocrpc(fd)) == nil){
+ close(fd);
+ return nil;
+ }
+ if(auth_rpc(rpc, "start", keyspec, strlen(keyspec)) != ARok){
+ authfree(rpc);
+ return nil;
+ }
+ return rpc;
+}
+
static void
-fsauth(Fmsg *m)
+fsauth(Fmsg *m, int iounit)
{
+ Dent *de;
Fcall r;
+ Fid f;
- r.type = Rerror;
- r.ename = "unimplemented auth";
+ if(fs->noauth){
+ rerror(m, Eauth);
+ return;
+ }
+ if((de = mallocz(sizeof(Dent), 1)) == nil){
+ rerror(m, Enomem);
+ return;
+ }
+ memset(de, 0, sizeof(Dent));
+ de->ref = 1;
+ de->qid.type = QTAUTH;
+ de->qid.path = inc64(&fs->nextqid, 1);
+ de->qid.vers = 0;
+ de->length = 0;
+ de->k = nil;
+ de->nk = 0;
+
+ memset(&f, 0, sizeof(Fid));
+ f.fid = NOFID;
+ f.mnt = nil;
+ f.qpath = de->qid.path;
+ f.pqpath = de->qid.path;
+ f.mode = -1;
+ f.iounit = iounit;
+ f.dent = de;
+ f.uid = -1;
+ f.duid = -1;
+ f.dgid = -1;
+ f.dmode = 0600;
+ f.auth = authnew();
+ if(dupfid(m->afid, &f) == nil){
+ rerror(m, Enomem);
+ return;
+ }
+ r.type = Rauth;
+ r.aqid = de->qid;
respond(m, &r);
}
@@ -575,14 +647,14 @@
}
static int
-fsaccess(Mount *mnt, int fmode, int fuid, int fgid, int m)
+fsaccess(Fid *f, int fmode, int fuid, int fgid, int m)
{
/* uid none gets only other permissions */
- if(mnt->uid != 0) {
- if(mnt->uid == fuid)
+ if(f->uid != 0) {
+ if(f->uid == fuid)
if((m & (fmode>>6)) == m)
return 0;
- if(ingroup(mnt->uid, fgid))
+ if(ingroup(f->uid, fgid))
if((m & (fmode>>3)) == m)
return 0;
}
@@ -589,7 +661,7 @@
if(m & fmode) {
if((fmode & DMDIR) && (m == DMEXEC))
return 0;
- if(!ingroup(mnt->uid, 9999))
+ if(!ingroup(f->uid, 9999))
return 0;
}
return -1;
@@ -617,12 +689,11 @@
return;
}
rlock(&fs->userlk);
- if((u = name2user("glenda")) == nil){
+ if((u = name2user(m->uname)) == nil){
rerror(m, Enouser);
runlock(&fs->userlk);
return;
}
- mnt->uid = u->id;
runlock(&fs->userlk);
if((mnt->root = openlabel(m->aname)) == nil){
@@ -665,7 +736,8 @@
f.mode = -1;
f.iounit = iounit;
f.dent = de;
- f.duid = mnt->uid;
+ f.uid = u->id;
+ f.duid = u->id;
f.dgid = d.gid;
f.dmode = d.mode;
if(dupfid(m->fid, &f) == nil){
@@ -859,7 +931,7 @@
rerror(m, Edir);
goto Out;
}
- if(fsaccess(f->mnt, de->mode, de->uid, de->gid, DMWRITE) == -1){
+ if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1){
rerror(m, Eperm);
goto Out;
}
@@ -941,8 +1013,8 @@
sync = 0;
}
op |= Owmuid;
- de->muid = f->mnt->uid;
- PBIT32(p, f->mnt->uid);
+ de->muid = f->uid;
+ PBIT32(p, f->uid);
p += 4;
opbuf[0] = op;
@@ -1018,7 +1090,7 @@
}
de = f->dent;
rlock(de);
- if(fsaccess(f->mnt, de->mode, de->uid, de->gid, DMWRITE) == -1){
+ if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1){
rerror(m, Eperm);
runlock(de);
return;
@@ -1042,9 +1114,9 @@
d.atime = nsec();
d.mtime = d.atime;
d.length = 0;
- d.uid = f->mnt->uid;
+ d.uid = f->uid;
d.gid = f->dgid;
- d.muid = f->mnt->uid;
+ d.muid = f->uid;
mb[nm].op = Oinsert;
if(dir2kv(f->qpath, &d, &mb[nm], buf, sizeof(buf)) == -1){
@@ -1162,7 +1234,7 @@
clunkfid(f);
return;
}
- if(fsaccess(f->mnt, f->dmode, f->duid, f->dgid, OWRITE) == -1){
+ if(fsaccess(f, f->dmode, f->duid, f->dgid, OWRITE) == -1){
rerror(m, Eperm);
runlock(f->dent);
return;
@@ -1218,7 +1290,7 @@
putfid(f);
return;
}
- if(fsaccess(f->mnt, d.mode, d.uid, d.gid, mbits) == -1){
+ if(fsaccess(f, d.mode, d.uid, d.gid, mbits) == -1){
rerror(m, Eperm);
putfid(f);
return;
@@ -1246,7 +1318,7 @@
// }
if(m->mode & OTRUNC){
wlock(f->dent);
- f->dent->muid = f->mnt->uid;
+ f->dent->muid = f->uid;
f->dent->qid.vers++;
f->dent->length = 0;
@@ -1254,7 +1326,7 @@
p = buf;
p[0] = Owsize|Owmuid; p += 1;
PBIT64(p, 0); p += 8;
- PBIT32(p, f->mnt->uid); p += 4;
+ PBIT32(p, f->uid); p += 4;
mb.k = f->dent->k;
mb.nk = f->dent->nk;
mb.v = buf;
@@ -1273,8 +1345,44 @@
}
static char*
-fsreaddir(Fmsg *m, Fid *f, Fcall *r)
+readauth(Fmsg *m, Fid *f, Fcall *r)
{
+ AuthInfo *ai;
+ AuthRpc *rpc;
+ User *u;
+
+ if((rpc = f->auth) == nil)
+ return Etype;
+
+ switch(auth_rpc(rpc, "read", nil, 0)){
+ default:
+ return Eauthp;
+ case ARdone:
+ if((ai = auth_getinfo(rpc)) == nil)
+ goto Phase;
+ u = name2user(ai->cuid);
+ auth_freeAI(ai);
+ if(u == nil)
+ return Enouser;
+ f->uid = u->id;
+ return nil;
+ case ARok:
+ if(m->count < rpc->narg)
+ return Eauthd;
+ if((r->data = malloc(rpc->narg)) == nil)
+ return Emem;
+ memmove(r->data, rpc->arg, rpc->narg);
+ r->count = rpc->narg;
+ return nil;
+ case ARphase:
+ Phase:
+ return Ephase;
+ }
+}
+
+static char*
+readdir(Fmsg *m, Fid *f, Fcall *r)
+{
char pfx[Dpfxsz], *p, *e;
int n, ns, done;
Scan *s;
@@ -1331,7 +1439,7 @@
}
static char*
-fsreadfile(Fmsg *m, Fid *f, Fcall *r)
+readfile(Fmsg *m, Fid *f, Fcall *r)
{
vlong n, c, o;
char *p;
@@ -1384,10 +1492,12 @@
putfid(f);
return;
}
- if(f->dent->qid.type & QTDIR)
- e = fsreaddir(m, f, &r);
+ if(f->dent->qid.type & QTAUTH)
+ e = readauth(m, f, &r);
+ else if(f->dent->qid.type & QTDIR)
+ e = readdir(m, f, &r);
else
- e = fsreadfile(m, f, &r);
+ e = readfile(m, f, &r);
if(e != nil)
rerror(m, e);
else
@@ -1396,7 +1506,22 @@
putfid(f);
}
+static char*
+writeauth(Fmsg *m, Fid *f, Fcall *r)
+{
+ AuthRpc *rpc;
+ if((rpc = f->auth) == nil)
+ return Etype;
+ if(auth_rpc(rpc, "write", m->data, m->count) != ARok)
+ return Ebotch;
+ r->type = Rwrite;
+ r->count = m->count;
+ return nil;
+
+}
+
+
static void
fswrite(Fmsg *m)
{
@@ -1418,6 +1543,15 @@
putfid(f);
return;
}
+ if(f->dent->qid.type == QTAUTH){
+ e = writeauth(m, f, &r);
+ if(e != nil)
+ rerror(m, e);
+ else
+ respond(m, &r);
+ putfid(f);
+ return;
+ }
wlock(f->dent);
p = m->data;
@@ -1457,7 +1591,7 @@
f->dent->length = m->offset+m->count;
}
sbuf[0] |= Owmuid;
- PBIT32(p, f->mnt->uid);
+ PBIT32(p, f->uid);
p += 4;
kv[i].v = sbuf;
@@ -1506,7 +1640,7 @@
switch(m->type){
/* sync setup */
case Tversion: fsversion(m, &msgmax); break;
- case Tauth: fsauth(m); break;
+ case Tauth: fsauth(m, msgmax); break;
case Tclunk: fsclunk(m); break;
case Tattach: fsattach(m, msgmax); break;
--- a/main.c
+++ b/main.c
@@ -11,6 +11,8 @@
int ream;
int debug;
+int noauth;
+int nproc;
char *srvname = "gefs";
vlong
@@ -32,6 +34,7 @@
if((fs = mallocz(sizeof(Gefs), 1)) == nil)
sysfatal("malloc: %r");
+ fs->noauth = noauth;
fs->cmax = cachesz/Blksz;
if(fs->cmax >= (2ULL*GiB)/sizeof(Bucket))
sysfatal("cache too big");
@@ -44,7 +47,7 @@
{
int pid;
-
+ assert(wid == -1 || wid < nelem(fs->active));
pid = rfork(RFPROC|RFMEM|RFNOWAIT);
if (pid < 0)
sysfatal("can't fork: %r");
@@ -83,8 +86,9 @@
void
main(int argc, char **argv)
{
- int srvfd, ctlfd;
+ int i, srvfd, ctlfd;
vlong cachesz;
+ char *s;
cachesz = 16*MiB;
ARGBEGIN{
@@ -100,6 +104,9 @@
case 's':
srvname = EARGF(usage());
break;
+ case 'A':
+ noauth = 1;
+ break;
default:
usage();
break;
@@ -125,6 +132,11 @@
fmtinstall('R', Rconv);
fmtinstall('F', fcallfmt);
fmtinstall('Q', Qconv);
+
+ if((s = getenv("NPROC")) != nil)
+ nproc = atoi(s);
+ if(nproc == 0)
+ nproc = 2;
if(ream){
reamfs(argv[0]);
exits(nil);
@@ -134,13 +146,13 @@
srvfd = postfd(srvname, "");
ctlfd = postfd(srvname, ".cmd");
loadfs(argv[0]);
- launch(runcons, fs->nproc++, (void*)ctlfd, "ctl");
- launch(runwrite, fs->nproc++, nil, "writeio");
- launch(runread, fs->nproc++, nil, "readio");
- launch(runtasks, fs->nproc++, nil, "tasks");
-// launch(runfs, fs->nproc++, (void*)srvfd, "fs");
- assert(fs->nproc < Maxproc);
- runfs(fs->nproc++, (void*)srvfd);
+ launch(runtasks, -1, nil, "tasks");
+ launch(runcons, fs->nquiesce++, (void*)ctlfd, "ctl");
+ launch(runwrite, fs->nquiesce++, nil, "writeio");
+ for(i = 0; i < nproc; i++)
+ launch(runread, fs->nquiesce++, nil, "readio");
+ if(srvfd != -1)
+ launch(runfs, -1, (void*)srvfd, "srvio");
exits(nil);
}
}
--- a/ream.c
+++ b/ream.c
@@ -167,7 +167,7 @@
asz = sz/fs->narena;
asz = asz - (asz % Blksz) - Blksz;
- if(asz < 512*MiB)
+ if(asz < 128*MiB)
sysfatal("disk too small");
fs->arenasz = asz;
off = 0;