[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interfa
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib |
Date: |
Wed, 7 Aug 2019 12:20:47 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 |
Hi,
On 8/7/19 9:14 AM, Balamuruhan S wrote:
> Adds scripting interface with python library to call functions in
> python modules from Qemu that can be used to feed input externally
> and without recompiling Qemu that can be used for early development,
> testing and can be extended to abstract some of Qemu code out to a
> python script to ease maintenance.
>
> Signed-off-by: Balamuruhan S <address@hidden>
> ---
> configure | 10 +++++
> include/sysemu/python_api.h | 30 +++++++++++++
> util/Makefile.objs | 1 +
> util/python_api.c | 100
> ++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 141 insertions(+)
> create mode 100644 include/sysemu/python_api.h
> create mode 100644 util/python_api.c
>
> diff --git a/configure b/configure
> index 714e7fb6a1..fddddcc879 100755
> --- a/configure
> +++ b/configure
> @@ -1866,6 +1866,11 @@ fi
> # Preserve python version since some functionality is dependent on it
> python_version=$($python -V 2>&1 | sed -e 's/Python\ //')
>
> +# Python config to be used for CFLAGS and LDFLAGS
> +if ! [ -z "$python" ]; then
> + python_config="$python-config"
> +fi
> +
> # Suppress writing compiled files
> python="$python -B"
>
> @@ -6304,6 +6309,11 @@ echo_version() {
> fi
> }
>
> +if ! [ -z "$python_config" ]; then
> + QEMU_CFLAGS="$QEMU_CFLAGS $($python_config --includes)"
> + QEMU_LDFLAGS="$QEMU_LDFLAGS $($python_config --ldflags)"
> +fi
> +
> # prepend pixman and ftd flags after all config tests are done
> QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS"
> QEMU_LDFLAGS="$fdt_ldflags $QEMU_LDFLAGS"
> diff --git a/include/sysemu/python_api.h b/include/sysemu/python_api.h
> new file mode 100644
> index 0000000000..ff02d58377
> --- /dev/null
> +++ b/include/sysemu/python_api.h
> @@ -0,0 +1,30 @@
> +#ifndef _PPC_PNV_PYTHON_H
> +#define _PPC_PNV_PYTHON_H
> +
> +#include <stdbool.h>
> +#include <Python.h>
> +
> +extern PyObject *python_callback(const char *abs_module_path, const char
> *mod,
> + const char *func, char *args[],
> + const int nargs);
> +
> +extern uint64_t python_callback_int(const char *abs_module_path,
> + const char *mod,
> + const char *func, char *args[],
> + const int nargs);
> +
> +extern char *python_callback_str(const char *abs_module_path, const char
> *mod,
> + const char *func, char *args[],
> + const int nargs);
> +
> +extern bool python_callback_bool(const char *abs_module_path, const char
> *mod,
> + const char *func, char *args[],
> + const int nargs);
> +
> +extern void python_args_init_cast_int(char *args[], int arg, int pos);
> +
> +extern void python_args_init_cast_long(char *args[], uint64_t arg, int pos);
> +
> +extern void python_args_clean(char *args[], int nargs);
> +
> +#endif
> diff --git a/util/Makefile.objs b/util/Makefile.objs
> index 41bf59d127..05851c94a7 100644
> --- a/util/Makefile.objs
> +++ b/util/Makefile.objs
> @@ -50,6 +50,7 @@ util-obj-y += range.o
> util-obj-y += stats64.o
> util-obj-y += systemd.o
> util-obj-y += iova-tree.o
> +util-obj-y += python_api.o
This is probably conditional to having python-dev (or whatever distribs
call the package) installed.
> util-obj-$(CONFIG_INOTIFY1) += filemonitor-inotify.o
> util-obj-$(CONFIG_LINUX) += vfio-helpers.o
> util-obj-$(CONFIG_POSIX) += drm.o
> diff --git a/util/python_api.c b/util/python_api.c
> new file mode 100644
> index 0000000000..854187e00f
> --- /dev/null
> +++ b/util/python_api.c
> @@ -0,0 +1,100 @@
> +#include "sysemu/python_api.h"
> +#include "qemu/osdep.h"
> +
> +PyObject *python_callback(const char *abs_module_path, const char *mod,
> + const char *func, char *args[], const int nargs)
> +{
> + PyObject *mod_name, *module, *mod_ref, *function, *arguments;
> + PyObject *result = 0;
> + PyObject *value = NULL;
> +
> + /* Set PYTHONPATH to absolute module path directory */
> + if (!abs_module_path)
> + abs_module_path = ".";
> + setenv("PYTHONPATH", abs_module_path, 1);
> +
> + /* Initialize the Python Interpreter */
> + Py_Initialize();
> + mod_name = PyUnicode_FromString(mod);
> + /* Import module object */
> + module = PyImport_Import(mod_name);
> + if (!module) {
> + PyErr_Print();
> + fprintf(stderr, "Failed to load \"%s\"\n", mod);
> + exit(EXIT_FAILURE);
> + }
> + mod_ref = PyModule_GetDict(module);
> + function = PyDict_GetItemString(mod_ref, func);
> + if (function && PyCallable_Check(function)) {
> + arguments = PyTuple_New(nargs);
> + for (int i = 0; i < nargs; i++) {
> + value = PyUnicode_FromString(args[i]);
> + if (!value) {
> + Py_DECREF(arguments);
> + Py_DECREF(module);
> + fprintf(stderr, "Cannot convert argument\n");
> + exit(EXIT_FAILURE);
> + }
> + PyTuple_SetItem(arguments, i, value);
> + }
> + PyErr_Print();
> + result = PyObject_CallObject(function, arguments);
> + PyErr_Print();
> + }
> + else {
> + if (PyErr_Occurred())
> + PyErr_Print();
> + fprintf(stderr, "Cannot find function \"%s\"\n", func);
> + exit(EXIT_FAILURE);
> + }
> + /* Clean up */
> + Py_DECREF(value);
> + Py_DECREF(module);
> + Py_DECREF(mod_name);
> + /* Finish the Python Interpreter */
> + Py_Finalize();
> + return result;
> +}
> +
> +uint64_t python_callback_int(const char *abs_module_path, const char *mod,
> + const char *func, char *args[], const int nargs)
> +{
> + PyObject *result;
> + result = python_callback(abs_module_path, mod, func, args, nargs);
> + return PyLong_AsLong(result);
> +}
> +
> +char *python_callback_str(const char *abs_module_path, const char *mod,
> + const char *func, char *args[], const int nargs)
> +{
> + PyObject *result;
> + result = python_callback(abs_module_path, mod, func, args, nargs);
> + return PyUnicode_AsUTF8(result);
> +}
> +
> +bool python_callback_bool(const char *abs_module_path, const char *mod,
> + const char *func, char *args[], const int nargs)
> +{
> + PyObject *result;
> + result = python_callback(abs_module_path, mod, func, args, nargs);
> + return (result == Py_True);
> +}
> +
> +void python_args_init_cast_int(char *args[], int arg, int pos)
> +{
> + args[pos]= malloc(sizeof(int));
> + sprintf(args[pos], "%d", arg);
> +}
> +
> +void python_args_init_cast_long(char *args[], uint64_t arg, int pos)
> +{
> + args[pos]= g_malloc(sizeof(uint64_t) * 2);
> + sprintf(args[pos], "%lx", arg);
> +}
> +
> +void python_args_clean(char *args[], int nargs)
> +{
> + for (int i = 0; i < nargs; i++) {
> + g_free(args[i]);
> + }
> +}
>
Wondering about security, is this feature safe to enable in production
environment? It seems to bypass all the hard effort to harden QEMU security.
- [Qemu-devel] [RFC PATCH 0/6] Enhancing Qemu MMIO emulation with scripting interface, Balamuruhan S, 2019/08/07
- [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Balamuruhan S, 2019/08/07
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib,
Philippe Mathieu-Daudé <=
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Stefan Hajnoczi, 2019/08/08
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Philippe Mathieu-Daudé, 2019/08/08
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Daniel P . Berrangé, 2019/08/08
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Stefan Hajnoczi, 2019/08/09
- Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Balamuruhan S, 2019/08/12
Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Stefan Hajnoczi, 2019/08/08
Re: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib, Daniel P . Berrangé, 2019/08/08