[Libvir] PATCH 1/4: QEMU driver char device support
Jim Meyering
jim at meyering.net
Thu Apr 24 20:01:29 UTC 2008
"Daniel P. Berrange" <berrange at redhat.com> wrote:
> On Fri, Apr 18, 2008 at 09:25:28PM +0100, Daniel P. Berrange wrote:
>> This supports the serial/character devices in QEMU. It is complete
>> except for fact that I don't extract the TTY path for type='pty'.
>> This needs addressing before merging
>
> This patch now includes the ability to extract the TTY path for
> serial and parallel devices, so we finally have 'virsh console'
> working for QEMU. THat said, plain QEMU/KVM has busted serial
> console which translates \r\n into \n\n, but I've sent a patch
> for that upstream
Nice!
...
> Index: src/qemu_conf.c
> ===================================================================
...
> +static int qemudGenerateXMLChar(virBufferPtr buf,
> + const struct qemud_vm_chr_def *dev,
> + const char *type)
> +{
> + const char *const types[] = {
> + "null",
> + "vc",
> + "pty",
> + "dev",
> + "file",
> + "pipe",
> + "stdio",
> + "udp",
> + "tcp",
> + "unix"
> + };
> + /*verify(ARRAY_CARDINALITY(types) == QEMUD_CHR_SRC_TYPE_LAST);*/
A couple days ago I relaxed the copyright on the gnulib module to
LGPLv2+, so you can go ahead and uncomment that, #include "verify.h",
and add "verify" to the list in bootstrap.
> Index: src/qemu_driver.c
> ===================================================================
...
> -static int qemudExtractMonitorPath(const char *haystack, char *path, int pathmax) {
> +static int qemudExtractMonitorPath(const char *haystack,
> + size_t *offset,
> + char *path, int pathmax) {
Thanks for shortening long lines ;-)
> static const char needle[] = "char device redirected to";
> char *tmp;
>
> - if (!(tmp = strstr(haystack, needle)))
> + /* First look for our magic string */
> + if (!(tmp = strstr(haystack + *offset, needle)))
> return -1;
>
> + /* Grab all the trailing data */
> strncpy(path, tmp+sizeof(needle), pathmax-1);
That should be sizeof(needle)-1.
Otherwise, if someone nasty gave you input ending with
"char device redirected to", the strncpy above would start
reading just past the NUL at the end of "haystack".
> path[pathmax-1] = '\0';
>
> - while (*path) {
> - /*
> - * The monitor path ends at first whitespace char
> - * so lets search for it & NULL terminate it there
> - */
> - if (isspace(*path)) {
> - *path = '\0';
> + /*
> + * And look for first whitespace character and nul terminate
> + * to mark end of the pty path
> + */
> + tmp = path;
> + while (*tmp) {
> + if (isspace(*tmp)) {
Since "tmp" has type "char", this causes trouble in an environment
where "char" is a signed type. When *tmp is larger than 127, it gets
sign-extended, and isspace can misbehave on the large negative number
(isspace is not defined for such values). Instead, do it like this:
if (isspace(*(unsigned char *)tmp)) {
or better, using the to_uchar function (from coreutils):
if (isspace(to_uchar(tmp))) {
/* Convert a possibly-signed character to an unsigned character. This is
a bit safer than casting to unsigned char, since it catches some type
errors that the cast doesn't. */
static inline unsigned char to_uchar (char ch) { return ch; }
I just happened upon this one, but have audited the rest of the code
for similar problems. To get an idea of the size of this task,
I got the list of is* functions from the man page and did this:
(tolower and toupper have the same limitation)
re=$(man isspace|grep is.....,.is|sed 's/ -.*//'|tr -s ', \n' \| \
|sed 's/^|//;s/|$//')
git grep -E "\b($re|tolower|toupper)\b"
Here's the output:
ChangeLog: Unlike in qemud.c, here we allow trailing "isspace", and in
ChangeLog: * src/virsh.c: Remove use of _GNU_SOURCE / isblank.
src/nodeinfo.c: while (*buf && isspace(*buf))
src/nodeinfo.c: while (*buf && isspace(*buf))
src/nodeinfo.c: && (*p == '\0' || *p == '.' || isspace(*p)))
src/nodeinfo.c: while (*buf && isspace(*buf))
src/nodeinfo.c: && (*p == '\0' || isspace(*p))
src/qemu_driver.c: if (isspace(*path)) {
src/sexpr.c: while (*ptr && !isspace(*ptr) && *ptr != ')' && *ptr != '
src/stats_linux.c: if (!isdigit(path[4]) || path[4] == '0' ||
src/stats_linux.c: if (p && (!isdigit(*p) || *p == '0' ||
src/stats_linux.c: if (!isdigit(path[3]) || path[3] == '0' ||
src/util.c:#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
src/util.c: while (*p == '0' && isxdigit (p[1]))
src/util.c: while (*q == '0' && isxdigit (q[1]))
src/util.c: if (!isxdigit(*str))
src/virsh.c: if (!isdigit (cpulist[i])) {
src/virsh.c: else if (!isdigit (cpulist[i])) {
src/virsh.c: && isalnum((unsigned char) *(p + 2))) {
So I've just posted a patch to fix those.
More information about the libvir-list
mailing list