X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fiface-keyed-stream.c;h=1f75aa0120725405ea84fa51d0c2c9e6ead88c81;hb=c8b23e99efde3aa5a2c26d1b8e9bc7dc914e6113;hp=5bce4315dc23ee52c27a9fac4f8a569896870968;hpb=e8ee9e1536b3fa2e69f5537a90f5e034e9529248;p=palacios.git diff --git a/linux_module/iface-keyed-stream.c b/linux_module/iface-keyed-stream.c index 5bce431..1f75aa0 100644 --- a/linux_module/iface-keyed-stream.c +++ b/linux_module/iface-keyed-stream.c @@ -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; }