ia64/xen-unstable

changeset 6769:80afc502461b

Change xenbus_dev interface from ioctl to read/write.
Check boundaries so we can recover if userspace dies.
Also simplifies libxenstore.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Mon Sep 12 21:12:16 2005 +0000 (2005-09-12)
parents 282d5698ea40
children d8637529daff
files .hgignore linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c tools/xenstore/Makefile tools/xenstore/xs.c
line diff
     1.1 --- a/.hgignore	Mon Sep 12 20:46:37 2005 +0000
     1.2 +++ b/.hgignore	Mon Sep 12 21:12:16 2005 +0000
     1.3 @@ -152,7 +152,6 @@
     1.4  ^tools/xenstat/xentop/xentop$
     1.5  ^tools/xenstore/testsuite/tmp/.*$
     1.6  ^tools/xenstore/xen$
     1.7 -^tools/xenstore/xenbus_dev.h$
     1.8  ^tools/xenstore/xenstored$
     1.9  ^tools/xenstore/xenstored_test$
    1.10  ^tools/xenstore/xenstore-read$
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Sep 12 20:46:37 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Sep 12 21:12:16 2005 +0000
     2.3 @@ -5,6 +5,7 @@
     2.4   * to xenstore.
     2.5   * 
     2.6   * Copyright (c) 2005, Christian Limpach
     2.7 + * Copyright (c) 2005, Rusty Russell, IBM Corporation
     2.8   * 
     2.9   * This file may be distributed separately from the Linux kernel, or
    2.10   * incorporated into other software packages, subject to the following license:
    2.11 @@ -41,105 +42,97 @@
    2.12  
    2.13  #include <asm/uaccess.h>
    2.14  #include <asm-xen/xenbus.h>
    2.15 -#include <asm-xen/linux-public/xenbus_dev.h>
    2.16  #include <asm-xen/xen_proc.h>
    2.17  
    2.18  struct xenbus_dev_data {
    2.19 -	int in_transaction;
    2.20 +	/* Are there bytes left to be read in this message? */
    2.21 +	int bytes_left;
    2.22 +	/* Are we still waiting for the reply to a message we wrote? */
    2.23 +	int awaiting_reply;
    2.24 +	/* Buffer for outgoing messages. */
    2.25 +	unsigned int len;
    2.26 +	union {
    2.27 +		struct xsd_sockmsg msg;
    2.28 +		char buffer[PAGE_SIZE];
    2.29 +	} u;
    2.30  };
    2.31  
    2.32  static struct proc_dir_entry *xenbus_dev_intf;
    2.33  
    2.34 -void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec,
    2.35 -	       unsigned int num_vecs, unsigned int *len);
    2.36 -
    2.37 -static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data)
    2.38 +/* Reply can be long (dir, getperm): don't buffer, just examine
    2.39 + * headers so we can discard rest if they die. */
    2.40 +static ssize_t xenbus_dev_read(struct file *filp,
    2.41 +			       char __user *ubuf,
    2.42 +			       size_t len, loff_t *ppos)
    2.43  {
    2.44 -	struct xenbus_dev_talkv xt;
    2.45 -	unsigned int len;
    2.46 -	void *resp, *base;
    2.47 -	struct kvec *iovec;
    2.48 -	int ret = -EFAULT, v = 0;
    2.49 -
    2.50 -	if (copy_from_user(&xt, (void *)data, sizeof(xt)))
    2.51 -		return -EFAULT;
    2.52 +	struct xenbus_dev_data *data = filp->private_data;
    2.53 +	struct xsd_sockmsg msg;
    2.54 +	int err;
    2.55  
    2.56 -	iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL);
    2.57 -	if (iovec == NULL)
    2.58 -		return -ENOMEM;
    2.59 -
    2.60 -	if (copy_from_user(iovec, xt.iovec,
    2.61 -			   xt.num_vecs * sizeof(struct kvec)))
    2.62 -		goto out;
    2.63 +	/* Refill empty buffer? */
    2.64 +	if (data->bytes_left == 0) {
    2.65 +		if (len < sizeof(msg))
    2.66 +			return -EINVAL;
    2.67  
    2.68 -	for (v = 0; v < xt.num_vecs; v++) {
    2.69 -		base = iovec[v].iov_base;
    2.70 -		iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL);
    2.71 -		if (iovec[v].iov_base == NULL ||
    2.72 -		    copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len))
    2.73 -		{
    2.74 -			if (iovec[v].iov_base)
    2.75 -				kfree(iovec[v].iov_base);
    2.76 -			else
    2.77 -				ret = -ENOMEM;
    2.78 -			v--;
    2.79 -			goto out;
    2.80 -		}
    2.81 +		err = xb_read(&msg, sizeof(msg));
    2.82 +		if (err)
    2.83 +			return err;
    2.84 +		data->bytes_left = msg.len;
    2.85 +		if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
    2.86 +			return -EFAULT;
    2.87 +		/* We can receive spurious XS_WATCH_EVENT messages. */
    2.88 +		if (msg.type != XS_WATCH_EVENT)
    2.89 +			data->awaiting_reply = 0;
    2.90 +		return sizeof(msg);
    2.91  	}
    2.92  
    2.93 -	resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len);
    2.94 -	if (IS_ERR(resp)) {
    2.95 -		ret = PTR_ERR(resp);
    2.96 -		goto out;
    2.97 -	}
    2.98 +	/* Don't read over next header, or over temporary buffer. */
    2.99 +	if (len > sizeof(data->u.buffer))
   2.100 +		len = sizeof(data->u.buffer);
   2.101 +	if (len > data->bytes_left)
   2.102 +		len = data->bytes_left;
   2.103  
   2.104 -	switch (xt.type) {
   2.105 -	case XS_TRANSACTION_START:
   2.106 -		u->in_transaction = 1;
   2.107 -		break;
   2.108 -	case XS_TRANSACTION_END:
   2.109 -		u->in_transaction = 0;
   2.110 -		break;
   2.111 -	default:
   2.112 -		break;
   2.113 -	}
   2.114 +	err = xb_read(data->u.buffer, len);
   2.115 +	if (err)
   2.116 +		return err;
   2.117  
   2.118 -	ret = len;
   2.119 -	if (len > xt.len)
   2.120 -		len = xt.len;
   2.121 -
   2.122 -	if (copy_to_user(xt.buf, resp, len))
   2.123 -		ret = -EFAULT;
   2.124 -
   2.125 -	kfree(resp);
   2.126 - out:
   2.127 -	while (v-- > 0)
   2.128 -		kfree(iovec[v].iov_base);
   2.129 -	kfree(iovec);
   2.130 -	return ret;
   2.131 +	data->bytes_left -= len;
   2.132 +	if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
   2.133 +		return -EFAULT;
   2.134 +	return len;
   2.135  }
   2.136  
   2.137 -static int xenbus_dev_ioctl(struct inode *inode, struct file *filp,
   2.138 -			    unsigned int cmd, unsigned long data)
   2.139 +/* We do v. basic sanity checking so they don't screw up kernel later. */
   2.140 +static ssize_t xenbus_dev_write(struct file *filp,
   2.141 +				const char __user *ubuf,
   2.142 +				size_t len, loff_t *ppos)
   2.143  {
   2.144 -	struct xenbus_dev_data *u = filp->private_data;
   2.145 -	int ret = -ENOSYS;
   2.146 +	struct xenbus_dev_data *data = filp->private_data;
   2.147 +	int err;
   2.148  
   2.149 -	switch (cmd) {
   2.150 -	case IOCTL_XENBUS_DEV_TALKV:
   2.151 -		ret = xenbus_dev_talkv(u, data);
   2.152 -		break;
   2.153 -	default:
   2.154 -		ret = -EINVAL;
   2.155 -		break;
   2.156 +	/* We gather data in buffer until we're ready to send it. */
   2.157 +	if (len > data->len + sizeof(data->u))
   2.158 +		return -EINVAL;
   2.159 +	if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
   2.160 +		return -EFAULT;
   2.161 +	data->len += len;
   2.162 +	if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
   2.163 +		err = xb_write(data->u.buffer, data->len);
   2.164 +		if (err)
   2.165 +			return err;
   2.166 +		data->len = 0;
   2.167 +		data->awaiting_reply = 1;
   2.168  	}
   2.169 -	return ret;
   2.170 +	return len;
   2.171  }
   2.172  
   2.173  static int xenbus_dev_open(struct inode *inode, struct file *filp)
   2.174  {
   2.175  	struct xenbus_dev_data *u;
   2.176  
   2.177 +	/* Don't try seeking. */
   2.178 +	nonseekable_open(inode, filp);
   2.179 +
   2.180  	u = kmalloc(sizeof(*u), GFP_KERNEL);
   2.181  	if (u == NULL)
   2.182  		return -ENOMEM;
   2.183 @@ -155,20 +148,25 @@ static int xenbus_dev_open(struct inode 
   2.184  
   2.185  static int xenbus_dev_release(struct inode *inode, struct file *filp)
   2.186  {
   2.187 -	struct xenbus_dev_data *u = filp->private_data;
   2.188 +	struct xenbus_dev_data *data = filp->private_data;
   2.189  
   2.190 -	if (u->in_transaction)
   2.191 -		xenbus_transaction_end(1);
   2.192 +	/* Discard any unread replies. */
   2.193 +	while (data->bytes_left || data->awaiting_reply)
   2.194 +		xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
   2.195 +
   2.196 +	/* Harmless if no transaction in progress. */
   2.197 +	xenbus_transaction_end(1);
   2.198  
   2.199  	up(&xenbus_lock);
   2.200  
   2.201 -	kfree(u);
   2.202 +	kfree(data);
   2.203  
   2.204  	return 0;
   2.205  }
   2.206  
   2.207  static struct file_operations xenbus_dev_file_ops = {
   2.208 -	.ioctl = xenbus_dev_ioctl,
   2.209 +	.read = xenbus_dev_read,
   2.210 +	.write = xenbus_dev_write,
   2.211  	.open = xenbus_dev_open,
   2.212  	.release = xenbus_dev_release,
   2.213  };
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Mon Sep 12 20:46:37 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Mon Sep 12 21:12:16 2005 +0000
     3.3 @@ -106,10 +106,10 @@ void xenbus_debug_write(const char *str,
     3.4  }
     3.5  
     3.6  /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
     3.7 -void *xs_talkv(enum xsd_sockmsg_type type,
     3.8 -	       const struct kvec *iovec,
     3.9 -	       unsigned int num_vecs,
    3.10 -	       unsigned int *len)
    3.11 +static void *xs_talkv(enum xsd_sockmsg_type type,
    3.12 +		      const struct kvec *iovec,
    3.13 +		      unsigned int num_vecs,
    3.14 +		      unsigned int *len)
    3.15  {
    3.16  	struct xsd_sockmsg msg;
    3.17  	void *ret = NULL;
     4.1 --- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h	Mon Sep 12 20:46:37 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,47 +0,0 @@
     4.4 -/*
     4.5 - * xenbus_dev.h
     4.6 - * 
     4.7 - * Copyright (c) 2005, Christian Limpach
     4.8 - * 
     4.9 - * This file may be distributed separately from the Linux kernel, or
    4.10 - * incorporated into other software packages, subject to the following license:
    4.11 - * 
    4.12 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    4.13 - * of this source file (the "Software"), to deal in the Software without
    4.14 - * restriction, including without limitation the rights to use, copy, modify,
    4.15 - * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    4.16 - * and to permit persons to whom the Software is furnished to do so, subject to
    4.17 - * the following conditions:
    4.18 - * 
    4.19 - * The above copyright notice and this permission notice shall be included in
    4.20 - * all copies or substantial portions of the Software.
    4.21 - * 
    4.22 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    4.23 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    4.24 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    4.25 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    4.26 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    4.27 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    4.28 - * IN THE SOFTWARE.
    4.29 - */
    4.30 -
    4.31 -#ifndef _XENBUS_DEV_H_
    4.32 -#define _XENBUS_DEV_H_
    4.33 -
    4.34 -struct xenbus_dev_talkv {
    4.35 -	enum xsd_sockmsg_type type;
    4.36 -	const struct kvec *iovec;
    4.37 -	unsigned int num_vecs;
    4.38 -	char *buf;
    4.39 -	unsigned int len;
    4.40 -};
    4.41 -
    4.42 -/*
    4.43 - * @cmd: IOCTL_XENBUS_DEV_TALKV
    4.44 - * @arg: struct xenbus_dev_talkv
    4.45 - * Return: 0 on success, error code on failure.
    4.46 - */
    4.47 -#define	IOCTL_XENBUS_DEV_TALKV \
    4.48 -	_IOC(_IOC_NONE, 'X', 0, sizeof(struct xenbus_dev_talkv))
    4.49 -
    4.50 -#endif /* _XENBUS_DEV_H_ */
     5.1 --- a/tools/xenstore/Makefile	Mon Sep 12 20:46:37 2005 +0000
     5.2 +++ b/tools/xenstore/Makefile	Mon Sep 12 21:12:16 2005 +0000
     5.3 @@ -17,7 +17,6 @@ BASECFLAGS+= -O3 $(PROFILE)
     5.4  BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
     5.5  BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public
     5.6  BASECFLAGS+= -I.
     5.7 -BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public
     5.8  
     5.9  CFLAGS  += $(BASECFLAGS)
    5.10  LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
     6.1 --- a/tools/xenstore/xs.c	Mon Sep 12 20:46:37 2005 +0000
     6.2 +++ b/tools/xenstore/xs.c	Mon Sep 12 21:12:16 2005 +0000
     6.3 @@ -36,12 +36,10 @@
     6.4  #include "xenstored.h"
     6.5  #include "xs_lib.h"
     6.6  #include "utils.h"
     6.7 -#include "xenbus_dev.h"
     6.8  
     6.9  struct xs_handle
    6.10  {
    6.11  	int fd;
    6.12 -	enum { SOCK, DEV } type;
    6.13  };
    6.14  
    6.15  /* Get the socket from the store daemon handle.
    6.16 @@ -68,7 +66,6 @@ static struct xs_handle *get_socket(cons
    6.17  		h = malloc(sizeof(*h));
    6.18  		if (h) {
    6.19  			h->fd = sock;
    6.20 -			h->type = SOCK;
    6.21  			return h;
    6.22  		}
    6.23  	}
    6.24 @@ -82,16 +79,15 @@ static struct xs_handle *get_socket(cons
    6.25  static struct xs_handle *get_dev(const char *connect_to)
    6.26  {
    6.27  	int fd, saved_errno;
    6.28 -	struct xs_handle *h = NULL;
    6.29 +	struct xs_handle *h;
    6.30  
    6.31 -	fd = open(connect_to, O_RDONLY);
    6.32 +	fd = open(connect_to, O_RDWR);
    6.33  	if (fd < 0)
    6.34  		return NULL;
    6.35  
    6.36  	h = malloc(sizeof(*h));
    6.37  	if (h) {
    6.38  		h->fd = fd;
    6.39 -		h->type = DEV;
    6.40  		return h;
    6.41  	}
    6.42  
    6.43 @@ -190,9 +186,9 @@ static void *read_reply(int fd, enum xsd
    6.44  }
    6.45  
    6.46  /* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
    6.47 -static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
    6.48 -			   const struct iovec *iovec, unsigned int num_vecs,
    6.49 -			   unsigned int *len)
    6.50 +static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
    6.51 +		      const struct iovec *iovec, unsigned int num_vecs,
    6.52 +		      unsigned int *len)
    6.53  {
    6.54  	struct xsd_sockmsg msg;
    6.55  	void *ret = NULL;
    6.56 @@ -253,54 +249,6 @@ close_fd:
    6.57  	return NULL;
    6.58  }
    6.59  
    6.60 -/* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
    6.61 -static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
    6.62 -			  const struct iovec *iovec, unsigned int num_vecs,
    6.63 -			  unsigned int *len)
    6.64 -{
    6.65 -	struct xenbus_dev_talkv dt;
    6.66 -	char *buf;
    6.67 -	int err, buflen = 1024;
    6.68 -
    6.69 - again:
    6.70 -	buf = malloc(buflen);
    6.71 -	if (buf == NULL) {
    6.72 -		errno = ENOMEM;
    6.73 -		return NULL;
    6.74 -	}
    6.75 -	dt.type = type;
    6.76 -	dt.iovec = (struct kvec *)iovec;
    6.77 -	dt.num_vecs = num_vecs;
    6.78 -	dt.buf = buf;
    6.79 -	dt.len = buflen;
    6.80 -	err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
    6.81 -	if (err < 0) {
    6.82 -		free(buf);
    6.83 -		errno = err;
    6.84 -		return NULL;
    6.85 -	}
    6.86 -	if (err > buflen) {
    6.87 -		free(buf);
    6.88 -		buflen = err;
    6.89 -		goto again;
    6.90 -	}
    6.91 -	if (len)
    6.92 -		*len = err;
    6.93 -	return buf;
    6.94 -}
    6.95 -
    6.96 -/* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
    6.97 -static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
    6.98 -		      const struct iovec *iovec, unsigned int num_vecs,
    6.99 -		      unsigned int *len)
   6.100 -{
   6.101 -	if (h->type == SOCK)
   6.102 -		return xs_talkv_sock(h, type, iovec, num_vecs, len);
   6.103 -	if (h->type == DEV)
   6.104 -		return xs_talkv_dev(h, type, iovec, num_vecs, len);
   6.105 -	return NULL;
   6.106 -}
   6.107 -
   6.108  /* free(), but don't change errno. */
   6.109  static void free_no_errno(void *p)
   6.110  {