checkpolicy: avoid memory leaks on redeclarations
If declare_symbol() returns 1 the id and the datum are already defined and not consumed by the function, so it they must be free'd by the caller. Example policy (generated by fuzzer): class s sid e class s{i}optional{require{bool K;}bool K true; Reported-by: oss-fuzz (issue 377544445) Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Acked-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
parent
20175564fc
commit
beca1ee16b
|
@ -190,7 +190,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_
|
||||||
* not be restricted pointers. */
|
* not be restricted pointers. */
|
||||||
int declare_symbol(uint32_t symbol_type,
|
int declare_symbol(uint32_t symbol_type,
|
||||||
hashtab_key_t key, hashtab_datum_t datum,
|
hashtab_key_t key, hashtab_datum_t datum,
|
||||||
uint32_t * dest_value, uint32_t * datum_value)
|
uint32_t * dest_value, const uint32_t * datum_value)
|
||||||
{
|
{
|
||||||
avrule_decl_t *decl = stack_top->decl;
|
avrule_decl_t *decl = stack_top->decl;
|
||||||
int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL);
|
int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL);
|
||||||
|
|
|
@ -28,7 +28,7 @@ int define_policy(int pass, int module_header_given);
|
||||||
*/
|
*/
|
||||||
int declare_symbol(uint32_t symbol_type,
|
int declare_symbol(uint32_t symbol_type,
|
||||||
hashtab_key_t key, hashtab_datum_t datum,
|
hashtab_key_t key, hashtab_datum_t datum,
|
||||||
uint32_t * dest_value, uint32_t * datum_value);
|
uint32_t * dest_value, const uint32_t * datum_value);
|
||||||
|
|
||||||
role_datum_t *declare_role(unsigned char isattr);
|
role_datum_t *declare_role(unsigned char isattr);
|
||||||
type_datum_t *declare_type(unsigned char primary, unsigned char isattr);
|
type_datum_t *declare_type(unsigned char primary, unsigned char isattr);
|
||||||
|
|
|
@ -156,9 +156,9 @@ static int id_has_dot(const char *id)
|
||||||
|
|
||||||
int define_class(void)
|
int define_class(void)
|
||||||
{
|
{
|
||||||
char *id = 0;
|
char *id = NULL;
|
||||||
class_datum_t *datum = 0;
|
class_datum_t *datum = NULL;
|
||||||
int ret;
|
int ret = -1;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
if (pass == 2) {
|
if (pass == 2) {
|
||||||
|
@ -175,27 +175,29 @@ int define_class(void)
|
||||||
datum = (class_datum_t *) malloc(sizeof(class_datum_t));
|
datum = (class_datum_t *) malloc(sizeof(class_datum_t));
|
||||||
if (!datum) {
|
if (!datum) {
|
||||||
yyerror("out of memory");
|
yyerror("out of memory");
|
||||||
goto bad;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memset(datum, 0, sizeof(class_datum_t));
|
memset(datum, 0, sizeof(class_datum_t));
|
||||||
ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value);
|
ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -3:{
|
case -3:{
|
||||||
yyerror("Out of memory!");
|
yyerror("Out of memory!");
|
||||||
goto bad;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
case -2:{
|
case -2:{
|
||||||
yyerror2("duplicate declaration of class %s", id);
|
yyerror2("duplicate declaration of class %s", id);
|
||||||
goto bad;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
case -1:{
|
case -1:{
|
||||||
yyerror("could not declare class here");
|
yyerror("could not declare class here");
|
||||||
goto bad;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0: {
|
||||||
case 1:{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 1:{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
default:{
|
default:{
|
||||||
assert(0); /* should never get here */
|
assert(0); /* should never get here */
|
||||||
}
|
}
|
||||||
|
@ -203,12 +205,10 @@ int define_class(void)
|
||||||
datum->s.value = value;
|
datum->s.value = value;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bad:
|
cleanup:
|
||||||
if (id)
|
free(id);
|
||||||
free(id);
|
free(datum);
|
||||||
if (datum)
|
return ret == 1 ? 0 : -1;
|
||||||
free(datum);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int define_permissive(void)
|
int define_permissive(void)
|
||||||
|
@ -785,8 +785,13 @@ int define_sens(void)
|
||||||
yyerror2("could not declare sensitivity level %s here", id);
|
yyerror2("could not declare sensitivity level %s here", id);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1:{
|
case 1:{
|
||||||
|
level_datum_destroy(datum);
|
||||||
|
free(datum);
|
||||||
|
free(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:{
|
default:{
|
||||||
|
@ -827,8 +832,13 @@ int define_sens(void)
|
||||||
("could not declare sensitivity alias %s here", id);
|
("could not declare sensitivity alias %s here", id);
|
||||||
goto bad_alias;
|
goto bad_alias;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1:{
|
case 1:{
|
||||||
|
level_datum_destroy(aliasdatum);
|
||||||
|
free(aliasdatum);
|
||||||
|
free(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:{
|
default:{
|
||||||
|
@ -957,15 +967,20 @@ int define_category(void)
|
||||||
yyerror2("could not declare category %s here", id);
|
yyerror2("could not declare category %s here", id);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:{
|
||||||
|
datum->s.value = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1:{
|
case 1:{
|
||||||
|
cat_datum_destroy(datum);
|
||||||
|
free(datum);
|
||||||
|
free(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:{
|
default:{
|
||||||
assert(0); /* should never get here */
|
assert(0); /* should never get here */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
datum->s.value = value;
|
|
||||||
|
|
||||||
while ((id = queue_remove(id_queue))) {
|
while ((id = queue_remove(id_queue))) {
|
||||||
if (id_has_dot(id)) {
|
if (id_has_dot(id)) {
|
||||||
|
@ -981,11 +996,11 @@ int define_category(void)
|
||||||
}
|
}
|
||||||
cat_datum_init(aliasdatum);
|
cat_datum_init(aliasdatum);
|
||||||
aliasdatum->isalias = TRUE;
|
aliasdatum->isalias = TRUE;
|
||||||
aliasdatum->s.value = datum->s.value;
|
aliasdatum->s.value = value;
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
declare_symbol(SYM_CATS, id, aliasdatum, NULL,
|
declare_symbol(SYM_CATS, id, aliasdatum, NULL,
|
||||||
&datum->s.value);
|
&value);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -3:{
|
case -3:{
|
||||||
yyerror("Out of memory!");
|
yyerror("Out of memory!");
|
||||||
|
@ -1001,8 +1016,13 @@ int define_category(void)
|
||||||
("could not declare category alias %s here", id);
|
("could not declare category alias %s here", id);
|
||||||
goto bad_alias;
|
goto bad_alias;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:{
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1:{
|
case 1:{
|
||||||
|
cat_datum_destroy(aliasdatum);
|
||||||
|
free(aliasdatum);
|
||||||
|
free(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:{
|
default:{
|
||||||
|
@ -1833,10 +1853,12 @@ int define_bool_tunable(int is_tunable)
|
||||||
yyerror2("could not declare boolean %s here", id);
|
yyerror2("could not declare boolean %s here", id);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:{
|
||||||
case 1:{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 1:{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
default:{
|
default:{
|
||||||
assert(0); /* should never get here */
|
assert(0); /* should never get here */
|
||||||
}
|
}
|
||||||
|
@ -1854,7 +1876,7 @@ int define_bool_tunable(int is_tunable)
|
||||||
return 0;
|
return 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
cond_destroy_bool(id, datum, NULL);
|
cond_destroy_bool(id, datum, NULL);
|
||||||
return -1;
|
return ret == 1 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
|
avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
|
||||||
|
|
Loading…
Reference in New Issue