Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Linux kernel compatability enhancements (through 3.19)
[palacios.git] / linux_module / iface-keyed-stream.c
index 5bce431..1f75aa0 100644 (file)
@@ -310,7 +310,7 @@ static v3_keyed_stream_t open_stream_mem(char *url,
                    return 0;
                }
 
-               strcpy(mykey,url+4);
+               strcpy(mykey,url+4); // will fit
                
                mks = (struct mem_keyed_stream *) palacios_alloc(sizeof(struct mem_keyed_stream));
 
@@ -382,7 +382,7 @@ static v3_keyed_stream_key_t open_key_mem(v3_keyed_stream_t stream,
            return 0;
        }
 
-       strcpy(mykey,key);
+       strcpy(mykey,key); // will fit
 
        m = create_mem_stream();
        
@@ -431,7 +431,7 @@ static void preallocate_hint_key_mem(v3_keyed_stream_t stream,
            return;
        }
        
-       strcpy(mykey,key);
+       strcpy(mykey,key); // will fit
        
        m = create_mem_stream_internal(size);
        
@@ -657,12 +657,157 @@ struct file_stream {
     struct file *f;   // the opened file
 };
 
+/* lookup directory, see if it is writeable, and if so, create it if asked*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41)
+
+static int lookup_check_mkdir(const char *path, int need_write, int create, unsigned short perms)
+{
+  struct nameidata nd;
+
+  if (path_lookup(path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) { 
+    
+    // directory does does not exist.  
+    
+    if (!create) { 
+      // we are not being asked to create it
+      ERROR("attempt to open %s, which does not exist\n",path);
+      return -1;
+    } else {
+      // We are being asked to create it
+
+      struct dentry *de;
+      int err;
+      
+      // Find its parent
+      if (path_lookup(path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) { 
+       ERROR("attempt to create %s failed because its parent cannot be looked up\n",path);
+       return -1;
+      }
+      
+      // Can we write to the parent?
+      
+      if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { 
+       ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",path);
+       return -1;
+      }
+
+      // OK, we can, so let's create it
+      
+      de = lookup_create(&nd,1);
+      
+      if (!de || IS_ERR(de)) { 
+       ERROR("cannot allocate dentry\n");
+       return -1;
+      }
+
+      err = vfs_mkdir(nd.path.dentry->d_inode, de, perms);
+      
+      // lookup_create locks this for us!
+      
+      mutex_unlock(&(nd.path.dentry->d_inode->i_mutex));
+
+      if (err) {
+       ERROR("attempt to create %s failed because mkdir failed\n",path);
+       return -1;
+      }
+
+      // successfully created it. 
+      return 0;
+
+    }
+
+  } else {
+    
+    // it exists, can we read (and write, if needed) to it?
+    
+    if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_READ | need_write ? MAY_WRITE : 0 )) {
+      ERROR("attempt to open %s, which has the wrong permissions\n",path);
+      return -1;
+    }
+    
+    return 0;
+  }
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)
+static int lookup_check_mkdir(const char *path, int need_write, int create, unsigned short perms)
+{
+  struct path p; 
+
+  if (kern_path(path, LOOKUP_DIRECTORY|LOOKUP_FOLLOW, &p)) { 
+    
+    // directory does does not exist.  
+    
+    if (!create) { 
+      // we are not being asked to create it
+      ERROR("attempt to open %s, which does not exist\n",path);
+      return -1;
+    } else {
+      // We are being asked to create it
+
+      struct dentry *de;
+      int err;
+      
+      // Find its parent
+      if (kern_path(path,LOOKUP_PARENT|LOOKUP_FOLLOW,&p)) { 
+       ERROR("attempt to create %s failed because its parent cannot be looked up\n",path);
+       return -1;
+      }
+      
+      // Can we write to the parent?
+      
+      if (inode_permission(p.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { 
+       ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",path);
+       return -1;
+      }
+
+      // OK, we can, so let's create it
+      
+      de = kern_path_create(AT_FDCWD,path,&p,1);
+      
+      if (!de || IS_ERR(de)) { 
+       ERROR("cannot allocate dentry\n");
+       return -1;
+      }
+
+      err = vfs_mkdir(p.dentry->d_inode, de, perms);
+      
+      // lookup_create locks this for us!
+      
+      mutex_unlock(&(p.dentry->d_inode->i_mutex));
+
+      if (err) {
+       ERROR("attempt to create %s failed because mkdir failed\n",path);
+       return -1;
+      }
+
+      // successfully created it. 
+      return 0;
+
+    }
+    
+  } else {
+    
+    // it exists, can we read (and write, if needed) to it?
+    
+    if (inode_permission(p.dentry->d_inode, MAY_EXEC | MAY_READ | need_write ? MAY_WRITE : 0 )) {
+      ERROR("attempt to open %s, which has the wrong permissions\n",path);
+      return -1;
+    }
+    
+    return 0;
+  }
+}
+
+#endif
+
 
 static v3_keyed_stream_t open_stream_file(char *url,
                                          v3_keyed_stream_open_t ot)
 {
     struct file_keyed_stream *fks;
-    struct nameidata nd;
 
     if (strncasecmp(url,"file:",5)) { 
        WARNING("illegitimate attempt to open file stream \"%s\"\n",url);
@@ -684,80 +829,18 @@ static v3_keyed_stream_t open_stream_file(char *url,
        return 0;
     }
     
-    strcpy(fks->path,url+5);
+    strcpy(fks->path,url+5); // will fit
     
     fks->stype=STREAM_FILE;
 
     fks->ot= ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
 
-    // Does the directory exist, and can we read/write it?
-   
-    if (path_lookup(fks->path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) { 
-
-       // directory does does not exist.  
-
-       if (ot==V3_KS_RD_ONLY || ot==V3_KS_WR_ONLY) { 
-
-           // we are not being asked to create it
-           ERROR("attempt to open %s, which does not exist\n",fks->path);
-           goto fail_out;
-
-       } else {
-
-           // We are being asked to create it
-
-           struct dentry *de;
-           int err;
-
-           // Find its parent
-           if (path_lookup(fks->path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) { 
-               ERROR("attempt to create %s failed because its parent cannot be looked up\n",fks->path);
-               goto fail_out;
-           }
-
-           // Can we write to the parent?
-
-           if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { 
-               ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",fks->path);
-               goto fail_out;
-           }
-
-           // OK, we can, so let's create it
-
-           de = lookup_create(&nd,1);
-
-           if (!de || IS_ERR(de)) { 
-               ERROR("cannot allocate dentry\n");
-               goto fail_out;
-           }
-
-           err = vfs_mkdir(nd.path.dentry->d_inode, de, 0700);
-
-           // lookup_create locks this for us!
-
-           mutex_unlock(&(nd.path.dentry->d_inode->i_mutex));
-
-           if (err) {
-               ERROR("attempt to create %s failed because mkdir failed\n",fks->path);
-               goto fail_out;
-           }
-
-           // now the directory should exist and have reasonable permissions
-           return (v3_keyed_stream_t) fks;
-       }
-    } 
-
-    
-    // we must be in V3_KS_RD_ONLY or V3_KS_WR_ONLY, 
-    // and the directory exists, so we must check the permissions
-
-    if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | (ot==V3_KS_RD_ONLY ? MAY_READ : MAY_WRITE))) {
-       ERROR("attempt to open %s, which has the wrong permissions\n",fks->path);
-       goto fail_out;
-    } else {
-       return (v3_keyed_stream_t) fks;
+    if (lookup_check_mkdir(fks->path,ot!=V3_KS_RD_ONLY,ot==V3_KS_WR_ONLY_CREATE,0700)) { 
+      ERROR("cannot find or create directory for stream\n");
+      goto fail_out;
     }
 
+    return fks;
 
  fail_out:
     palacios_free(fks->path);
@@ -796,6 +879,7 @@ static v3_keyed_stream_key_t open_key_file(v3_keyed_stream_t stream,
        ERROR("cannot allocate file keyed stream for key %s\n",key);
        return 0;
     }
+    // this sequence will fit and terminate with a zero
     strcpy(path,fks->path);
     strcat(path,"/");
     strcat(path,key);
@@ -1852,6 +1936,7 @@ static long keyed_stream_ioctl_user(struct file * filp, unsigned int ioctl, unsi
             return -EFAULT;
         }
 
+       // overflow possible here for very large request
        if (resize_op(&(s->op),size-sizeof(struct palacios_user_keyed_stream_op))) {
            ERROR("unable to resize op in user key push response\n");
             palacios_spinlock_unlock_irqrestore(&(s->lock), flags);
@@ -1933,6 +2018,7 @@ int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned
        return -1;
     }
 
+    // overflow possible here, but only if this is a huge guest request (>4GB)
     url = palacios_alloc(len);
     
     if (!url) { 
@@ -2082,7 +2168,7 @@ static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
 
     s->op->type = PALACIOS_KSTREAM_OPEN_KEY;
     s->op->buf_len = len;
-    strncpy(s->op->buf,key,len);
+    strncpy(s->op->buf,key,len); // will terminate buffer
 
     // enter with it locked
     if (do_request_to_response(s,&flags)) { 
@@ -2349,8 +2435,12 @@ static int send_msg(struct net_stream *ns,  char * buf, int len)
        msg.msg_namelen = 0;
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
+#else
+       iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0);
+#endif
 
        iov.iov_base = (char *)&(buf[len-left]);
        iov.iov_len = (size_t)left;
@@ -2403,8 +2493,12 @@ static int recv_msg(struct net_stream *ns, char * buf, int len)
        msg.msg_namelen = 0;
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
+#else
+       iov_iter_init(&(msg.msg_iter),READ,&iov,1,0);
+#endif
        
        iov.iov_base = (void *)&(buf[len-left]);
        iov.iov_len = (size_t)left;
@@ -2779,7 +2873,7 @@ static sint64_t write_key_net(v3_keyed_stream_t stream, v3_keyed_stream_key_t ke
            ERROR("Could not send tag length in write_key_net\n");
            return -1;
        } 
-       if (send_msg(nks->ns,tag,taglen)!=len) { 
+       if (send_msg(nks->ns,tag,taglen)!=taglen) { 
            ERROR("Could not send tag in write_key_net\n");
            return -1;
        }