Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lunatik states management for GSoC 2020 #20

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
2775fba
Import states and luautil from NFLua
May 25, 2020
2b9aeb0
Adapt NFLua states management to Lunatik
MatheusNtg Jun 23, 2020
c1c757b
Operations per namespace implementation
MatheusNtg Jul 14, 2020
9623807
Import luautil from NFLua
Jul 14, 2020
8a1bbb2
Netlink implementation
MatheusNtg Jul 14, 2020
38b9a14
Import user space lib and nfluaconf from NFLua
Jul 21, 2020
d1fe1b5
Adapt control API from NFLua
MatheusNtg Jul 21, 2020
99c40c7
Change list protocol
MatheusNtg Jul 26, 2020
c74f246
Change lua_Buffer to a normal buffer
MatheusNtg Jul 27, 2020
cc4e3b6
Remove unnucessary functions
MatheusNtg Jul 27, 2020
54ec7f4
Name changes to fit with lua API's
MatheusNtg Jul 27, 2020
5ea4da3
Refatoration of functions
MatheusNtg Jul 27, 2020
2092d56
Add lua-memory as dependecy
MatheusNtg Jul 30, 2020
8c3240a
Send data to kernel
MatheusNtg Aug 7, 2020
764f083
Import luanetlink from NFLua
Jul 30, 2020
650f7de
Receiving data from kernel
MatheusNtg Aug 7, 2020
9948f46
Solve send to kernel bug
MatheusNtg Aug 4, 2020
ca465c1
Add user space API documentation
MatheusNtg Aug 6, 2020
723619b
Chage receive and send socket to state
MatheusNtg Aug 8, 2020
7c2bfaa
Adapt messages sent to kernel
MatheusNtg Aug 8, 2020
9ef7222
Adapt received data from kernel
MatheusNtg Aug 9, 2020
20eecdb
Update documentation
MatheusNtg Aug 10, 2020
0027028
Add get state functionality
MatheusNtg Aug 11, 2020
8f4e595
Make the global network namespace as default space to store states
MatheusNtg Aug 11, 2020
7303d68
Unnecessary functions remotion, and documentation update
MatheusNtg Aug 11, 2020
9b86a2e
Add tests
MatheusNtg Aug 11, 2020
d2bebc6
Add lua memory compilation from user lib
MatheusNtg Aug 15, 2020
a2f2841
Functions refatoration
MatheusNtg Aug 15, 2020
694d9cc
Update documentation
MatheusNtg Aug 11, 2020
5620872
Add lunatik_getenv function
MatheusNtg Aug 16, 2020
e863b1c
Add support to get namespace from a given lunatik state
MatheusNtg Aug 16, 2020
4256e8d
Change socket of states related operation to the state instead of ses…
MatheusNtg Aug 23, 2020
2987eca
Add function to get current memory usage of states, update documentat…
MatheusNtg Aug 23, 2020
ea758c8
Update makefile to automatically remove unecessary objects (Last GSoC…
MatheusNtg Aug 24, 2020
b325f15
fixup! Netlink implementation
MatheusNtg Sep 4, 2020
103e61f
Update lua-memory submodule
MatheusNtg Sep 7, 2020
5bffd2a
fixup! Change lua_Buffer to a normal buffer
MatheusNtg Sep 8, 2020
6302115
fixup! Add function to get current memory usage of states, update doc…
MatheusNtg Sep 8, 2020
de406cf
fixup! Adapt NFLua states management to Lunatik
MatheusNtg Sep 8, 2020
cb6b769
fixup! Add lua-memory as dependecy
MatheusNtg Sep 4, 2020
be94eca
fixup! Add tests
MatheusNtg Sep 11, 2020
8f8d8aa
fixup! Send data to kernel
MatheusNtg Sep 11, 2020
d103135
fixup! Adapt control API from NFLua
MatheusNtg Sep 11, 2020
e335ddc
fixup! Adapt messages sent to kernel
MatheusNtg Sep 11, 2020
21f35ea
fixup! Change socket of states related operation to the state instead…
MatheusNtg Sep 11, 2020
6388358
fixup! RABID-561 adjust Makefiles for generic compilation
MatheusNtg Sep 11, 2020
9277e14
Solved bug on module remotion
MatheusNtg Oct 14, 2020
e9663d3
Implementation of put state function
MatheusNtg Oct 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "deps/lua-memory"]
path = deps/lua-memory
url = https://github.com/MatheusNtg/lua-memory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should refers to upstream, right? or do you have modifications in your fork?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modifications on my fork.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, you need to make a PR as well.. what's the upstream repo? I think we should fork it on luainkernel and make a PR for it..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The upstream repo can be found here. I made a PR to lua-memory repo now

20 changes: 14 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ccflags-y += -D_LUNATIK -D_KERNEL -I$(src) -D_CONFIG_FULL_PANIC
ccflags-y += -D_LUNATIK -D_KERNEL -I$(src) -D_CONFIG_FULL_PANIC -DLUNATIK_UNUSED -DDEBUG\
-I$(src)/lua -I$(src)/deps/lua-memory/src
asflags-y += -D_LUNATIK -D_KERNEL

ifeq ($(ARCH), $(filter $(ARCH),i386 x86))
Expand All @@ -18,23 +19,30 @@ ifeq ($(ARCH), mips)
endif
AFLAGS_setjmp.o += -D_MIPS_ISA_MIPS64 \
-D_MIPS_ISA=_MIPS_ISA_MIPS64
else
else
AFLAGS_setjmp.o += -D__mips_o32 -D_MIPS_ISA_MIPS32 \
-D_MIPS_ISA=_MIPS_ISA_MIPS32
endif
endif
endif

obj-$(CONFIG_LUNATIK) += lunatik.o

lunatik-objs += lua/lapi.o lua/lcode.o lua/lctype.o lua/ldebug.o lua/ldo.o \
lua-objs = lua/lapi.o lua/lcode.o lua/lctype.o lua/ldebug.o lua/ldo.o \
lua/ldump.o lua/lfunc.o lua/lgc.o lua/llex.o lua/lmem.o \
lua/lobject.o lua/lopcodes.o lua/lparser.o lua/lstate.o \
lua/lstring.o lua/ltable.o lua/ltm.o \
lua/lundump.o lua/lvm.o lua/lzio.o lua/lauxlib.o lua/lbaselib.o \
lua/lbitlib.o lua/lcorolib.o lua/ldblib.o lua/lstrlib.o \
lua/ltablib.o lua/lutf8lib.o lua/loslib.o lua/lmathlib.o lua/linit.o \
lua/loadlib.o \
arch/$(ARCH)/setjmp.o util/modti3.o lunatik_core.o
lua/loadlib.o luautil.o

lua_memory-path = deps/lua-memory/src

lua_memory-objs = $(lua_memory-path)/lmemlib.o $(lua_memory-path)/lmemmod.o

lunatik-objs += $(lua-objs) \
arch/$(ARCH)/setjmp.o util/modti3.o lunatik_core.o states.o netlink.o $(lua_memory-objs) \
luanetlink.o

ifeq ($(shell [ "${VERSION}" -lt "4" ] && [ "${VERSION}${PATCHLEVEL}" -lt "312" ] && echo y),y)
lunatik-objs += util/div64.o
Expand Down
1 change: 1 addition & 0 deletions deps/lua-memory
Submodule lua-memory added at 3fe228
122 changes: 122 additions & 0 deletions doc/lib.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# User Space API documentation

## Introduction

This document provides the documentation of the user space API of Lunatik. This API is divided in two main features, being the control API and the data API, the first one is responsible to send messages to Lunatik kernel module to perform some operations, whereas the data API is responsible to exchange data between the kernel module and this user space API.

## Constants

#### `lunatik.datamaxsize`

Integer that represents the maximum amount of data that a state can receive or send each time.

#### `lunatik.defaultmaxallocbytes`

The default amount of memory that a state will be able to use if no value is passed on creation.

#### `lunatik.maxstates`

The maximum number of states that the lunatik module is able to store.

#### `lunatik.scriptnamemaxsize`

The maximum length of a script name, this name is used on debug porpuses, for example, show a name for the script on the callback stack trace.

#### `lunatik.statenamemaxsize`

The maximum length of a state name.

## Control API

Responsable to send messages to Lunatik kernel module perform some operations, these are:
* States creations
* States deletion
* States listing
* Code execution

To use this API, first you must to include the lunatik module on your lua code, you can do this as follow:

```lua
local lunatik = require'lunatik'
```

After that, you have to create a lunatik session. This session represents a connection between kernel and user space API. To do it, simple store the return of the function `lunatik.session()` for example:

```lua
local lunatik = require'lunatik'
local session = lunatik.session()
```

Now you can use the variable `session` to do all operations related to control API. These operations will be showed next.

#### `session:newstate(name [, maxalloc])`

Tells the lunatik kernel module to create a state with the name `name`. If some value is passed to `maxalloc` that you be the maximum amount of memory that the state `name` can use during it execution, if no value is passed, a state with a default `maxalloc` will be created. If the state is succesfully created, the function returns a userdata, such userdata is used to perform all needed operations on that state. You can imagine this userdata as your user space representation of the state created on the kernel side. If the state creation fails, this function returns a `nil` value alongside with a error message.

#### `session:list()`

Returns a table with all states present on kernel. Each entry of that table is another table containing the following informations about the state: `name`, `curralloc` and `maxalloc`. `name` represents the state name, `curralloc` the amount of memory that the state `name` is using in that given moment (when the function `session:list()` was called) and `maxalloc` has the same meaning showed at [`session:new`](#sessionnewname--maxalloc).

#### `session:close()`

Closes the connection with the kernel, after that, all references for the states will be lost, so it's important to check if you don't have any states in use before close the connection with the kernel to avoid memory leaks.

#### `session:getstate(name)`

Gets a user representation of the state with the name `name` which was created on kernel. Returns a userdata as described on [`session:new`](#sessionnewname--maxalloc) if such state is found and `nil` otherwise.

#### `session:getfd()`

Returns the session file descriptor of the control socket.

### State related operations

As mentioned at [`session:new`](#sessionnewname--maxalloc) function, when you call that function, if the state is succesfully created, it will be returned a userdata. That userdata is used to perform all operations related to that state, for example:

```lua
local mystate = session:newstate'somename'
```

This code will create a state named `somename` on kernel and store the userdata to perform all operations related to the state `somename` on the variable `mystate`. From now on, it will be used `mystate` to explain all operations that can be done at that state.

#### `mystate:dostring(code [, codename])`

Runs on the kernel, the code given by `code`, you can give a name for that code, this can be used for debug purposes, if something get wrong on the execution of the code, then the name present on `codename` will be showed at the stack trace. If no value is passed, the default value `'lua in kernel'` will be showed for all states that loaded code without a `codename`.

#### `mystate:close()`

Closes on the kernel the state that `mystate` represents.

#### `mystate:getname()`

Returns the name of state `mystate` as it is in the kernel.

#### `mystate:getmaxalloc()`

Return the maximum amount of memory that `mystate` can use in the kernel.

#### `mystate:getcurralloc()`

Return the current memory usage in the kernel of the state represent by `mystate`.

## Data API

To transmit data from kernel to user space (and vice versa), we use lua memory (see [lua memory](https://github.com/luainkernel/lua-memory)).

#### `mystate:send(memory)`

Sends a [memory](https://github.com/luainkernel/lua-memory/blob/master/doc/manual.md#writable-byte-sequences) `memory` to the kernel state represented by `mystate`.

In order to receive this memory on the kernel side you must to define a global function called `receive_callback` with one parameter which represents the memory which was sent from the user space. For example:

```lua
function receive_callback(mem)
-- Here I can do whatever I want with mem
end
```

This callback will be called every time that a memory is received by the kernel. It's important to say that the module `memory` from lua memory is loaded by default in this version of Lunatik, thus you can do all supported operations with memory that Lua Memory offers.

#### `mystate:receive()`

Receives from the state represented by `mystate` the data sent from kernel and return a [memory](https://github.com/luainkernel/lua-memory/blob/master/doc/manual.md#writable-byte-sequences) to manipulate the data sent by kernel. If no data is available to be received, this function blocks until receive some data.
122 changes: 122 additions & 0 deletions doc/lunatik.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Lunatik API Documentation

## Introduction

This document provides a documentation of the Lunatik kernel module, this module is resposible for safe states management. Two main APIs are offered to the user, the first one has correlation with [network namespaces](https://man7.org/linux/man-pages/man8/ip-netns.8.html#DESCRIPTION), and provides a full isolation of the states based on each namespace, the second one provides a state management without relation with namespace, and all operations related to this API will be made based on the global network namespace.

The API is based on the data structure `lunatik_State` which is used to perform all needed operations.

## The `lunatik_State` struct

Defined at `states.h` as:

```c
typedef struct lunatik_state {
struct hlist_node node;
struct lunatik_instance instance;
struct genl_info usr_state_info;
lua_State *L;
char *code_buffer;
int buffer_offset;
spinlock_t lock;
refcount_t users;
size_t maxalloc;
size_t curralloc;
size_t scriptsize;
bool inuse;
unsigned char name[LUNATIK_NAME_MAXSIZE];
} lunatik_State;
```

The elements in the struct has the following meaning:

**`struct hlist_node node`**

Is a variable used by kernel hash table API to storage the `lunatik_State` structure.

**`struct lunatik_instance instance`**

The instance of lunatik that some state belongs to. This is used to have access to informations related to the instance of lunatik that that state belongs. As mentioned at the [introduction](#introduction), its possible to have multiples set of states stored based on network namespaces, we know in what set this state belongs through this variable.

**`struct genl_info usr_state_info`**

Information related to the user space API. This variable is used to hold information about the user space API and consequently send needed informations through generic netlink.

**`lua_State L`**

Is the Lua state used by Lunatik to do all operations related to Lua.

**`char *code_buffer`**

A buffer used to store code through multiples function calls and contexts switchs between kernel and user space.

**`int buffer_offset`**

The buffer offset, used to hold information about where the cursor of `code_buffer` is at some time.

**`spinlock_t lock`**

Is a spinlock variable used to manage concurrency control.

**`refcount_t users`**

Represents how many users are referring to a given `lunatik_State`.

**`size_t maxalloc`**

Represents the maximum memory that the lua state `L` can use.

**`size_t curralloc`**

Represents the current memory that the lua state `L` is using.

**`bool inuse`**

Tells if the states is in use for some process on the user space.

**`unsigned char name[LUNATIK_NAME_MAXSIZE]`**

Is the unique identifier to `lunatik_State`, used to search it in the kernel hash table, note that this is limited by `LUNATIK_NAME_MAXSIZE`.

## Namespace independent functions

"Namespace independent functions" means that you don't have concern about namespaces management, this can be used when your aplication don't need to work isolated of other aplications. If this is not the case, then use the namespace dependent functions.

#### `lunatik_State *lunatik_statelookup(const char *name)`

Searches for a state with the name `name`. If a state with that name is found returns a pointer to the `lunatik_State`, returns `NULL` otherwise.

#### `lunatik_State *lunatik_newstate(const char *name, size_t maxalloc)`

Creates a `lunatik_State` with the max memory usage defined by `maxalloc` and a unique identifier to acess such state defined by `name`. Return a pointer to `lunatik_State` represeting the lunatik state or `NULL` if any errors occours during the creation.

#### `int lunatik_close(const char *name)`

Searchs and close a `lunatik_State` with the name `name`, returns `0` if no errors occours during this operation and `-1` if any error occours.

#### `bool lunatik_getstate(lunatik_State *s)`

Tries to get a reference to the state `s`, return `true` if such reference is succesfully acquired and `false` otherwise.
It's important to get a reference to the state before perform any action because this is the way that Lunatik knows if there is someone using the state or not (to close a state for example), so if you don't acquire the state to perform the action, the state can be closed and you will try to perform actions on a memory area that have been freed.

#### `void lunatik_putstate(lunatik_State *s)`

Put back the reference of the state. This tells the lunatik that you're are done with that state.

#### `lunatik_State *lunatik_getenv(lua_State *L)`

Returns the lunatik state which the lua state `L` is contained into.

## Namespace depedent functions

#### `lunatik_State *lunatik_netnewstate(const char *name, size_t maxalloc, struct net *net)`

Does the same of [`lunatik_newstate`](#lunatik_state-lunatik_newstatesize_t-maxalloc-const-char-name) but stores the state on the lunatik instance present on the network namespace referenced by `net`.

#### `int lunatik_netclosestate(const char *name, struct net *net)`

Does the same of [`lunatik_close`](#int-lunatik_closeconst-char-name) but closes the state stored on the lunatik instance present on the namespace referenced by `net`.

#### `lunatik_State *lunatik_netstatelookup(const char *name, struct net *net)`

Does the same of [`lunatik_statelookup`](#lunatik_state-lunatik_statelookupconst-char-name) but searching on the lunatik instance present on the namespace referenced by `net`.
53 changes: 53 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) 2020 Matheus Rodrigues <[email protected]>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you copying this makefile if you have a submodule?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the makefile of lunatik user space module. What are you suggesting is to build the lunatik user space module from the submodule makefile?

# Copyright (C) 2017-2019 CUJO LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

CC = gcc
CFLAGS = -fPIC -Wall -Wextra -O2 -g -I/usr/include/lua5.3/ -I/usr/include/libnl3 -D_UNUSED \
-I$(src)../deps/lua-memory/src
LDFLAGS = -shared -lnl-genl-3 -lnl-3 -llua5.3 -L../deps/lua-memory/src -lluamemlib
RM = rm -f

LIBS = lunatik.so
OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
DEPS = $(OBJS:.o=.d)

.PHONY: all
all: lua_memory $(LIBS) clean_objs

lua_memory: lua_memory_clean
$(MAKE) -C ../deps/lua-memory/src linux CFLAGS="-fPIC -I/usr/include/lua5.3"

%.so:
$(CC) -o $@ $^ $(LDFLAGS)

%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<

-include $(DEPS)

.PHONY: clean
clean: lua_memory_clean
$(RM) $(LIBS) $(OBJS) $(DEPS)

lua_memory_clean:
$(MAKE) -C ../deps/lua-memory/src clean

clean_objs:
$(MAKE) -C ../deps/lua-memory/src clean_objs

$(LIBS): $(OBJS)
Loading