1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2015-2016 Dmitry V. Levin <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2016 Red Hat, Inc.
4*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2016-2017 The strace developers.
5*cf84ac9aSAndroid Build Coastguard Worker * All rights reserved.
6*cf84ac9aSAndroid Build Coastguard Worker *
7*cf84ac9aSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
8*cf84ac9aSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
9*cf84ac9aSAndroid Build Coastguard Worker * are met:
10*cf84ac9aSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
11*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
12*cf84ac9aSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
13*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
14*cf84ac9aSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
15*cf84ac9aSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
16*cf84ac9aSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
17*cf84ac9aSAndroid Build Coastguard Worker *
18*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*cf84ac9aSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*cf84ac9aSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*cf84ac9aSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*cf84ac9aSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*cf84ac9aSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*cf84ac9aSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*cf84ac9aSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*cf84ac9aSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*cf84ac9aSAndroid Build Coastguard Worker */
29*cf84ac9aSAndroid Build Coastguard Worker
30*cf84ac9aSAndroid Build Coastguard Worker #include "tests.h"
31*cf84ac9aSAndroid Build Coastguard Worker #include <asm/unistd.h>
32*cf84ac9aSAndroid Build Coastguard Worker
33*cf84ac9aSAndroid Build Coastguard Worker #if defined __NR_userfaultfd && defined HAVE_LINUX_USERFAULTFD_H
34*cf84ac9aSAndroid Build Coastguard Worker
35*cf84ac9aSAndroid Build Coastguard Worker # include <fcntl.h>
36*cf84ac9aSAndroid Build Coastguard Worker # include <inttypes.h>
37*cf84ac9aSAndroid Build Coastguard Worker # include <stdint.h>
38*cf84ac9aSAndroid Build Coastguard Worker # include <stdio.h>
39*cf84ac9aSAndroid Build Coastguard Worker # include <string.h>
40*cf84ac9aSAndroid Build Coastguard Worker # include <unistd.h>
41*cf84ac9aSAndroid Build Coastguard Worker
42*cf84ac9aSAndroid Build Coastguard Worker # include <sys/ioctl.h>
43*cf84ac9aSAndroid Build Coastguard Worker # include <sys/mman.h>
44*cf84ac9aSAndroid Build Coastguard Worker # include <linux/ioctl.h>
45*cf84ac9aSAndroid Build Coastguard Worker # include <linux/userfaultfd.h>
46*cf84ac9aSAndroid Build Coastguard Worker
47*cf84ac9aSAndroid Build Coastguard Worker #include "xlat.h"
48*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/uffd_api_features.h"
49*cf84ac9aSAndroid Build Coastguard Worker
50*cf84ac9aSAndroid Build Coastguard Worker int
main(void)51*cf84ac9aSAndroid Build Coastguard Worker main(void)
52*cf84ac9aSAndroid Build Coastguard Worker {
53*cf84ac9aSAndroid Build Coastguard Worker int rc;
54*cf84ac9aSAndroid Build Coastguard Worker int fd = syscall(__NR_userfaultfd, O_NONBLOCK);
55*cf84ac9aSAndroid Build Coastguard Worker size_t pagesize = getpagesize();
56*cf84ac9aSAndroid Build Coastguard Worker
57*cf84ac9aSAndroid Build Coastguard Worker if (fd < 0)
58*cf84ac9aSAndroid Build Coastguard Worker perror_msg_and_skip("userfaultfd");
59*cf84ac9aSAndroid Build Coastguard Worker
60*cf84ac9aSAndroid Build Coastguard Worker /* ---- API ---- */
61*cf84ac9aSAndroid Build Coastguard Worker TAIL_ALLOC_OBJECT_CONST_PTR(struct uffdio_api, api_struct);
62*cf84ac9aSAndroid Build Coastguard Worker
63*cf84ac9aSAndroid Build Coastguard Worker /* With a bad fd */
64*cf84ac9aSAndroid Build Coastguard Worker memset(api_struct, 0, sizeof(*api_struct));
65*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_API, api_struct);
66*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_API, {api=0, features=0}) = %d %s (%m)\n",
67*cf84ac9aSAndroid Build Coastguard Worker rc, errno2name());
68*cf84ac9aSAndroid Build Coastguard Worker /* With a bad pointer */
69*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_API, NULL);
70*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_API, NULL) = %d %s (%m)\n",
71*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
72*cf84ac9aSAndroid Build Coastguard Worker /* Normal call */
73*cf84ac9aSAndroid Build Coastguard Worker api_struct->api = UFFD_API;
74*cf84ac9aSAndroid Build Coastguard Worker api_struct->features = 0;
75*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_API, api_struct);
76*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_API, {api=0xaa, features=0", fd);
77*cf84ac9aSAndroid Build Coastguard Worker if (api_struct->features) {
78*cf84ac9aSAndroid Build Coastguard Worker printf(" => features=");
79*cf84ac9aSAndroid Build Coastguard Worker printflags(uffd_api_features, api_struct->features,
80*cf84ac9aSAndroid Build Coastguard Worker "UFFD_FEATURE_???");
81*cf84ac9aSAndroid Build Coastguard Worker }
82*cf84ac9aSAndroid Build Coastguard Worker printf(", ioctls=1<<_UFFDIO_REGISTER|"
83*cf84ac9aSAndroid Build Coastguard Worker "1<<_UFFDIO_UNREGISTER|1<<_UFFDIO_API");
84*cf84ac9aSAndroid Build Coastguard Worker api_struct->ioctls &= ~(1ull<<_UFFDIO_REGISTER|
85*cf84ac9aSAndroid Build Coastguard Worker 1ull<<_UFFDIO_UNREGISTER|
86*cf84ac9aSAndroid Build Coastguard Worker 1ull<<_UFFDIO_API);
87*cf84ac9aSAndroid Build Coastguard Worker if (api_struct->ioctls)
88*cf84ac9aSAndroid Build Coastguard Worker printf("|%#" PRIx64, (uint64_t)api_struct->ioctls);
89*cf84ac9aSAndroid Build Coastguard Worker printf("}) = %d\n", rc);
90*cf84ac9aSAndroid Build Coastguard Worker
91*cf84ac9aSAndroid Build Coastguard Worker /* For the rest of the tests we need some anonymous memory */
92*cf84ac9aSAndroid Build Coastguard Worker void *area1 = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
93*cf84ac9aSAndroid Build Coastguard Worker MAP_PRIVATE|MAP_ANONYMOUS,
94*cf84ac9aSAndroid Build Coastguard Worker -1, 0);
95*cf84ac9aSAndroid Build Coastguard Worker if (area1 == MAP_FAILED)
96*cf84ac9aSAndroid Build Coastguard Worker perror_msg_and_fail("mmap area1");
97*cf84ac9aSAndroid Build Coastguard Worker void *area2 = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
98*cf84ac9aSAndroid Build Coastguard Worker MAP_PRIVATE|MAP_ANONYMOUS,
99*cf84ac9aSAndroid Build Coastguard Worker -1, 0);
100*cf84ac9aSAndroid Build Coastguard Worker if (area2 == MAP_FAILED)
101*cf84ac9aSAndroid Build Coastguard Worker perror_msg_and_fail("mmap area2");
102*cf84ac9aSAndroid Build Coastguard Worker madvise(area2, pagesize, MADV_DONTNEED);
103*cf84ac9aSAndroid Build Coastguard Worker *(char *)area1 = 42;
104*cf84ac9aSAndroid Build Coastguard Worker
105*cf84ac9aSAndroid Build Coastguard Worker /* ---- REGISTER ---- */
106*cf84ac9aSAndroid Build Coastguard Worker struct uffdio_register *register_struct =
107*cf84ac9aSAndroid Build Coastguard Worker tail_alloc(sizeof(*register_struct));
108*cf84ac9aSAndroid Build Coastguard Worker memset(register_struct, 0, sizeof(*register_struct));
109*cf84ac9aSAndroid Build Coastguard Worker
110*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_REGISTER, register_struct);
111*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_REGISTER, {range={start=0, len=0}, "
112*cf84ac9aSAndroid Build Coastguard Worker "mode=0}) = %d %s (%m)\n", rc, errno2name());
113*cf84ac9aSAndroid Build Coastguard Worker
114*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_REGISTER, NULL);
115*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_REGISTER, NULL) = %d %s (%m)\n",
116*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
117*cf84ac9aSAndroid Build Coastguard Worker
118*cf84ac9aSAndroid Build Coastguard Worker register_struct->range.start = (uint64_t)(uintptr_t)area2;
119*cf84ac9aSAndroid Build Coastguard Worker register_struct->range.len = pagesize;
120*cf84ac9aSAndroid Build Coastguard Worker register_struct->mode = UFFDIO_REGISTER_MODE_MISSING;
121*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_REGISTER, register_struct);
122*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_REGISTER, {range={start=%p, len=%#zx}, "
123*cf84ac9aSAndroid Build Coastguard Worker "mode=UFFDIO_REGISTER_MODE_MISSING, ioctls="
124*cf84ac9aSAndroid Build Coastguard Worker "1<<_UFFDIO_WAKE|1<<_UFFDIO_COPY|1<<_UFFDIO_ZEROPAGE",
125*cf84ac9aSAndroid Build Coastguard Worker fd, area2, pagesize);
126*cf84ac9aSAndroid Build Coastguard Worker register_struct->ioctls &= ~(1ull<<_UFFDIO_WAKE|
127*cf84ac9aSAndroid Build Coastguard Worker 1ull<<_UFFDIO_COPY|
128*cf84ac9aSAndroid Build Coastguard Worker 1ull<<_UFFDIO_ZEROPAGE);
129*cf84ac9aSAndroid Build Coastguard Worker if (register_struct->ioctls)
130*cf84ac9aSAndroid Build Coastguard Worker printf("|%#" PRIx64, (uint64_t)register_struct->ioctls);
131*cf84ac9aSAndroid Build Coastguard Worker printf("}) = %d\n", rc);
132*cf84ac9aSAndroid Build Coastguard Worker
133*cf84ac9aSAndroid Build Coastguard Worker /* With area2 registered we can now do the atomic copies onto it
134*cf84ac9aSAndroid Build Coastguard Worker * but be careful not to access it in any other way otherwise
135*cf84ac9aSAndroid Build Coastguard Worker * userfaultfd will cause us to stall.
136*cf84ac9aSAndroid Build Coastguard Worker */
137*cf84ac9aSAndroid Build Coastguard Worker /* ---- COPY ---- */
138*cf84ac9aSAndroid Build Coastguard Worker TAIL_ALLOC_OBJECT_CONST_PTR(struct uffdio_copy, copy_struct);
139*cf84ac9aSAndroid Build Coastguard Worker
140*cf84ac9aSAndroid Build Coastguard Worker memset(copy_struct, 0, sizeof(*copy_struct));
141*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_COPY, copy_struct);
142*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_COPY, {dst=0, src=0, len=0, mode=0"
143*cf84ac9aSAndroid Build Coastguard Worker "}) = %d %s (%m)\n", rc, errno2name());
144*cf84ac9aSAndroid Build Coastguard Worker
145*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_COPY, NULL);
146*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_COPY, NULL) = %d %s (%m)\n",
147*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
148*cf84ac9aSAndroid Build Coastguard Worker
149*cf84ac9aSAndroid Build Coastguard Worker copy_struct->dst = (uint64_t)(uintptr_t)area2;
150*cf84ac9aSAndroid Build Coastguard Worker copy_struct->src = (uint64_t)(uintptr_t)area1;
151*cf84ac9aSAndroid Build Coastguard Worker copy_struct->len = pagesize;
152*cf84ac9aSAndroid Build Coastguard Worker copy_struct->mode = UFFDIO_COPY_MODE_DONTWAKE;
153*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_COPY, copy_struct);
154*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_COPY, {dst=%p, src=%p, len=%#zx,"
155*cf84ac9aSAndroid Build Coastguard Worker " mode=UFFDIO_COPY_MODE_DONTWAKE, copy=%#zx}) = %d\n",
156*cf84ac9aSAndroid Build Coastguard Worker fd, area2, area1, pagesize, pagesize, rc);
157*cf84ac9aSAndroid Build Coastguard Worker
158*cf84ac9aSAndroid Build Coastguard Worker /* ---- ZEROPAGE ---- */
159*cf84ac9aSAndroid Build Coastguard Worker TAIL_ALLOC_OBJECT_CONST_PTR(struct uffdio_zeropage, zero_struct);
160*cf84ac9aSAndroid Build Coastguard Worker madvise(area2, pagesize, MADV_DONTNEED);
161*cf84ac9aSAndroid Build Coastguard Worker
162*cf84ac9aSAndroid Build Coastguard Worker memset(zero_struct, 0, sizeof(*zero_struct));
163*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_ZEROPAGE, zero_struct);
164*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_ZEROPAGE, {range={start=0, len=0}, mode=0"
165*cf84ac9aSAndroid Build Coastguard Worker "}) = %d %s (%m)\n", rc, errno2name());
166*cf84ac9aSAndroid Build Coastguard Worker
167*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_ZEROPAGE, NULL);
168*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_ZEROPAGE, NULL) = %d %s (%m)\n",
169*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
170*cf84ac9aSAndroid Build Coastguard Worker
171*cf84ac9aSAndroid Build Coastguard Worker zero_struct->range.start = (uint64_t)(uintptr_t)area2;
172*cf84ac9aSAndroid Build Coastguard Worker zero_struct->range.len = pagesize;
173*cf84ac9aSAndroid Build Coastguard Worker zero_struct->mode = UFFDIO_ZEROPAGE_MODE_DONTWAKE;
174*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_ZEROPAGE, zero_struct);
175*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_ZEROPAGE, {range={start=%p, len=%#zx},"
176*cf84ac9aSAndroid Build Coastguard Worker " mode=UFFDIO_ZEROPAGE_MODE_DONTWAKE, zeropage=%#zx}) = %d\n",
177*cf84ac9aSAndroid Build Coastguard Worker fd, area2, pagesize, pagesize, rc);
178*cf84ac9aSAndroid Build Coastguard Worker
179*cf84ac9aSAndroid Build Coastguard Worker /* ---- WAKE ---- */
180*cf84ac9aSAndroid Build Coastguard Worker TAIL_ALLOC_OBJECT_CONST_PTR(struct uffdio_range, range_struct);
181*cf84ac9aSAndroid Build Coastguard Worker memset(range_struct, 0, sizeof(*range_struct));
182*cf84ac9aSAndroid Build Coastguard Worker
183*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_WAKE, range_struct);
184*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_WAKE, {start=0, len=0}) = %d %s (%m)\n",
185*cf84ac9aSAndroid Build Coastguard Worker rc, errno2name());
186*cf84ac9aSAndroid Build Coastguard Worker
187*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_WAKE, NULL);
188*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_WAKE, NULL) = %d %s (%m)\n",
189*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
190*cf84ac9aSAndroid Build Coastguard Worker
191*cf84ac9aSAndroid Build Coastguard Worker range_struct->start = (uint64_t)(uintptr_t)area2;
192*cf84ac9aSAndroid Build Coastguard Worker range_struct->len = pagesize;
193*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_WAKE, range_struct);
194*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_WAKE, {start=%p, len=%#zx}) = %d\n",
195*cf84ac9aSAndroid Build Coastguard Worker fd, area2, pagesize, rc);
196*cf84ac9aSAndroid Build Coastguard Worker
197*cf84ac9aSAndroid Build Coastguard Worker /* ---- UNREGISTER ---- */
198*cf84ac9aSAndroid Build Coastguard Worker memset(range_struct, 0, sizeof(*range_struct));
199*cf84ac9aSAndroid Build Coastguard Worker
200*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(-1, UFFDIO_UNREGISTER, range_struct);
201*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(-1, UFFDIO_UNREGISTER, {start=0, len=0}) = %d %s (%m)\n",
202*cf84ac9aSAndroid Build Coastguard Worker rc, errno2name());
203*cf84ac9aSAndroid Build Coastguard Worker
204*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_UNREGISTER, NULL);
205*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_UNREGISTER, NULL) = %d %s (%m)\n",
206*cf84ac9aSAndroid Build Coastguard Worker fd, rc, errno2name());
207*cf84ac9aSAndroid Build Coastguard Worker
208*cf84ac9aSAndroid Build Coastguard Worker range_struct->start = (uint64_t)(uintptr_t)area2;
209*cf84ac9aSAndroid Build Coastguard Worker range_struct->len = pagesize;
210*cf84ac9aSAndroid Build Coastguard Worker rc = ioctl(fd, UFFDIO_UNREGISTER, range_struct);
211*cf84ac9aSAndroid Build Coastguard Worker printf("ioctl(%d, UFFDIO_UNREGISTER, {start=%p, len=%#zx}) = %d\n",
212*cf84ac9aSAndroid Build Coastguard Worker fd, area2, pagesize, rc);
213*cf84ac9aSAndroid Build Coastguard Worker puts("+++ exited with 0 +++");
214*cf84ac9aSAndroid Build Coastguard Worker return 0;
215*cf84ac9aSAndroid Build Coastguard Worker }
216*cf84ac9aSAndroid Build Coastguard Worker
217*cf84ac9aSAndroid Build Coastguard Worker #else
218*cf84ac9aSAndroid Build Coastguard Worker
219*cf84ac9aSAndroid Build Coastguard Worker SKIP_MAIN_UNDEFINED("__NR_userfaultfd && HAVE_LINUX_USERFAULTFD_H")
220*cf84ac9aSAndroid Build Coastguard Worker
221*cf84ac9aSAndroid Build Coastguard Worker #endif
222