A patch for knfsd-981022

H.J. Lu (hjl@lucon.org)
Thu, 5 Nov 1998 09:56:39 -0800 (PST)


>
>
> > I have some bug fixes for knfsd-981022. Unfortunately, Linux 2.1.126
> > doesn't boot on my machine. I am waiting for 2.1.127. Should I make
> > a new knfsd without any new kernel patches, or wait for 2.1.127 and
> > fix whatever is broken in 2.1.127?
>

Here is a patch for knfsd-981022. It fixes some bugs:

1. Fix buffer overruns from Peter Benie <pjb1008@cus.cam.ac.uk>.
2. Fix hostname matching.
3. Correctly handle dupilcations in /etc/exports.
4. Add -F flag to statd.

I will make a full release when the kernel is stable again.

-- 
H.J. Lu (hjl@gnu.org)
---
Index: support/export/export.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/support/export/export.c,v
retrieving revision 1.9
diff -u -p -r1.9 export.c
--- support/export/export.c	1998/10/01 00:31:35	1.9
+++ support/export/export.c	1998/10/28 16:36:02
@@ -27,11 +27,28 @@ int
 export_read(char *fname)
 {
 	struct exportent	*eep;
+	nfs_export		*exp;
 
 	setexportent(fname, "r");
 	while ((eep = getexportent()) != NULL) {
-		if (!export_lookup(eep->e_hostname, eep->e_path))
-			export_create(eep);
+	  exp = export_lookup(eep->e_hostname, eep->e_path);
+	  if (!exp)
+	    export_create(eep);
+	  else {
+	    if (exp->m_export.e_flags != eep->e_flags) {
+	      xlog(L_ERROR, "incompatible dupilcated export entries:");
+	      xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
+		   eep->e_path, eep->e_flags);
+	      xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
+		   exp->m_export.e_path, exp->m_export.e_flags);
+	    }
+	    else {
+	      xlog(L_ERROR, "dupilcated export entries:");
+	      xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
+	      xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
+		   exp->m_export.e_path);
+	    }
+	  }
 	}
 	endexportent();
 
Index: support/export/hostname.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/support/export/hostname.c,v
retrieving revision 1.2
diff -u -p -r1.2 hostname.c
--- support/export/hostname.c	1998/09/23 01:45:58	1.2
+++ support/export/hostname.c	1998/10/28 05:35:55
@@ -99,21 +99,42 @@ hostent_dup (struct hostent *hp)
 int
 matchhostname (const char *h1, const char *h2)
 {
-  struct hostent *hp;
-  char *name;
+  struct hostent *hp1, *hp2;
+  int status;
 
   if (strcasecmp (h1, h2) == 0)
     return 1;
 
-  hp = gethostbyname (h1);
-  if (hp == NULL)
+  hp1 = gethostbyname (h1);
+  if (hp1 == NULL)
     return 0;
 
-  name = alloca (strlen (hp->h_name) + 1);
-  strcpy (name, hp->h_name);
+  hp1 = hostent_dup (hp1);
 
-  hp = gethostbyname (h2);
-  return hp && strcasecmp (name, hp->h_name) == 0;
+  hp2 = gethostbyname (h2);
+  if (hp2)
+    {
+      if (strcasecmp (hp1->h_name, hp2->h_name) == 0)
+	status = 1;
+      else
+	{
+	  char **ap1, **ap2;
+
+	  status = 0;
+	  for (ap1 = hp1->h_addr_list; *ap1 && status == 0; *ap1++)
+	    for (ap2 = hp2->h_addr_list; *ap2; *ap2++)
+	      if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0)
+		{
+		  status = 1;
+		  break;
+		}
+	}
+    }
+  else
+    status = 0;
+
+  free (hp1);
+  return status;
 }
 
 #ifdef TEST
@@ -150,6 +171,8 @@ main (int argc, char **argv)
       print_host (cp);
       free (cp);
     }
+  printf ("127.0.0.1 == %s: %d\n", argv [1],
+	  matchhostname ("127.0.0.1", argv [1]));
   return 0;
 }
 #endif
Index: support/nfs/rpcmisc.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/support/nfs/rpcmisc.c,v
retrieving revision 1.2
diff -u -p -r1.2 rpcmisc.c
--- support/nfs/rpcmisc.c	1998/09/09 15:27:55	1.2
+++ support/nfs/rpcmisc.c	1998/10/23 17:06:10
@@ -175,6 +175,8 @@ void
 rpc_logcall(struct svc_req *rqstp, char *xname, char *arg)
 {
 	char		buff[1024];
+	int		buflen=sizeof(buff);
+	int		len;
 	char		*sp;
 	int		i;
 
@@ -192,19 +194,29 @@ rpc_logcall(struct svc_req *rqstp, char 
 
 		unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
 		tm = localtime(&unix_cred->aup_time);
-		sprintf(sp, "UNIX %d/%d/%d %02d:%02d:%02d %s %d.%d",
+		snprintf(sp, buflen, "UNIX %d/%d/%d %02d:%02d:%02d %s %d.%d",
 			tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
 			tm->tm_hour, tm->tm_min, tm->tm_sec,
 			unix_cred->aup_machname,
 			unix_cred->aup_uid,
 			unix_cred->aup_gid);
-		sp += strlen(sp);
+		sp[buflen-1] = 0;
+		len = strlen(sp);
+		sp += buflen;
+		buflen -= len;
 		if ((int) unix_cred->aup_len > 0) {
-			sprintf(sp, "+%d", unix_cred->aup_gids[0]);
-			sp += strlen(sp);
+			snprintf(sp, buflen, "+%d", unix_cred->aup_gids[0]);
+			sp[buflen-1] = 0;
+			len = strlen(sp);
+			sp += buflen;
+			buflen -= len;
 			for (i = 1; i < unix_cred->aup_len; i++) {
-				sprintf(sp, ",%d", unix_cred->aup_gids[i]);
-				sp += strlen(sp);
+				snprintf(sp, buflen, ",%d", 
+					unix_cred->aup_gids[i]);
+				sp[buflen-1] = 0;
+				len = strlen(sp);
+				sp += buflen;
+				buflen -= len;
 			}
 		}
 		}
Index: support/nfs/xlog.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/support/nfs/xlog.c,v
retrieving revision 1.2
diff -u -p -r1.2 xlog.c
--- support/nfs/xlog.c	1998/10/01 00:31:36	1.2
+++ support/nfs/xlog.c	1998/10/31 19:24:29
@@ -140,8 +140,9 @@ xlog(int kind, const char *fmt, ...)
 		return;
 
 	va_start(args, fmt);
-	vsprintf(buff, fmt, args);
+	vsnprintf(buff, sizeof (buff), fmt, args);
 	va_end(args);
+	buff[sizeof (buff) - 1] = 0;
 
 	if ((n = strlen(buff)) > 0 && buff[n-1] != '\n') {
 		buff[n++] = '\n'; buff[n++] = '\0';
Index: utils/rquotad/hasquota.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/rquotad/hasquota.c,v
retrieving revision 1.4
diff -u -p -r1.4 hasquota.c
--- utils/rquotad/hasquota.c	1998/10/01 00:31:36	1.4
+++ utils/rquotad/hasquota.c	1998/10/31 19:14:16
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include <string.h>
 #include "mntent.h"
+#include "xmalloc.h"
 
 #undef min
 #define min(x,y) ((x) < (y)) ? (x) : (y)
@@ -32,8 +33,6 @@
 (!strcmp(type,MNTTYPE_EXT2))
 
 char *qfextension[] = INITQFNAMES;
-static char *qfname = QUOTAFILENAME;
-static char qfullname[PATH_MAX];
 
 /*
  * Check to see if a particular quota is to be enabled.
@@ -41,6 +40,7 @@ static char qfullname[PATH_MAX];
 int
 hasquota(struct mntent *mnt, int type, char **qfnamep)
 {
+   char *qfname = QUOTAFILENAME;
    char *buf, *option, *pathname;
 
    if (!CORRECT_FSTYPE(mnt->mnt_type))
@@ -49,21 +49,21 @@ hasquota(struct mntent *mnt, int type, c
    if (((type == USRQUOTA) && (option = hasmntopt(mnt, MNTOPT_USRQUOTA)) != (char *)0) ||
        ((type == GRPQUOTA) && (option = hasmntopt(mnt, MNTOPT_GRPQUOTA)) != (char *)0)) {
       if ((pathname = strchr(option, '=')) == (char *)0) {
-         (void) sprintf(qfullname, "%s%s%s.%s", mnt->mnt_dir,
-                       (mnt->mnt_dir[strlen(mnt->mnt_dir) - 1] == '/') ? "" : "/",
-                       qfname, qfextension[type]);
+	  *qfnamep=xmalloc(strlen(mnt->mnt_dir)+strlen(qfname)+strlen(qfextension[type])+2);
+	  (void) sprintf(*qfnamep, "%s%s%s.%s", mnt->mnt_dir,
+			(mnt->mnt_dir[strlen(mnt->mnt_dir) - 1] == '/') ? "" : "/",
+			qfname, qfextension[type]);
       } else {
          if ((option = strchr(++pathname, ',')) != (char *)NULL) {
-            strncpy(qfullname, pathname,
-		    min((option - pathname), sizeof(qfullname)) - 1);
-            qfullname [min((option - pathname), sizeof(qfullname)) - 1] = '\0';
+	    int len=option-pathname;
+	    *qfnamep=xmalloc(len);
+            memcpy(*qfnamep, pathname, len-1);
+            (*qfnamep) [len-1] = '\0';
 	 }
          else {
-            strncpy(qfullname, pathname, sizeof(qfullname) - 1);
-            qfullname [sizeof(qfullname) - 1] = '\0';
+	    *qfnamep=xstrdup(pathname);
 	 }
       }
-      *qfnamep = strdup(qfullname);
       return (1);
    } else
       return (0);
Index: utils/rquotad/rquota_server.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/rquotad/rquota_server.c,v
retrieving revision 1.4
diff -u -p -r1.4 rquota_server.c
--- utils/rquotad/rquota_server.c	1998/10/01 00:31:36	1.4
+++ utils/rquotad/rquota_server.c	1998/10/23 17:06:10
@@ -176,7 +176,11 @@ getquota_rslt *getquotainfo(int flags, c
          if ((err = quotactl(QCMD(Q_GETQUOTA, type), devicename, id,
             (caddr_t)&dq_dqb)) == -1 && !(flags & ACTIVE)) {
             if ((fd = open(qfpathname, O_RDONLY)) < 0)
+	    {
+	       free(qfpathname);
                continue;
+	    }
+            free(qfpathname);
             lseek(fd, (long) dqoff(id), L_SET);
             switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
                case 0:/* EOF */
Index: utils/showmount/showmount.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/showmount/showmount.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 showmount.c
--- utils/showmount/showmount.c	1998/08/19 02:37:45	1.1.1.1
+++ utils/showmount/showmount.c	1998/10/23 17:06:10
@@ -263,18 +263,15 @@ char **argv;
 		if (headers)
 			printf("All mount points on %s:\n", hostname);
 		while (dumplist) {
-			char s[1024];
 			char *t;
 
-			sprintf(s, "%s:%s", dumplist->ml_hostname,
-				dumplist->ml_directory);
-			t = malloc(strlen(s) + 1);
-			if (t)
-				strcpy(t, s);
-			else {
-				printf("%s: out of memory\n", program_name);
+			t=malloc(strlen(dumplist->ml_hostname)+strlen(dumplist->ml_directory)+2);
+			if (!t)
+			{
+				fprintf(stderr, "%s: out of memory\n", program_name);
 				exit(1);
 			}
+			sprintf(t, "%s:%s", dumplist->ml_hostname, dumplist->ml_directory);
 			dumpv[i++] = t;
 			dumplist = dumplist->ml_next;
 		}
Index: utils/statd/log.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/log.c,v
retrieving revision 1.2
diff -u -p -r1.2 log.c
--- utils/statd/log.c	1998/10/01 00:31:36	1.2
+++ utils/statd/log.c	1998/10/23 17:06:10
@@ -60,8 +60,9 @@ die(char *fmt, ...)
     va_list	ap;
 
     va_start(ap, fmt);
-    vsprintf (buffer, fmt, ap);
+    vsnprintf (buffer, 1024, fmt, ap);
     va_end(ap);
+    buffer[1023]=0;
 
     log(L_FATAL, "%s", buffer);
 
@@ -79,8 +80,9 @@ log(int level, char *fmt, ...)
     va_list	ap;
 
     va_start(ap, fmt);
-    vsprintf (buffer, fmt, ap);
+    vsnprintf (buffer, 1024, fmt, ap);
     va_end(ap);
+    buffer[1023]=0;
 
     if (level < L_DEBUG) {
     	syslog(level, buffer);
Index: utils/statd/misc.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/misc.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 misc.c
--- utils/statd/misc.c	1998/08/19 02:37:45	1.1.1.1
+++ utils/statd/misc.c	1998/10/31 19:19:46
@@ -28,7 +28,7 @@ xmalloc (size_t size)
 
   if (!(ptr = malloc (size)))
     /* SHIT!  SHIT!  SHIT! */
-    die ("malloc: %s", strerror (errno));
+    die ("malloc failed");
 
   return (ptr);
 }
@@ -44,7 +44,7 @@ xstrdup (const char *string)
 
   /* Will only fail if underlying malloc() fails (ENOMEM). */
   if (!(result = strdup (string)))
-    die ("strdup: %s", strerror (errno));
+    die ("strdup failed");
 
   return (result);
 }
@@ -57,9 +57,10 @@ xstrdup (const char *string)
 void
 xunlink (char *path, char *host, short int check)
 {
-  char tozap[PATH_MAX];
+  char *tozap;
 
-  snprintf (tozap, PATH_MAX, "%s/%s", path, host);
+  tozap=alloca (strlen(path)+strlen(host)+2);
+  sprintf (tozap, "%s/%s", path, host);
 
   if (!check || !nlist_gethost(rtnl, host, 0))
     if (unlink (tozap) == -1)
Index: utils/statd/monitor.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/monitor.c,v
retrieving revision 1.4
diff -u -p -r1.4 monitor.c
--- utils/statd/monitor.c	1998/10/10 23:57:28	1.4
+++ utils/statd/monitor.c	1998/10/23 17:06:10
@@ -33,7 +33,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
 	char		*mon_name = argp->mon_id.mon_name,
 			*my_name  = argp->mon_id.my_id.my_name;
 	struct my_id	*id = &argp->mon_id.my_id;
-	char            path[PATH_MAX];
+	char            *path;
 	int             fd;
 	notify_list	*clnt;
 
@@ -114,14 +114,17 @@ sm_mon_1_svc(struct mon *argp, struct sv
 	/*
 	 * Now, Create file on stable storage for host.
 	 */
-	snprintf(path, PATH_MAX, SM_DIR "/%s", mon_name);
+
+	path=xmalloc(strlen(SM_DIR)+strlen(mon_name)+2);
+	sprintf(path, SM_DIR "/%s", mon_name);
 	if ((fd = open(path, O_WRONLY|O_SYNC|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
 		/* Didn't fly.  We won't monitor. */
 		log(L_ERROR, "creat(%s) failed: %m", path);
 		nlist_free(NULL, clnt);
+		free(path);
 		goto failure;
 	}
-
+	free(path);
 	nlist_insert(&rtnl, clnt);
 	close(fd);
 
Index: utils/statd/notify.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/notify.c,v
retrieving revision 1.2
diff -u -p -r1.2 notify.c
--- utils/statd/notify.c	1998/09/20 23:43:14	1.2
+++ utils/statd/notify.c	1998/10/23 17:06:10
@@ -54,11 +54,14 @@ notify_hosts(void)
 		 * (e.g. with cfsd) */
 		if (matchhostname(de->d_name, MY_NAME)
 		 || matchhostname(de->d_name, "localhost")) {
-			char	fname[PATH_MAX];
-
+			char *fname;
+			fname=xmalloc(strlen(SM_BAK_DIR)+sizeof(de->d_name)+2);
 			dprintf(L_DEBUG, "We're on our own notify list?!?");
 			sprintf(fname, SM_BAK_DIR "/%s", de->d_name);
-			unlink(fname);
+			if (unlink(fname)) 
+				log(L_ERROR, "unlink(%s): %s", 
+					fname, strerror(errno));
+			free(fname);
 			continue;
 		}
 
Index: utils/statd/statd.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/statd.c,v
retrieving revision 1.2
diff -u -p -r1.2 statd.c
--- utils/statd/statd.c	1998/08/31 18:51:53	1.2
+++ utils/statd/statd.c	1998/10/31 17:55:07
@@ -7,6 +7,7 @@
 
 #include <signal.h>
 #include <unistd.h>
+#include <string.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
 #include "statd.h"
@@ -47,21 +48,31 @@ int
 main (int argc, char **argv)
 {
   int pid;
+  int foreground = 0;
 
   log_init (argv[0]);
 
+  if (argc == 2 && strcmp (argv [1], "-F") == 0) {
+    foreground = 1;
+    argc--;
+    argv++;
+  }
+
 #ifdef SIMULATIONS
   if (argc > 1)
     simulator (--argc, ++argv);	/* simulator() does exit() */
 #endif
   
-  if ((pid = fork ()) < 0) {
-    perror ("Could not fork");
-    exit (1);
-  } else if (pid != 0) {
-    /* Parent. */
-    exit (0);
+  if (!foreground) {
+    if ((pid = fork ()) < 0) {
+      perror ("Could not fork");
+      exit (1);
+    } else if (pid != 0) {
+      /* Parent. */
+      exit (0);
+    }
   }
+
   /* Child. */
   signal (SIGHUP, killer);
   signal (SIGINT, killer);
Index: utils/statd/state.c
===================================================================
RCS file: /home/work/cvs/linux/knfsd/utils/statd/state.c,v
retrieving revision 1.2
diff -u -p -r1.2 state.c
--- utils/statd/state.c	1998/10/01 00:31:36	1.2
+++ utils/statd/state.c	1998/10/23 17:06:10
@@ -85,7 +85,8 @@ shuffle_dirs (void)
   DIR *nld;
   struct dirent *de;
   struct stat st;
-  char src[PATH_MAX], dst[PATH_MAX];
+  char *src, *dst;
+  int len1, len2, len;
   
   if (stat (SM_DIR, &st) == -1 && errno != ENOENT)
     die ("stat (%s): %s", SM_DIR, strerror (errno));
@@ -106,13 +107,20 @@ shuffle_dirs (void)
   if (!(nld = opendir (SM_DIR)))
     die ("opendir (%s): %s", SM_DIR, strerror (errno));
 
+  len1=strlen(SM_DIR);
+  len2=strlen(SM_BAK_DIR);
   while ((de = readdir (nld))) {
     if (de->d_name[0] == '.')
       continue;
-    snprintf (src, PATH_MAX, "%s/%s", SM_DIR, de->d_name);
-    snprintf (dst, PATH_MAX, "%s/%s", SM_BAK_DIR, de->d_name);
+    len=strlen(de->d_name);
+    src=xmalloc(len1+len+2);
+    dst=xmalloc(len2+len+2);
+    sprintf (src, "%s/%s", SM_DIR, de->d_name);
+    sprintf (dst, "%s/%s", SM_BAK_DIR, de->d_name);
     if (rename (src, dst) == -1)
       die ("rename (%s to %s): %s", SM_DIR, SM_BAK_DIR, strerror (errno));
+    free(src);
+    free(dst);
   }
   if (closedir (nld) == -1)
     log (L_ERROR, "closedir (%s): %s", SM_DIR, strerror (errno));

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/