Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 23 additions & 8 deletions security/lua/auxlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ void luaL_requiref(lua_State *L, const char *modname,
}
}

const struct cflag_opt lua_lsm_cap_opts[] = {
{ "noaudit", CAP_OPT_NOAUDIT },
{ "insetid", CAP_OPT_INSETID },
{ NULL, 0 }
};

const unsigned int lua_lsm_cap_opt_flags = CAP_OPT_NOAUDIT |
CAP_OPT_INSETID;

unsigned int tocflags(lua_State *L, int idx, int top,
const struct cflag_opt *opts, unsigned int d)
{
Expand Down Expand Up @@ -548,16 +557,14 @@ int arg2cap(lua_State *L, int idx)
/*
* [task:]capable(CAP_MAC_ADMIN)
* [task:]capable('mac_admin')
* [task:]capable(ns, CAP_MAC_ADMIN)
* [task:]capable(task, 'mac_admin')
* [task:]capable(task, 'mac_admin', 'noaudit', 'insetid')
*/
int aux_capable(lua_State *L, const struct cred *cred, int idx)
int aux_capable(lua_State *L, const struct cred *cred,
struct user_namespace *default_ns, int idx)
{
static const struct cflag_opt opts[] = {
{ "noaudit", CAP_OPT_NOAUDIT },
{ "insetid", CAP_OPT_INSETID },
{ NULL, 0 }
};
struct user_namespace *ns = default_ns;
unsigned int opt = CAP_OPT_NONE;
int top = lua_gettop(L);
int cap;
Expand All @@ -568,13 +575,21 @@ int aux_capable(lua_State *L, const struct cred *cred, int idx)

if (top == idx) {
cap = arg2cap(L, idx);
err = cap_capable(cred, current_user_ns(), cap, opt);
err = cap_capable(cred, ns, cap, opt);
} else if (tousernsp(L, idx)) {
ns = touserns(L, idx);
cap = arg2cap(L, idx + 1);
if (top >= idx + 2)
opt = tocflags(L, idx + 2, top,
lua_lsm_cap_opts, CAP_OPT_NONE);
err = cap_capable(cred, ns, cap, opt);
} else {
struct task_struct *task = totask(L, idx);

cap = arg2cap(L, idx + 1);
if (top >= idx + 2)
opt = tocflags(L, idx + 2, top, opts, CAP_OPT_NONE);
opt = tocflags(L, idx + 2, top,
lua_lsm_cap_opts, CAP_OPT_NONE);

rcu_read_lock();
err = cap_capable(cred, __task_cred(task)->user_ns, cap, opt);
Expand Down
7 changes: 6 additions & 1 deletion security/lua/auxlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
struct cred;
struct dentry;
struct file;
struct user_namespace;

static inline gfp_t lua_lsm_gfp(void)
{
Expand Down Expand Up @@ -53,6 +54,9 @@ struct cflag_opt {
unsigned int flag;
};

extern const struct cflag_opt lua_lsm_cap_opts[];
extern const unsigned int lua_lsm_cap_opt_flags;

unsigned int tocflags(lua_State *L, int idx, int top,
const struct cflag_opt *opts, unsigned int d);

Expand Down Expand Up @@ -86,6 +90,7 @@ int aux_file_path(lua_State *L, struct file *filp);
int aux_dentry_path(lua_State *L, struct dentry *dentry, int rawpath);

int arg2cap(lua_State *L, int idx);
int aux_capable(lua_State *L, const struct cred *cred, int idx);
int aux_capable(lua_State *L, const struct cred *cred,
struct user_namespace *default_ns, int idx);

#endif /* ! _SECURITY_LUA_LSM_AUXLIB_H */
6 changes: 3 additions & 3 deletions security/lua/lsm_defs.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,16 @@ LUA_LSM_INT_DEFINE5(capset, struct cred *, new, const struct cred *, old,
}

/**
* TODO: capable
* capable
* Default: 0
*/
LUA_LSM_INT_DEFINE4(capable, const struct cred *, cred,
struct user_namespace *, ns, int, cap, unsigned int, opts)
{
*(const struct cred **)newcred(L) = cred;
lua_pushnil(L); /* TODO: ns */
*newuserns(L) = ns;
lua_pushinteger(L, (lua_Integer)cap);
lua_pushinteger(L, (lua_Integer)opts);
table_fromopts(L, lua_lsm_cap_opts, lua_lsm_cap_opt_flags, opts);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion security/lua/lua_capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "debug.h"
#include <linux/capability.h>
#include <linux/cred.h>
#include "lsm.h"
#include "auxlib.h"
#include "lua_object.h"
Expand Down Expand Up @@ -158,7 +159,7 @@ static int capability_cap_full(lua_State *L)

static int capability_capable(lua_State *L)
{
return aux_capable(L, current_cred(), 1);
return aux_capable(L, current_cred(), current_user_ns(), 1);
}

static const luaL_Reg capabilitylib[] = {
Expand Down
122 changes: 121 additions & 1 deletion security/lua/lua_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/printk.h>
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/user_namespace.h>
#include <linux/lua.h>
#include <linux/lualib.h>
#include <linux/lauxlib.h>
Expand Down Expand Up @@ -132,13 +133,118 @@ static int kernel_cred_securebits(lua_State *L)
return 0;
}

static int kernel_cred_userns(lua_State *L)
{
const struct cred *cred = tocred(L, 1);

*newgcuserns(L) = get_user_ns(cred->user_ns);
return 1;
}

static int kernel_cred_capable(lua_State *L)
{
const struct cred *cred = tocred(L, 1);

return aux_capable(L, cred, cred->user_ns, 2);
}

static const luaL_Reg cred_meth[] = {
{ "uids", kernel_cred_uids },
{ "gids", kernel_cred_gids },
{ "cap_eip", kernel_cred_cap_eip },
{ "cap_bset", kernel_cred_cap_bset },
{ "cap_ambient", kernel_cred_cap_ambient },
{ "securebits", kernel_cred_securebits },
{ "userns", kernel_cred_userns },
{ "capable", kernel_cred_capable },
{ NULL, NULL }
};

/********************************* userns *********************************/

static int kernel_userns_is_initial(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushboolean(L, ns == &init_user_ns);
return 1;
}

static int kernel_userns_level(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushinteger(L, ns->level);
return 1;
}

static int kernel_userns_owner_uid(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushinteger(L, (lua_Integer)ns->owner.val);
return 1;
}

static int kernel_userns_owner_gid(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushinteger(L, (lua_Integer)ns->group.val);
return 1;
}

static int kernel_userns_inum(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushinteger(L, (lua_Integer)ns->ns.inum);
return 1;
}

static int kernel_userns_same(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);
struct user_namespace *other = touserns(L, 2);

lua_pushboolean(L, ns == other);
return 1;
}

static int meth_userns_tostring(lua_State *L)
{
struct user_namespace *ns = touserns(L, 1);

lua_pushfstring(L, "userns: <inum = %d, level = %d>",
(int)ns->ns.inum, ns->level);
return 1;
}

static const luaL_Reg userns_meth[] = {
{ "is_initial", kernel_userns_is_initial },
{ "level", kernel_userns_level },
{ "owner_uid", kernel_userns_owner_uid },
{ "owner_gid", kernel_userns_owner_gid },
{ "inum", kernel_userns_inum },
{ "same", kernel_userns_same },
{ "__tostring", meth_userns_tostring },
{ NULL, NULL }
};

static int meth_userns_gc(lua_State *L)
{
struct user_namespace **nsp = togcusernsp(L, 1);

if (*nsp) {
put_user_ns(*nsp);
*nsp = NULL;
}
return 0;
}

static const luaL_Reg userns_gc_meth[] = {
{ "__tostring", meth_userns_tostring },
{ "__gc", meth_userns_gc },
{ NULL, NULL }
};

Expand All @@ -160,6 +266,16 @@ static int kernel_task_cred(lua_State *L)
return 1;
}

static int kernel_task_userns(lua_State *L)
{
struct task_struct *task = totask(L, 1);
const struct cred *cred = get_task_cred(task);

*newgcuserns(L) = get_user_ns(cred->user_ns);
put_cred(cred);
return 1;
}

static int kernel_task_comm(lua_State *L)
{
struct task_struct *task = totask(L, 1);
Expand Down Expand Up @@ -286,10 +402,12 @@ static int kernel_task_cmdline(lua_State *L)
static int kernel_task_capable(lua_State *L)
{
struct task_struct *task = totask(L, 1);
const struct cred *cred;
int nres;

rcu_read_lock();
nres = aux_capable(L, __task_cred(task), 2);
cred = __task_cred(task);
nres = aux_capable(L, cred, cred->user_ns, 2);
rcu_read_unlock();
return nres;
}
Expand Down Expand Up @@ -356,6 +474,7 @@ static int meth_task_tostring(lua_State *L)
static const luaL_Reg task_meth[] = {
{ "pids", kernel_task_pids },
{ "cred", kernel_task_cred },
{ "userns", kernel_task_userns },
{ "comm", kernel_task_comm },
{ "nr_threads", kernel_task_nr_threads },
{ "group_leader", kernel_task_group_leader },
Expand Down Expand Up @@ -558,6 +677,7 @@ LUALIB_API int luaopen_kernel(lua_State *L)
luaL_newlib(L, kernellib);
create_task_meta(L, task_meth, task_gc_meth);
create_cred_meta(L, cred_meth, NULL);
create_userns_meta(L, userns_meth, userns_gc_meth);
create_perfevent_meta(L, NULL, NULL);
create_ipc_meta(L, NULL, NULL);
create_msgmsg_meta(L, NULL, NULL);
Expand Down
1 change: 1 addition & 0 deletions security/lua/lua_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
#define LUA_OBJECTS_LIST \
LUA_OBJECT(task, kernel, task, struct task_struct *, NULL) \
LUA_OBJECT(object, kernel, cred, struct cred *, NULL) \
LUA_OBJECT(func, kernel, userns, struct user_namespace *, NULL) \
LUA_OBJECT(func, kernel, perfevent, struct perf_event *, NULL) \
LUA_OBJECT(object, ipc, ipc, struct kern_ipc_perm *, NULL) \
LUA_OBJECT(object, ipc, msgmsg, struct msg_msg *, NULL) \
Expand Down