[PATCH 7.1 005/228] selinux: reject an unclaimed class value in security_get_classes()
Greg Kroah-Hartman <[email protected]>
| Newsgroups | dev.linux.lists.patches,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
7.1-stable review patch. If anyone has any objections, please let me know. ------------------ From: Bryam Vargas <[email protected]> commit 22b05fec62c0fe9864cfceb52f7d0f3a34d9b1dd upstream. security_get_classes() sizes an array by p_classes.nprim and fills it at value - 1, so a class value the policy never defines leaves a NULL. sel_make_classes() passes every entry to sel_make_dir(), reaching the same d_alloc_name() dereference as the permission array. The class symbol table is allowed to be sparse (policydb_class_isvalid() exists to absorb that), but this getter builds its own array straight from the hash table and has no such predicate. Fail the lookup when a value went unclaimed instead of handing out the NULL. Conforming policies define every class they declare and are unaffected. Cc: [email protected] Fixes: 55fcf09b3fe4 ("selinux: add support for querying object classes and permissions from the running policy") Signed-off-by: Bryam Vargas <[email protected]> Acked-by: Stephen Smalley <[email protected]> Signed-off-by: Paul Moore <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> --- security/selinux/ss/services.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3303,6 +3303,7 @@ int security_get_classes(struct selinux_ char ***classes, u32 *nclasses) { struct policydb *policydb; + u32 i; int rc; policydb = &policy->policydb; @@ -3315,16 +3316,29 @@ int security_get_classes(struct selinux_ rc = hashtab_map(&policydb->p_classes.table, get_classes_callback, *classes); - if (rc) { - u32 i; + if (rc) + goto err; - for (i = 0; i < *nclasses; i++) - kfree((*classes)[i]); - kfree(*classes); + /* + * The class symtab may be sparse, which policydb_class_isvalid() exists + * to absorb; the callback fills this array by value, so an unclaimed + * one leaves a NULL that sel_make_classes() hands to sel_make_dir(). + */ + for (i = 0; i < *nclasses; i++) { + if (!(*classes)[i]) { + rc = -EINVAL; + goto err; + } } out: return rc; + +err: + for (i = 0; i < *nclasses; i++) + kfree((*classes)[i]); + kfree(*classes); + return rc; } static int get_permissions_callback(void *k, void *d, void *args)