diff --git a/security/lua/auxlib.c b/security/lua/auxlib.c index d1667d5ec26b..5a17abba4984 100644 --- a/security/lua/auxlib.c +++ b/security/lua/auxlib.c @@ -540,6 +540,8 @@ int arg2cap(lua_State *L, int idx) default: return luaL_argerror(L, idx, "integer or string expected"); } + if (!cap_valid(cap)) + return luaL_argerror(L, idx, "invalid capability"); return cap; } diff --git a/security/lua/lsm_defs.c b/security/lua/lsm_defs.c index 4326c13dec3d..17ecd3fe102f 100644 --- a/security/lua/lsm_defs.c +++ b/security/lua/lsm_defs.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include /* for __MAP */ @@ -769,6 +770,44 @@ LUA_LSM_VOID_DEFINE1(inode_free_security_rcu, void *, inode_security) lua_pushnil(L); /* TODO: inode_security */ } +static int lua_lsm_init_xattr(lua_State *L, int name_idx, int value_idx, + struct xattr *xattr) +{ + size_t name_len, value_len; + const char *name, *value; + char *buffer; + + name = lua_tolstring(L, name_idx, &name_len); + value = lua_tolstring(L, value_idx, &value_len); + + if (!name_len || name_len > XATTR_NAME_MAX - XATTR_SECURITY_PREFIX_LEN) + return -EINVAL; + if (memchr(name, '\0', name_len)) + return -EINVAL; + if (value_len > XATTR_SIZE_MAX) + return -E2BIG; + + buffer = kmalloc(value_len + name_len + 1, GFP_NOFS); + if (!buffer) + return -ENOMEM; + + memcpy(buffer, value, value_len); + memcpy(buffer + value_len, name, name_len); + buffer[value_len + name_len] = '\0'; + + /* + * FIXME: xattr->name must not share xattr->value storage. Some + * initxattrs users, notably OCFS2, duplicate only value and keep + * the name pointer after security_inode_init_security() frees value. + * This needs separate name storage with a lifetime that covers those + * delayed users. + */ + xattr->value = buffer; + xattr->value_len = value_len; + xattr->name = buffer + value_len; + return 0; +} + /** * inode_init_security * Default: -EOPNOTSUPP @@ -780,7 +819,7 @@ LUA_LSM_VOID_DEFINE1(inode_free_security_rcu, void *, inode_security) * false : -EPERM * false, errno : -errno * nil, errno : -errno - * name, value : fill the xattr struct, XXX: name must not be freed + * name, value : fill the xattr struct */ LUA_LSM_INT_NAKED_DEFINE5(inode_init_security, struct inode *, inode, struct inode *, dir, const struct qstr *, qstr, @@ -822,23 +861,10 @@ LUA_LSM_INT_NAKED_DEFINE5(inode_init_security, struct inode *, inode, ret = -errno; } else if (lua_isstring(L, top) && lua_isstring(L, top + 1)) { struct xattr *xattr; - const char *value; - size_t len; xattr = lsm_get_xattr_slot(xattrs, xattr_count); - if (xattr) { - value = lua_tolstring(L, top + 1, &len); - xattr->value = kmemdup(value, len, GFP_NOFS); - if (xattr->value == NULL) { - ret = -ENOMEM; - break; - } - xattr->value_len = len; - xattr->name = lua_tostring(L, top); - ret = 0; - } else { - /* TODO */ - } + if (xattr) + ret = lua_lsm_init_xattr(L, top, top + 1, xattr); } break; }