mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 18:17:09 +00:00
add correct line number and filename tracking for error conditions (LP: #588014)
Bug: https://launchpad.net/bugs/588014
This commit is contained in:
parent
67bd489ba8
commit
7cfc7e1133
@ -270,3 +270,63 @@ static char *stripblanks(char *s)
|
||||
*s = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
struct include_stack_t {
|
||||
char *filename;
|
||||
int lineno;
|
||||
struct include_stack_t *next;
|
||||
};
|
||||
|
||||
struct include_stack_t *include_stack_head = NULL;
|
||||
|
||||
static void start_include_position(char *filename)
|
||||
{
|
||||
if (current_filename)
|
||||
free(current_filename);
|
||||
current_filename = strdup(filename ? filename : "stdin");
|
||||
current_lineno = 0;
|
||||
}
|
||||
|
||||
void push_include_stack(char *filename)
|
||||
{
|
||||
struct include_stack_t *include = NULL;
|
||||
|
||||
include = malloc(sizeof(*include));
|
||||
if (!include) {
|
||||
perror("malloc of included file stack tracker");
|
||||
/* failures in this area are non-fatal */
|
||||
return;
|
||||
}
|
||||
|
||||
include->filename = strdup(current_filename);
|
||||
include->lineno = current_lineno;
|
||||
include->next = include_stack_head;
|
||||
include_stack_head = include;
|
||||
|
||||
start_include_position(filename);
|
||||
}
|
||||
|
||||
void pop_include_stack(void)
|
||||
{
|
||||
struct include_stack_t *include = NULL;
|
||||
|
||||
if (!include_stack_head)
|
||||
return;
|
||||
|
||||
include = include_stack_head;
|
||||
include_stack_head = include->next;
|
||||
|
||||
if (current_filename)
|
||||
free(current_filename);
|
||||
current_filename = include->filename;
|
||||
current_lineno = include->lineno;
|
||||
free(include);
|
||||
}
|
||||
|
||||
void reset_include_stack(char *filename)
|
||||
{
|
||||
while (include_stack_head)
|
||||
pop_include_stack();
|
||||
|
||||
start_include_position(filename);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
@ -21,6 +19,8 @@
|
||||
#define PARSER_INCLUDE_H
|
||||
|
||||
extern int preprocess_only;
|
||||
extern int current_lineno;
|
||||
extern char *current_filename;
|
||||
|
||||
extern int add_search_dir(char *dir);
|
||||
extern void init_base_dir(void);
|
||||
@ -29,4 +29,8 @@ extern void parse_default_paths(void);
|
||||
extern int do_include_preprocessing(char *profilename);
|
||||
FILE *search_path(char *filename, char **fullpath);
|
||||
|
||||
extern void push_include_stack(char *filename);
|
||||
extern void pop_include_stack(void);
|
||||
extern void reset_include_stack(char *filename);
|
||||
|
||||
#endif
|
||||
|
@ -49,7 +49,8 @@
|
||||
#endif
|
||||
#define NPDEBUG(fmt, args...) /* Do nothing */
|
||||
|
||||
int current_lineno = 1;
|
||||
int current_lineno = 0;
|
||||
char *current_filename = NULL;
|
||||
|
||||
struct ignored_suffix_t {
|
||||
char * text;
|
||||
@ -87,7 +88,8 @@ void include_filename(char *filename, int search)
|
||||
}
|
||||
|
||||
if (!include_file)
|
||||
yyerror(_("Could not open '%s'"), fullpath);
|
||||
yyerror(_("Could not open '%s'"),
|
||||
fullpath ? fullpath: filename);
|
||||
|
||||
if (fstat(fileno(include_file), &my_stat))
|
||||
yyerror(_("fstat failed for '%s'"), fullpath);
|
||||
@ -95,6 +97,7 @@ void include_filename(char *filename, int search)
|
||||
if (S_ISREG(my_stat.st_mode)) {
|
||||
yyin = include_file;
|
||||
PDEBUG("Opened include \"%s\"\n", fullpath);
|
||||
push_include_stack(fullpath);
|
||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||
}
|
||||
|
||||
@ -139,8 +142,9 @@ void include_filename(char *filename, int search)
|
||||
yyerror(_("stat failed for '%s'"), dirent_path);
|
||||
if (S_ISREG(my_stat.st_mode)) {
|
||||
if (!(yyin = fopen(dirent_path,"r")))
|
||||
yyerror(_("Could not open '%s'"), filename);
|
||||
PDEBUG("Opened include \"%s\"\n", filename);
|
||||
yyerror(_("Could not open '%s' in '%s'"), dirent_path, filename);
|
||||
PDEBUG("Opened include \"%s\" in \"%s\"\n", dirent_path, filename);
|
||||
push_include_stack(dirent_path);
|
||||
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
}
|
||||
}
|
||||
@ -228,6 +232,7 @@ LT_EQUAL <=
|
||||
|
||||
<<EOF>> {
|
||||
fclose(yyin);
|
||||
pop_include_stack();
|
||||
yypop_buffer_state();
|
||||
if ( !YY_CURRENT_BUFFER ) yyterminate();
|
||||
}
|
||||
|
@ -89,8 +89,6 @@ int perms_create = 0; /* perms contain create flag */
|
||||
char *profile_namespace = NULL;
|
||||
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
|
||||
|
||||
extern int current_lineno;
|
||||
|
||||
/* per-profile settings */
|
||||
int force_complain = 0;
|
||||
char *profilename = NULL;
|
||||
@ -228,8 +226,10 @@ void pwarn(char *fmt, ...)
|
||||
if (conf_quiet || names_only || option == OPTION_REMOVE)
|
||||
return;
|
||||
|
||||
rc = asprintf(&newfmt, _("Warning (%s line %d): %s"),
|
||||
rc = asprintf(&newfmt, _("Warning from %s (%s%sline %d): %s"),
|
||||
profilename ? profilename : "stdin",
|
||||
current_filename ? current_filename : "",
|
||||
current_filename ? " " : "",
|
||||
current_lineno,
|
||||
fmt);
|
||||
if (!newfmt)
|
||||
@ -699,12 +699,13 @@ int process_binary(int option, char *profilename)
|
||||
return retval;
|
||||
}
|
||||
|
||||
void reset_parser(void)
|
||||
void reset_parser(char *filename)
|
||||
{
|
||||
free_aliases();
|
||||
free_symtabs();
|
||||
free_policies();
|
||||
reset_regex();
|
||||
reset_include_stack(filename);
|
||||
}
|
||||
|
||||
int process_profile(int option, char *profilename)
|
||||
@ -800,7 +801,7 @@ int process_profile(int option, char *profilename)
|
||||
|
||||
if (yyin)
|
||||
yyrestart(yyin);
|
||||
reset_parser();
|
||||
reset_parser(profilename);
|
||||
|
||||
retval = yyparse();
|
||||
if (retval != 0)
|
||||
|
@ -32,6 +32,7 @@
|
||||
/* #define DEBUG */
|
||||
|
||||
#include "parser.h"
|
||||
#include "parser_include.h"
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
@ -63,10 +64,6 @@
|
||||
|
||||
#define CAP_TO_MASK(x) (1ull << (x))
|
||||
|
||||
/* from lex_config, for nice error messages */
|
||||
/* extern char *current_file; */
|
||||
extern int current_lineno;
|
||||
|
||||
struct value_list {
|
||||
char *value;
|
||||
struct value_list *next;
|
||||
@ -1109,10 +1106,15 @@ void yyerror(char *msg, ...)
|
||||
va_end(arg);
|
||||
|
||||
if (profilename) {
|
||||
PERROR(_("AppArmor parser error in %s at line %d: %s\n"),
|
||||
profilename, current_lineno, buf);
|
||||
PERROR(_("AppArmor parser error for %s%s%s at line %d: %s\n"),
|
||||
profilename,
|
||||
current_filename ? " in " : "",
|
||||
current_filename ? current_filename : "",
|
||||
current_lineno, buf);
|
||||
} else {
|
||||
PERROR(_("AppArmor parser error, line %d: %s\n"),
|
||||
PERROR(_("AppArmor parser error,%s%s line %d: %s\n"),
|
||||
current_filename ? " in " : "",
|
||||
current_filename ? current_filename : "",
|
||||
current_lineno, buf);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
PROVE=/usr/bin/prove
|
||||
TESTS=simple.pl
|
||||
PARSER_DIR=..
|
||||
PARSER_BIN=apparmor_parser
|
||||
PARSER=$(PARSER_DIR)/$(PARSER_BIN)
|
||||
|
||||
ifeq ($(VERBOSE),1)
|
||||
PROVE_ARG=-v
|
||||
@ -10,9 +11,19 @@ endif
|
||||
|
||||
all: tests
|
||||
|
||||
.PHONY: tests
|
||||
tests: ../apparmor_parser
|
||||
.PHONY: tests error_output parser_sanity
|
||||
tests: error_output parser_sanity
|
||||
|
||||
error_output: $(PARSER)
|
||||
$(PARSER) -S -I errors >/dev/null errors/okay.sd
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/single.sd | \
|
||||
grep -q "AppArmor parser error for errors/single.sd in errors/single.sd at line 3: Could not open 'failure'"
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/double.sd | \
|
||||
grep -q "AppArmor parser error for errors/double.sd in errors/includes/busted at line 67: Could not open 'does-not-exist'"
|
||||
@echo "Error Output: PASS"
|
||||
|
||||
parser_sanity: $(PARSER)
|
||||
$(Q)${PROVE} ${PROVE_ARG} ${TESTS}
|
||||
|
||||
../apparmor_parser:
|
||||
make -C .. apparmor_parser
|
||||
$(PARSER):
|
||||
make -C $(PARSER_DIR) $(PARSER_BIN)
|
||||
|
@ -64,5 +64,3 @@ The simple script looks for a few special comments in the profile,
|
||||
loop.
|
||||
|
||||
Otherwise, the profile is passed on as-is to the subdomain parser.
|
||||
|
||||
$Id$
|
||||
|
5
parser/tst/errors/double.sd
Normal file
5
parser/tst/errors/double.sd
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
/does/not/exist {
|
||||
#include <includes/base>
|
||||
#include <includes/busted>
|
||||
}
|
81
parser/tst/errors/includes/base
Normal file
81
parser/tst/errors/includes/base
Normal file
@ -0,0 +1,81 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# (Note that the ldd profile has inlined this file; if you make
|
||||
# modifications here, please consider including them in the ldd
|
||||
# profile as well.)
|
||||
|
||||
# The __canary_death_handler function writes a time-stamped log
|
||||
# message to /dev/log for logging by syslogd. So, /dev/log, timezones,
|
||||
# and localisations of date should be available EVERYWHERE, so
|
||||
# StackGuard, FormatGuard, etc., alerts can be properly logged.
|
||||
/dev/log w,
|
||||
/dev/urandom r,
|
||||
/etc/locale/** r,
|
||||
/etc/localtime r,
|
||||
/usr/share/locale/** r,
|
||||
/usr/share/zoneinfo/** r,
|
||||
|
||||
/usr/lib64/locale/** r,
|
||||
/usr/lib64/gconv/*.so r,
|
||||
/usr/lib64/gconv/gconv-modules* r,
|
||||
/usr/lib/locale/** r,
|
||||
/usr/lib/gconv/*.so r,
|
||||
/usr/lib/gconv/gconv-modules* r,
|
||||
|
||||
# used by glibc when binding to ephemeral ports
|
||||
/etc/bindresvport.blacklist r,
|
||||
|
||||
# ld.so.cache and ld are used to load shared libraries; they are best
|
||||
# available everywhere
|
||||
/etc/ld.so.cache r,
|
||||
# 'px' requires a profile to be available for the transition to
|
||||
# function; without a loaded profile, the kernel will fail the exec.
|
||||
/lib/ld-*.so px,
|
||||
/lib64/ld-*.so px,
|
||||
/opt/*-linux-uclibc/lib/ld-uClibc*so* px,
|
||||
|
||||
# we might as well allow everything to use common libraries
|
||||
/lib/lib*.so* r,
|
||||
/lib/tls/lib*.so* r,
|
||||
/lib/power4/lib*.so* r,
|
||||
/lib/power5/lib*.so* r,
|
||||
/lib/power5+/lib*.so* r,
|
||||
/lib64/power4/lib*.so* r,
|
||||
/lib64/power5/lib*.so* r,
|
||||
/lib64/power5+/lib*.so* r,
|
||||
/usr/lib/*.so* r,
|
||||
/usr/lib/tls/lib*.so* r,
|
||||
/usr/lib/power4/lib*.so* r,
|
||||
/usr/lib/power5/lib*.so* r,
|
||||
/usr/lib/power5+/lib*.so* r,
|
||||
/lib64/lib*.so* r,
|
||||
/lib64/tls/lib*.so* r,
|
||||
/usr/lib64/*.so* r,
|
||||
/usr/lib64/tls/lib*.so* r,
|
||||
|
||||
# /dev/null is pretty harmless and frequently used
|
||||
/dev/null rw,
|
||||
# as is /dev/zero
|
||||
/dev/zero rw,
|
||||
|
||||
# Sometimes used to determine kernel/user interfaces to use
|
||||
/proc/sys/kernel/version r,
|
||||
# Depending on which glibc routine uses this file, base may not be the
|
||||
# best place -- but many profiles require it, and it is quite harmless.
|
||||
/proc/sys/kernel/ngroups_max r,
|
||||
|
||||
# glibc's sysconf(3) routine to determine free memory, etc
|
||||
/proc/meminfo r,
|
||||
/proc/stat r,
|
||||
/proc/cpuinfo r,
|
83
parser/tst/errors/includes/busted
Normal file
83
parser/tst/errors/includes/busted
Normal file
@ -0,0 +1,83 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# (Note that the ldd profile has inlined this file; if you make
|
||||
# modifications here, please consider including them in the ldd
|
||||
# profile as well.)
|
||||
|
||||
# The __canary_death_handler function writes a time-stamped log
|
||||
# message to /dev/log for logging by syslogd. So, /dev/log, timezones,
|
||||
# and localisations of date should be available EVERYWHERE, so
|
||||
# StackGuard, FormatGuard, etc., alerts can be properly logged.
|
||||
/dev/log w,
|
||||
/dev/urandom r,
|
||||
/etc/locale/** r,
|
||||
/etc/localtime r,
|
||||
/usr/share/locale/** r,
|
||||
/usr/share/zoneinfo/** r,
|
||||
|
||||
/usr/lib64/locale/** r,
|
||||
/usr/lib64/gconv/*.so r,
|
||||
/usr/lib64/gconv/gconv-modules* r,
|
||||
/usr/lib/locale/** r,
|
||||
/usr/lib/gconv/*.so r,
|
||||
/usr/lib/gconv/gconv-modules* r,
|
||||
|
||||
# used by glibc when binding to ephemeral ports
|
||||
/etc/bindresvport.blacklist r,
|
||||
|
||||
# ld.so.cache and ld are used to load shared libraries; they are best
|
||||
# available everywhere
|
||||
/etc/ld.so.cache r,
|
||||
# 'px' requires a profile to be available for the transition to
|
||||
# function; without a loaded profile, the kernel will fail the exec.
|
||||
/lib/ld-*.so px,
|
||||
/lib64/ld-*.so px,
|
||||
/opt/*-linux-uclibc/lib/ld-uClibc*so* px,
|
||||
|
||||
# we might as well allow everything to use common libraries
|
||||
/lib/lib*.so* r,
|
||||
/lib/tls/lib*.so* r,
|
||||
/lib/power4/lib*.so* r,
|
||||
/lib/power5/lib*.so* r,
|
||||
/lib/power5+/lib*.so* r,
|
||||
/lib64/power4/lib*.so* r,
|
||||
/lib64/power5/lib*.so* r,
|
||||
/lib64/power5+/lib*.so* r,
|
||||
/usr/lib/*.so* r,
|
||||
/usr/lib/tls/lib*.so* r,
|
||||
/usr/lib/power4/lib*.so* r,
|
||||
/usr/lib/power5/lib*.so* r,
|
||||
/usr/lib/power5+/lib*.so* r,
|
||||
/lib64/lib*.so* r,
|
||||
/lib64/tls/lib*.so* r,
|
||||
/usr/lib64/*.so* r,
|
||||
/usr/lib64/tls/lib*.so* r,
|
||||
|
||||
#include <does-not-exist>
|
||||
|
||||
# /dev/null is pretty harmless and frequently used
|
||||
/dev/null rw,
|
||||
# as is /dev/zero
|
||||
/dev/zero rw,
|
||||
|
||||
# Sometimes used to determine kernel/user interfaces to use
|
||||
/proc/sys/kernel/version r,
|
||||
# Depending on which glibc routine uses this file, base may not be the
|
||||
# best place -- but many profiles require it, and it is quite harmless.
|
||||
/proc/sys/kernel/ngroups_max r,
|
||||
|
||||
# glibc's sysconf(3) routine to determine free memory, etc
|
||||
/proc/meminfo r,
|
||||
/proc/stat r,
|
||||
/proc/cpuinfo r,
|
4
parser/tst/errors/okay.sd
Normal file
4
parser/tst/errors/okay.sd
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
/does/not/exist {
|
||||
#include <includes/base>
|
||||
}
|
7
parser/tst/errors/single.sd
Normal file
7
parser/tst/errors/single.sd
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
#
|
||||
#include <failure>
|
||||
#
|
||||
/does/not/exist {
|
||||
#include <includes/base>
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user