[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-13 Thread Jes Sorensen
On 12/10/10 18:09, Michael Roth wrote:
 I think with strictly enforced size limits the major liability for
 viewfile is, as you mentioned, users using it to view binary data or
 carefully crafted files that can mess up or fool users/shells/programs
 interpreting monitor output.
 
 But plain-text does not include escape sequences, so it's completely
 reasonable that we'd scrape them. And I'm not sure if a (qemu) in the
 text is a potential liability. Would there be any other issues to consider?
 
 If we can guard against those things, do you agree it wouldn't be an
 inherently dangerous interface? State-full, asynchronous RPCs like
 copyfile and exec are not really something I'd planned for the initial
 release. I think they'll take some time to get right, and a simple
 low-risk interface to cover what I'm fairly sure is the most common use
 case seems reasonable.

I am still wary of relying on strict limit enforcement. It is the sort
of thing that will eventually change without us noticing and we end up
with a security hole.

IMHO QEMU should not try to do these sorts of things, instead it should
provide the transport and control services. I don't think file viewing
belongs in QEMU at all. I would be a lot more comfortable if this was
implemented as a standalone monitor interface that connected to QEMU's
QMP interface. I could then use QMP to perform actions like copying the
file to /tmp and if viewing the file caused the monitor to lock up, we
wouldn't lose the guest. This could indeed be the start of an external
monitor :)

Cheers,
Jes



[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-09 Thread Michael Roth

On 12/07/2010 08:26 AM, Jes Sorensen wrote:

On 12/03/10 19:03, Michael Roth wrote:

Utilize the getfile RPC to provide a means to view text files in the
guest. Getfile can handle binary files as well but we don't advertise
that here due to the special handling requiring to store it and provide
it back to the user (base64 encoding it for instance). Hence the
otherwise confusing viewfile as opposed to getfile.

Signed-off-by: Michael Rothmdr...@linux.vnet.ibm.com
---
  hmp-commands.hx |   16 +
  monitor.c   |1 +
  qmp-commands.hx |   33 +++
  virtagent.c |   96 +++
  virtagent.h |3 ++
  5 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index e5585ba..423c752 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1212,6 +1212,22 @@ show available trace events and their state
  ETEXI
  #endif

+{
+.name   = agent_viewfile,
+.args_type  = filepath:s,
+.params = filepath,
+.help   = Echo a file from the guest filesystem,
+.user_print = do_agent_viewfile_print,
+.mhandler.cmd_async = do_agent_viewfile,
+.flags  = MONITOR_CMD_ASYNC,
+},
+
+STEXI
+...@item agent_viewfile @var{filepath}
+...@findex agent_viewfile
+Echo the file identified by @var{filepath} on the guest filesystem
+ETEXI
+
  STEXI
  @end table
  ETEXI
diff --git a/monitor.c b/monitor.c
index 8cee35d..145895d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -56,6 +56,7 @@
  #include json-parser.h
  #include osdep.h
  #include exec-all.h
+#include virtagent.h
  #ifdef CONFIG_SIMPLE_TRACE
  #include trace.h
  #endif
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 793cf1c..efa2137 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -738,6 +738,39 @@ Example:
  EQMP

  {
+.name   = agent_viewfile,
+.args_type  = filepath:s,
+.params = filepath,
+.help   = Echo a file from the guest filesystem,
+.user_print = monitor_user_noop,
+.mhandler.cmd_async = do_agent_viewfile,
+.flags  = MONITOR_CMD_ASYNC,
+},
+
+STEXI
+...@item agent_viewfile @var{filepath}
+...@findex agent_viewfile
+Echo the file identified by @var{filepath} on the guest filesystem
+ETEXI
+SQMP
+agent_viewfile
+
+
+Echo the file identified by @var{filepath} from the guest filesystem.
+
+Arguments:
+
+- filepath: Full guest path of the desired file
+
+Example:
+
+-  { execute: agent_viewfile,
+arguments: { filepath: /sys/kernel/kexec_loaded } }
+- { return: { contents: 0 } }
+
+EQMP
+
+{
  .name   = qmp_capabilities,
  .args_type  = ,
  .params = ,
diff --git a/virtagent.c b/virtagent.c
index 34d8545..4a4dc8a 100644
--- a/virtagent.c
+++ b/virtagent.c
@@ -139,3 +139,99 @@ out_free:
  out:
  return ret;
  }
+
+/* QMP/HMP RPC client functions */
+
+void do_agent_viewfile_print(Monitor *mon, const QObject *data)
+{
+QDict *qdict;
+const char *contents = NULL;
+int i;
+
+qdict = qobject_to_qdict(data);
+if (!qdict_haskey(qdict, contents)) {
+return;
+}
+
+contents = qdict_get_str(qdict, contents);
+if (contents != NULL) {
+ /* monitor_printf truncates so do it in chunks. also, file_contents
+  * may not be null-termed at proper location so explicitly calc
+  * last chunk sizes */
+for (i = 0; i  strlen(contents); i += 1024) {
+monitor_printf(mon, %.1024s, contents + i);
+}
+}
+monitor_printf(mon, \n);
+}
+
+static void do_agent_viewfile_cb(const char *resp_data,
+ size_t resp_data_len,
+ MonitorCompletion *mon_cb,
+ void *mon_data)
+{
+xmlrpc_value *resp = NULL;
+char *file_contents = NULL;
+size_t file_size;
+int ret;
+xmlrpc_env env;
+QDict *qdict = qdict_new();
+
+if (resp_data == NULL) {
+LOG(error handling RPC request);
+goto out_no_resp;
+}
+
+xmlrpc_env_init(env);
+resp = xmlrpc_parse_response(env, resp_data, resp_data_len);
+if (va_rpc_has_error(env)) {
+ret = -1;
+goto out_no_resp;
+}
+
+xmlrpc_parse_value(env, resp, 6,file_contents,file_size);
+if (va_rpc_has_error(env)) {
+ret = -1;
+goto out;


I believe this suffers from the same architectural problem I mentioned
in my comment to 07/21 - you don't restrict the file size, so it could
blow up the QEMU process on the host trying to view the wrong file.


It's restricted on the guest side:

virtagent-server.c:va_getfile():

while ((ret = read(fd, buf, VA_FILEBUF_LEN))  0) {
file_contents = qemu_realloc(file_contents, count + 
VA_FILEBUF_LEN);

memcpy(file_contents + count, buf, ret);
count += ret;
if (count  VA_GETFILE_MAX) {

[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-09 Thread Jes Sorensen
On 12/09/10 22:12, Michael Roth wrote:
 On 12/07/2010 08:26 AM, Jes Sorensen wrote:
 I believe this suffers from the same architectural problem I mentioned
 in my comment to 07/21 - you don't restrict the file size, so it could
 blow up the QEMU process on the host trying to view the wrong file.
 
 It's restricted on the guest side:
 
 virtagent-server.c:va_getfile():
 
 while ((ret = read(fd, buf, VA_FILEBUF_LEN))  0) {
 file_contents = qemu_realloc(file_contents, count +
 VA_FILEBUF_LEN);
 memcpy(file_contents + count, buf, ret);
 count += ret;
 if (count  VA_GETFILE_MAX) {
 xmlrpc_faultf(env, max file size (%d bytes) exceeded,
   VA_GETFILE_MAX);
 goto EXIT_CLOSE_BAD;
 }
 }

You cannot rely on the guest controlling this. You really have to treat
any guest as hostile and keep control and security in the host,
otherwise a hacked guest could end up attacking the host by blowing up
the host's QEMU process.

Cheers,
Jes



Re: [Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-07 Thread Michael Roth

On 12/06/2010 05:20 PM, Michael Roth wrote:

On 12/06/2010 04:08 PM, Adam Litke wrote:

On Fri, 2010-12-03 at 12:03 -0600, Michael Roth wrote:

Utilize the getfile RPC to provide a means to view text files in the
guest. Getfile can handle binary files as well but we don't advertise
that here due to the special handling requiring to store it and provide
it back to the user (base64 encoding it for instance). Hence the
otherwise confusing viewfile as opposed to getfile.


What happens to the monitor if you use this to view a binary file?


At the very least we probably get a lot of truncated files from the
binary-string conversion via monitor_printf(). Im not sure how the
qobject/json layer would deal with things.


Retrieving binary files progmatically using the QMP interface is a valid
use case right?


For getfile (the RPC), but not for viewfile (HMP/QMP). It's doable, but
we'd *have to* pass this data to the user as base64-encoded data at the
QMP level. At the HMP level I think we're good either way, since we
could just base64 decode in the print function.

So in the case of QMP we'd be pushing complexity to the user in exchange
for not having a seperate plain-text-only interface.

Either way seems reasonable, but I'd been planning on adding a seperate
`agent_copyfile remote_path local_path` command for dealing with
binary data, and making viewfile quick and easy for plain text (both for
HMP and QMP).



Although, agent_copyfile doesn't seem like the right approach looking at 
things like future libvirt integration. So we will most likely end up 
with a QMP command that passes base64-encoded binary data to the 
end-user for binary data, which we can provide a pretty-printing HMP 
function to decode. We'd need to take care to differentiate the HMP 
command from the QMP one however, else we'd have users tempted to do 
something like:


echo agent_getfile /remotepath/rand.bin | socat stdin 
unix-connect:monitor.sock  /localpath/rand.bin


to avoid having to decode the data. Would documenting the HMP 
counterpart as being reliable only for plain-text be sufficient? Or 
Should be have QMP:agent_getfile() and HMP:agent_viewfile()?





[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-07 Thread Jes Sorensen
On 12/03/10 19:03, Michael Roth wrote:
 Utilize the getfile RPC to provide a means to view text files in the
 guest. Getfile can handle binary files as well but we don't advertise
 that here due to the special handling requiring to store it and provide
 it back to the user (base64 encoding it for instance). Hence the
 otherwise confusing viewfile as opposed to getfile.
 
 Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com
 ---
  hmp-commands.hx |   16 +
  monitor.c   |1 +
  qmp-commands.hx |   33 +++
  virtagent.c |   96 
 +++
  virtagent.h |3 ++
  5 files changed, 149 insertions(+), 0 deletions(-)
 
 diff --git a/hmp-commands.hx b/hmp-commands.hx
 index e5585ba..423c752 100644
 --- a/hmp-commands.hx
 +++ b/hmp-commands.hx
 @@ -1212,6 +1212,22 @@ show available trace events and their state
  ETEXI
  #endif
  
 +{
 +.name   = agent_viewfile,
 +.args_type  = filepath:s,
 +.params = filepath,
 +.help   = Echo a file from the guest filesystem,
 +.user_print = do_agent_viewfile_print,
 +.mhandler.cmd_async = do_agent_viewfile,
 +.flags  = MONITOR_CMD_ASYNC,
 +},
 +
 +STEXI
 +...@item agent_viewfile @var{filepath}
 +...@findex agent_viewfile
 +Echo the file identified by @var{filepath} on the guest filesystem
 +ETEXI
 +
  STEXI
  @end table
  ETEXI
 diff --git a/monitor.c b/monitor.c
 index 8cee35d..145895d 100644
 --- a/monitor.c
 +++ b/monitor.c
 @@ -56,6 +56,7 @@
  #include json-parser.h
  #include osdep.h
  #include exec-all.h
 +#include virtagent.h
  #ifdef CONFIG_SIMPLE_TRACE
  #include trace.h
  #endif
 diff --git a/qmp-commands.hx b/qmp-commands.hx
 index 793cf1c..efa2137 100644
 --- a/qmp-commands.hx
 +++ b/qmp-commands.hx
 @@ -738,6 +738,39 @@ Example:
  EQMP
  
  {
 +.name   = agent_viewfile,
 +.args_type  = filepath:s,
 +.params = filepath,
 +.help   = Echo a file from the guest filesystem,
 +.user_print = monitor_user_noop,
 +.mhandler.cmd_async = do_agent_viewfile,
 +.flags  = MONITOR_CMD_ASYNC,
 +},
 +
 +STEXI
 +...@item agent_viewfile @var{filepath}
 +...@findex agent_viewfile
 +Echo the file identified by @var{filepath} on the guest filesystem
 +ETEXI
 +SQMP
 +agent_viewfile
 +
 +
 +Echo the file identified by @var{filepath} from the guest filesystem.
 +
 +Arguments:
 +
 +- filepath: Full guest path of the desired file
 +
 +Example:
 +
 +- { execute: agent_viewfile,
 +arguments: { filepath: /sys/kernel/kexec_loaded } }
 +- { return: { contents: 0 } }
 +
 +EQMP
 +
 +{
  .name   = qmp_capabilities,
  .args_type  = ,
  .params = ,
 diff --git a/virtagent.c b/virtagent.c
 index 34d8545..4a4dc8a 100644
 --- a/virtagent.c
 +++ b/virtagent.c
 @@ -139,3 +139,99 @@ out_free:
  out:
  return ret;
  }
 +
 +/* QMP/HMP RPC client functions */
 +
 +void do_agent_viewfile_print(Monitor *mon, const QObject *data)
 +{
 +QDict *qdict;
 +const char *contents = NULL;
 +int i;
 +
 +qdict = qobject_to_qdict(data);
 +if (!qdict_haskey(qdict, contents)) {
 +return;
 +}
 +
 +contents = qdict_get_str(qdict, contents);
 +if (contents != NULL) {
 + /* monitor_printf truncates so do it in chunks. also, file_contents
 +  * may not be null-termed at proper location so explicitly calc
 +  * last chunk sizes */
 +for (i = 0; i  strlen(contents); i += 1024) {
 +monitor_printf(mon, %.1024s, contents + i);
 +}
 +}
 +monitor_printf(mon, \n);
 +}
 +
 +static void do_agent_viewfile_cb(const char *resp_data,
 + size_t resp_data_len,
 + MonitorCompletion *mon_cb,
 + void *mon_data)
 +{
 +xmlrpc_value *resp = NULL;
 +char *file_contents = NULL;
 +size_t file_size;
 +int ret;
 +xmlrpc_env env;
 +QDict *qdict = qdict_new();
 +
 +if (resp_data == NULL) {
 +LOG(error handling RPC request);
 +goto out_no_resp;
 +}
 +
 +xmlrpc_env_init(env);
 +resp = xmlrpc_parse_response(env, resp_data, resp_data_len);
 +if (va_rpc_has_error(env)) {
 +ret = -1;
 +goto out_no_resp;
 +}
 +
 +xmlrpc_parse_value(env, resp, 6, file_contents, file_size);
 +if (va_rpc_has_error(env)) {
 +ret = -1;
 +goto out;

I believe this suffers from the same architectural problem I mentioned
in my comment to 07/21 - you don't restrict the file size, so it could
blow up the QEMU process on the host trying to view the wrong file.

I really think it is a bad idea to put this kind of command into the
monitor.

Jes




[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-06 Thread Adam Litke
On Fri, 2010-12-03 at 12:03 -0600, Michael Roth wrote:
 Utilize the getfile RPC to provide a means to view text files in the
 guest. Getfile can handle binary files as well but we don't advertise
 that here due to the special handling requiring to store it and provide
 it back to the user (base64 encoding it for instance). Hence the
 otherwise confusing viewfile as opposed to getfile.

What happens to the monitor if you use this to view a binary file?
Retrieving binary files progmatically using the QMP interface is a valid
use case right?  If so, I don't think it makes sense to introduce
confusion by renaming the rpc function from getfile to viewfile when we
are just exposing the getfile interface.

-- 
Thanks,
Adam




[Qemu-devel] Re: [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command

2010-12-06 Thread Michael Roth

On 12/06/2010 04:08 PM, Adam Litke wrote:

On Fri, 2010-12-03 at 12:03 -0600, Michael Roth wrote:

Utilize the getfile RPC to provide a means to view text files in the
guest. Getfile can handle binary files as well but we don't advertise
that here due to the special handling requiring to store it and provide
it back to the user (base64 encoding it for instance). Hence the
otherwise confusing viewfile as opposed to getfile.


What happens to the monitor if you use this to view a binary file?


At the very least we probably get a lot of truncated files from the 
binary-string conversion via monitor_printf(). Im not sure how the 
qobject/json layer would deal with things.



Retrieving binary files progmatically using the QMP interface is a valid
use case right?


For getfile (the RPC), but not for viewfile (HMP/QMP). It's doable, but 
we'd *have to* pass this data to the user as base64-encoded data at the 
QMP level. At the HMP level I think we're good either way, since we 
could just base64 decode in the print function.


So in the case of QMP we'd be pushing complexity to the user in exchange 
for not having a seperate plain-text-only interface.


Either way seems reasonable, but I'd been planning on adding a seperate 
`agent_copyfile remote_path local_path` command for dealing with 
binary data, and making viewfile quick and easy for plain text (both for 
HMP and QMP).