From 03c70cc2e629e2ad8dcd5718be0132f17b9b8328 Mon Sep 17 00:00:00 2001
From: rtm <rtm>
Date: Sat, 26 Aug 2006 16:31:05 +0000
Subject: [PATCH] consistently ignore more than 14 chars in path component
 forbid create or write of existing directory mkdir("d1/d2/d3"), .. should
 refer to d2, not cwd mkdir increase parent link count

---
 fs.c      |  5 ++++-
 fstests.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 syscall.c | 30 ++++++++++++++++++-------
 3 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/fs.c b/fs.c
index a83e937..6c552e6 100644
--- a/fs.c
+++ b/fs.c
@@ -499,7 +499,10 @@ namei(char *path, int mode, uint *ret_off, char **ret_last, struct inode **ret_i
         for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++)
           if(cp[i] != ep->name[i])
             break;
-        if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){
+        if((cp[i] == '\0' || cp[i] == '/' || i >= DIRSIZ) &&
+           (i >= DIRSIZ || ep->name[i] == '\0')){
+          while(cp[i] != '\0' && cp[i] != '/')
+            i++;
           off += (uchar*)ep - bp->data;
           ninum = ep->inum;
           brelse(bp);
diff --git a/fstests.c b/fstests.c
index d6356ac..ac9478e 100644
--- a/fstests.c
+++ b/fstests.c
@@ -412,8 +412,9 @@ bigdir()
 void
 subdir()
 {
-  int fd;
+  int fd, cc;
 
+  unlink("ff");
   if(mkdir("dd") != 0){
     puts("subdir mkdir dd failed\n");
     exit();
@@ -440,6 +441,18 @@ subdir()
   write(fd, "FF", 2);
   close(fd);
 
+  fd = open("dd/dd/../ff", 0);
+  if(fd < 0){
+    puts("open dd/dd/../ff failed\n");
+    exit();
+  }
+  cc = read(fd, buf, sizeof(buf));
+  if(cc != 2 || buf[0] != 'f'){
+    puts("dd/dd/../ff wrong content\n");
+    exit();
+  }
+  close(fd);
+
   if(link("dd/dd/ff", "dd/dd/ffff") != 0){
     puts("link dd/dd/ff dd/dd/ffff failed\n");
     exit();
@@ -487,6 +500,18 @@ subdir()
     puts("create dd/xx/ff succeeded!\n");
     exit();
   }
+  if(open("dd", O_CREATE) >= 0){
+    puts("create dd succeeded!\n");
+    exit();
+  }
+  if(open("dd", O_RDWR) >= 0){
+    puts("open dd rdwr succeeded!\n");
+    exit();
+  }
+  if(open("dd", O_WRONLY) >= 0){
+    puts("open dd wronly succeeded!\n");
+    exit();
+  }
   if(link("dd/ff/ff", "dd/dd/xx") == 0){
     puts("link dd/ff/ff dd/dd/xx succeeded!\n");
     exit();
@@ -597,11 +622,50 @@ bigfile()
   puts("bigfile ok\n");
 }
 
+void
+fourteen()
+{
+  int fd;
+
+  if(mkdir("12345678901234") != 0){
+    puts("mkdir 12345678901234 failed\n");
+    exit();
+  }
+  if(mkdir("12345678901234/123456789012345") != 0){
+    puts("mkdir 12345678901234/123456789012345 failed\n");
+    exit();
+  }
+  fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
+  if(fd < 0){
+    puts("create 123456789012345/123456789012345/123456789012345 failed\n");
+    exit();
+  }
+  close(fd);
+  fd = open("12345678901234/12345678901234/12345678901234", 0);
+  if(fd < 0){
+    puts("open 12345678901234/12345678901234/12345678901234 failed\n");
+    exit();
+  }
+  close(fd);
+
+  if(mkdir("12345678901234/12345678901234") == 0){
+    puts("mkdir 12345678901234/12345678901234 succeeded!\n");
+    exit();
+  }
+  if(mkdir("123456789012345/12345678901234") == 0){
+    puts("mkdir 12345678901234/123456789012345 succeeded!\n");
+    exit();
+  }
+
+  puts("fourteen ok\n");
+}
+
 int
 main(int argc, char *argv[])
 {
   puts("fstests starting\n");
 
+  fourteen();
   bigfile();
   subdir();
   // bigdir(); // slow
diff --git a/syscall.c b/syscall.c
index 9e256a8..b0933db 100644
--- a/syscall.c
+++ b/syscall.c
@@ -240,12 +240,19 @@ sys_open(void)
         return -1;
     } else if(ip == 0){
       return -1;
+    } else if(ip->type == T_DIR){
+      iput(ip);
+      return -1;
     }
   } else {
     ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0);
     if(ip == 0)
       return -1;
   }
+  if(ip->type == T_DIR && ((arg1 & O_RDWR) || (arg1 & O_WRONLY))){
+    iput(ip);
+    return -1;
+  }
 
   if((fd = fd_alloc()) == 0){
     iput(ip);
@@ -305,10 +312,11 @@ sys_mkdir(void)
 {
   struct proc *cp = curproc[cpu()];
   struct inode *nip;
-  struct inode *pip;
+  struct inode *dp;
   uint arg0;
   int l;
   struct dirent de;
+  char *last;
 
   if(fetcharg(0, &arg0) < 0) 
     return -1;
@@ -316,26 +324,32 @@ sys_mkdir(void)
   if((l = checkstring(arg0)) < 0)
     return -1;
 
-  if(l >= DIRSIZ)
+  dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, 0);
+  if(dp == 0)
     return -1;
 
-  nip = mknod (cp->mem + arg0, T_DIR, 0, 0);
-  if(nip == 0)
+  nip = mknod1(dp, last, T_DIR, 0, 0);
+  if(nip == 0){
+    iput(dp);
     return -1;
+  }
+
+  dp->nlink += 1;
+  iupdate(dp);
   
   memset (de.name, '\0', DIRSIZ);
   de.name[0] = '.';
   de.inum = nip->inum;
   writei (nip, (char *) &de, 0, sizeof(de));
 
-  pip = namei(".", NAMEI_LOOKUP, 0, 0, 0);
-  de.inum = pip->inum;
+  de.inum = dp->inum;
   de.name[1] = '.';
-  iput(pip);
   writei (nip, (char *) &de, sizeof(de), sizeof(de));
 
+  iput(dp);
   iput(nip);
-  return (nip == 0) ? -1 : 0;
+
+  return 0;
 }
 
 
-- 
GitLab