I'm exploring the getdents64 syscall. The resulting struct linux_dirent64 is not defined by the relevant headers. Both the related question and the example in man 2 getdirents64 are declaring their own structs. Although I'm aware of Linux syscall backwards compatibility, defining the struct locally like that looks like a hack. Is there another header I need to include that has this struct linux_dirent64 defined inside?
#define _GNU_SOURCE
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
struct linux_dirent64 {
ino64_t d_ino;
off64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
void test() {
char buf[1024];
const int procfs = open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
getdents64(procfs, buf, 1024);
printf("%lu\n", ((struct linux_dirent64 *) buf)->d_ino);
close(procfs);
}
Change struct linux_dirent64 to just struct dirent64. This works with glibc 2.36. It is not necessary to include another header as #include <dirent.h> provides it with #define _GNU_SOURCE. The original code would look like the following:
#define _GNU_SOURCE
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
void test() {
char buf[1024];
const int procfs = open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
getdents64(procfs, buf, 1024);
printf("%lu\n", ((struct dirent64 *) buf)->d_ino);
close(procfs);
}
Related
I wrote very simple code using struct iwreq.
Also, I expected this will be error.
But it is compiled and works.
I looked inside linux/wireless.h which has the definition of struct iwreq.
And the iwreq does not ifr_name as a member.
Would someone can give me an idea?
Here is the simple code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/wireless.h>
int main(void)
{
char *intf = "eth0";
struct iwreq iwr;
strncpy(iwr.ifr_name, intf, sizeof(iwr.ifr_name));
printf("main : intf = %s, iwr.ifr_name = %s\n", intf, iwr.ifr_name);
return 0;
}
wireless.h includes if.h, and inside if.h you can find:
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
So the code is translated to:
strncpy(iwr.ifr_ifrn.ifrn_name, intf, sizeof(iwr.ifr_ifrn.ifrn_name));
/usr/include/linux/wireless.h includes linux/if.h:
#include <linux/if.h> /* for IFNAMSIZ and co... */
And in /usr/include/linux/if.h there is:
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
I'm writing a project. This project will be injected into another program and will enable that program to write CRUD operations on the files it wants. The constructor I wrote in my project will take a struct (data) from the injected program and define it as a type with typedef (like 'typedef struct Book_ Entity'). It will then do all of its operations over this type. However, the point where I stuck is this: After declaring an Entity with typedef, I wrote 'typedef type_t Entity;' in the Constructor macro I wrote. the line of code does not work or is valid only within the macro. You can better understand what the problem is from the program below.
NOTE: The data_num in data_constructor tells how many variables the data consists of. Required for Delete and Update operations.
Part of Constructors.h
#include <stdio.h>
#include <string.h>
#ifndef CONSTRUCTORS
#define CONSTRUCTORS
#define DATA_CONSTRUCTOR
typedef Entity;
#define data_constructor(type_t, number_of_data) typedef type_t Entity; int data_num = number_of_data;
#define FILE_CONSTRUCTOR
inline void file_constructor(const char* path)
{
char* g_file_path;
strcpy(g_file_path, path);
}
#endif
The constructor I wrote above is included. It defines the data structure (such as 'struct Book_') received from the user as a type. I got an error like expected 'Entity' {aka 'int'} but argument is of type 'struct Book_' when I ran the program while waiting for a structure like 'typedef struct Book_ Entity'.
Part of InMemoryDal.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Constructors.h"
#include "Defines.h"
#include "FileHelper.h"
#ifndef IN_MEMORY_H
#define IN_MEMORY_H
#endif
extern char *g_file_path;
extern int data_num;
FILE *g_file;
FILE *g_temp_file;
void Add(Entity entity);
void Delete(Entity entity);
void Update(Entity entity);
void Add(Entity entity)
{
F_OPEN(g_file, g_file_path, MODE_AB);
F_WRITE(&entity, sizeof(Entity), 1, g_file);
fclose(g_file);
}
This is where I write the functions of the program. Here, the Add () function takes an Entity type entity from the user and prints it to the file. Macros such as F_OPEN and F_WRITE used in it are defined in another file. It is just below in the file.
#include <stdio.h>
#include <stdlib.h>
#ifndef MODES
#define MODE_W "w"
#define MODE_R "r"
#define MODE_WB "wb"
#define MODE_RB "rb"
#define MODE_A "a"
#define MODE_AB "ab"
#endif
#define TEMP_FILE_PATH "temp_file.txt"
#define F_OPEN(fp, f_path, mode) fp=fopen(f_path, mode); if(fp == NULL) exit(1);
#define F_WRITE(buffer, element_size, element_count, fp) fwrite(buffer, element_size, element_count, fp); if(fwrite==0) exit(1);
Here is the code I tested the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "InMemoryDal.h"
struct Book_
{
int id;
char title[50];
char author[50];
int print_number;
};
int main()
{
data_constructor(struct Book_, 4);
file_constructor("\\test123.txt");
struct Book_ b;
b.id=1;
strcpy(b.title, "testname");
strcpy(b.author, "testauthor");
b.print_number=34;
Add(b);
return 0;
}
I think I explained my problem well. I want your help to set up the constructor structure I want. Thanks!
I am checking socket options and I got this error when I compile. I tried to google it and it looks like no one has encountered this problem before.
#include <netinet/tcp.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
static char *sock_str_flag(union val *, int);
struct sock_opts {
const char *opt_str;
int opt_level;
int opt_name;
char *(*opt_val_str)(union val *, int);
}sock_opts[] = {
{ "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag } //this is the error
};
The socket option SO_USELOOPBACK is not a POSIX standard. The man page setsockopt() describes the nature of SO_USELOOPBACK in detail.
The SO_USELOOPBACK is a [Digital] standard. Text paragraphs preceded by [Digital] document features that are included in the DIGITAL UNIX software but are not currently specified by any standard that applies to the interface being described. Use these features when source code portability across multiple UNIX platforms is less important than the capabilities that the features provide.
For portability, you need to have ifdef checks.
struct sock_opts {
const char *opt_str;
int opt_level;
int opt_name;
char *(*opt_val_str)(union val *, int);
}sock_opts[] = {
/* .... */
#ifdef SO_USELOOPBACK
{"SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag }
#endif
/* .... */
};
this is simple sys_call_table hooking code
#include <asm/unistd.h>
#include <linux/autoconf.h>
#include <linux/in.h>
#include <linux/init_task.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/syscalls.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/version.h>
#include <linux/workqueue.h>
ssize_t *sys_call_table = (ssize_t *)0xc0026e04;
asmlinkage ssize_t (*orig_open)(const char *pathname, int flags);
asmlinkage ssize_t hacked_open(const char *pathname, int flags)
{
printk(KERN_INFO "SYS_OPEN called : %s\n", pathname);
return orig_open(pathname, flags);
}
int init_module(void)
{
orig_open = sys_call_table[__NR_open]; /* line 33 */
sys_call_table[__NR_open] = hacked_open; /* line 34 */
return 0;
}
void cleanup_module(void)
{
sys_call_table[__NR_open] = orig_open; /* line 40 */
}
MODULE_LICENSE("GPL");
i got an warning like below
this code works fine but i want to delete warnings. how can i do?
/home/tester/tools/lkm/a.c: In function 'init_module':
/home/tester/tools/lkm/a.c:33: warning: assignment makes integer from pointer without a cast
/home/tester/tools/lkm/a.c:34: warning: assignment makes integer from pointer without a cast
/home/tester/tools/lkm/a.c: In function 'cleanup_module':
/home/tester/tools/lkm/a.c:40: warning: assignment makes integer from pointer without a cast
If you want to silence your compiler, you have to add typecasts (even if it is often a bad idea, this is how your compiler turns it).
ssize_t *sys_call_table = (ssize_t *)0xc0026e04;
typedef ssize_t (*ftype)(const char *, int);
ftype orig_open;
ssize_t hacked_open(const char *pathname, int flags)
{
printf("SYS_OPEN called : %s\n", pathname);
return orig_open(pathname, flags);
}
int init_module(void)
{
orig_open = (ftype)sys_call_table[__NR_open];
sys_call_table[__NR_open] = (ssize_t)hacked_open;
return 0;
}
When you look at line 33 you will see the problem:
orig_open = sys_call_table[__NR_open];
You have defined sys_call_table to be a pointer to integer. That's the reason for the warning.
Same problem with the other lines. If you define sys_call_table properly, the warnings will go away.
You should at least define it as an array of pointers or pointer to pointers, because if ssize_t is only 32 bit on 64 bit system, you might truncate the 64 bit addresses to a 32 bit integer.
I am using sigaction for a signal and I am using a simple struct for that. I actually took it from the man page. Can someone explain to me what does the second line in the struct do? Also there is an error there:
error: expected declaration specifiers or '...' before 'siginfo_t'
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>
#include <getopt.h>
#include <signal.h>
#include <sys/time.h>
#define _POSIX_C_SOURCE 200112L
#define MAX_WORD 256
void parseFile (FILE * fp, FILE *sketcher);
void handle_timeout(int signal);
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
You are not supposed to declare the struct sigaction yourself. It is provided in the man page for your information, but it is actually declared by <signal.h>.
The second line in the struct defines a function pointer (as does the first, but with a different type).