RFC userfaultfd ioctl decode

Dmitry V. Levin ldv at altlinux.org
Fri Apr 22 00:48:13 UTC 2016


On Thu, Apr 21, 2016 at 02:04:33PM +0100, Dr. David Alan Gilbert wrote:
[...]
> --- a/configure.ac
> +++ b/configure.ac
> @@ -420,6 +420,9 @@ AC_CHECK_HEADERS([linux/input.h], [
>  	AC_CHECK_MEMBERS([struct input_absinfo.resolution],,, [#include <linux/input.h>])
>  ])
>  
> +AC_CHECK_HEADERS([linux/userfaultfd.h], [
> +])

This should rather go to the first (big) AC_CHECK_HEADERS list
in the file.

> --- a/ioctl.c
> +++ b/ioctl.c
> @@ -263,6 +263,8 @@ ioctl_decode(struct tcb *tcp)
>  	case 'E':
>  		return evdev_ioctl(tcp, code, arg);
>  #endif
> +	case 0xaa:
> +		return uffdio_ioctl(tcp, code, arg);

The tradition approach is to wrap this into
#ifdef HAVE_LINUX_USERFAULTFD_H / #endif
so that ...

> --- a/userfaultfd.c
> +++ b/userfaultfd.c
> @@ -27,9 +27,50 @@
>  
>  #include "defs.h"
>  #include <fcntl.h>
> +#include <linux/ioctl.h>
> +#ifdef HAVE_LINUX_USERFAULTFD_H
> +#include <linux/userfaultfd.h>
> +#endif
>  
>  #include "xlat/uffd_flags.h"
>  
> +
> +int
> +uffdio_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
> +{
> +#ifdef HAVE_LINUX_USERFAULTFD_H

... the whole parser with all headers it needs could be wrapped
with a single ifdef.

> +	case UFFDIO_COPY: {
> +		struct uffdio_copy uc;
> +		if (!umove_or_printaddr(tcp, arg, &uc)) {
> +			if (entering(tcp)) {
> +				tprintf("{dst=%" PRIx64 ", src=%" PRIx64
> +				", len=%" PRIu64 ", mode=%" PRIu64 "}",
> +				(uint64_t)uc.dst, (uint64_t)uc.src,
> +				(uint64_t)uc.len, (uint64_t)uc.mode);

I suppose you can use recently added PRI__*64 instead of PRI*64,
this way you won't need explicit casts.

> +				return 1;
> +			} else {
> +				/* copy also returns the number of bytes
> +				 * copied */
> +				sprintf(auxbuf, "copy=%" PRId64,
> +				(int64_t)uc.copy);
> +				tcp->auxstr = auxbuf;
> +				return RVAL_STR | 1;
> +			}

The preferred method is to print uc.copy as a part of structure:

	if (entering(tcp)) {
		if (umove_or_printaddr(tcp, arg, &uc))
			return RVAL_DECODED | 1;
		tprintf("{dst=%" PRI__x64 ", src=%" PRI__x64
			", len=%" PRI__u64 ", mode=%" PRI__u64
			", copy=",
			uc.dst, uc.src, uc.len, uc.mode);
			return 1;
	} else {
		if (!umove_or_printaddr(tcp, arg, &uc.copy))
			tprintf("%" PRI__d64, uc.copy);
		tprints("}");
		return 1;
	}

> +		}
> +		break;

As (your edition of) this parser has already printed something at this
point, it has to return 1 + RVAL_something to let the caller know,
otherwise the address will be printed twice.  You can easily reproduce
this by invoking UFFDIO_COPY with NULL address.

> +	}
> +#endif
> +
> +	default:
> +		return 0;

As this parser in default case is not going to do anything on exiting,
it report this to the caller by returning RVAL_DECODED.


-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20160422/fb29695d/attachment.bin>


More information about the Strace-devel mailing list