Commit e244c280 authored by John Johansen's avatar John Johansen

Add simple policy notification interface

The simple policy notification interface allows applications to
receive notifications when a policy change (load, replace, remove)
occurs for a given policy namespace.

The revision notification only guarentees one or more revisions have
occurred. The returned revision number can be compared to a previously
stored value to find out how many revisions have occured.
Signed-off-by: 's avatarJohn Johansen <john.johansen@canonical.com>
parent 1294d74e
......@@ -18,8 +18,10 @@
#ifndef _SYS_APPARMOR_H
#define _SYS_APPARMOR_H 1
#include <sys/select.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/time.h>
#include <sys/types.h>
#ifdef __cplusplus
......@@ -214,6 +216,12 @@ extern int aa_policy_cache_remove(int dirfd, const char *path);
extern int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
aa_kernel_interface *kernel_interface);
int aa_policy_notification_open(const char *ns);
void aa_policy_notification_close(int fd);
long aa_policy_revision(int fd);
long aa_policy_wait(int fd, const struct timespec *timeout,
const sigset_t *sigmask);
#ifdef __cplusplus
}
#endif
......
......@@ -48,7 +48,7 @@ af_protos.h: /usr/include/netinet/in.h
lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c notify.c
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
......
/*
* Copyright (c) 2017
* Canonical, Ltd. (All rights reserved)
*
* 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.
*/
#include <limits.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/apparmor.h>
#include "private.h"
/* The policy notification api provides some abstraction from the actual
* kernel communication method
*/
/**
* aa_policy_notification_open - open an fd for policy update notifications
* @ns: name of namespace to open notifications for. If null current ns
* Returns: an fd or -1 on error
*
* This provides a generic mechanism to receive policy update notifications.
* The under lying mechanism of the notifications is not guarenteed nor
* is the wire format of the data on the fd. To access the data use the
* access fns. The only guarentee is that the fd can be used in
* select/poll.
*/
int aa_policy_notification_open(const char *ns)
{
autofree char *aafs;
autofree char *aafs_rev;
int ret;
ret = aa_find_mountpoint(&aafs);
if (ret < 0)
return -1;
ret = asprintf(&aafs_rev, "%s/.revision", aafs);
if (ret < 0)
return -1;
return open(aafs_rev, O_RDONLY);
}
/**
* aa_policy_notification_close - close fd associated with policy notifications
* @fd: the fd to close.
*/
void aa_policy_notification_close(int fd)
{
close(fd);
}
/**
* aa_policy_revision - return the current policy revision.
* @fd: a policy revision fd opened by aa_policy_notification_open
* Returns: policy revision or -1 on error with errno set
*/
long aa_policy_revision(int fd)
{
char buf[32];
char *end;
ssize_t ret;
long rev;
ret = read(fd, buf, sizeof(buf));
if (ret < 0)
return -1;
buf[ret] = 0;
rev = strtol(buf, &end, 0);
if (rev == LONG_MIN || rev == LONG_MAX || rev < 0)
return -1;
return rev;
}
/**
* aa_policy_wait - wait for the next policy revision and return its value
* @fd: the policy fd to wait on
* @timeout: maximum time to block, Maybe NULL for no timeout
* @sigmask: sigmask that can cause
* Returns: the revision # of updated revision or -1 on error with errno set
*
* Note: may not block if policy has already been updated
* EINTR - a signal caused the wakeup
*/
long aa_policy_wait(int fd, const struct timespec *timeout,
const sigset_t *sigmask)
{
fd_set fds;
int ret;
FD_ZERO(&fds);
FD_SET(fd, &fds);
ret = pselect(fd+1, &fds, NULL, NULL, timeout, sigmask);
if (ret == -1)
return -1;
return aa_policy_revision(fd);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment