Annotation of src/tests/lib/libc/sys/t_mmap.c, Revision 1.13
1.13 ! christos 1: /* $NetBSD: t_mmap.c,v 1.12 2017/01/16 16:31:05 christos Exp $ */
1.1 jruoho 2:
3: /*-
4: * Copyright (c) 2011 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jukka Ruohonen.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
1.2 jruoho 31:
32: /*-
33: * Copyright (c)2004 YAMAMOTO Takashi,
34: * All rights reserved.
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: */
1.1 jruoho 57: #include <sys/cdefs.h>
1.13 ! christos 58: __RCSID("$NetBSD: t_mmap.c,v 1.12 2017/01/16 16:31:05 christos Exp $");
1.1 jruoho 59:
60: #include <sys/param.h>
1.12 christos 61: #include <sys/disklabel.h>
1.1 jruoho 62: #include <sys/mman.h>
1.10 christos 63: #include <sys/stat.h>
1.2 jruoho 64: #include <sys/socket.h>
1.1 jruoho 65: #include <sys/sysctl.h>
66: #include <sys/wait.h>
67:
1.2 jruoho 68: #include <atf-c.h>
1.1 jruoho 69: #include <errno.h>
70: #include <fcntl.h>
71: #include <signal.h>
1.3 jruoho 72: #include <stdio.h>
1.1 jruoho 73: #include <stdlib.h>
74: #include <string.h>
75: #include <unistd.h>
1.5 martin 76: #include <paths.h>
1.1 jruoho 77:
78: static long page = 0;
79: static char path[] = "mmap";
80: static void map_check(void *, int);
81: static void map_sighandler(int);
1.2 jruoho 82: static void testloan(void *, void *, char, int);
83:
84: #define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */
1.1 jruoho 85:
86: static void
87: map_check(void *map, int flag)
88: {
89:
90: if (flag != 0) {
91: ATF_REQUIRE(map == MAP_FAILED);
92: return;
93: }
94:
95: ATF_REQUIRE(map != MAP_FAILED);
96: ATF_REQUIRE(munmap(map, page) == 0);
97: }
98:
1.2 jruoho 99: void
100: testloan(void *vp, void *vp2, char pat, int docheck)
101: {
102: char buf[BUFSIZE];
103: char backup[BUFSIZE];
104: ssize_t nwritten;
105: ssize_t nread;
106: int fds[2];
107: int val;
108:
109: val = BUFSIZE;
110:
111: if (docheck != 0)
112: (void)memcpy(backup, vp, BUFSIZE);
113:
114: if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0)
115: atf_tc_fail("socketpair() failed");
116:
117: val = BUFSIZE;
118:
119: if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
120: atf_tc_fail("setsockopt() failed, SO_RCVBUF");
121:
122: val = BUFSIZE;
123:
124: if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0)
125: atf_tc_fail("setsockopt() failed, SO_SNDBUF");
126:
127: if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0)
128: atf_tc_fail("fcntl() failed");
129:
130: nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page);
131:
132: if (nwritten == -1)
133: atf_tc_fail("write() failed");
134:
135: /* Break loan. */
136: (void)memset(vp2, pat, BUFSIZE);
137:
138: nread = read(fds[1], buf + page, BUFSIZE - page);
139:
140: if (nread == -1)
141: atf_tc_fail("read() failed");
142:
143: if (nread != nwritten)
144: atf_tc_fail("too short read");
145:
146: if (docheck != 0 && memcmp(backup, buf + page, nread) != 0)
147: atf_tc_fail("data mismatch");
148:
149: ATF_REQUIRE(close(fds[0]) == 0);
150: ATF_REQUIRE(close(fds[1]) == 0);
151: }
152:
1.1 jruoho 153: static void
154: map_sighandler(int signo)
155: {
156: _exit(signo);
157: }
158:
1.3 jruoho 159: ATF_TC(mmap_block);
160: ATF_TC_HEAD(mmap_block, tc)
161: {
162: atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device");
1.5 martin 163: atf_tc_set_md_var(tc, "require.user", "root");
1.3 jruoho 164: }
165:
166: ATF_TC_BODY(mmap_block, tc)
167: {
1.5 martin 168: static const int mib[] = { CTL_HW, HW_DISKNAMES };
169: static const unsigned int miblen = __arraycount(mib);
170: char *map, *dk, *drives, dev[PATH_MAX];
171: size_t len;
172: int fd = -1;
1.3 jruoho 173:
1.7 bouyer 174: atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)");
1.3 jruoho 175:
1.5 martin 176: ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0);
177: drives = malloc(len);
178: ATF_REQUIRE(drives != NULL);
179: ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0);
180: for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) {
1.13 ! christos 181: if (strncmp(dk, "dk", 2) == 0)
! 182: snprintf(dev, sizeof(dev), _PATH_DEV "%s", dk);
! 183: else
! 184: snprintf(dev, sizeof(dev), _PATH_DEV "%s%c", dk,
! 185: 'a' + RAW_PART);
1.5 martin 186: fprintf(stderr, "trying: %s\n", dev);
1.3 jruoho 187:
1.5 martin 188: if ((fd = open(dev, O_RDONLY)) >= 0) {
189: (void)fprintf(stderr, "using %s\n", dev);
1.3 jruoho 190: break;
1.13 ! christos 191: } else
! 192: (void)fprintf(stderr, "%s: %s\n", dev, strerror(errno));
1.3 jruoho 193: }
1.5 martin 194: free(drives);
1.3 jruoho 195:
1.5 martin 196: if (fd < 0)
1.4 jruoho 197: atf_tc_skip("failed to find suitable block device");
1.3 jruoho 198:
199: map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0);
1.13 ! christos 200: ATF_REQUIRE_MSG(map != MAP_FAILED, "mmap: %s", strerror(errno));
1.3 jruoho 201:
202: (void)fprintf(stderr, "first byte %x\n", *map);
203: ATF_REQUIRE(close(fd) == 0);
204: (void)fprintf(stderr, "first byte %x\n", *map);
205:
206: ATF_REQUIRE(munmap(map, 4096) == 0);
207: }
208:
1.1 jruoho 209: ATF_TC(mmap_err);
210: ATF_TC_HEAD(mmap_err, tc)
211: {
212: atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
213: }
214:
215: ATF_TC_BODY(mmap_err, tc)
216: {
217: size_t addr = SIZE_MAX;
218: void *map;
219:
220: errno = 0;
221: map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
222:
223: ATF_REQUIRE(map == MAP_FAILED);
224: ATF_REQUIRE(errno == EBADF);
225:
226: errno = 0;
227: map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0);
228:
229: ATF_REQUIRE(map == MAP_FAILED);
230: ATF_REQUIRE(errno == EINVAL);
231:
232: errno = 0;
233: map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
234:
235: ATF_REQUIRE(map == MAP_FAILED);
236: ATF_REQUIRE(errno == EINVAL);
237: }
238:
1.2 jruoho 239: ATF_TC_WITH_CLEANUP(mmap_loan);
240: ATF_TC_HEAD(mmap_loan, tc)
241: {
242: atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)");
243: }
244:
245: ATF_TC_BODY(mmap_loan, tc)
246: {
247: char buf[BUFSIZE];
248: char *vp, *vp2;
249: int fd;
250:
251: fd = open(path, O_RDWR | O_CREAT, 0600);
252: ATF_REQUIRE(fd >= 0);
253:
254: (void)memset(buf, 'x', sizeof(buf));
255: (void)write(fd, buf, sizeof(buf));
256:
257: vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
258: MAP_FILE | MAP_PRIVATE, fd, 0);
259:
260: ATF_REQUIRE(vp != MAP_FAILED);
261:
262: vp2 = vp;
263:
264: testloan(vp, vp2, 'A', 0);
265: testloan(vp, vp2, 'B', 1);
266:
267: ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
268:
269: vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
270: MAP_FILE | MAP_SHARED, fd, 0);
271:
272: vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
273: MAP_FILE | MAP_SHARED, fd, 0);
274:
275: ATF_REQUIRE(vp != MAP_FAILED);
276: ATF_REQUIRE(vp2 != MAP_FAILED);
277:
278: testloan(vp, vp2, 'E', 1);
279:
280: ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
281: ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0);
282: }
283:
284: ATF_TC_CLEANUP(mmap_loan, tc)
285: {
286: (void)unlink(path);
287: }
288:
1.1 jruoho 289: ATF_TC_WITH_CLEANUP(mmap_prot_1);
290: ATF_TC_HEAD(mmap_prot_1, tc)
291: {
292: atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
293: }
294:
295: ATF_TC_BODY(mmap_prot_1, tc)
296: {
297: void *map;
298: int fd;
299:
300: /*
301: * Open a file write-only and try to
302: * map it read-only. This should fail.
303: */
304: fd = open(path, O_WRONLY | O_CREAT, 0700);
305:
306: if (fd < 0)
307: return;
308:
309: ATF_REQUIRE(write(fd, "XXX", 3) == 3);
310:
311: map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
312: map_check(map, 1);
313:
314: map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
315: map_check(map, 0);
316:
317: ATF_REQUIRE(close(fd) == 0);
318: }
319:
320: ATF_TC_CLEANUP(mmap_prot_1, tc)
321: {
322: (void)unlink(path);
323: }
324:
325: ATF_TC(mmap_prot_2);
326: ATF_TC_HEAD(mmap_prot_2, tc)
327: {
328: atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
329: }
330:
331: ATF_TC_BODY(mmap_prot_2, tc)
332: {
333: char buf[2];
334: void *map;
335: pid_t pid;
336: int sta;
337:
338: /*
339: * Make a PROT_NONE mapping and try to access it.
340: * If we catch a SIGSEGV, all works as expected.
341: */
342: map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
343: ATF_REQUIRE(map != MAP_FAILED);
344:
345: pid = fork();
346: ATF_REQUIRE(pid >= 0);
347:
348: if (pid == 0) {
349: ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
350: ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
351: }
352:
353: (void)wait(&sta);
354:
355: ATF_REQUIRE(WIFEXITED(sta) != 0);
356: ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
357: ATF_REQUIRE(munmap(map, page) == 0);
358: }
359:
360: ATF_TC_WITH_CLEANUP(mmap_prot_3);
361: ATF_TC_HEAD(mmap_prot_3, tc)
362: {
363: atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
364: }
365:
366: ATF_TC_BODY(mmap_prot_3, tc)
367: {
368: char buf[2];
369: int fd, sta;
370: void *map;
371: pid_t pid;
372:
373: /*
374: * Open a file, change the permissions
375: * to read-only, and try to map it as
376: * PROT_NONE. This should succeed, but
377: * the access should generate SIGSEGV.
378: */
379: fd = open(path, O_RDWR | O_CREAT, 0700);
380:
381: if (fd < 0)
382: return;
383:
384: ATF_REQUIRE(write(fd, "XXX", 3) == 3);
385: ATF_REQUIRE(close(fd) == 0);
386: ATF_REQUIRE(chmod(path, 0444) == 0);
387:
388: fd = open(path, O_RDONLY);
389: ATF_REQUIRE(fd != -1);
390:
391: map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
392: ATF_REQUIRE(map != MAP_FAILED);
393:
394: pid = fork();
395:
396: ATF_REQUIRE(pid >= 0);
397:
398: if (pid == 0) {
399: ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
400: ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
401: }
402:
403: (void)wait(&sta);
404:
405: ATF_REQUIRE(WIFEXITED(sta) != 0);
406: ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
407: ATF_REQUIRE(munmap(map, 3) == 0);
408: }
409:
410: ATF_TC_CLEANUP(mmap_prot_3, tc)
411: {
412: (void)unlink(path);
413: }
414:
415: ATF_TC_WITH_CLEANUP(mmap_truncate);
416: ATF_TC_HEAD(mmap_truncate, tc)
417: {
418: atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
419: }
420:
421: ATF_TC_BODY(mmap_truncate, tc)
422: {
423: char *map;
424: long i;
425: int fd;
426:
427: fd = open(path, O_RDWR | O_CREAT, 0700);
428:
429: if (fd < 0)
430: return;
431:
432: /*
433: * See that ftruncate(2) works
434: * while the file is mapped.
435: */
436: ATF_REQUIRE(ftruncate(fd, page) == 0);
437:
438: map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
439: fd, 0);
440: ATF_REQUIRE(map != MAP_FAILED);
441:
442: for (i = 0; i < page; i++)
443: map[i] = 'x';
444:
445: ATF_REQUIRE(ftruncate(fd, 0) == 0);
446: ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
447: ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
448: ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
449: ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
450: ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
451:
1.11 christos 452: (void)munmap(map, page);
1.1 jruoho 453: ATF_REQUIRE(close(fd) == 0);
454: }
455:
456: ATF_TC_CLEANUP(mmap_truncate, tc)
457: {
458: (void)unlink(path);
459: }
460:
1.8 christos 461: ATF_TC_WITH_CLEANUP(mmap_truncate_signal);
462: ATF_TC_HEAD(mmap_truncate_signal, tc)
463: {
464: atf_tc_set_md_var(tc, "descr",
465: "Test mmap(2) ftruncate(2) causing signal");
466: }
467:
468: ATF_TC_BODY(mmap_truncate_signal, tc)
469: {
470: char *map;
471: long i;
472: int fd, sta;
473: pid_t pid;
474:
475: fd = open(path, O_RDWR | O_CREAT, 0700);
476:
477: if (fd < 0)
478: return;
479:
480: ATF_REQUIRE(write(fd, "foo\n", 5) == 5);
481:
482: map = mmap(NULL, page, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
483: ATF_REQUIRE(map != MAP_FAILED);
484:
485: sta = 0;
486: for (i = 0; i < 5; i++)
487: sta += map[i];
488: ATF_REQUIRE(sta == 334);
489:
490: ATF_REQUIRE(ftruncate(fd, 0) == 0);
491: pid = fork();
492: ATF_REQUIRE(pid >= 0);
493:
494: if (pid == 0) {
495: ATF_REQUIRE(signal(SIGBUS, map_sighandler) != SIG_ERR);
1.9 martin 496: ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
1.8 christos 497: sta = 0;
498: for (i = 0; i < page; i++)
499: sta += map[i];
1.9 martin 500: /* child never will get this far, but the compiler will
501: not know, so better use the values calculated to
502: prevent the access to be optimized out */
1.8 christos 503: ATF_REQUIRE(i == 0);
1.9 martin 504: ATF_REQUIRE(sta == 0);
1.11 christos 505: (void)munmap(map, page);
506: (void)close(fd);
1.9 martin 507: return;
1.8 christos 508: }
509:
510: (void)wait(&sta);
511:
512: ATF_REQUIRE(WIFEXITED(sta) != 0);
1.9 martin 513: if (WEXITSTATUS(sta) == SIGSEGV)
514: atf_tc_fail("child process got SIGSEGV instead of SIGBUS");
1.8 christos 515: ATF_REQUIRE(WEXITSTATUS(sta) == SIGBUS);
516: ATF_REQUIRE(munmap(map, page) == 0);
517: ATF_REQUIRE(close(fd) == 0);
518: }
519:
520: ATF_TC_CLEANUP(mmap_truncate_signal, tc)
521: {
522: (void)unlink(path);
523: }
524:
1.1 jruoho 525: ATF_TC(mmap_va0);
526: ATF_TC_HEAD(mmap_va0, tc)
527: {
528: atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
529: }
530:
531: ATF_TC_BODY(mmap_va0, tc)
532: {
533: int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
534: size_t len = sizeof(int);
535: void *map;
536: int val;
537:
538: /*
539: * Make an anonymous fixed mapping at zero address. If the address
540: * is restricted as noted in security(7), the syscall should fail.
541: */
542: if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
543: atf_tc_fail("failed to read vm.user_va0_disable");
544:
545: map = mmap(NULL, page, PROT_EXEC, flags, -1, 0);
546: map_check(map, val);
547:
548: map = mmap(NULL, page, PROT_READ, flags, -1, 0);
549: map_check(map, val);
550:
551: map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
552: map_check(map, val);
553:
554: map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
555: map_check(map, val);
556:
557: map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
558: map_check(map, val);
559: }
560:
561: ATF_TP_ADD_TCS(tp)
562: {
563: page = sysconf(_SC_PAGESIZE);
564: ATF_REQUIRE(page >= 0);
565:
1.3 jruoho 566: ATF_TP_ADD_TC(tp, mmap_block);
1.1 jruoho 567: ATF_TP_ADD_TC(tp, mmap_err);
1.2 jruoho 568: ATF_TP_ADD_TC(tp, mmap_loan);
1.1 jruoho 569: ATF_TP_ADD_TC(tp, mmap_prot_1);
570: ATF_TP_ADD_TC(tp, mmap_prot_2);
571: ATF_TP_ADD_TC(tp, mmap_prot_3);
572: ATF_TP_ADD_TC(tp, mmap_truncate);
1.8 christos 573: ATF_TP_ADD_TC(tp, mmap_truncate_signal);
1.1 jruoho 574: ATF_TP_ADD_TC(tp, mmap_va0);
575:
576: return atf_no_error();
577: }
CVSweb <webmaster@jp.NetBSD.org>