What is missing in my syscall implementation? - c

I tried many guides and for some reason, my syscall isnt implementing correctly. ERRNO is 38 (function not implemented). Here are my steps to creating a basic one for me as a beginner:
I am doing this on a raspberry pi 64 bit. with linux 4.14.93
inside "/linux/" folder:
I created a folder called "mycall" with files mycall.c, mycall.h, & Makefile
mycall.c:
#include <linux/kernel.h>
#include <linux/init.h>
#include <sched.h>
#include <syscalls.h>
#include <linux/unistd.h>
#include "mycall.h"
asmlinkage long sys_mysyscall(int *id, int username, int *size)
{
printk("hello");
return 0;
}
mycall.h:
asmlinkage long sys_mysyscall(int *id, int username, int *size);
Makefile:
obj-y := mycall.o
then I went into all of the places where I THOUGHT i should declare the syscall.
// inside of /linux/include/linux/syscalls.h
asmlinkage long sys_mysyscall(int __user *myid, int username, int __user *size);
then to
// inside of /linux/arch/arm/tools/syscall.tbl
398 common mysyscall sys_mysyscall
finally i added
// inside of /linux/Makefile
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypt/ block/ mycall/
thats my set up. then the final thing I do is make a userspace in /linux directory
userspace.c:
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <pwd.h>
int main ()
{
int id = 0;
int username = 7;
int size = 2;
int ret_val = syscall(398, &id, username, &size);
printf("%d\n", ret_val);
return 0;
}
// recompiling & copying . then I run the userspace again
cd ~/linux
KERNEL=kernel7
make bcm2709_defconfig
make -j4 zImage modules dtbs
sudo make INSTALL_MOD_PATH=/root modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
the return value is -1 so this doesn't work.
please let me know what I'm doing wrong. I have read several implementation guides and have no idea how I'm implementing this wrong.

Related

Build RSA-Signature of a file with libgmp

I want to implement RSA-Signature where I can calculate the signature of a file and verify a signature of a file. Therefore I use the libary gmp.
But when I want to print the data of the file, it always prints 0 even though the file is not empty. Here is my code:
//compiled with gcc rsa-sig.c -O3 -Wall -l gmp -o rsa-sig
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <math.h>
#include <gmp.h> /* GNU Multi Precision library */
int main(int argc, char *argv[])
{
int r;
mpz_t modulus;
mpz_init(modulus);
r=mpz_set_str(modulus, "FFFF",16); //just an example modulus
mpz_t data;
mpz_init(data);
FILE * stream;
stream = fopen("file.bin", "rb");
r= mpz_inp_str(data, stream,16);
mpz_mod(data,data,modulus);
gmp_printf("%Zd\n",data);
}
I can't figure out why the output of that is 0. Maybe one of you guys have an idea.
Thanks!!

Is SCHED_DEADLINE officially supported in Ubuntu 16.04?

Currently I'm running Ubuntu 16.04 with linux kernel version to be 4.16. I wrote a dummy program that changes its scheduler to SCHED_DEADLINE. But when I tried to compile it, it cannot find definition of structs and macros needed for SCHED_DEADLINE. Most of the code snippet was taken from here (page 24). Below is the test program:
#define _GNU_SOURCE
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sched.h>
int main(int argc, char* argv[]) {
struct sched_attr attr;
attr.size = sizeof(attr);
attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = 30000000;
attr.sched_period = 100000000;
attr.sched_deadline = attr.sched_period;
if (sched_setattr(gettid(), &attr, 0))
perror("sched_setattr()");
return 0;
}
Here's the output of the compilation:
sched_deadline.c: In function ‘main’:
sched_deadline.c:11:20: error: storage size of ‘attr’ isn’t known
struct sched_attr attr;
^
sched_deadline.c:12:21: error: invalid application of ‘sizeof’ to incomplete type ‘struct attr’
attr.size = sizeof(struct attr);
^
sched_deadline.c:13:22: error: ‘SCHED_DEADLINE’ undeclared (first use in this function)
attr.sched_policy = SCHED_DEADLINE;
My gcc version:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
However, the sample code posted in the official website works for me, but the sample code manually defines all the needed macros and system calls in the program. My goal was to compile the application without adding those definitions, which should already be included in the newest kernel version. I have seen various places saying that SCHED_DEADLINE is officially supported after Linux 3.14.10, and upgrading the kernel would automatically solve this issue.
Things I've tried:
Recompiling 4.16 kernel. Previously I thought I need to turn on a switch in config file, but I was not able to find it.
Look into /usr/include/linux/sched.h. Clearly the macros are defined in this header file, but somehow my compiler cannot find it.
I also looked into other posts in the community, but all those questions are for older linux (pre 3.14.10).
You need to include #include <linux/sched.h>
But for the definition of sched_setattr() and gettid(), see the link posted by #CraigEstey
The reason about that, it that glibc will not add function wrappers of linux specific syscall.
For example for gettid(), in the manual we can read this:
Note: There is no glibc wrapper for this system call; see NOTES.
Glibc does not provide a wrapper for this system call; call it using
syscall(2).
The thread ID returned by this call is not the same thing as a POSIX thread ID
Have a look at this article: https://lwn.net/Articles/711058/
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sched.h>
#include <linux/sched.h>
#include <sys/types.h>
struct sched_attr {
uint32_t size;
uint32_t sched_policy;
uint64_t sched_flags;
/* SCHED_NORMAL, SCHED_BATCH */
int32_t sched_nice;
/* SCHED_FIFO, SCHED_RR */
uint32_t sched_priority;
/* SCHED_DEADLINE (nsec) */
uint64_t sched_runtime;
uint64_t sched_deadline;
uint64_t sched_period;
};
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
return syscall(__NR_sched_setattr, pid, attr, flags);
}
int main(int argc, char* argv[]) {
struct sched_attr attr = {
.size = sizeof(attr),
.sched_policy = SCHED_DEADLINE,
.sched_runtime = 30000000,
.sched_period = 100000000,
.sched_deadline = 100000000
};
pid_t tid = syscall(SYS_gettid);
if (sched_setattr(tid, &attr, 0))
perror("sched_setattr()");
return 0;
}
Or a more shorter code, without the redefinition of struct sched_attr
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched/types.h>
#include <linux/sched.h>
#include <sys/types.h>
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
return syscall(__NR_sched_setattr, pid, attr, flags);
}
int main(int argc, char* argv[]) {
struct sched_attr attr = {
.size = sizeof(attr),
.sched_policy = SCHED_DEADLINE,
.sched_runtime = 30000000,
.sched_period = 100000000,
.sched_deadline = 100000000
};
pid_t tid = syscall(SYS_gettid);
if (sched_setattr(tid, &attr, 0))
perror("sched_setattr()");
return 0;
}
But this needs to be executed as root, otherwise I got sched_setattr(): Operation not permitted
Or the application needs to have the right linux capabilities.

Ruby C Extensions, loading external libraries

I'm trying to build a Ruby C Extension for Raspberry Pi using some existing C code. The code relies on the bcm2835-1.35 library for some functions. Problem is that when I try to run the a ruby program using on the RPi, I get the following:
ruby: symbol lookup error: /usr/lib/ruby/site_ruby/2.1.0/armv6l-linux-eabihf/dht_test.so: undefined symbol: bcm2835_gpio_fsel
Here's what the code looks like, this is all in one directory (~/Ruby/dht_test)
extconf.rb
# Loads mkmf which is used to make makefiles for Ruby extensions
require 'mkmf'
# Load Libraries
LIBDIR = RbConfig::CONFIG['libdir']
INCLUDEDIR = RbConfig::CONFIG['includedir']
HEADER_DIRS = [
# First search /opt/local for macports
'/opt/local/include',
# Then search /usr/local for people that installed from source
'/usr/local/include',
# Check the ruby install locations
INCLUDEDIR,
# Finally fall back to /usr
'/usr/include',
]
LIB_DIRS = [
# Then search /usr/local for people that installed from source
'/usr/local/lib',
# Check the ruby install locations
LIBDIR,
# Finally fall back to /usr
'/usr/lib',
]
unless find_header('bcm2835.h')
abort 'bcm2835 is missing'
end
dir_config('bcm2835', HEADER_DIRS, LIB_DIRS) # Tried with the line commented out, doesn't make any difference
# Give it a name
extension_name = 'dht_test'
# The destination
dir_config(extension_name)
# Do the work
create_makefile(extension_name)
dhtreader.h
/* for usleep */
//#define _BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <bcm2835.h>
#include <unistd.h>
int readDHT(int type, int pin, float *temp_p, float *hum_p);
dhtreader.c
#include "dhtreader.h"
int readDHT(int type, int pin, float *temp_p, float *hum_p)
{
int counter = 0;
int laststate = HIGH;
int i = 0;
int j = 0;
int checksum = 0;
#ifdef DEBUG
int bitidx = 0;
int bits[250];
#endif
int data[100];
// Set GPIO pin to output
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(pin, HIGH);
usleep(500000); // 500 ms
bcm2835_gpio_write(pin, LOW);
usleep(20000);
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
ect....
dht_test.c
// Include the Ruby headers and goodies
#include "ruby.h"
#include "dhtreader.h"
// Defining a space for information and references about the module to be stored internally
VALUE DhtTest = Qnil;
// Prototype for the initialization method - Ruby calls this, not you
void Init_dht_test();
// Prototype for our method 'test1' - methods are prefixed by 'method_' here
VALUE method_test1(VALUE self);
VALUE method_test2(VALUE self);
// The initialization method for this module
void Init_dht_test() {
DhtTest = rb_define_module("DhtTest");
rb_define_method(DhtTest, "test1", method_test1, 0);
rb_define_method(DhtTest, "test2", method_test2, 0);
}
// Our 'test1' method.. it simply returns a value of '10' for now.
VALUE method_test1(VALUE self) {
int x = 10;
return INT2NUM(x);
}
VALUE method_test2(VALUE self){
float temp;
float hum;
readDHT(22, 4, &temp, &hum);
printf("Temperture: %f, Humidity %f", temp, hum);
return temp;
}
Finally
I try to run the following irb, the first function test1 works fine, the second function which requires the bcm2835 fails with the previously stated error
require 'dht_test'
include DhtTest
puts test1
puts test2
I'm new to this stuff and I'm sure I'm making some egregious mistakes, but I'm pretty much stuck and would appreciate any help I can get.
Figured it out, I needed to add the following to my extconf.rb
unless have_library('bcm2835') && append_library($libs, 'bcm2835')
abort "Unable to appended Library bcm2835!"
end
Also this is needed to compile in c99
$CFLAGS << ' -std=c99' // yes you need the space

write() returns -1 when writing to I2C_SLAVE device

I've read through the Linux kernel documents on i2c and written a code to try to replicate the command i2cset -y 0 0x60 0x05 0xff
The code that I've written is here:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>
int main(){
int file;
file = open("/dev/i2c-0", O_RDWR);
if (file < 0) {
exit(1);
}
int addr = 0x60;
if(ioctl(file, I2C_SLAVE, addr) < 0){
exit(1);
}
__u8 reg = 0x05;
__u8 res;
__u8 data = 0xff;
int written = write(file, &reg, 1);
printf("write returned %d\n", written);
written = write(file, &data, 1);
printf("write returned %d\n", written);
}
When I compile and run this code I get:
write returned -1
write returned -1
I've tried to follow exactly what the docs tell me, my understanding is that the address is set first with the call to ioctl, then I need to write() the register and then the data that I want sent to the register.
I've also tried to use use SMbus, but I can't get my code to compile using this, it complains at the linking stage that it can't find the functions.
Have I made any mistakes in this code? I'm a beginner to i2c and don't have a lot of experience with c either.
EDIT: errno give the following message: Operation not supported. I am logged in as root on this machine though, so I don't think it can be a permissions thing, although I may be wrong.
The way I got around this problem was to use SMBus, in particular the functions i2c_smbus_write_byte_data and i2c_smbus_read_byte_data. I was able to use these functions to successfully read and write to the device.
I did have a little trouble finding these functions, I kept trying to download libraries using apt-get to install the appropriate header files. In the end I simply downloaded the files smbus.c and smbus.h.
Then the code I needed was:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "smbus.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
int main(){
int file;
file = open("/dev/i2c-0", O_RDWR);
if (file < 0) {
exit(1);
}
int addr = 0x60;
if(ioctl(file, I2C_SLAVE, addr) < 0){
exit(1);
}
__u8 reg = 0x05; /* Device register to access */
__s32 res;
res = i2c_smbus_write_byte_data(file, reg, 0xff);
close(file);
}
Then if I compile the smbus.c file: gcc -c smbus.c and myfile: gcc -c myfile.c, then link them: gcc smbus.o myfile.o -o myexe I get a working executable that runs my I2C command. Ofcourse, I have smbus.c and smbus.h in the same directory as myfile.c.
In C, you can check the content of the errno variable to get more details into what went wrong. It is automatically declared when including errno.h and you can get a more descriptive text by calling strerror(errno).
Have you checked that you had write access to /dev/i2c-0 ?

Conflict error when trying to compile a syscall .c file in freebsd

i am trying to add a new syscall to freebsd 8. i am using freebsd on VMplayer .when i trying to
compile the module i give this error :
my code is(i also have a Makefile file) :
#include <sys/param.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
struct user_datas{
};
static char* rot13func(struct thread* td , void* args)
{
struct user_datas* upp=args;
char* myarray=(upp->input);
return myarray;
}
static struct sysent rot13func_sysent={
1,
rot13func
};
static int offset=NO_SYSCALL;
static int load (struct module *module , int cmd, void *arg)
{
int error=0;
switch(cmd){
case MOD_LOAD:
break;
case MOD_UNLOAD:
break;
default:
error=EOPNOTSUPP;
break;
}
return(error);
}
SYSCALL_MODULE(rot13func, &offset , & rot13func_sysent , load, NULL);
It looks like your Makefile is incorrect and uses wrong include paths. Try using one from the /usr/share/examples/kld/syscall/module/ example, which looks like:
# Makefile for building the sample syscall module
# $FreeBSD: src/share/examples/kld/syscall/module/Makefile,v 1.2 2001/09/18 12:03:42 ru Exp $
KMOD= syscall
SRCS= syscall.c
.include <bsd.kmod.mk>
It will do appropriate steps to set up proper module build environment for you.

Resources