1/* 2 * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "defs.h" 29#include <fcntl.h> 30 31#include "xlat/uffd_flags.h" 32 33SYS_FUNC(userfaultfd) 34{ 35 printflags(uffd_flags, tcp->u_arg[0], "UFFD_???"); 36 37 return RVAL_DECODED | RVAL_FD; 38} 39 40#ifdef HAVE_LINUX_USERFAULTFD_H 41# include <linux/ioctl.h> 42# include <linux/userfaultfd.h> 43 44# include "xlat/uffd_api_flags.h" 45# include "xlat/uffd_copy_flags.h" 46# include "xlat/uffd_register_ioctl_flags.h" 47# include "xlat/uffd_register_mode_flags.h" 48# include "xlat/uffd_zeropage_flags.h" 49 50static void 51tprintf_uffdio_range(const struct uffdio_range *range) 52{ 53 tprintf("{start=%#" PRI__x64 ", len=%#" PRI__x64 "}", 54 range->start, range->len); 55} 56 57int 58uffdio_ioctl(struct tcb *const tcp, const unsigned int code, 59 const kernel_ulong_t arg) 60{ 61 switch (code) { 62 case UFFDIO_API: { 63 struct uffdio_api ua; 64 if (entering(tcp)) { 65 tprints(", "); 66 if (umove_or_printaddr(tcp, arg, &ua)) 67 return RVAL_DECODED | 1; 68 /* Features is intended to contain some flags, but 69 * there aren't any defined yet. 70 */ 71 tprintf("{api=%#" PRI__x64 72 ", features=%#" PRI__x64, 73 ua.api, ua.features); 74 } else { 75 if (!syserror(tcp) && !umove(tcp, arg, &ua)) { 76 tprintf(", features.out=%#" PRI__x64 77 ", ioctls=", ua.features); 78 printflags64(uffd_api_flags, ua.ioctls, 79 "_UFFDIO_???"); 80 } 81 tprints("}"); 82 } 83 return 1; 84 } 85 86 case UFFDIO_COPY: { 87 struct uffdio_copy uc; 88 if (entering(tcp)) { 89 tprints(", "); 90 if (umove_or_printaddr(tcp, arg, &uc)) 91 return RVAL_DECODED | 1; 92 tprintf("{dst=%#" PRI__x64 ", src=%#" PRI__x64 93 ", len=%#" PRI__x64 ", mode=", 94 uc.dst, uc.src, uc.len); 95 printflags64(uffd_copy_flags, uc.mode, 96 "UFFDIO_COPY_???"); 97 } else { 98 if (!syserror(tcp) && !umove(tcp, arg, &uc)) 99 tprintf(", copy=%#" PRI__x64, uc.copy); 100 tprints("}"); 101 } 102 return 1; 103 } 104 105 case UFFDIO_REGISTER: { 106 struct uffdio_register ur; 107 if (entering(tcp)) { 108 tprints(", "); 109 if (umove_or_printaddr(tcp, arg, &ur)) 110 return RVAL_DECODED | 1; 111 tprints("{range="); 112 tprintf_uffdio_range(&ur.range); 113 tprints(", mode="); 114 printflags64(uffd_register_mode_flags, ur.mode, 115 "UFFDIO_REGISTER_MODE_???"); 116 } else { 117 if (!syserror(tcp) && !umove(tcp, arg, &ur)) { 118 tprints(", ioctls="); 119 printflags64(uffd_register_ioctl_flags, 120 ur.ioctls, "UFFDIO_???"); 121 } 122 tprints("}"); 123 } 124 return 1; 125 } 126 127 case UFFDIO_UNREGISTER: 128 case UFFDIO_WAKE: { 129 struct uffdio_range ura; 130 tprints(", "); 131 if (!umove_or_printaddr(tcp, arg, &ura)) 132 tprintf_uffdio_range(&ura); 133 return RVAL_DECODED | 1; 134 } 135 136 case UFFDIO_ZEROPAGE: { 137 struct uffdio_zeropage uz; 138 if (entering(tcp)) { 139 tprints(", "); 140 if (umove_or_printaddr(tcp, arg, &uz)) 141 return RVAL_DECODED | 1; 142 tprints("{range="); 143 tprintf_uffdio_range(&uz.range); 144 tprints(", mode="); 145 printflags64(uffd_zeropage_flags, uz.mode, 146 "UFFDIO_ZEROPAGE_???"); 147 } else { 148 if (!syserror(tcp) && !umove(tcp, arg, &uz)) 149 tprintf(", zeropage=%#" PRI__x64, uz.zeropage); 150 tprints("}"); 151 } 152 return 1; 153 } 154 155 default: 156 return RVAL_DECODED; 157 } 158} 159#endif /* HAVE_LINUX_USERFAULTFD_H */ 160