1e701e381faac8977f472b881d426335b869998dcLucas De Marchi/* 2e6b0e49b4ea7937a98b16f23d621244ee1a3e588Lucas De Marchi * Copyright (C) 2012-2013 ProFUSION embedded systems 30ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi * Copyright (C) 2012-2013 Lucas De Marchi <lucas.de.marchi@gmail.com> 4e701e381faac8977f472b881d426335b869998dcLucas De Marchi * 5e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * This program is free software; you can redistribute it and/or 6e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * modify it under the terms of the GNU Lesser General Public 7e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * License as published by the Free Software Foundation; either 8e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * version 2.1 of the License, or (at your option) any later version. 9e701e381faac8977f472b881d426335b869998dcLucas De Marchi * 10e701e381faac8977f472b881d426335b869998dcLucas De Marchi * This program is distributed in the hope that it will be useful, 11e701e381faac8977f472b881d426335b869998dcLucas De Marchi * but WITHOUT ANY WARRANTY; without even the implied warranty of 12e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * Lesser General Public License for more details. 14e701e381faac8977f472b881d426335b869998dcLucas De Marchi * 15e1b1ab24ab7b690343dbddd8087b17f6d722327cLucas De Marchi * You should have received a copy of the GNU Lesser General Public 16dea2dfee9b301da84dbb09cf510b8ebf2ef28fffLucas De Marchi * License along with this library; if not, see <http://www.gnu.org/licenses/>. 17e701e381faac8977f472b881d426335b869998dcLucas De Marchi */ 18e701e381faac8977f472b881d426335b869998dcLucas De Marchi 1955112d19f7067dff89b1481d5bd8cc49139c4ecbLucas De Marchi#ifndef HAVE_FINIT_MODULE 2055112d19f7067dff89b1481d5bd8cc49139c4ecbLucas De Marchi#define HAVE_FINIT_MODULE 1 2155112d19f7067dff89b1481d5bd8cc49139c4ecbLucas De Marchi#endif 2255112d19f7067dff89b1481d5bd8cc49139c4ecbLucas De Marchi 2353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <assert.h> 24c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <dirent.h> 25c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <dlfcn.h> 26fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi#include <elf.h> 2753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <errno.h> 2853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <fcntl.h> 2953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <limits.h> 3053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <stdarg.h> 3153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <stddef.h> 3253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <stdio.h> 33c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stdlib.h> 34c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <string.h> 35c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <unistd.h> 36e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook#include <sys/mman.h> 3753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include <sys/stat.h> 380ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi#include <sys/syscall.h> 39c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <sys/types.h> 40063086e038657de64f9980bc51954b0817fa8e6cMichal Marek#include <sys/utsname.h> 4153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 4296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <shared/util.h> 4396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi 4453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi/* kmod_elf_get_section() is not exported, we need the private header */ 451315123955f8c53e5ac9f7f5fb937c5e110aa4f1Lucas De Marchi#include <libkmod/libkmod-internal.h> 4653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 4753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi/* FIXME: hack, change name so we don't clash */ 4853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#undef ERR 4953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include "testsuite.h" 5053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi#include "stripped-module.h" 5153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 5253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistruct mod { 5353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct mod *next; 5453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi int ret; 5553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi int errcode; 5653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi char name[]; 5753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi}; 5853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 5953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistatic struct mod *modules; 6053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistatic bool need_init = true; 61a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchistatic struct kmod_ctx *ctx; 6253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 6353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistatic void parse_retcodes(struct mod *_modules, const char *s) 6453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi{ 6553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi const char *p; 6653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 6753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (s == NULL) 6853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return; 6953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 7053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi for (p = s;;) { 7153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct mod *mod; 7253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi const char *modname; 7353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi char *end; 7453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi size_t modnamelen; 7553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi int ret, errcode; 7653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi long l; 7753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 7853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi modname = p; 7953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (modname == NULL || modname[0] == '\0') 8053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 8153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 8253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi modnamelen = strcspn(s, ":"); 8353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (modname[modnamelen] != ':') 8453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 8553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 8653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi p = modname + modnamelen + 1; 8753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (p == NULL) 8853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 8953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 9053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi l = strtol(p, &end, 0); 9153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (end == p || *end != ':') 9253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 9353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi ret = (int) l; 9453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi p = end + 1; 9553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 9653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi l = strtol(p, &end, 0); 9753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (*end == ':') 9853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi p = end + 1; 9953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi else if (*end != '\0') 10053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 10153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 10253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi errcode = (int) l; 10353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 10453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod = malloc(sizeof(*mod) + modnamelen + 1); 10553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (mod == NULL) 10653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi break; 10753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 10853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi memcpy(mod->name, modname, modnamelen); 10953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod->name[modnamelen] = '\0'; 11053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod->ret = ret; 11153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod->errcode = errcode; 11253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod->next = _modules; 11353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi _modules = mod; 11453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi } 11553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi} 11653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 1175a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchistatic int write_one_line_file(const char *fn, const char *line, int len) 1185a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi{ 1195a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi FILE *f; 1205a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi int r; 1215a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1225a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi assert(fn); 1235a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi assert(line); 1245a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1255a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi f = fopen(fn, "we"); 1265a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi if (!f) 1275a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi return -errno; 1285a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1295a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi errno = 0; 1305a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi if (fputs(line, f) < 0) { 1315a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi r = -errno; 1325a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi goto finish; 1335a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi } 1345a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1355a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi fflush(f); 1365a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1375a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi if (ferror(f)) { 1385a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi if (errno != 0) 1395a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi r = -errno; 1405a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi else 1415a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi r = -EIO; 1425a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi } else 1435a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi r = 0; 1445a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1455a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchifinish: 1465a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi fclose(f); 1475a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi return r; 1485a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi} 1495a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1505a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchistatic int create_sysfs_files(const char *modname) 1515a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi{ 1525a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi char buf[PATH_MAX]; 1535a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi const char *sysfsmod = "/sys/module/"; 1545a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi int len = strlen(sysfsmod); 1555a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1565a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi memcpy(buf, sysfsmod, len); 1575a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi strcpy(buf + len, modname); 1585a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi len += strlen(modname); 1595a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 160c493b937509596eb038a00926a714c3c99615287Lucas De Marchi assert(mkdir_p(buf, len, 0755) >= 0); 1615a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 1625a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi strcpy(buf + len, "/initstate"); 1635a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi return write_one_line_file(buf, "live\n", strlen("live\n")); 1645a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi} 1655a2949cdf32cf6193992e3362c161ee1df978d2aLucas De Marchi 16653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistatic struct mod *find_module(struct mod *_modules, const char *modname) 16753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi{ 16853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct mod *mod; 16953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 17053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi for (mod = _modules; mod != NULL; mod = mod->next) { 1715c42c5fcedb3d1ce1de62711870e691cf768f4caLucas De Marchi if (streq(mod->name, modname)) 17253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return mod; 17353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi } 17453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 17553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return NULL; 17653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi} 17753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 17853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchistatic void init_retcodes(void) 17953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi{ 18053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi const char *s; 18153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 18253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (!need_init) 18353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return; 18453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 18553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi need_init = false; 18653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi s = getenv(S_TC_INIT_MODULE_RETCODES); 18753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (s == NULL) { 18853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi fprintf(stderr, "TRAP init_module(): missing export %s?\n", 18953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi S_TC_INIT_MODULE_RETCODES); 19053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi } 19153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 192a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi ctx = kmod_new(NULL, NULL); 193a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 19453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi parse_retcodes(modules, s); 19553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi} 19653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 197a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchistatic inline bool module_is_inkernel(const char *modname) 198a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi{ 199a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi struct kmod_module *mod; 200a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi int state; 201a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi bool ret; 202a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 203a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi if (kmod_module_new_from_name(ctx, modname, &mod) < 0) 204a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi return false; 205a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 206a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi state = kmod_module_get_initstate(mod); 207a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 208a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi if (state == KMOD_MODULE_LIVE || 209a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi state == KMOD_MODULE_BUILTIN) 210a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi ret = true; 211a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi else 212a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi ret = false; 213a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 214a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi kmod_module_unref(mod); 215a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 216a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi return ret; 217a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi} 218a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 219fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchistatic uint8_t elf_identify(void *mem) 220fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi{ 221fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi uint8_t *p = mem; 222fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi return p[EI_CLASS]; 223fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi} 224fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi 22553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De MarchiTS_EXPORT long init_module(void *mem, unsigned long len, const char *args); 22653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 22753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi/* 228ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * Default behavior is to try to mimic init_module behavior inside the kernel. 229ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * If it is a simple test that you know the error code, set the return code 230ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * in TESTSUITE_INIT_MODULE_RETCODES env var instead. 231ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * 232ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * The exception is when the module name is not find in the memory passed. 233ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * This is because we want to be able to pass dummy modules (and not real 234ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi * ones) and it still work. 23553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi */ 23653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchilong init_module(void *mem, unsigned long len, const char *args) 23753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi{ 23853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi const char *modname; 23953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct kmod_elf *elf; 24053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct mod *mod; 24153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi const void *buf; 24253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi uint64_t bufsize; 24353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi int err; 244fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi uint8_t class; 245fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi off_t offset; 24653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 24753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi init_retcodes(); 24853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 24953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi elf = kmod_elf_new(mem, len); 25053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (elf == NULL) 25153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return 0; 25253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 25353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi err = kmod_elf_get_section(elf, ".gnu.linkonce.this_module", &buf, 25453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi &bufsize); 25553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi kmod_elf_unref(elf); 25653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 257fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi /* We couldn't parse the ELF file. Just exit as if it was successful */ 25853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi if (err < 0) 25953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi return 0; 26053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 261fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi /* We need to open both 32 and 64 bits module - hack! */ 262fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi class = elf_identify(mem); 263fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi if (class == ELFCLASS64) 264fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi offset = MODULE_NAME_OFFSET_64; 265fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi else 266fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi offset = MODULE_NAME_OFFSET_32; 267fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi 268fca5b9bcd4c57abb74eed3f766d5c58a7b827e71Lucas De Marchi modname = (char *)buf + offset; 26953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi mod = find_module(modules, modname); 270ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi if (mod != NULL) { 271ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi errno = mod->errcode; 272ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi err = mod->ret; 273a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi } else if (module_is_inkernel(modname)) { 274a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi err = -1; 275a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi errno = EEXIST; 276a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi } else 277ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi err = 0; 27853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 279ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi if (err == 0) 280ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi create_sysfs_files(modname); 281ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi 282ddf1e7a61711580fee4d8d904a4a388aafecce27Lucas De Marchi return err; 28353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi} 28453646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi 285063086e038657de64f9980bc51954b0817fa8e6cMichal Marekstatic int check_kernel_version(int major, int minor) 286063086e038657de64f9980bc51954b0817fa8e6cMichal Marek{ 287063086e038657de64f9980bc51954b0817fa8e6cMichal Marek struct utsname u; 288063086e038657de64f9980bc51954b0817fa8e6cMichal Marek const char *p; 289063086e038657de64f9980bc51954b0817fa8e6cMichal Marek int maj = 0, min = 0; 290063086e038657de64f9980bc51954b0817fa8e6cMichal Marek 291063086e038657de64f9980bc51954b0817fa8e6cMichal Marek if (uname(&u) < 0) 292063086e038657de64f9980bc51954b0817fa8e6cMichal Marek return false; 293063086e038657de64f9980bc51954b0817fa8e6cMichal Marek for (p = u.release; *p >= '0' && *p <= '9'; p++) 294063086e038657de64f9980bc51954b0817fa8e6cMichal Marek maj = maj * 10 + *p - '0'; 295063086e038657de64f9980bc51954b0817fa8e6cMichal Marek if (*p == '.') 296063086e038657de64f9980bc51954b0817fa8e6cMichal Marek for (p++; *p >= '0' && *p <= '9'; p++) 297063086e038657de64f9980bc51954b0817fa8e6cMichal Marek min = min * 10 + *p - '0'; 298063086e038657de64f9980bc51954b0817fa8e6cMichal Marek if (maj > major || (maj == major && min >= minor)) 299063086e038657de64f9980bc51954b0817fa8e6cMichal Marek return true; 300063086e038657de64f9980bc51954b0817fa8e6cMichal Marek return false; 301063086e038657de64f9980bc51954b0817fa8e6cMichal Marek} 302063086e038657de64f9980bc51954b0817fa8e6cMichal Marek 303063086e038657de64f9980bc51954b0817fa8e6cMichal Marek 304e87352d289aa19ed388e9e19507d86a39936f3b4Kees CookTS_EXPORT int finit_module(const int fd, const char *args, const int flags); 305e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 306e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cookint finit_module(const int fd, const char *args, const int flags) 307e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook{ 308e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook int err; 309e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook void *mem; 310e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook unsigned long len; 311e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook struct stat st; 312e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 313063086e038657de64f9980bc51954b0817fa8e6cMichal Marek if (!check_kernel_version(3, 8)) { 314063086e038657de64f9980bc51954b0817fa8e6cMichal Marek errno = ENOSYS; 315063086e038657de64f9980bc51954b0817fa8e6cMichal Marek return -1; 316063086e038657de64f9980bc51954b0817fa8e6cMichal Marek } 317e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook if (fstat(fd, &st) < 0) 318e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook return -1; 319e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 320e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook len = st.st_size; 321e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 322e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook if (mem == MAP_FAILED) 323e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook return -1; 324e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 325e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook err = init_module(mem, len, args); 326e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook munmap(mem, len); 327e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 328e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook return err; 329e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook} 330e87352d289aa19ed388e9e19507d86a39936f3b4Kees Cook 3310ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De MarchiTS_EXPORT long int syscall(long int __sysno, ...) 3320ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi{ 3330ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi va_list ap; 3340ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi long ret; 3350ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3368e00db9537fee379d900b352b4f6750c52d17726Lucas De Marchi if (__sysno == -1) { 3378e00db9537fee379d900b352b4f6750c52d17726Lucas De Marchi errno = ENOSYS; 3380ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi return -1; 3398e00db9537fee379d900b352b4f6750c52d17726Lucas De Marchi } 3408e00db9537fee379d900b352b4f6750c52d17726Lucas De Marchi 3418e00db9537fee379d900b352b4f6750c52d17726Lucas De Marchi if (__sysno == __NR_finit_module) { 3420ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi const char *args; 3430ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi int flags; 3440ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi int fd; 3450ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3460ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi va_start(ap, __sysno); 3470ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3480ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi fd = va_arg(ap, int); 3490ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi args = va_arg(ap, const char *); 3500ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi flags = va_arg(ap, int); 3510ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3520ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi ret = finit_module(fd, args, flags); 3530ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3540ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi va_end(ap); 3550ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi return ret; 3560ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi } 3570ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 3580ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi /* 3590ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi * FIXME: no way to call the libc function - let's hope there are no 3600ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi * other users. 3610ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi */ 3620ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi abort(); 3630ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi} 3640ae58609dc0b983aa17ea7aa38c071cf1830819aLucas De Marchi 36553646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi/* the test is going away anyway, but lets keep valgrind happy */ 36653646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchivoid free_resources(void) __attribute__((destructor)); 36753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchivoid free_resources(void) 36853646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi{ 36953646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi while (modules) { 37053646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi struct mod *mod = modules->next; 37153646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi free(modules); 37253646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi modules = mod; 37353646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi } 374a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi 375a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi if (ctx) 376a655370541b5ddd681e864ddf23b1e3e214830b7Lucas De Marchi kmod_unref(ctx); 37753646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbcLucas De Marchi} 378