shithub: riscv

Download patch

ref: 6eed7a47863553bab31c7f9b1b5b314989efc640
parent: 40706d95cc2b75ab68033a14118e35d93eefc65d
author: Jacob Moody <moody@posixcafe.org>
date: Sat Jul 29 15:20:04 EDT 2023

kernel: make walk/open errors more consistent with userspace

As is the error for an open would be in the form:
	'filename' does not exist
This changes it to be of the form:
	file does not exist: 'filename'

This brings it more in line with what could
be expected from a userspace filesystem.
Existing code, perhaps due to this discrepancy,
all uses strstr to check for this error. They can
now instead check for explicitly the error as a prefix.
This would avoid issues with potentially maliciously
named files such as "does not exist".

Likewise this also helps filesystems such as exportfs,
which spit back the errstr from open(2) directly as Rerror
to their clients.

--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -950,7 +950,6 @@
  * Either walks all the way or not at all.  No partial results in *cp.
  * *nerror is the number of names to display in an error message.
  */
-static char Edoesnotexist[] = "does not exist";
 int
 walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 {
@@ -1066,7 +1065,7 @@
 					if(wq->nqid == 0 || (wq->qid[wq->nqid-1].type&QTDIR) != 0){
 						if(nerror)
 							*nerror = nhave+wq->nqid+1;
-						kstrcpy(up->errstr, Edoesnotexist, ERRMAX);
+						kstrcpy(up->errstr, Enonexist, ERRMAX);
 					}else{
 						if(nerror)
 							*nerror = nhave+wq->nqid;
@@ -1204,7 +1203,7 @@
 	}
 }
 
-static void
+void
 namelenerror(char *aname, int len, char *err)
 {
 	char *ename, *name, *next;
@@ -1247,14 +1246,8 @@
 		snprint(up->genbuf, sizeof up->genbuf, "...%.*s",
 			utfnlen(name, ename-name), name);
 	}				
-	snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err);
+	snprint(up->errstr, ERRMAX, "%s: %#q", err, up->genbuf);
 	nexterror();
-}
-
-void
-nameerror(char *name, char *err)
-{
-	namelenerror(name, strlen(name), err);
 }
 
 /*
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -206,7 +206,7 @@
 void		mul64fract(uvlong*, uvlong, uvlong);
 void		muxclose(Mnt*);
 Chan*		namec(char*, int, int, ulong);
-void		nameerror(char*, char*);
+void		namelenerror(char*, int, char*);
 int		needpages(void*);
 Chan*		newchan(void);
 int		newfd(Chan*, int);
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -1233,6 +1233,7 @@
 {
 	long l;
 	int namelen;
+	char *p;
 
 	if(waserror()){
 		cclose(c);
@@ -1244,8 +1245,10 @@
 		 * (which should be renamed? the mount point or the mounted Chan?).
 		 */
 		dirname(d, &namelen);
-		if(namelen)
-			nameerror(chanpath(c), Eismtpt);
+		if(namelen){
+			p = chanpath(c);
+			namelenerror(p, strlen(p), Eismtpt);
+		}
 	}
 	l = devtab[c->type]->wstat(c, d, nd);
 	poperror();