From 2f276964ff3e1aac68d3c1402cf3105ad1d6afeb Mon Sep 17 00:00:00 2001 From: Matheus Rodrigues Date: Sun, 23 Aug 2020 16:17:59 +0000 Subject: [PATCH] Change socket of states related operation to the state instead of session --- lib/lunatik.c | 108 +++++++++++++++++++++++++++++++++---------- lib/lunatik.h | 9 ++-- lib/lunatik_module.c | 16 +++---- lib/tests/close.lua | 14 ++++++ lunatik.h | 1 + netlink.c | 24 +++++++--- 6 files changed, 129 insertions(+), 43 deletions(-) diff --git a/lib/lunatik.c b/lib/lunatik.c index 867f6da16..734e3d302 100644 --- a/lib/lunatik.c +++ b/lib/lunatik.c @@ -81,8 +81,8 @@ static int send_simple_control_msg(struct lunatik_session *session, int command, return err; } -static int send_fragment(struct lunatik_session *session, const char *original_script, int offset, - const char *state_name, const char *script_name, int flags) +static int send_fragment(struct lunatik_nl_state *state, const char *original_script, int offset, + const char *script_name, int flags) { struct nl_msg *msg; char *fragment; @@ -98,7 +98,7 @@ static int send_fragment(struct lunatik_session *session, const char *original_s } strncpy(fragment, original_script + (offset * LUNATIK_FRAGMENT_SIZE), LUNATIK_FRAGMENT_SIZE); - NLA_PUT_STRING(msg, STATE_NAME, state_name); + NLA_PUT_STRING(msg, STATE_NAME, state->name); NLA_PUT_STRING(msg, CODE, fragment); if (offset == 0) @@ -109,7 +109,7 @@ static int send_fragment(struct lunatik_session *session, const char *original_s NLA_PUT_U8(msg, FLAGS, flags); - if ((err = nl_send_auto(session->control_sock, msg)) < 0) { + if ((err = nl_send_auto(state->control_sock, msg)) < 0) { printf("Failed to send fragment\n %s\n", nl_geterror(err)); nlmsg_free(msg); return err; @@ -125,7 +125,7 @@ static int send_fragment(struct lunatik_session *session, const char *original_s return err; } -static int receive_op_result(struct lunatik_session *session){ +static int receive_session_op_result(struct lunatik_session *session){ int ret; if ((ret = nl_recvmsgs_default(session->control_sock))) { @@ -143,6 +143,24 @@ static int receive_op_result(struct lunatik_session *session){ return 0; } +static int receive_state_op_result(struct lunatik_nl_state *state){ + int ret; + + if ((ret = nl_recvmsgs_default(state->control_sock))) { + printf("Failed to receive message from kernel: %s\n", nl_geterror(ret)); + return ret; + } + + nl_wait_for_ack(state->control_sock); + + if (state->cb_result == CB_ERROR){ + state->cb_result = CB_EMPTY_RESULT; + return -1; + } + + return 0; +} + int init_recv_datasocket_on_kernel(struct lunatik_nl_state *state) { struct nl_msg *msg; @@ -197,49 +215,49 @@ int lunatikS_newstate(struct lunatik_session *session, struct lunatik_nl_state * return ret; } - return receive_op_result(session); + return receive_session_op_result(session); nla_put_failure: printf("Failed to put attributes on message\n"); return ret; } -int lunatikS_closestate(struct lunatik_nl_state *state) +int lunatik_closestate(struct lunatik_nl_state *state) { - struct lunatik_session *session; struct nl_msg *msg; int ret = -1; - session = state->session; - if ((msg = prepare_message(DESTROY_STATE, 0)) == NULL) return ret; NLA_PUT_STRING(msg, STATE_NAME, state->name); - if ((ret = nl_send_auto(session->control_sock, msg)) < 0) { - printf("Failed to send destroy message:\n %s\n", nl_geterror(ret)); + if ((ret = nl_send_auto(state->control_sock, msg)) < 0) { + printf("Failed to send destroy message:\n\t%s\n", nl_geterror(ret)); return ret; } + ret = receive_state_op_result(state); + nl_socket_free(state->send_datasock); nl_socket_free(state->recv_datasock); + nl_socket_free(state->control_sock); - return receive_op_result(session); + return ret; nla_put_failure: printf("Failed to put attributes on netlink message\n"); return ret; } -int lunatikS_dostring(struct lunatik_session *session, const char *state_name, +int lunatik_dostring(struct lunatik_nl_state *state, const char *script, const char *script_name, size_t total_code_size) { int err = -1; int parts = 0; if (total_code_size <= LUNATIK_FRAGMENT_SIZE) { - err = send_fragment(session, script, 0, state_name, script_name, LUNATIK_INIT | LUNATIK_DONE); + err = send_fragment(state, script, 0, script_name, LUNATIK_INIT | LUNATIK_DONE); if (err) return err; } else { @@ -249,22 +267,22 @@ int lunatikS_dostring(struct lunatik_session *session, const char *state_name, for (int i = 0; i < parts - 1; i++) { if (i == 0) - err = send_fragment(session, script, i, state_name, script_name, LUNATIK_INIT | LUNATIK_MULTI); + err = send_fragment(state, script, i, script_name, LUNATIK_INIT | LUNATIK_MULTI); else - err = send_fragment(session, script, i, state_name, script_name, LUNATIK_MULTI); + err = send_fragment(state, script, i, script_name, LUNATIK_MULTI); - nl_wait_for_ack(session->control_sock); + nl_wait_for_ack(state->control_sock); if (err) return err; } - err = send_fragment(session, script, parts - 1, state_name, script_name, LUNATIK_DONE); + err = send_fragment(state, script, parts - 1, script_name, LUNATIK_DONE); if (err) return err; } - return receive_op_result(session); + return receive_state_op_result(state); } int lunatikS_list(struct lunatik_session *session) @@ -446,7 +464,6 @@ static int response_handler(struct nl_msg *msg, void *arg) { case CREATE_STATE: case DESTROY_STATE: - case EXECUTE_CODE: if (attrs_tb[OP_SUCESS] && nla_get_u8(attrs_tb[OP_SUCESS])) { session->cb_result = CB_SUCCESS; } else if (attrs_tb[OP_ERROR] && nla_get_u8(attrs_tb[OP_ERROR])) { @@ -510,6 +527,30 @@ static int response_handler(struct nl_msg *msg, void *arg) return NL_OK; } +static int response_state_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = genlmsg_hdr(nh); + struct nlattr * attrs_tb[ATTRS_COUNT + 1]; + struct lunatik_nl_state *state = (struct lunatik_nl_state *)arg; + + if (nla_parse(attrs_tb, ATTRS_COUNT, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL)) + { + printf("Error parsing attributes\n"); + state->cb_result = CB_ERROR; + return NL_OK; + } + + if (attrs_tb[OP_SUCESS] && nla_get_u8(attrs_tb[OP_SUCESS])) { + state->cb_result = CB_SUCCESS; + } else if (attrs_tb[OP_ERROR] && nla_get_u8(attrs_tb[OP_ERROR])) { + state->cb_result = CB_ERROR; + } + + return NL_OK; +} + static int init_data_buffer(struct data_buffer *data_buffer, size_t size); static int data_handler(struct nl_msg *msg, void *arg) @@ -657,7 +698,7 @@ void release_data_buffer(struct data_buffer *data_buffer) data_buffer->size = 0; } -int lunatikS_receive(struct lunatik_nl_state *state) +int lunatik_receive(struct lunatik_nl_state *state) { int err = 0; @@ -671,7 +712,7 @@ int lunatikS_receive(struct lunatik_nl_state *state) return err; } -int lunatikS_initdata(struct lunatik_nl_state *state) +static int lunatik_initdata(struct lunatik_nl_state *state) { int ret = 0; @@ -712,7 +753,7 @@ struct lunatik_nl_state *lunatikS_getstate(struct lunatik_session *session, cons return NULL; } - if (receive_op_result(session)) + if (receive_session_op_result(session)) return NULL; if ((session->cb_result == CB_STATE_NOT_FOUND) || (session->cb_result == CB_ERROR)) { @@ -726,3 +767,22 @@ struct lunatik_nl_state *lunatikS_getstate(struct lunatik_session *session, cons printf("Failed to put attributes on netlink message\n"); return NULL; } + +int lunatik_initstate(struct lunatik_nl_state *state) +{ + int err; + + if ((err = lunatik_initdata(state))) { + return err; + } + + if ((err = init_socket(&state->control_sock))) { + printf("Failed to initialize the control socket for state %s\n", state->name); + nl_socket_free(state->control_sock); + return err; + } + + nl_socket_modify_cb(state->control_sock, NL_CB_MSG_IN, NL_CB_CUSTOM, response_state_handler, state); + + return 0; +} \ No newline at end of file diff --git a/lib/lunatik.h b/lib/lunatik.h index 733f3dfb3..fdf7077d0 100644 --- a/lib/lunatik.h +++ b/lib/lunatik.h @@ -48,6 +48,7 @@ struct lunatik_nl_state { struct lunatik_session *session; struct nl_sock *send_datasock; struct nl_sock *recv_datasock; + struct nl_sock *control_sock; struct data_buffer data_buffer; enum callback_result cb_result; uint32_t maxalloc; @@ -94,16 +95,16 @@ void lunatikS_close(struct lunatik_session *session); int lunatikS_newstate(struct lunatik_session *session, struct lunatik_nl_state *s); -int lunatikS_closestate(struct lunatik_nl_state *state); +int lunatik_closestate(struct lunatik_nl_state *state); -int lunatikS_dostring(struct lunatik_session *session, const char *state_name, +int lunatik_dostring(struct lunatik_nl_state *state, const char *script, const char *script_name, size_t total_code_size); int lunatikS_list(struct lunatik_session *session); -int lunatikS_receive(struct lunatik_nl_state *state); +int lunatik_receive(struct lunatik_nl_state *state); -int lunatikS_initdata(struct lunatik_nl_state *state); +int lunatik_initstate(struct lunatik_nl_state *state); struct lunatik_nl_state *lunatikS_getstate(struct lunatik_session *session, const char *name); diff --git a/lib/lunatik_module.c b/lib/lunatik_module.c index b4409e02f..1c0609858 100644 --- a/lib/lunatik_module.c +++ b/lib/lunatik_module.c @@ -141,8 +141,8 @@ static int lsession_newstate(lua_State *L) return 2; } - if (lunatikS_initdata(state)) { - lua_pushnil(L); + if (lunatik_initstate(state)) { + pusherrmsg(L, "Failed to initialize state\n"); return 1; } @@ -154,7 +154,7 @@ static int lsession_newstate(lua_State *L) static int lstate_close(lua_State *L) { struct lunatik_nl_state *state = getnlstate(L); - if (lunatikS_closestate(state)){ + if (lunatik_closestate(state)){ lua_pushnil(L); return 1; } @@ -166,8 +166,6 @@ static int lstate_close(lua_State *L) static int lstate_dostring(lua_State *L) { struct lunatik_nl_state *s = getnlstate(L); - struct lunatik_session *session = s->session; - const char *name = s->name; size_t len; const char *payload = luaL_checklstring(L, 2, &len); const char *script_name = luaL_optstring(L, 3, "Lunatik"); @@ -176,7 +174,7 @@ static int lstate_dostring(lua_State *L) printf("script name too long\n"); goto error; } - int status = lunatikS_dostring(session, name, payload, script_name, len); + int status = lunatik_dostring(s, payload, script_name, len); if (status) goto error; @@ -243,8 +241,8 @@ static int lsession_getstate(lua_State *L) *state = *received_state; - if (lunatikS_initdata(state)) { - lua_pushnil(L); + if (lunatik_initstate(state)) { + pusherrmsg(L, "Failed to initialize the state\n"); return 1; } @@ -292,7 +290,7 @@ static int lstate_datareceive(lua_State *L) struct lunatik_nl_state *state = getnlstate(L); char *memory; - if (lunatikS_receive(state)) + if (lunatik_receive(state)) goto error; memory = luamem_newalloc(L, state->data_buffer.size); diff --git a/lib/tests/close.lua b/lib/tests/close.lua index 38fa69c85..7946ff898 100644 --- a/lib/tests/close.lua +++ b/lib/tests/close.lua @@ -7,3 +7,17 @@ assert(s1 ~= nil) local err = s1:close() assert(err ~= nil) + +-- Using state after close session +s1 = session:new's1' +assert(s1 ~= nil) + +session:close() +assert(s1:getname() == 's1') + +err = s1:close() +assert(err) + +-- Trying to close nonexistent state +err = s1:close() +assert(err == nil) diff --git a/lunatik.h b/lunatik.h index d450741ae..ff8392281 100644 --- a/lunatik.h +++ b/lunatik.h @@ -47,6 +47,7 @@ typedef struct lunatik_state { size_t maxalloc; size_t curralloc; size_t scriptsize; + bool inuse; unsigned char name[LUNATIK_NAME_MAXSIZE]; } lunatik_State; diff --git a/netlink.c b/netlink.c index 7a9da5aa4..7d6756c9b 100644 --- a/netlink.c +++ b/netlink.c @@ -230,14 +230,20 @@ static int lunatikN_newstate(struct sk_buff *buff, struct genl_info *info) s = lunatik_netnewstate(state_name, *max_alloc, genl_info_net(info)); - if (s == NULL) { - reply_with(OP_ERROR, CREATE_STATE, info); - } else { - s->instance = *instance; - reply_with(OP_SUCESS, CREATE_STATE, info); - } + if (s == NULL) + goto error; + + if (s->inuse) + goto error; + + s->instance = *instance; + reply_with(OP_SUCESS, CREATE_STATE, info); return 0; + +error: + reply_with(OP_ERROR, CREATE_STATE, info); + return 0; } static void init_codebuffer(lunatik_State *s, struct genl_info *info) @@ -627,6 +633,12 @@ static int lunatikN_sendstate(struct sk_buff *buff, struct genl_info *info) return 0; } + if (state->inuse) { + pr_info("State %s is already in use\n", state_name); + reply_with(OP_ERROR, GET_STATE, info); + return 0; + } + if (sendstate_msg(state, info)) { pr_err("Failed to send message to user space\n"); reply_with(OP_ERROR, GET_STATE, info);