The def fields are zeros for my ebpf map in the ebpf obj file - maps

I am playing a simple ebpf with the map definition as follows:
struct event {
char comm[TASK_COMM_LEN];
pid_t pid;
uid_t uid;
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 128);
__type(key, pid_t);
__type(value, struct event);
} execs_1 SEC(".maps");
when I load the corresponding elf obj file using https://elixir.bootlin.com/linux/v4.14.2/source/samples/bpf/bpf_load.c, I saw correct map name as 'execs_1'. But when I was trying to get the map definition, all fields are just zero. See line 421 in the link. Basically, I am curious the bpf info kept in the corresponding elf obj file. I checked the corresponding code https://github.com/torvalds/linux/blob/master/tools/lib/bpf/libbpf.c at line 2026. It seems that there is no diff. Any comments on how to get the field info of the map from elf bpf object file:
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
unsigned int map_flags;
unsigned int inner_map_idx;
unsigned int numa_node;
};
Thanks.

Related

Reading from the header of a bmp file

I am writing a program to read a bmp header. I've written some code that was working when it was all in main. How to implement this code as a function of its own and then implementing it onto main?
Here is the whole code :
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdin.h>
struct bmp_header {
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
uint32_t dib_size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bpp;
uint32_t compression;
uint32_t image_size;
uint32_t x_ppm;
uint32_t y_ppm;
uint32_t num_colors;
uint32_t important_colors;
};
void read_bmp(FILE *BMPFile,struct bmp_header* Header) {
fread(&(Header->type), 2, 1, BMPFile);
fread(&(Header->size),4,1,BMPFile);
fread(&(Header->reserved1),2,1,BMPFile);
fread(&(Header->reserverd2),2,1,BMPFile);
fread(&(Header->offset),4,1,BMPFile);
fread(&(Header->dib_size),4,1,BMPFile);
fread(&(Header->width),4,1,BMPFile);
fread(&(Header->height),4,1,BMPFile);
fread(&(Header->planes),2,1,BMPFile);
fread(&(Header->bpp),2,1,BMPFile);
fread(&(Header->compression),4,1,BMPFile);
fread(&(Header->image_size),4,1,BMPFile);
fread(&(Header->x_ppm),4,1,BMPFile);
fread(&(Header->y_pp),4,1,BMPFile);
fread(&(Header->num_colors),4,1,BMPFile);
fread(&(Header->important_colors),4,1,BMPFile);
}
int main() {
FILE *BMPFile = fopen("image.bmp","rb");
if(BMPFile == NULL)
{
return;
}
struct bmp_header* Header;
read_bmp(BMPFile,Header);
fclose(BMPFile);
return 0;
}
The relevant parts of the version of the program with all reading action in main, that worked as expected, is reported below
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
fread(&Header.size),4,1,BMPFile);
fread(&Header.reserved1),2,1,BMPFile);
fread(&Header.reserverd2),2,1,BMPFile);
fread(&Header.offset),4,1,BMPFile);
fread(&Header.dib_size),4,1,BMPFile);
fread(&Header.width),4,1,BMPFile);
fread(&Header.height),4,1,BMPFile);
fread(&Header.planes),2,1,BMPFile);
fread(&Header.bpp),2,1,BMPFile);
fread(&Header.compression),4,1,BMPFile);
fread(&Header.image_size),4,1,BMPFile);
fread(&Header.x_ppm),4,1,BMPFile);
fread(&Header.y_pp),4,1,BMPFile);
fread(&Header.num_colors),4,1,BMPFile);
fread(&Header.important_colors),4,1,BMPFile);
/* Header fields print section */
/* ... */
}
Whenever a working code stops working, it is useful to focus on the changes between the two versions of the code. So, why does your original code work correctly? It looks like this:
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
...
}
You declare Header, of type struct bmp_header, in main's stack (as local variable). In this way the structure will be for sure allocated during all program's lifetime.
You memset it to 0
You pass Header's fields addresses directly to fread
In the new version of the program you have a function defined as
void read_bmp(FILE *BMPFile,struct bmp_header* Header);
so you need a pointer to struct bmp_header to be passed to it. For this reason you declare
struct bmp_header* Header;
and call read_bmp(BMPFile,Header);.
What is the different with the working version? Well, the pointer! Declaring a pointer you say to the compiler that it contains an address, in this case the address of the structure required by read_bmp().
But you never say to the compiler what the address is, so that freads within read_bmp() will write to random location causing a segmentation fault.
What to do
You need to pass to read_bmp() a valid struct bmp_header address, and you have two options.
You can allocate Header in the stack like you did before, and pass its address to read_bmp(), through & operator. It should have been your first attempt, since it was really similar to your working solution.
struct bmp_header Header;
read_bmp(BMPFile, &Header);
You can declare Header as a pointer, but you will need to dynamically allocate its memory through malloc:
struct bmp_header * Header = malloc(sizeof(struct bmp_header));
read_bmp(BMPFile, Header);
You have to create struct bmp_header* type function. Next create struct bmp_header pointer in your function & allocate memory (header size == 54B) for returned reference.

How to send and receive a struct through netlink?

I'm trying to send a struct from user-space to my module in kernel space using netlink, my struct in the user-space is:
struct test{
unsigned int length;
char name[MAX_NAME_LENGTH];
};
and in the kernel space is:
struct test{
__u32 length;
char name[MAX_NAME_LENGTH];
};
where MAX_NAME_LENGTH is a macro defined to be equal 50.
In the user-space, I've the function main which send my struct to the kernel with the following code:
int main(){
struct iovec iov[2];
int sock_fd;
struct sockaddr_nl src_add;
struct sockaddr_nl dest_add;
struct nlmsghdr * nl_hdr = NULL;
struct msghdr msg;
struct test message;
memset(&message, 0, sizeof(struct test));
message.length = 18;
strcpy(message.name, "Just a test\0");
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0){
printf("Netlink socket creation failed\n");
return -1;
}
memset(&src_add, 0, sizeof(src_add));
src_add.nl_family = AF_NETLINK;
src_add.nl_pid = getpid();
memset(&dest_add, 0, sizeof(dest_add));
dest_add.nl_family = AF_NETLINK;
dest_add.nl_pid = 0; // Send to linux kernel
dest_add.nl_groups = 0; // Unicast
bind(sock_fd,(struct sockaddr *)&src_add,sizeof(src_add));
nl_hdr = (struct nlmsghdr *) malloc(NLMSG_SPACE(sizeof(struct test)));
memset(nl_hdr, 0, NLMSG_SPACE(sizeof (struct test)));
nl_hdr->nlmsg_len = NLMSG_SPACE(sizeof(struct test));
nl_hdr->nlmsg_pid = getpid();
nl_hdr->nlmsg_flags = 0;
iov[0].iov_base = (void *)nl_hdr;
iov[0].iov_len = nl_hdr->nlmsg_len;
iov[1].iov_base = &message;
iov[1].iov_len = sizeof(struct test);
memset(&msg,0, sizeof(msg));
msg.msg_name = (void *)&dest_add;
msg.msg_namelen = sizeof(dest_add);
msg.msg_iov = &iov[0];
msg.msg_iovlen = 2;
sendmsg(sock_fd,&msg,0);
close(sock_fd);
return 0;
}
And in the kernel side I've registered a function called callback to be called every time that a message is received, this is the callback function:
static void callback(struct sk_buff *skb){
struct nlmsghdr *nl_hdr;
struct test * msg_rcv;
nl_hdr = (struct nlmsghdr*)skb->data;
msg_rcv = (struct test*) nlmsg_data(nl_hdr);
printk(KERN_INFO "Priting the length and name in the struct:%u, %s\n",msg_rcv->length, msg_rcv->name);
}
When I run these codes and see the dmesg output I receive the following message: Priting the length and name in the struct:0,, so why the fields of the struct filled in the user-space side aren't being sent to the kernel?
Btw, NETLINK_USER is defined as 31.
DON'T DO THAT. YOUR CODE HAS BUGS BY DESIGN.
I'm going to first explain the one superfluous issue that prevents your code from doing what you want, then explain why what you want is a bad idea, then explain the right solution.
1. Doing what you want
You "want" to send a packet consisting of a netlink header followed by a struct. In other words, this:
+-----------------+-------------+
| struct nlmsghdr | struct test |
| (16 bytes) | (54 bytes) |
+-----------------+-------------+
The problem is that's not what you're telling your iovec. According to your iovec code, the packet looks like this:
+-----------------+--------------+-------------+
| struct nlmsghdr | struct test | struct test |
| (16 bytes) | (54 bytes) | (54 bytes) |
| (data) | (all zeroes) | (data) |
+-----------------+--------------+-------------+
This line:
iov[0].iov_len = nl_hdr->nlmsg_len;
Should be this:
iov[0].iov_len = NLMSG_HDRLEN;
Because your first iovec slot is just the Netlink header; not the whole packet.
2. Why what you want is bad
C has a gotcha called "data structure padding." Don't skip this lecture; I'd argue that anyone who deals with the C language MUST read it ASAP: http://www.catb.org/esr/structure-packing/
The gist of it is that C compilers are allowed to introduce garbage between the members of any structure. Thus, when you declare this:
struct test {
unsigned int length;
char name[MAX_NAME_LENGTH];
};
The compiler is technically allowed to mutate that during implementation into something like
struct test {
unsigned int length;
unsigned char garbage[4];
char name[MAX_NAME_LENGTH];
};
See the problem? If your kernel module and your userspace client were generated by different compilers, or by the same compiler but with slightly different flags, or even by slightly different versions of the same compiler, the structures might differ and the kernel will receive garbage, no matter how correct your code looks.
Update: Someone asked me to elaborate on that, so here it goes:
Suppose you have the following structure:
struct example {
__u8 value8;
__u16 value16;
};
In userspace, the compiler decides to leave it as is. However, in kernelspace the compiler "randomly" decides to convert it to:
struct example {
__u8 value8;
__u8 garbage;
__u16 value16;
};
In your userspace client, you then write this code:
struct example x;
x.value8 = 0x01;
x.value16 = 0x0203;
In memory, the structure will look like this:
01 <- value8
02 <- First byte of value16
03 <- Second byte of value16
When you send that to the kernel, the kernel will, of course, receive the same thing:
01
02
03
But it will interpret it differently:
01 <- value8
02 <- garbage
03 <- First byte of value16
junk <- Second byte of value16
(End of Update)
In your case the problem is aggravated by the fact that you define test.length as unsigned int in userspace, yet for some reason you change it into __u32 in kernelspace. Your code is problematic even before structure padding; if your userspace defines basic integers as 64-bit, the bug will also inevitably trigger.
And there's another problem: "Btw, NETLINK_USER is defined as 31" tells me you're following tutorials or code samples long obsolete or written by people who don't know what they are doing. Do you know where that 31 comes from? It's the identifier of your "Netlink family." They define it as 31 because that's the highest possible value it can have (0-31), and therefore, it's the most unlikely one to collide with other Netlink families defined by the kernel. (Because they are numbered monotonically.) But most careless Netlink users are following the tutorials, and therefore most of their Netlink families identify as 31. Therefore, your kernel module will be unable to coexist with any of them. netlink_kernel_create() will kick you out because 31 is already claimed.
And you might be wondering, "well shit. There are only 32 available slots, 23 of them are already taken by the kernel and there's an unknown but likely large number of additional people wanting to register different Netlink families. What do I do?!"
3. The proper way
It's 2020. We don't use Netlink anymore. We use better-Netlink: Generic Netlink.
Generic Netlink uses strings and dynamic integers as family identifiers, and drives you to use Netlink's "attribute" framework by default. (The latter encourages you to serialize and deserialize structures in a portable way, which is the real solution to your original problem.)
This code needs to be visible to both your userspace client and kernel module:
#define SAMPLE_FAMILY "Sample Family"
enum sample_operations {
SO_TEST, /* from your "struct test" */
/* List more here for different request types. */
};
enum sample_attribute_ids {
/* Numbering must start from 1 */
SAI_LENGTH = 1, /* From your test.length */
SAI_NAME, /* From your test.name */
/* This is a special one; don't list any more after this. */
SAI_COUNT,
#define SAI_MAX (SAI_COUNT - 1)
};
This is the kernel module:
#include <linux/module.h>
#include <linux/version.h>
#include <net/genetlink.h>
#include "../include/protocol.h"
/*
* A "policy" is a bunch of rules. The kernel will validate the request's fields
* match these data types (and other defined constraints) for us.
*/
struct nla_policy const sample_policy[SAI_COUNT] = {
[SAI_LENGTH] = { .type = NLA_U32 },
[SAI_NAME] = { .type = NLA_STRING },
};
/*
* This is the function the kernel calls whenever the client sends SO_TEST
* requests.
*/
static int handle_test_operation(struct sk_buff *skb, struct genl_info *info)
{
if (!info->attrs[SAI_LENGTH]) {
pr_err("Invalid request: Missing length attribute.\n");
return -EINVAL;
}
if (!info->attrs[SAI_NAME]) {
pr_err("Invalid request: Missing name attribute.\n");
return -EINVAL;
}
pr_info("Printing the length and name: %u, '%s'\n",
nla_get_u32(info->attrs[SAI_LENGTH]),
(unsigned char *)nla_data(info->attrs[SAI_NAME]));
return 0;
}
static const struct genl_ops ops[] = {
/*
* This is what tells the kernel to use the function above whenever
* userspace sends SO_TEST requests.
* Add more array entries if you define more sample_operations.
*/
{
.cmd = SO_TEST,
.doit = handle_test_operation,
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
/* Before kernel 5.2, each op had its own policy. */
.policy = sample_policy,
#endif
},
};
/* Descriptor of our Generic Netlink family */
static struct genl_family sample_family = {
.name = SAMPLE_FAMILY,
.version = 1,
.maxattr = SAI_MAX,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
/* Since kernel 5.2, the policy is family-wide. */
.policy = sample_policy,
#endif
.module = THIS_MODULE,
.ops = ops,
.n_ops = ARRAY_SIZE(ops),
};
/* Called by the kernel when the kernel module is inserted */
static int test_init(void)
{
return genl_register_family(&sample_family);
}
/* Called by the kernel when the kernel module is removed */
static void test_exit(void)
{
genl_unregister_family(&sample_family);
}
module_init(test_init);
module_exit(test_exit);
And here's the userspace client (You need to install libnl-genl-3 --sudo apt install libnl-genl-3-dev on Debian/Ubuntu):
#include <errno.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include "../include/protocol.h"
static struct nl_sock *sk;
static int genl_family;
static void prepare_socket(void)
{
sk = nl_socket_alloc();
genl_connect(sk);
genl_family = genl_ctrl_resolve(sk, SAMPLE_FAMILY);
}
static struct nl_msg *prepare_message(void)
{
struct nl_msg *msg;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, genl_family, 0, 0, SO_TEST, 1);
/*
* The nla_put* functions ensure that your data will be stored in a
* portable way.
*/
nla_put_u32(msg, SAI_LENGTH, 18);
nla_put_string(msg, SAI_NAME, "Just a test");
return msg;
}
int main(int argc, char **argv)
{
struct nl_msg *msg;
prepare_socket();
msg = prepare_message();
nl_send_auto(sk, msg); /* Send message */
nlmsg_free(msg);
nl_socket_free(sk);
return 0;
}
This code should work starting from kernel 4.10. (I tested it in 4.15.) The kernel API was somewhat different before that.
I left a pocket version of my test environment (with makefiles and proper error handling and everything) in my Dropbox, so you can run it easily.

Why do my 2 structs have different structure in debug watch?

I use 2 structs in my µC-project:
struct cRGB LED_OUTPUT[3] = {0};
struct LED_Object LEDS[3] = {0};
which are initiated in 2 separate header files as
struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
and
struct LED_Object{
struct cRGB Color;
uint8_t brightnessReduction;
int8_t fadingDirection;
...}
In my debug watch window I get this view:
Why is LEDS[0] through [2] shown separately and LED_OUTPUT as one Object?
Because maybe that has to do with my problem when I enter a function and LED_OUTPUT is still visible in the Window and LEDS shows "Unknown Location".

Pointer value changing across function call

I have the following structures in the kernel
struct state {
/* Current algorithm iteration */
int tune_id;
/* Thread id */
pid_t tid;
#ifndef __KERNEL__
/* Paths */
char *stats_path;
char *budget_path;
char *controller_path;
#endif /* __KERNEL__ */
int budget;
/* Stats */
struct statistics prev_stats;
struct parameters current_params;
u64 cur_time;
/* Algorithm specific data */
void *data;
};
struct tuning {
struct algorithm *algorithm;
struct state *state;
struct energy energy;
};
I've defined a function tune() as follows:
void tune(struct task_struct *task) {
struct statistics stats;
struct state *state;
get_current_stats(&stats);
state = task->tuning.state;
get_current_params(&state->current_params);
compute_energy(&stats, state);
}
The other functions are defined as:
void get_current_params(struct parameters *params)
{
printk(KERN_DEBUG "get_current_params: parameters:0x%X\n", (unsigned int) params);
params->cpu_frequency_MHZ = (cpufreq_get(0) + 500) / 1000;
params->mem_frequency_MHZ = (memfreq_get() + 500) / 1000;
}
void compute_energy(struct statistics *stats, struct state *state)
{
struct statistics *diffs;
struct frontier *frontier;
u64 energy_budget;
int threshold;
int i,j;
struct configuration s;
struct configuration emin;
#ifdef TIMING
u64 ns;
ns = get_thread_time();
#endif
#ifdef DEBUG
#ifdef __KERNEL__
printk(KERN_DEBUG "compute_energy: parameters:0x%X\n", (unsigned int) &state->current_params);
#endif /* __KERNEL__ */
#endif
}
When I call tune(), the output is as follows:
[ 7.160139] get_current_params: parameters:0xBF396BA0
[ 7.160298] compute_energy: parameters:0xBF396B98
I don't understand why the addresses differ by 0x8.
This in turn causes a divide by 0 exception in the kernel since the struct parameters seems to have values of 0 instead of what was initialized by get_current_params
Why is it that the address of the member current_params of struct state changes across function calls?
Update:
I've verified that this bug only occurs for PID 0.
Looking at include/linux/init_task.h, I see that PID 0 is statically initialized. This is the only difference I could find between PID 0 and the other tasks. Could this somehow be responsible for the issue I'm having?
For what I can see, you are right in that both addresses should be the same. So there can only be one option: task information changes in the kernel in the meanwhile.
Considering this snippet of your code:
void tune(struct task_struct *task) {
...
struct state *state;
...
state = task->tuning.state;
You are managing two structs over which you may have no control (you should check that):
(*task): struct task_struct
and
(*task->tuning.state): struct state
So when in tune() you call
get_current_params(&state->current_params);
compute_energy(&stats, state);
something could happen between both printk functions, so there is where I think you have to put your focus in.
Try saving task->tuning.state before the call to get_current_params() so you could check that it continues to be the same value after call to compute_energy().
Hope this helps.

Activate paging in kernel programming

I'm reading this tutorial "http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html" about kenrel programming and the author is using the below struct to build the page directory
typedef struct page_directory
{
/**
Array of pointers to pagetables.
**/
page_table_t *tables[1024];
/**
Array of pointers to the pagetables above, but gives their *physical*
location, for loading into the CR3 register.
**/
u32int tablesPhysical[1024];
/**
The physical address of tablesPhysical. This comes into play
when we get our kernel heap allocated and the directory
may be in a different location in virtual memory.
**/
u32int physicalAddr;
} page_directory_t;
my question is why he is loading the address of the page directory like this in the function void switch_page_directory(page_directory_t *new);
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
and not like this
asm volatile("mov %0, %%cr3":: "r"(current_directory ));
I've been testing with as shown in the code below
#include<stdio.h>
#include<stdlib.h>
typedef struct page
{
unsigned int present : 1; // Page present in memory
unsigned int rw : 1; // Read-only if clear, readwrite if set
unsigned int user : 1; // Supervisor level only if clear
unsigned int accessed : 1; // Has the page been accessed since last refresh?
unsigned int dirty : 1; // Has the page been written to since last refresh?
unsigned int unused : 7; // Amalgamation of unused and reserved bits
unsigned int frame : 20; // Frame address (shifted right 12 bits)
} page_t;
typedef struct page_table
{
page_t pages[1024];
} page_table_t;
typedef struct page_directory
{
page_table_t *tables[1024];
unsigned int tablesPhysical[1024];
unsigned int physicalAddr;
} page_directory_t;
int main()
{
page_directory_t *n;
n = malloc(sizeof(page_directory_t));
printf("n=%p i=%p y=%p\n", n,&n->tablesPhysical, &n->tables);
}
the result is below
n=0x833b008 i=0x833c008 y=0x833b008
I'm not sure why the address is always the same for the printf?
your function is not written correctly, and you don't include the whole relevant code in the question.
That said, I'd say that the text is unclear, but I'd read the Multitasking segment, which covers what current_directory is eventually used for.

Resources