1. Access system calls from user mode. Generally, system calls are supported by library C. You can use the system call by adding a standard header file and linking it to the C library. However, the glibc library may not support writing system calls.
The good news is that Linux itself provides a set of macro-defined Linux/include/asm-x86_64/unistd. H files. The bad news is that the kernel version later than 2.6.20 canceled the macros, causing an error when compiling the source file at the beginning, and found the code in 2.6.18. In fact, the main function of this Assembly is to pass the system call number to the eax register and retrieve the return value from the eax register.
//test.c#include <stdio.h>#include <syscall.h>#include <linux/errno.h>#include <errno.h>#define __NR_foo 312#define MAX_ERRNO 127#define __syscall "syscall"#define __syscall_clobber "r11","rcx","memory"#define __syscall_return(type,res)\ do{\ if((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)){\ errno = -res;\ res = -1;\ }\ return (type)(res);\ }while(0)#define _syscall0(type,name)\ type name(void){\ long __res;\ __asm__ volatile(__syscall\ : "=a" (__res)\ : "0" (__NR_##name) : __syscall_clobber );\ __syscall_return(type,__res);\ }_syscall0(long,foo)int main(int argc,char** argv){ long stack_size = 0; stack_size = foo(); if(stack_size == -1) perror("ERROR"); printf("The kernel stack size is %ld\n",stack_size); return 0;}Output: The kernel stack size is 8192
Note the following points.
(1) Since the kernel version of my compiled environment is 3.2.6, I have already introduced unistd after 2.6.20. these macros no longer exist in the H file, so the macros need to be declared by themselves. The above macro declaration was copied from the 2.6.18 kernel.
(2) In addition, a macro _ syscall_return (type, Res) is used to return the returned value after the system call is executed.
(3) There is a _ syscall macro in the _ syscallx macro. It is defined as "syscall" at the beginning of the source file. It was tried to find its definition, but it was not found. It should be noted that the system call fails when I first used "int $0x80" instead of "syscall. Error: Dad address.
(4) There is no semicolon after declaration _ syscall0 (long, foo.
The following example is found on the Internet. You can see that the system call number is passed in through the syscall function. This makes it easier to call the system.
//test1.c#include <stdio.h>#include <asm/unistd_64.h>#include <syscall.h>#include <sys/syscall.h>#define __NR_foo 312int main(int argc,char** argv){ long ret = 0; ret = syscall(__NR_foo); printf("Thread Stack Size is %ld\n",ret); return 0;}Output: Thread Stack Size is 8192
Ii. User-Mode Access super invocation The following is an example of a user-mode calling xen hypervisor found on the Internet. In this example, a super call is added in the xen file.
#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/types.h>#include <fcntl.h>#include <string.h>#include <xenctrl.h>#include <xen/sys/privcmd.h>#define __HYPERVISOR_print_string 39int main(int argc,char** argv){ int fd = 0; int ret = 0; char* message = NULL; if(argc != 2) { printf("Please input one parameter!\n"); return -1; } message = (char*)malloc(sizeof(char) * strlen(argv[1] + 1)); if (message == NULL) { printf("malloc failed"); return -1; } strcpy(message,argv[1]); privcmd_hypercall_t hcall = {__HYPERVISOR_print_string, {message,0,0,0,0}}; fd = open("/proc/xen/privcmd",O_RDWR); if(fd < 0) { perror("open"); exit(1); } else printf("fd=%d\n",fd); ret = ioctl(fd,IOCTL_PRIVCMD_HYPERCALL,&hcall); perror("ioctl err"); printf("ret = %d\n",ret); close(fd); return 0;}
Then, use xen to reload the xen hypervisor and run the XM dmesg command to view the hypercall running result.