summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/man/8/fs6
-rw-r--r--sys/src/cmd/cwfs/9p1.c62
-rw-r--r--sys/src/cmd/cwfs/9p2.c59
-rw-r--r--sys/src/cmd/cwfs/all.h6
-rw-r--r--sys/src/cmd/cwfs/con.c26
-rw-r--r--sys/src/cmd/cwfs/config.c3
-rw-r--r--sys/src/cmd/cwfs/portfns.h3
-rw-r--r--sys/src/cmd/cwfs/sub.c35
8 files changed, 101 insertions, 99 deletions
diff --git a/sys/man/8/fs b/sys/man/8/fs
index 7ec89abe7..e65d208cc 100644
--- a/sys/man/8/fs
+++ b/sys/man/8/fs
@@ -9,6 +9,7 @@ fs, exsort \- file server maintenance
]
.PP
.B allow
+.RI [ uid ]
.PP
.B arp
.I subcommand
@@ -158,7 +159,10 @@ incorrect or incomplete parameters.
.PP
.I Allow
disables permission checking and allows
-.BR wstat .
+.BR wstat
+for the specified
+.I uid
+or for any user if omited.
This may help in initializing a file system.
Use this with caution.
.PP
diff --git a/sys/src/cmd/cwfs/9p1.c b/sys/src/cmd/cwfs/9p1.c
index 3c9a0a190..827a541d7 100644
--- a/sys/src/cmd/cwfs/9p1.c
+++ b/sys/src/cmd/cwfs/9p1.c
@@ -57,7 +57,7 @@ f_session(Chan *cp, Fcall *in, Fcall *ou)
memmove(aip->rchal, in->chal, sizeof(aip->rchal));
mkchallenge(aip);
memmove(ou->chal, aip->chal, sizeof(ou->chal));
- if(noauth || wstatallow)
+ if(noauth)
memset(ou->authid, 0, sizeof(ou->authid));
else
memmove(ou->authid, nvr.authid, sizeof(ou->authid));
@@ -78,7 +78,7 @@ authorize(Chan *cp, Fcall *in, Fcall *ou)
ulong bit;
Authinfo *aip;
- if(noauth || wstatallow) /* set to allow entry during boot */
+ if(noauth)
return 1;
if(strcmp(in->uname, "none") == 0)
@@ -245,7 +245,7 @@ f_attach(Chan *cp, Fcall *in, Fcall *ou)
ou->err = Ealloc;
goto out;
}
- if (iaccess(f, d, DEXEC) ||
+ if(iaccess(f, d, DEXEC) ||
f->uid == 0 && fs->dev->type == Devro) {
/*
* 'none' not allowed on dump
@@ -370,7 +370,7 @@ f_walk(Chan *cp, Fcall *in, Fcall *ou)
}
if(ou->err = mkqidcmp(&f->qid, d))
goto out;
- if(cp != cons.chan && iaccess(f, d, DEXEC)) {
+ if(iaccess(f, d, DEXEC)) {
ou->err = Eaccess;
goto out;
}
@@ -469,7 +469,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
File *f;
Tlock *t;
Qid qid;
- int ro, fmod, wok;
+ int ro, fmod;
if(CHAT(cp)) {
fprint(2, "c_open %d\n", cp->chan);
@@ -477,10 +477,6 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
fprint(2, "\tmode = %o\n", in->mode);
}
- wok = 0;
- if(cp == cons.chan || writeallow)
- wok = 1;
-
p = 0;
f = filep(cp, in->fid, 0);
if(!f) {
@@ -528,14 +524,13 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
switch(in->mode & 7) {
case OREAD:
- if(iaccess(f, d, DREAD) && !wok)
+ if(iaccess(f, d, DREAD))
goto badaccess;
fmod = FREAD;
break;
case OWRITE:
- if((d->mode & DDIR) ||
- (iaccess(f, d, DWRITE) && !wok))
+ if((d->mode & DDIR) || iaccess(f, d, DWRITE))
goto badaccess;
if(ro) {
ou->err = Eronly;
@@ -545,9 +540,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
break;
case ORDWR:
- if((d->mode & DDIR) ||
- (iaccess(f, d, DREAD) && !wok) ||
- (iaccess(f, d, DWRITE) && !wok))
+ if((d->mode & DDIR) || iaccess(f, d, DREAD) || iaccess(f, d, DWRITE))
goto badaccess;
if(ro) {
ou->err = Eronly;
@@ -557,8 +550,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
break;
case OEXEC:
- if((d->mode & DDIR) ||
- (iaccess(f, d, DEXEC) && !wok))
+ if((d->mode & DDIR) || iaccess(f, d, DEXEC))
goto badaccess;
fmod = FREAD;
break;
@@ -568,8 +560,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
goto out;
}
if(in->mode & OTRUNC) {
- if((d->mode & DDIR) ||
- (iaccess(f, d, DWRITE) && !wok))
+ if((d->mode & DDIR) || iaccess(f, d, DWRITE))
goto badaccess;
if(ro) {
ou->err = Eronly;
@@ -617,7 +608,7 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
Iobuf *p, *p1;
Dentry *d, *d1;
File *f;
- int slot, slot1, fmod, wok;
+ int slot, slot1, fmod;
Off addr, addr1, path;
Qid qid;
Tlock *t;
@@ -632,10 +623,6 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
fprint(2, "\tmode = %o\n", in->mode);
}
- wok = 0;
- if(cp == cons.chan || writeallow)
- wok = 1;
-
p = 0;
f = filep(cp, in->fid, 0);
if(!f) {
@@ -659,7 +646,7 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
ou->err = Edir2;
goto out;
}
- if(iaccess(f, d, DWRITE) && !wok) {
+ if(iaccess(f, d, DWRITE)) {
ou->err = Eaccess;
goto out;
}
@@ -1118,7 +1105,7 @@ out:
}
int
-doremove(File *f, int wok)
+doremove(File *f)
{
Iobuf *p, *p1;
Dentry *d, *d1;
@@ -1144,7 +1131,7 @@ doremove(File *f, int wok)
err = Ephase;
goto out;
}
- if(iaccess(f, d1, DWRITE) && !wok) {
+ if(iaccess(f, d1, DWRITE)) {
err = Eaccess;
goto out;
}
@@ -1202,7 +1189,7 @@ out:
}
static int
-doclunk(File* f, int remove, int wok)
+doclunk(File* f, int remove)
{
Tlock *t;
int err;
@@ -1214,7 +1201,7 @@ doclunk(File* f, int remove, int wok)
f->tlock = 0;
}
if(remove)
- err = doremove(f, wok);
+ err = doremove(f);
f->open = 0;
freewp(f->wpath);
freefp(f);
@@ -1236,7 +1223,7 @@ f_clunk(Chan *cp, Fcall *in, Fcall *ou)
if(!f)
ou->err = Efid;
else {
- doclunk(f, f->open & FREMOV, 0);
+ doclunk(f, f->open & FREMOV);
qunlock(f);
}
ou->fid = in->fid;
@@ -1256,7 +1243,7 @@ f_remove(Chan *cp, Fcall *in, Fcall *ou)
if(!f)
ou->err = Efid;
else {
- ou->err = doclunk(f, 1, cp==cons.chan);
+ ou->err = doclunk(f, 1);
qunlock(f);
}
ou->fid = in->fid;
@@ -1371,7 +1358,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
* if chown,
* must be god
*/
- if(xd.uid != d->uid && !wstatallow) { /* set to allow chown during boot */
+ if(xd.uid != d->uid && !isallowed(f)) {
ou->err = Ewstatu;
goto out;
}
@@ -1382,10 +1369,9 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
* a) owner and in new group
* b) leader of both groups
*/
- if (xd.gid != d->gid &&
- (!wstatallow && !writeallow && /* set to allow chgrp during boot */
+ if (xd.gid != d->gid && !isallowed(f) &&
(d->uid != f->uid || !ingroup(f->uid, xd.gid)) &&
- (!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid)))) {
+ (!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid))) {
ou->err = Ewstatg;
goto out;
}
@@ -1439,8 +1425,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
goto out;
}
- if (!wstatallow && !writeallow && /* set to allow rename during boot */
- (!d1 || iaccess(f, d1, DWRITE))) {
+ if(iaccess(f, d1, DWRITE)) {
ou->err = Eaccess;
goto out;
}
@@ -1453,8 +1438,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
*/
if (d->mtime != xd.mtime ||
((d->mode^xd.mode) & (DAPND|DLOCK|0777)))
- if (!wstatallow && /* set to allow chmod during boot */
- d->uid != f->uid &&
+ if (d->uid != f->uid && !isallowed(f) &&
!leadgroup(f->uid, xd.gid) &&
!leadgroup(f->uid, d->gid)) {
ou->err = Ewstatu;
diff --git a/sys/src/cmd/cwfs/9p2.c b/sys/src/cmd/cwfs/9p2.c
index 97fafe55f..e72756c01 100644
--- a/sys/src/cmd/cwfs/9p2.c
+++ b/sys/src/cmd/cwfs/9p2.c
@@ -148,7 +148,7 @@ auth(Chan* chan, Fcall* f, Fcall* r)
Filsys *fs;
int error;
- if(noauth || wstatallow)
+ if(noauth)
return Eauthdisabled;
error = 0;
@@ -201,7 +201,7 @@ authorize(Chan* chan, Fcall* f)
db = cons.flags & authdebugflag;
- if(noauth || wstatallow){
+ if(noauth){
uid = strtouid(f->uname);
if(db)
fprint(2, "permission granted by noauth uid %s = %d\n",
@@ -290,7 +290,7 @@ attach(Chan* chan, Fcall* f, Fcall* r)
error = Ealloc;
goto out;
}
- if (iaccess(file, d, DEXEC) ||
+ if(iaccess(file, d, DEXEC) ||
file->uid == 0 && fs->dev->type == Devro) {
/*
* 'none' not allowed on dump
@@ -394,7 +394,7 @@ walkname(File* file, char* wname, Qid* wqid)
* For walked elements the implied user must
* have permission to search the directory.
*/
- if(file->cp != cons.chan && iaccess(file, d, DEXEC)){
+ if(iaccess(file, d, DEXEC)){
error = Eaccess;
goto out;
}
@@ -607,14 +607,9 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
File *file;
Tlock *t;
Qid qid;
- int error, ro, fmod, wok;
+ int error, ro, fmod;
- wok = 0;
p = nil;
-
- if(chan == cons.chan || writeallow)
- wok = 1;
-
if((file = filep(chan, f->fid, 0)) == nil){
error = Efid;
goto out;
@@ -672,13 +667,13 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
switch(f->mode & 7){
case OREAD:
- if(iaccess(file, d, DREAD) && !wok)
+ if(iaccess(file, d, DREAD))
goto badaccess;
fmod = FREAD;
break;
case OWRITE:
- if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))
+ if((d->mode & DDIR) || iaccess(file, d, DWRITE))
goto badaccess;
if(ro){
error = Eronly;
@@ -689,8 +684,8 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
case ORDWR:
if((d->mode & DDIR)
- || (iaccess(file, d, DREAD) && !wok)
- || (iaccess(file, d, DWRITE) && !wok))
+ || iaccess(file, d, DREAD)
+ || iaccess(file, d, DWRITE))
goto badaccess;
if(ro){
error = Eronly;
@@ -700,7 +695,7 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
break;
case OEXEC:
- if((d->mode & DDIR) || (iaccess(file, d, DEXEC) && !wok))
+ if((d->mode & DDIR) || iaccess(file, d, DEXEC))
goto badaccess;
fmod = FREAD;
break;
@@ -710,7 +705,7 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
goto out;
}
if(f->mode & OTRUNC){
- if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))
+ if((d->mode & DDIR) || iaccess(file, d, DWRITE))
goto badaccess;
if(ro){
error = Eronly;
@@ -759,17 +754,13 @@ fs_create(Chan* chan, Fcall* f, Fcall* r)
Iobuf *p, *p1;
Dentry *d, *d1;
File *file;
- int error, slot, slot1, fmod, wok;
+ int error, slot, slot1, fmod;
Off addr, addr1, path;
Tlock *t;
Wpath *w;
- wok = 0;
p = nil;
- if(chan == cons.chan || writeallow)
- wok = 1;
-
if((file = filep(chan, f->fid, 0)) == nil){
error = Efid;
goto out;
@@ -799,7 +790,7 @@ fs_create(Chan* chan, Fcall* f, Fcall* r)
error = Edir2;
goto out;
}
- if(iaccess(file, d, DWRITE) && !wok) {
+ if(iaccess(file, d, DWRITE)) {
error = Eaccess;
goto out;
}
@@ -1273,7 +1264,7 @@ out:
}
static int
-_clunk(File* file, int remove, int wok)
+_clunk(File* file, int remove)
{
Tlock *t;
int error;
@@ -1285,7 +1276,7 @@ _clunk(File* file, int remove, int wok)
file->tlock = 0;
}
if(remove && (file->qid.type & QTAUTH) == 0)
- error = doremove(file, wok);
+ error = doremove(file);
file->open = 0;
freewp(file->wpath);
authfree(file->auth);
@@ -1304,7 +1295,7 @@ clunk(Chan* chan, Fcall* f, Fcall*)
if((file = filep(chan, f->fid, 0)) == nil)
return Efid;
- _clunk(file, file->open & FREMOV, 0);
+ _clunk(file, file->open & FREMOV);
return 0;
}
@@ -1315,8 +1306,7 @@ fs_remove(Chan* chan, Fcall* f, Fcall*)
if((file = filep(chan, f->fid, 0)) == nil)
return Efid;
-
- return _clunk(file, 1, chan == cons.chan);
+ return _clunk(file, 1);
}
static int
@@ -1433,13 +1423,10 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
* .qid.path, .qid.vers and .muid are checked for validity but
* any attempt to change them is an error.
* .qid.type/.mode, .mtime, .name, .length, .uid and .gid can
- * possibly be changed (and .muid iff wstatallow).
+ * possibly be changed (and .muid iff is god).
*
* 'Op' flags there are changed fields, i.e. it's not a no-op.
* 'Tsync' flags all fields are defaulted.
- *
- * Wstatallow and writeallow are set to allow changes during the
- * fileserver bootstrap phase.
*/
tsync = 1;
if(dir.qid.path != ~0){
@@ -1526,7 +1513,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
gl = leadgroup(file->uid, gid) != 0;
gl += leadgroup(file->uid, d->gid) != 0;
- if(op && !wstatallow && d->uid != file->uid && !gl){
+ if(op && !isallowed(file) && d->uid != file->uid && !gl){
error = Ewstato;
goto out;
}
@@ -1613,7 +1600,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
/*
* Check write permission in the parent.
*/
- if(!wstatallow && !writeallow && iaccess(file, d1, DWRITE)){
+ if(iaccess(file, d1, DWRITE)){
error = Eaccess;
goto out;
}
@@ -1625,7 +1612,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
if(dir.uid != nil && *dir.uid != '\0'){
uid = strtouid(dir.uid);
if(uid != d->uid){
- if(!wstatallow){
+ if(!isallowed(file)){
error = Ewstatu;
goto out;
}
@@ -1637,7 +1624,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
if(dir.muid != nil && *dir.muid != '\0'){
muid = strtouid(dir.muid);
if(muid != d->muid){
- if(!wstatallow){
+ if(!isallowed(file)){
error = Ewstatm;
goto out;
}
@@ -1652,7 +1639,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
* either owner and in new group or leader of both groups.
*/
if(gid != d->gid){
- if(!(wstatallow || writeallow)
+ if(!isallowed(file)
&& !(d->uid == file->uid && ingroup(file->uid, gid))
&& !(gl == 2)){
error = Ewstatg;
diff --git a/sys/src/cmd/cwfs/all.h b/sys/src/cmd/cwfs/all.h
index 1cf878b04..4c358ba78 100644
--- a/sys/src/cmd/cwfs/all.h
+++ b/sys/src/cmd/cwfs/all.h
@@ -85,12 +85,10 @@ int noauth; /* auth is disable */
int nonone; /* attach as none disabled */
int noatime; /* atime is disabled */
int noatimeset; /* noatime was changed (reset after dump) */
-int wstatallow; /* set to circumvent wstat permissions */
-int writeallow; /* set to circumvent write permissions */
+int allowed; /* allow wstat and disable permission checks
+ * for user or anyone when -1 */
int duallow; /* single user to allow du */
int readonly; /* disable writes if true */
-
-
int rawreadok; /* allow reading raw data */
File* flist[5003]; /* base of file structures */
diff --git a/sys/src/cmd/cwfs/con.c b/sys/src/cmd/cwfs/con.c
index 00fadf6bb..bace9df29 100644
--- a/sys/src/cmd/cwfs/con.c
+++ b/sys/src/cmd/cwfs/con.c
@@ -461,15 +461,31 @@ cmd_clri(int argc, char *argv[])
}
static void
-cmd_allow(int, char**)
+cmd_allow(int argc, char *argv[])
{
- wstatallow = writeallow = 1;
+ char *name;
+ int uid;
+
+ uid = -1;
+ name = "any user";
+ if(argc > 1){
+ name = argv[1];
+ uid = strtouid(name);
+ if(uid < 0)
+ uid = number(name, -2, 10);
+ if(uid < 0) {
+ print("bad uid %s\n", name);
+ return;
+ }
+ }
+ print("allowed %s\n", name);
+ allowed = uid;
}
static void
cmd_disallow(int, char**)
{
- wstatallow = writeallow = 0;
+ allowed = 0;
}
void
@@ -748,14 +764,14 @@ cmd_chatty(int argc, char *argv[])
static void
installcmds(void)
{
- cmd_install("allow", "-- disable permission checking", cmd_allow);
+ cmd_install("allow", "[uid] -- disable permission checking", cmd_allow);
cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
cmd_install("chatty", "n -- set chattiness", cmd_chatty);
cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
cmd_install("check", "[options]", cmd_check);
cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
cmd_install("create", "path uid gid perm [lad] -- make a file/dir", cmd_create);
- cmd_install("disallow", "-- enable permission checking", cmd_disallow);
+ cmd_install("disallow", "-- (re)enable permission checking", cmd_disallow);
cmd_install("duallow", "uid -- duallow", cmd_duallow);
cmd_install("flag", "-- print set flags", cmd_flag);
cmd_install("fstat", "path -- print info on a file/dir", cmd_fstat);
diff --git a/sys/src/cmd/cwfs/config.c b/sys/src/cmd/cwfs/config.c
index da71fcd69..a59306e90 100644
--- a/sys/src/cmd/cwfs/config.c
+++ b/sys/src/cmd/cwfs/config.c
@@ -1105,9 +1105,6 @@ arginit(void)
}
switch(verb) {
case FREAM:
- if(strcmp(fs->name, "main") == 0)
- wstatallow = 1; /* only set, never reset */
- /* fallthrough */
case FRECOVER:
fs->flags |= verb;
break;
diff --git a/sys/src/cmd/cwfs/portfns.h b/sys/src/cmd/cwfs/portfns.h
index ba584caf0..d6628c640 100644
--- a/sys/src/cmd/cwfs/portfns.h
+++ b/sys/src/cmd/cwfs/portfns.h
@@ -66,7 +66,7 @@ Devsize devsize(Device*);
int devwrite(Device*, Off, void*);
Iobuf* dnodebuf(Iobuf*, Dentry*, Off, int, int);
Iobuf* dnodebuf1(Iobuf*, Dentry*, Off, int, int);
-int doremove(File*, int);
+int doremove(File*);
void dtrunc(Iobuf*, Dentry*, int);
int dtrunclen(Iobuf *p, Dentry *, Off newsize, int uid);
int dumpblock(Device*);
@@ -107,6 +107,7 @@ void iobufinit(void);
void* iobufmap(Iobuf*);
void iobufunmap(Iobuf*);
int iobufql(QLock*);
+int isallowed(File*);
int jukeread(Device*, Off, void*);
int jukewrite(Device*, Off, void*);
void jukeinit(Device*);
diff --git a/sys/src/cmd/cwfs/sub.c b/sys/src/cmd/cwfs/sub.c
index bf9a59e1d..c64f77c10 100644
--- a/sys/src/cmd/cwfs/sub.c
+++ b/sys/src/cmd/cwfs/sub.c
@@ -89,7 +89,7 @@ loop:
f->tlock = 0;
}
if(f->open & FREMOV)
- doremove(f, 0);
+ doremove(f);
freewp(f->wpath);
f->open = 0;
authfree(f->auth);
@@ -237,26 +237,41 @@ iaccess(File *f, Dentry *d, int m)
return 0;
}
- /*
- * other
- */
+ /* other */
if(m & d->mode) {
+ /*
+ * walk directories regardless.
+ * otherwise its impossible to get
+ * from the root to noworld's directories.
+ */
if((d->mode & DDIR) && (m == DEXEC))
return 0;
if(!ingroup(f->uid, 9999))
return 0;
}
- /*
- * various forms of superuser
- */
- if(wstatallow)
- return 0;
+ /* read access for du */
if(duallow != 0 && duallow == f->uid)
if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
return 0;
- return 1;
+ /* allow god */
+ return !isallowed(f);
+}
+
+int
+isallowed(File *f)
+{
+ if(f->cp == cons.chan)
+ return 1;
+ switch(allowed){
+ case 0:
+ return 0;
+ case -1:
+ return 1;
+ default:
+ return f->uid == allowed;
+ }
}
Tlock*