apparmor/parser/parser_include.c
John Johansen 94ff870f78 remove subdomainfs support
It has been over 10 years since transition from subdomainfs to
using securityfs. Lets drop this deprecated code.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/258
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: seth.arnold@canonical.com
2018-11-08 18:23:21 -08:00

280 lines
5.7 KiB
C

/*
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
* Copyright (c) 2010 - 2012
* Canonical Ltd.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Canonical, Ltd.
*/
/* Handle apparmor includes, as a straight forward preprocessing phase.
While we are at it we will strip comments. Why? because it made it
easier.
We support 2 types of includes
#include <name> which searches for the first occurance of name in the
apparmor directory path.
#include "name" which will search for a relative or absolute pathed
file
-p : preprocess only. Dump output to stdout
-I path : add a path to be search by #include < >
-b path : set the base path to something other than /etc/apparmor.d
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <limits.h>
#include "lib.h"
#include "parser.h"
#include "parser_include.h"
/* An array of search directories, I sure hope 100's enough */
#define MAX_PATH 100
/* maximum depth of nesting */
#define MAX_NEST_LEVEL 100
static char *path[MAX_PATH] = { NULL };
static int npath = 0;
static int fgetline(FILE * f, char *buffer, size_t len);
static int stripcomment(char *s);
static char *stripblanks(char *s);
/* default base directory is /etc/apparmor.d, it can be overriden
with the -b option. */
const char *basedir;
static const char *default_basedir = "/etc/apparmor.d";
/* set up basedir so that it can be overridden/used later. */
void init_base_dir(void)
{
int rc;
struct stat sbuf;
/* basedir should always start out NULL; if not, something's
* wrong.*/
assert(basedir == NULL);
rc = stat(default_basedir, &sbuf);
if (rc == 0 && S_ISDIR(sbuf.st_mode)) {
basedir = default_basedir;
return;
}
}
/* Set the base dir. Used to change default path for relative includes */
void set_base_dir(char *dir)
{
char *t;
int i, rc;
struct stat sbuf;
t = strndup(dir, PATH_MAX);
if (!t) {
PERROR(_("Error: Out of memory.\n"));
return;
}
/*strip trailing /'s */
for (i = strlen(t) - 1; i >= 0 && t[i] == '/'; i--)
t[i] = 0;
rc = stat(t, &sbuf);
if (rc == -1 || !S_ISDIR(sbuf.st_mode)) {
PERROR(_("Error: basedir %s is not a directory, skipping.\n"), t);
free(t);
return;
}
basedir = t;
return;
}
/* Add a directory to the search path. */
int add_search_dir(const char *dir)
{
char *t;
size_t len;
if (npath >= MAX_PATH) {
PERROR(_("Error: Could not add directory %s to search path.\n"),
dir);
return 0;
}
if (!dir)
return 1;
len = strlen(dir);
if (len == 0)
return 1;
t = strdup(dir);
if (t == NULL) {
PERROR(_("Error: Could not allocate memory.\n"));
return 0;
}
/*strip trailing /'s */
while (len > 0 && t[--len] == '/')
t[len] = '\0';
path[npath] = t;
npath++;
return 1;
}
void parse_default_paths(void)
{
add_search_dir(basedir);
}
FILE *search_path(char *filename, char **fullpath)
{
FILE *newf = NULL;
char *buf = NULL;
int i;
for (i = 0; i < npath; i++) {
if (asprintf(&buf, "%s/%s", path[i], filename) < 0) {
perror("asprintf");
exit(1);
}
newf = fopen(buf, "r");
if (newf && fullpath)
*fullpath = buf;
else
free(buf);
buf = NULL;
if (newf)
break;
}
return newf;
}
/* get a line from the file. If it is to long truncate it. */
static int fgetline(FILE * f, char *buffer, size_t len)
{
char *b = buffer;
int c;
while (((c = fgetc(f)) != EOF) && (c != '\n')
&& (strlen(buffer) < len - 1)) {
*b = c;
b++;
}
*b = '\0';
if (c != EOF)
return 1;
return 0;
}
/* If there is a comment null terminate the string,
return strlen of the stripped string*/
static int stripcomment(char *s)
{
char *t = s;
while (*s != '#' && *s != 0)
s++;
*s = 0;
return strlen(t);
}
static char *stripblanks(char *s)
{
char *c;
while (isspace(*s))
s++;
c = s;
while (!isspace(*s) && *s != 0)
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(const char *filename)
{
if (current_filename)
free(current_filename);
current_filename = strdup(filename ? filename : "stdin");
current_lineno = 1;
}
void push_include_stack(char *filename)
{
struct include_stack_t *include = NULL;
include = (struct include_stack_t *) 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(const char *filename)
{
while (include_stack_head)
pop_include_stack();
start_include_position(filename);
}