150476Speter/* $NetBSD: t_modcmd.c,v 1.10 2017/01/13 21:30:43 christos Exp $ */ 21987Swollman 31987Swollman/* 41987Swollman * Copyright (c) 2009 The NetBSD Foundation, Inc. 5100346Sru * All rights reserved. 6100346Sru * 7100346Sru * Redistribution and use in source and binary forms, with or without 8100346Sru * modification, are permitted provided that the following conditions 9100346Sru * are met: 10100346Sru * 1. Redistributions of source code must retain the above copyright 11100346Sru * notice, this list of conditions and the following disclaimer. 12100346Sru * 2. Redistributions in binary form must reproduce the above copyright 13100346Sru * notice, this list of conditions and the following disclaimer in the 14100346Sru * documentation and/or other materials provided with the distribution. 15100346Sru * 16100346Sru * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17100346Sru * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18100346Sru * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19100346Sru * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20100346Sru * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21100346Sru * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22100346Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23100346Sru * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24100346Sru * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25100346Sru * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26100346Sru * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27100346Sru * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28100346Sru */ 29100346Sru 30100346Sru#include <sys/types.h> 31100346Sru#include <sys/mount.h> 32100346Sru#include <sys/sysctl.h> 33100346Sru 34100346Sru#include <rump/rump.h> 35100346Sru#include <rump/rump_syscalls.h> 36100346Sru 374257Sphk#include <fs/tmpfs/tmpfs_args.h> 38100346Sru 39100346Sru#include <atf-c.h> 40100346Sru#include <dlfcn.h> 41100346Sru#include <err.h> 42100346Sru#include <errno.h> 43100346Sru#include <stdio.h> 44100346Sru#include <stdlib.h> 45100346Sru#include <string.h> 46100346Sru#include <unistd.h> 47100346Sru#include <util.h> 48100346Sru 49100346Sru#include "h_macros.h" 50100346Sru/* 51100346Sru * We verify that modules can be loaded and unloaded. 52100346Sru * tmpfs was chosen because it does not depend on an image. 53100346Sru */ 54100346Sru 55100346SruATF_TC(cmsg_modcmd); 56100346SruATF_TC_HEAD(cmsg_modcmd, tc) 57100346Sru{ 58100346Sru atf_tc_set_md_var(tc, "descr", "Checks that loading and unloading " 59100346Sru "a module (vfs/tmpfs) is possible"); 60100346Sru} 61100346Sru 62100346Srustatic int 63100346Srudisable_autoload(void) 64100346Sru{ 65100346Sru struct sysctlnode q, ans[256]; 66100346Sru int mib[3]; 67100346Sru size_t alen; 68100346Sru unsigned i; 69100346Sru bool no; 70100346Sru 71100346Sru mib[0] = CTL_KERN; 72100346Sru mib[1] = CTL_QUERY; 73100346Sru alen = sizeof(ans); 74100346Sru 75100346Sru memset(&q, 0, sizeof(q)); 76100346Sru q.sysctl_flags = SYSCTL_VERSION; 77100346Sru 78100346Sru if (rump_sys___sysctl(mib, 2, ans, &alen, &q, sizeof(q)) == -1) 79100346Sru return -1; 80100346Sru 81100346Sru for (i = 0; i < __arraycount(ans); i++) 82100346Sru if (strcmp("module", ans[i].sysctl_name) == 0) 83100346Sru break; 84100346Sru if (i == __arraycount(ans)) { 85100346Sru errno = ENOENT; 86100346Sru return -1; 87100346Sru } 88100346Sru 89100346Sru mib[1] = ans[i].sysctl_num; 90100346Sru mib[2] = CTL_QUERY; 91100346Sru 92100346Sru if (rump_sys___sysctl(mib, 3, ans, &alen, &q, sizeof(q)) == -1) 93100346Sru return errno; 94100346Sru 95100346Sru for (i = 0; i < __arraycount(ans); i++) 96100346Sru if (strcmp("autoload", ans[i].sysctl_name) == 0) 97100346Sru break; 98100346Sru if (i == __arraycount(ans)) { 99100346Sru errno = ENOENT; 100100346Sru return -1; 101100346Sru } 102100346Sru 103100346Sru mib[2] = ans[i].sysctl_num; 104100346Sru 105100346Sru no = false; 106100346Sru alen = 0; 107100346Sru if (rump_sys___sysctl(mib, 3, NULL, &alen, &no, sizeof(no)) == -1) 108100346Sru return errno; 109100346Sru 110100346Sru return 0; 111100346Sru 112100346Sru} 113100346Sru 114100346Sru#define TMPFSMODULE "librumpfs_tmpfs.so" 115100346SruATF_TC_BODY(cmsg_modcmd, tc) 116100346Sru{ 117100346Sru struct tmpfs_args args; 118100346Sru const struct modinfo *const *mi_start, *const *mi_end; 119100346Sru void *handle; 120100346Sru int i, rv, loop = 0; 121100346Sru 122100346Sru rump_init(); 123100346Sru 124100346Sru if (disable_autoload() == -1) 125100346Sru atf_tc_fail_errno("count not disable module autoload"); 126100346Sru 127100346Sru memset(&args, 0, sizeof(args)); 128100346Sru args.ta_version = TMPFS_ARGS_VERSION; 129100346Sru args.ta_root_mode = 0777; 130100346Sru 131100346Sru if (rump_sys_mkdir("/mp", 0777) == -1) 132100346Sru atf_tc_fail_errno("mkdir mountpoint"); 133100346Sru if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) 134100346Sru atf_tc_fail("mount unexpectedly succeeded"); 135100346Sru 136100346Sru handle = dlopen(TMPFSMODULE, RTLD_GLOBAL); 137100346Sru if (handle == NULL) { 138100346Sru const char *dlmsg = dlerror(); 139100346Sru atf_tc_fail("cannot open %s: %s", TMPFSMODULE, dlmsg); 140100346Sru } 141100346Sru 142100346Sru again: 143100346Sru mi_start = dlsym(handle, "__start_link_set_modules"); 144100346Sru mi_end = dlsym(handle, "__stop_link_set_modules"); 145100346Sru if (mi_start == NULL || mi_end == NULL) 146100346Sru atf_tc_fail("cannot find module info"); 147121580Semax if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))!=0) 148100346Sru atf_tc_fail("module init failed: %d (%s)", rv, strerror(rv)); 149100346Sru if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))==0) 150100346Sru atf_tc_fail("module double init succeeded"); 151100346Sru 152100346Sru if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) == -1) 153100346Sru atf_tc_fail_errno("still cannot mount"); 154100346Sru if (rump_sys_unmount("/mp", 0) == -1) 155100346Sru atf_tc_fail("cannot unmount"); 156100346Sru for (i = 0; i < (int)(mi_end-mi_start); i++) { 157100346Sru if ((rv = rump_pub_module_fini(mi_start[i])) != 0) 158100346Sru atf_tc_fail("module fini failed: %d (%s)", 159100346Sru rv, strerror(rv)); 160100346Sru } 161100346Sru for (i = 0; i < (int)(mi_end-mi_start); i++) { 162100346Sru if ((rv = rump_pub_module_fini(mi_start[i])) == 0) 163100346Sru atf_tc_fail("module double fini succeeded"); 164100346Sru } 165100346Sru if (loop++ == 0) 166100346Sru goto again; 167100346Sru 168100346Sru if (dlclose(handle)) { 169100346Sru const char *dlmsg = dlerror(); 170100346Sru atf_tc_fail("cannot close %s: %s", TMPFSMODULE, dlmsg); 171100346Sru } 172100346Sru 173100346Sru if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) 174100346Sru atf_tc_fail("mount unexpectedly succeeded"); 175100346Sru} 176100346Sru 177100346SruATF_TP_ADD_TCS(tp) 178100346Sru{ 179100346Sru ATF_TP_ADD_TC(tp, cmsg_modcmd); 180100346Sru 181100346Sru return atf_no_error(); 182100346Sru} 183100346Sru