insmod module param : invalid parameters - linux-kernel

I'm developping sample kernel module driver.ko. I want to specify the block size of data_node structure with module parameter BlockSize. when I run insmod driver.ko alone, it works, but when I specify BlockSize insmod driver.ko BlockSize = 10 I get this eror :
Error: could not insert module driver.ko: Invalid parameters
modinfo -p ./driver.ko command give me this :
BlockSize: size of buffer (int)
driver.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/slab.h>
/* parametter */
static int BlockNumber = 8;
static int BlockSize = 512;
module_param( variable name, type, permission); */
module_param(BlockSize, int, S_IRUGO);
MODULE_PARM_DESC(BlockSize , " size of buffer");
/* using 'k' as magic number */
#define SAMPLE_IOC_MAGIC 'k'
#define SAMPLE_IOCRESET _IOWR(SAMPLE_IOC_MAGIC, 0, int)
#define SAMPLE_IOC_MAXNR 0
struct cdev* my_cdev;
dev_t dev;
static int size_to_read;
/* Macro used to compute the minimum */
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/* data buffer structure */
typedef struct dnode
{
int bufSize;
char *buffer;
struct dnode *next;
} data_node;
/* liste stucture */
typedef struct lnode
{
data_node *head;
data_node *cur_write_node;
data_node *cur_read_node;
int cur_read_offset;
int cur_write_offset;
}liste;
code ..........................
..

It appears that module parameters should be passed without a space between the name and value, ie you should use:
insmod driver.ko BlockSize=10
This makes some sense, as in the command line to insmod itself "BlockSize=10" is a single entry in *argv[] which can be handed off to the kernel as a chunk, while "BlockSize = 10" would be three distinct entries ("BlockSize", "=", "10") which someone would have to write code to re-join.

Related

Writing a custom nss hosts module

I'm seeking to implement a custom nss module for the getent hosts lookup. Based on glibc's resolv/nss-dns/dns-host.c and gnunet's src/gns/nss/nss_gns.c I wrote the following minimal implementation that I hoped at least should write something to syslog - which it sadly doesn't.
#include <netdb.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#define _nss_lash_gethostbyname2_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname3_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname4_r _nss_lash_gethostbyname_r
#define _nss_lash_getcanonname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_gethostbyaddr2_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyaddr_r _nss_lash_gethostbyaddr_r
typedef char addr[1];
const addr default_addrs[2] = {0x01, 0x00};
enum nss_status
_nss_lash_gethostbyname_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_WARNING, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
enum nss_status
_nss_lash_gethostbyaddr_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_ERR, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
I've added lash to /etc/nsswitch.conf. strace shows that the /lib/libnss_lash.so.2 file is being successfully opened. However the return value from the nss lookup is NSS_UNAVAIL / ENOENT. If I add [unavail=return] to /etc/nsswitch.conf after the lash entry, I get the same result.
Anyone have any clues to what I'm missing?
(the #define lines attempt to catch all symbols found in objdump -T /lib/libnss_dns.so, which seems to be the simpler implementation)
Using:
glibc 2.30
gnunet 0.11.6-ish
nss 3.49.2

linux hw_breakpoint does not work while accessing memory from userspace

I am debugging a ARMv7 board and I want to know whether a kernel symbol is accessed. So I have to use hw_breakpoint in kernel.
For simplicity, I use kernel sample code:data_breakpoint to test, which locates in samples/hw_breakpoint/data_breakpoint.c.
Then I did the following operation:
insmod data_breakpoint.ko ksym=max
cat /proc/kallsyms | grep max
./read_kmem c06fa128
But this did not trigger the callback function.
If I print the value in that address in any kernel module, callback function will be triggered.
I read the cpu manual and it says that the breakpoint register in my cpu support virtual address matching. But I don't know why it doesn't work while accessing memory from userspace. I think that program does read the right value of kernel symbol.
read_kmem.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#define DEVKMEM "/dev/kmem"
#define PAGE_SIZE 0x1000
#define PAGE_MASK (~(PAGE_SIZE-1))
int main(int argc, char* argv[])
{
int fd;
char *mbase;
char read_buf[10];
unsigned int varAddr;
varAddr = strtoul(argv[1], 0, 16);
unsigned int ptr = varAddr & ~(PAGE_MASK);
fd = open(DEVKMEM, O_RDONLY);
if (fd == -1) {
perror("open");
exit(-1);
}
mbase = mmap(0,PAGE_SIZE,PROT_READ,MAP_SHARED,fd, (varAddr & PAGE_MASK));
if (mbase == MAP_FAILED) {
printf("map failed %s\n",strerror(errno));
}
printf("varAddr = 0x%X \n", varAddr);
printf("mapbase = 0x%X \n", (unsigned int)mbase);
printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr));
close(fd);
munmap(mbase,PAGE_SIZE);
return 0;
}
Your userspace does not access address c06fa128, it accesses a different address - one that that mmap() returned (plus offset). Thus no breakpoint hit.
The fact that virtual address being accessed resolves to same physical address as some other virtual address that has a breapoint, does not matter. CPU executing your userspace code has no idea that different mapping exists.

#including <alsa/asoundlib.h> and <sys/time.h> results in multiple definition conflict

Here is the minimal C program to reproduce:
#include <alsa/asoundlib.h>
#include <sys/time.h>
int main( void )
{
}
This will compile with gcc -c -o timealsa.o timealsa.c, but if you include the -std=c99 switch, you get a redefinition error:
In file included from /usr/include/sys/time.h:28:0,
from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
struct timeval
^
In file included from /usr/include/alsa/asoundlib.h:49:0,
from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
struct timeval {
^
How can I resolve this conflict while still using -std=c99?
Since your question suggests you are using GLIBC's time.h there is a way to avoid this by telling it not to define timeval. Include asoundlib.h first then define _STRUCT_TIMEVAL. The one defined in asoundlib.h will be the one that gets used.
#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
# define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>
int main( void )
{
}
With C99 and later you can't have duplicate definitions of the same struct. The problem is that alsa/asoundlib.h includes alsa/global.h which contains this code:
/* for timeval and timespec */
#include <time.h>
...
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#endif
So the Michael Petch's solution won't work - by the time you've included alsa/asoundlib.h it is already too late. The proper solution is to define _POSIX_C_SOURCE (_POSIX_SOURCE is obsolete). There's more information about these macros here and here.
For example you could try -D_POSIX_C_SOURCE=200809L. However, if you do that you'll get errors like this:
/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
struct timeval it_interval;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
struct timeval it_value;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
extern int utimes (const char *__file, const struct timeval __tvp[2])
^
This is all a big mess of old C code and macro madness. The only way I got it to work was to give up and use -std=gnu11.

how to create multiple containers in boost shared memory?

Constructing multiple objects in shared memory is possible as shown in this example:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <functional>
#include <iostream>
using namespace boost::interprocess;
void construct_objects(managed_shared_memory &managed_shm)
{
managed_shm.construct<int>("Integer")(99);
managed_shm.construct<float>("Float")(3.14);
}
int main()
{
shared_memory_object::remove("Boost");
managed_shared_memory managed_shm{open_or_create, "Boost", 1024};
auto atomic_construct = std::bind(construct_objects,
std::ref(managed_shm));
managed_shm.atomic_func(atomic_construct);
std::cout << *managed_shm.find<int>("Integer").first << '\n';
std::cout << *managed_shm.find<float>("Float").first << '\n';
}
But when I try to create two vectors or a vector and a list, I run into problems with the memory allocation. Is there a way to create multiple containers in a single shared memory in Boost?
I had a look at managed_memory_impl.hpp, but it wasn't of much help either.
This is my code (you have to link it with lib pthread and librt):
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <cstddef>
#include <cassert>
#include <utility>
#include <iostream>
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator; //Define an STL compatible allocator of ints that allocates from the managed_shared_memory. This allocator will allow placing containers in the segment
typedef boost::interprocess::vector<int, ShmemAllocator> MyVector; //Alias a vector that uses the previous STL-like allocator so that allocates its values from the segment
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemListAllocator;
typedef boost::interprocess::list<int, ShmemListAllocator> MyList;
int main(int argc, char *argv[])
{
//Construct managed shared memory
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "MySharedMemory", 65536);
//const ShmemAllocator alloc_inst(segment.get_segment_manager());
MyVector *instance = segment.construct<MyVector>("MyType instance")(segment.get_segment_manager());
MyVector *instance2 = segment.construct<MyVector>("MyType instance")(segment.get_segment_manager());
MyList *instance3 = segment.construct<MyList>("MyList instance")(segment.get_segment_manager());
return 0;
}//main
You should either use unique names, or you can use the indexed ("array") style of construction.
See the documentation for the Object construction function family:
//!Allocates and constructs an array of objects of type MyType (throwing version)
//!Each object receives the same parameters (par1, par2, ...)
MyType *ptr = managed_memory_segment.construct<MyType>("Name")[count](par1, par2...);
and
//!Tries to find a previously created object. If not present, allocates and
//!constructs an array of objects of type MyType (throwing version). Each object
//!receives the same parameters (par1, par2, ...)
MyType *ptr = managed_memory_segment.find_or_construct<MyType>("Name")[count](par1, par2...);
and
//!Allocates and constructs an array of objects of type MyType (throwing version)
//!Each object receives parameters returned with the expression (*it1++, *it2++,... )
MyType *ptr = managed_memory_segment.construct_it<MyType>("Name")[count](it1, it2...);
and possibly some more. Look for [count].
(I recommend using unique names for simplicity)
Update
To the comments, here's what I meant with "unique name". I've tested it, and itworks fine:
Live1 On Coliru
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cassert>
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator; // Define an STL compatible allocator of ints that allocates from the managed_shared_memory. This allocator
// will allow placing containers in the segment
typedef boost::interprocess::vector<int, ShmemAllocator> MyVector; // Alias a vector that uses the previous STL-like allocator so
// that allocates its values from the segment
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemListAllocator;
typedef boost::interprocess::list<int, ShmemListAllocator> MyList;
int main()
{
// Construct managed shared memory
std::remove("/dev/shm/MySharedMemory");
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "MySharedMemory", 65536);
// const ShmemAllocator alloc_inst(segment.get_segment_manager());
MyVector *instance = segment.construct<MyVector>("MyType instance 1")(segment.get_segment_manager());
MyVector *instance2 = segment.construct<MyVector>("MyType instance 2")(segment.get_segment_manager());
MyList *instance3 = segment.construct<MyList> ("MyList instance")(segment.get_segment_manager());
assert(instance);
assert(instance2);
assert(instance3);
assert(!std::equal_to<void*>()(instance, instance2));
assert(!std::equal_to<void*>()(instance, instance3));
assert(!std::equal_to<void*>()(instance2, instance3));
}
1 Of course, SHM is not supported on Coliru. However, identical sample using mapped file: Live On Coliru

"struct has no member named" error with gcc on dev machine

#include <stdio.h>
#include <stdlib.h>
#include "ReadMethods.h"
int main(int argc,char * argv[])
{
DPDA WordChecker;
DPDA * WordCheckerPointer=&WordChecker;
WordChecker.DPDAFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAInputFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAOutputFilename=(char*)malloc(25*sizeof(char));
strcpy( WordChecker.DPDAFilename,argv[1]);
strcpy( WordChecker.DPDAInputFilename,argv[2]);
strcpy( WordChecker.DPDAOutputFilename,argv[3]);
readDPDA(argv[1],WordCheckerPointer);
readInputLines(argv[2],WordCheckerPointer,argv[3]);
return 0;
}
This is my code that gives error from mallocs until last strcpy() ,total 6 lines.The error is "DPDA has no member named DPDAFilename" and same for other fields for every malloc and strcpy linesthat i work on.Here is the part of header file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagRule{
char *startingState;
char symbolToPop;
char expectedInput;
char *endingState;
char symbolToPush;
}Rule;
typedef struct tagStackDPDA{
char * arrayOfSymbols;
int stackElementCount;
char * currentState;
}stackDPDA;
typedef struct tagDPDA{
char * alphabet;
char * stackSymbols;
char ** states;
char *startingState;
char **finalStates;
int finalStatesAmount;
Rule * ruleList;
stackDPDA stackOfDPDA;
int sizeArray[4];//This array holds amount values of states,alphabet symbols,stack symbols and transition rules
char *DPDAFilename;
char *DPDAInputFilename;
char *DPDAOutputFilename;
}DPDA;
The code works fine in codeblocks environment but in gcc (-Wall -ansi).Those filenames come from input text files yet i am not sure it can cause this error.
Edit:By the way I am using this command line to compile;
gcc -Wall -ansi main.c ReadMethods.h -o WordChecker
May be if you compile in C mode, you have to use C-style comments in header?
/**/ instead of //

Resources