mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00
periodic merge from apparmor trunk
This commit is contained in:
commit
0e3b8d8fd5
651 changed files with 14712 additions and 1599 deletions
|
@ -167,3 +167,4 @@ tests/regression/apparmor/unlink
|
|||
tests/regression/apparmor/xattrs
|
||||
tests/regression/apparmor/coredump
|
||||
**/__pycache__/
|
||||
*.orig
|
||||
|
|
|
@ -53,7 +53,7 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
|
|||
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
|
||||
AA_LDLIBS = -lapparmor
|
||||
endif
|
||||
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
|
||||
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
|
||||
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
|
||||
LIBS=-lpam $(AA_LDLIBS)
|
||||
OBJECTS=${NAME}.o get_options.o
|
||||
|
|
|
@ -5,9 +5,9 @@ PODCHECKER = podchecker
|
|||
|
||||
if ENABLE_MAN_PAGES
|
||||
|
||||
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2
|
||||
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3
|
||||
|
||||
PODS = $(subst .2,.pod,$(man_MANS))
|
||||
PODS = $(subst .2,.pod,$(man_MANS)) $(subst .3,.pod,$(man_MANS))
|
||||
|
||||
EXTRA_DIST = $(man_MANS) $(PODS)
|
||||
|
||||
|
@ -23,4 +23,13 @@ CLEANFILES = $(man_MANS)
|
|||
--stderr \
|
||||
$< > $@
|
||||
|
||||
%.3: %.pod
|
||||
$(PODCHECKER) -warnings -warnings $<
|
||||
$(POD2MAN) \
|
||||
--section=3 \
|
||||
--release="AppArmor $(VERSION)" \
|
||||
--center="AppArmor" \
|
||||
--stderr \
|
||||
$< > $@
|
||||
|
||||
endif
|
||||
|
|
148
libraries/libapparmor/doc/aa_features.pod
Normal file
148
libraries/libapparmor/doc/aa_features.pod
Normal file
|
@ -0,0 +1,148 @@
|
|||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_features - an opaque object representing a set of AppArmor kernel features
|
||||
|
||||
aa_features_new - create a new aa_features object based on a path
|
||||
|
||||
aa_features_new_from_string - create a new aa_features object based on a string
|
||||
|
||||
aa_features_new_from_kernel - create a new aa_features object based on the current kernel
|
||||
|
||||
aa_features_ref - increments the ref count of an aa_features object
|
||||
|
||||
aa_features_unref - decrements the ref count and frees the aa_features object when 0
|
||||
|
||||
aa_features_write_to_file - write a string representation of an aa_features object to a file
|
||||
|
||||
aa_features_is_equal - equality test for two aa_features objects
|
||||
|
||||
aa_features_supports - provides aa_features object support status
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_features aa_features;>
|
||||
|
||||
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
|
||||
|
||||
B<int aa_features_new_from_kernel(aa_features **features);>
|
||||
|
||||
B<aa_features *aa_features_ref(aa_features *features);>
|
||||
|
||||
B<void aa_features_unref(aa_features *features);>
|
||||
|
||||
B<int aa_features_write_to_file(aa_features *features, int dirfd, const char *path);>
|
||||
|
||||
B<bool aa_features_is_equal(aa_features *features1, aa_features *features2);>
|
||||
|
||||
B<bool aa_features_supports(aa_features *features, const char *str);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_features> object contains information about the AppArmor features
|
||||
supported by a kernel. The feature support information is based upon the files
|
||||
AppArmor represents in securityfs, which is typically found at
|
||||
/sys/kernel/security/apparmor/features/. That information may be parsed and
|
||||
turned into a string or flat file in order to represent a set of features of a
|
||||
kernel that is not currently running.
|
||||
|
||||
The aa_features_new() function creates an I<aa_features> object based upon a
|
||||
directory file descriptor and path. The I<path> can point to a file or
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. The
|
||||
allocated I<features> object must be freed using aa_features_unref().
|
||||
|
||||
The aa_features_new_from_string() function is similar except that it accepts a
|
||||
NUL-terminated string representation of the AppArmor features as the I<string>
|
||||
argument. The length of the features string, not counting the NUL-terminator,
|
||||
must be specified as the I<size> argument. The allocated I<features> object
|
||||
must be freed using aa_features_unref().
|
||||
|
||||
The aa_features_new_from_kernel() function creates an I<aa_features> object
|
||||
from the current running kernel. The allocated I<features> object must be freed
|
||||
using aa_features_unref().
|
||||
|
||||
aa_features_ref() increments the reference count on the I<features> object.
|
||||
|
||||
aa_features_unref() decrements the reference count on the I<features> object
|
||||
and releases all corresponding resources when the reference count reaches zero.
|
||||
|
||||
The aa_features_write_to_file() function writes a string representation of the
|
||||
I<features> object to the file specified by the I<dirfd> and I<path>
|
||||
combination.
|
||||
|
||||
aa_features_is_equal() can be used to detect if the I<features1> and
|
||||
I<features2> objects are equal. The definition of equality is private to
|
||||
libapparmor and may be changed in ways that do not break backward
|
||||
compatibility.
|
||||
|
||||
The aa_features_supports() function can be used to query the I<features> object
|
||||
to determine if a feature is supported. The I<str> argument should be equal to
|
||||
the path, relative to the "apparmor/features/" directory of securityfs, of the
|
||||
feature to query. For example, to test if policy version 6 is supported, I<str>
|
||||
would be "policy/versions/v6".
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_features_new() family of functions return 0 on success and I<*features>
|
||||
will point to an I<aa_features> object that must be freed by
|
||||
aa_features_unref(). -1 is returned on error, with errno set appropriately, and
|
||||
I<*features> will be set to NULL.
|
||||
|
||||
aa_features_ref() returns the value of I<features>.
|
||||
|
||||
aa_features_write_to_file() returns 0 on success. -1 is returned on error, with
|
||||
errno set appropriately.
|
||||
|
||||
aa_features_is_equal() returns true if I<features1> and I<features2> are equal
|
||||
and false if they are not equal.
|
||||
|
||||
aa_features_supports() returns true if the feature represented by I<str> is
|
||||
supported and false if it is not supported.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_features> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_features functions described above are present in libapparmor version
|
||||
2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
openat(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
|
@ -131,7 +131,7 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
|||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
|
||||
aa_splitcon(3) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
|
162
libraries/libapparmor/doc/aa_kernel_interface.pod
Normal file
162
libraries/libapparmor/doc/aa_kernel_interface.pod
Normal file
|
@ -0,0 +1,162 @@
|
|||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_kernel_interface - an opaque object representing the AppArmor kernel interface for policy loading, replacing, and removing
|
||||
|
||||
aa_kernel_interface_new - create a new aa_kernel_interface object from an optional path
|
||||
|
||||
aa_kernel_interface_ref - increments the ref count of an aa_kernel_interface object
|
||||
|
||||
aa_kernel_interface_unref - decrements the ref count and frees the aa_kernel_interface object when 0
|
||||
|
||||
aa_kernel_interface_load_policy - load a policy from a buffer into the kernel
|
||||
|
||||
aa_kernel_interface_load_policy_from_file - load a policy from a file into the kernel
|
||||
|
||||
aa_kernel_interface_load_policy_from_fd - load a policy from a file descriptor into the kernel
|
||||
|
||||
aa_kernel_interface_replace_policy - replace a policy in the kernel with a policy from a buffer
|
||||
|
||||
aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel with a policy from a file
|
||||
|
||||
aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel with a policy from a file descriptor
|
||||
|
||||
aa_kernel_interface_remove_policy - remove a policy from the kernel
|
||||
|
||||
aa_kernel_interface_write_policy - write a policy to a file descriptor
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_kernel_interface aa_kernel_interface;>
|
||||
|
||||
B<int aa_kernel_interface_new(aa_kernel_interface **kernel_interface, aa_features *kernel_features, const char *apparmorfs);>
|
||||
|
||||
B<aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);>
|
||||
|
||||
B<void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
|
||||
|
||||
B<int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface, const char *fqname);>
|
||||
|
||||
B<int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_kernel_interface> object contains information about the AppArmor
|
||||
kernel interface for policy loading, replacing, and removing.
|
||||
|
||||
The aa_kernel_interface_new() function creates an I<aa_kernel_interface> object
|
||||
based on an optional I<aa_features> object and an optional path to the apparmor
|
||||
directory of securityfs, which is typically found at
|
||||
"/sys/kernel/security/apparmor/". If I<kernel_features> is NULL, then the
|
||||
features of the current kernel are used. When specifying a valid
|
||||
I<kernel_features> object, it must be compatible with the features of the
|
||||
currently running kernel. If I<apparmorfs> is NULL, then the default location
|
||||
is used. The allocated I<kernel_interface> object must be freed using
|
||||
aa_kernel_interface_unref().
|
||||
|
||||
aa_kernel_interface_ref() increments the reference count on the
|
||||
I<kernel_interface> object.
|
||||
|
||||
aa_kernel_interface_unref() decrements the reference count on the
|
||||
I<kernel_interface> object and releases all corresponding resources when the
|
||||
reference count reaches zero.
|
||||
|
||||
The aa_kernel_interface_load() family of functions load a policy into the
|
||||
kernel. The operation will fail if a policy of the same name is already loaded.
|
||||
Use the aa_kernel_interface_replace() family of functions if you wish to
|
||||
replace a previously loaded policy with a new policy of the same name. The
|
||||
aa_kernel_interface_replace() functions can also be used to load a policy that
|
||||
does not correspond to a previously loaded policy.
|
||||
|
||||
When loading or replacing from a buffer, the I<buffer> will contain binary
|
||||
data. The I<size> argument must specify the size of the I<buffer> argument.
|
||||
|
||||
When loading or replacing from a file, the I<dirfd> and I<path> combination are
|
||||
used to specify the location of the file. See the openat(2) man page for
|
||||
examples of I<dirfd> and I<path>.
|
||||
|
||||
It is also possible to load or replace from a file descriptor specified by the
|
||||
I<fd> argument. The file must be open for reading and the file offset must be
|
||||
set appropriately.
|
||||
|
||||
The aa_kernel_interface_remove_policy() function can be used to unload a
|
||||
previously loaded policy. The fully qualified policy name must be specified
|
||||
with the I<fqname> argument. The operation will fail if a policy matching
|
||||
I<fqname> is not found.
|
||||
|
||||
The aa_kernel_interface_write_policy() function allows for a policy, which is
|
||||
stored in I<buffer> and consists of I<size> bytes, to be written to a file
|
||||
descriptor. The I<fd> must be open for writing and the file offset must be set
|
||||
appropriately.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_kernel_interface_new() function returns 0 on success and
|
||||
I<*kernel_interface> will point to an I<aa_kernel_interface> object that must
|
||||
be freed by aa_kernel_interface_unref(). -1 is returned on error, with errno
|
||||
set appropriately, and I<*kernel_interface> will be set to NULL.
|
||||
|
||||
aa_kernel_features_ref() returns the value of I<kernel_features>.
|
||||
|
||||
The aa_kernel_interface_load() family of functions, the
|
||||
aa_kernel_interface_replace() family of functions,
|
||||
aa_kernel_interface_remove(), and aa_kernel_interface_write_policy()
|
||||
return 0 on success. -1 is returned on error, with errno set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_kernel_interface> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_kernel_interface functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), openat(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
125
libraries/libapparmor/doc/aa_policy_cache.pod
Normal file
125
libraries/libapparmor/doc/aa_policy_cache.pod
Normal file
|
@ -0,0 +1,125 @@
|
|||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_policy_cache - an opaque object representing an AppArmor policy cache
|
||||
|
||||
aa_policy_cache_new - create a new aa_policy_cache object from a path
|
||||
|
||||
aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
|
||||
|
||||
aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
|
||||
|
||||
aa_policy_cache_remove - removes all policy cache files under a path
|
||||
|
||||
aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_policy_cache aa_policy_cache;>
|
||||
|
||||
B<int aa_policy_cache_new(aa_policy_cache **policy_cache, aa_features *kernel_features, int dirfd, const char *path, uint16_t max_caches);>
|
||||
|
||||
B<aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);>
|
||||
|
||||
B<void aa_policy_cache_unref(aa_policy_cache *policy_cache);>
|
||||
|
||||
B<int aa_policy_cache_remove(int dirfd, const char *path);>
|
||||
|
||||
B<int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_policy_cache> object contains information about a set of AppArmor
|
||||
policy cache files. The policy cache files are the binary representation of a
|
||||
human-readable AppArmor profile. The binary representation is the form that is
|
||||
loaded into the kernel.
|
||||
|
||||
The aa_policy_cache_new() function creates an I<aa_policy_cache> object based
|
||||
upon a directory file descriptor and path. The I<path> must point to a
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. If
|
||||
I<kernel_features> is NULL, then the features of the current kernel are used.
|
||||
When specifying a valid I<kernel_features> object, it must be the compatible
|
||||
with the features of the kernel of interest. The value of I<max_caches> should
|
||||
be equal to the number of caches that should be allowed before old caches are
|
||||
automatically reaped. The definition of what is considered to be an old cache
|
||||
is private to libapparmor. Specifying 0 means that no new caches should be
|
||||
created and only existing, valid caches may be used. Specifying UINT16_MAX
|
||||
means that a new cache may be created and that the reaping of old caches is
|
||||
disabled. The allocated I<aa_policy_cache> object must be freed using
|
||||
aa_policy_cache_unref().
|
||||
|
||||
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
|
||||
object.
|
||||
|
||||
aa_policy_cache_unref() decrements the reference count on the I<policy_cache>
|
||||
object and releases all corresponding resources when the reference count
|
||||
reaches zero.
|
||||
|
||||
The aa_policy_cache_remove() function deletes all of the policy cache files
|
||||
based upon a directory file descriptor and path. The I<path> must point to a
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>.
|
||||
|
||||
The aa_policy_cache_replace_all() function can be used to perform a policy
|
||||
replacement of all of the cache policies in the cache directory represented by
|
||||
the I<policy_cache> object. If I<kernel_interface> is NULL, then the current
|
||||
kernel interface is used. When specifying a valid I<kernel_interface> object,
|
||||
it must be the interface of the currently running kernel.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_policy_cache_new() function returns 0 on success and I<*policy_cache>
|
||||
will point to an I<aa_policy_cache> object that must be freed by
|
||||
aa_policy_cache_unref(). -1 is returned on error, with errno set appropriately,
|
||||
and I<*policy_cache> will be set to NULL.
|
||||
|
||||
aa_policy_cache_ref() returns the value of I<policy_cache>.
|
||||
|
||||
aa_policy_cache_remove() and aa_policy_cache_replace_all() return 0 on success.
|
||||
-1 is returned on error, with errno set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_policy_cache> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_policy_cache functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), aa_kernel_interface(3), openat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
137
libraries/libapparmor/doc/aa_query_label.pod
Normal file
137
libraries/libapparmor/doc/aa_query_label.pod
Normal file
|
@ -0,0 +1,137 @@
|
|||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_query_label - query access permission associated with a label
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<int aa_query_label((uint32_t mask, char *query, size_t size,
|
||||
int *allowed, int *audited);>
|
||||
|
||||
B<int aa_query_file_path((uint32_t mask, const char *label, size_t label_len,
|
||||
const char *path, int *allowed, int *audited);>
|
||||
|
||||
B<int aa_query_file_path_len((uint32_t mask, const char *label,
|
||||
size_t label_len, const char *path, size_t path_len,
|
||||
int *allowed, int *audited);>
|
||||
|
||||
B<int aa_query_link_path_len(const char *label, size_t label_len,
|
||||
const char *target, size_t target_len,
|
||||
const char *link, size_t link_len,
|
||||
int *allowed, int *audited);>
|
||||
|
||||
B<int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);>
|
||||
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The aa_query_label function fetches the current permissions granted by the
|
||||
specified I<label> in the I<query> string.
|
||||
|
||||
The query is a raw binary formatted query, containing the label and
|
||||
permission query to make. The returned I<allowed> and I<audited> values are
|
||||
interpreted boolean values, simple stating whether the query is allowed and
|
||||
if it is audited.
|
||||
|
||||
The mask of the query string is a bit mask of permissions to query and is
|
||||
class type dependent (see AA_CLASS_xxx) entries in I<sys/apparmor.h>.
|
||||
|
||||
The format of the query string is also dependent on the B<AA_CLASS> and as
|
||||
such the the aa_query_xxx helper functions should usually be used instead
|
||||
of directly using I<aa_query_label>. If directly using the interface the
|
||||
I<query> string is required to have a header of B<AA_QUERY_CMD_LABEL_SIZE>
|
||||
that will be used by I<aa_query_label>.
|
||||
|
||||
The B<aa_query_file_path> and B<aa_query_file_path_len> functions are helper
|
||||
function that assemble a properly formatted file path query for the
|
||||
B<aa_query_label> function. The I<label> is a valid apparmor label as
|
||||
returned by I<aa_splitcon> with I<label_len> being the length of the I<label>.
|
||||
The I<path> is any valid filesystem path to query permissions for. For the
|
||||
B<aa_query_file_path_len> variant the I<path_len> parameter specifies the
|
||||
number of bytes in the I<path> to use as part of the query.
|
||||
|
||||
The B<aa_query_link_path> and B<aa_query_link_path_len> functions are helper
|
||||
functions that assemble a properly formatted link path query for the
|
||||
B<aa_query_label> function. The I<link_len> and I<target_len> parameters
|
||||
specify the number of bytes in the I<link> and I<target> to use as part of
|
||||
the query.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
On success 0 is returned, and the I<allowed> and I<audited> parameters
|
||||
contain a boolean value of 0 not allowed/audited or 1 allowed/audited. On
|
||||
error, -1 is returned, and errno(3) is set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<EINVAL>
|
||||
|
||||
The requested I<mask> is empty.
|
||||
|
||||
The I<size> of the query is E<lt> the query B<AA_QUER?Y_CMD_LABEL_SIZE>
|
||||
|
||||
The apparmor kernel module is not loaded or the he kernel interface access
|
||||
interface is not available
|
||||
|
||||
=item B<ENOMEM>
|
||||
|
||||
Insufficient memory was available.
|
||||
|
||||
=item B<EACCES>
|
||||
|
||||
Access to the specified I<label> or query interface was denied.
|
||||
|
||||
=item B<ENOENT>
|
||||
|
||||
The specified I<label> does not exist or is not visible.
|
||||
|
||||
=item B<ERANGE>
|
||||
|
||||
The confinement data is too large to fit in the supplied buffer.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The label permissions returned are only valid for the time of the
|
||||
query and can change at any point in the future.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_getcon(2), aa_splitcon(3)
|
||||
and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
72
libraries/libapparmor/doc/aa_splitcon.pod
Normal file
72
libraries/libapparmor/doc/aa_splitcon.pod
Normal file
|
@ -0,0 +1,72 @@
|
|||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_splitcon - split the confinement context into a label and mode
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<char *aa_splitcon(char *con, char **mode);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The aa_splitcon() function splits a confinement context into separate label
|
||||
and mode strings. The @con string is modified so that the label portion is NUL
|
||||
terminated. The enforcement mode is also NUL terminated and the parenthesis
|
||||
surrounding the mode are removed. If @mode is non-NULL, it will point to the
|
||||
first character in the enforcement mode string on success.
|
||||
|
||||
The Linux kernel's /proc/E<lt>PIDE<gt>/attr/current interface appends a
|
||||
trailing newline character to AppArmor contexts that are read from that file.
|
||||
If @con contains a single trailing newline character, it will be stripped by
|
||||
aa_splitcon() prior to all other processing.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
Returns a pointer to the first character in the label string. NULL is returned
|
||||
on error.
|
||||
|
||||
=head1 EXAMPLE
|
||||
|
||||
Context Label Mode
|
||||
----------------------------- ------------------ -------
|
||||
unconfined unconfined NULL
|
||||
unconfined\n unconfined NULL
|
||||
/bin/ping (enforce) /bin/ping enforce
|
||||
/bin/ping (enforce)\n /bin/ping enforce
|
||||
/usr/sbin/rsyslogd (complain) /usr/sbin/rsyslogd complain
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_getcon(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
|
@ -27,10 +27,31 @@ __BEGIN_DECLS
|
|||
/*
|
||||
* Class of public mediation types in the AppArmor policy db
|
||||
*/
|
||||
|
||||
#define AA_CLASS_FILE 2
|
||||
#define AA_CLASS_DBUS 32
|
||||
|
||||
|
||||
/* Permission flags for the AA_CLASS_FILE mediation class */
|
||||
#define AA_MAY_EXEC (1 << 0)
|
||||
#define AA_MAY_WRITE (1 << 1)
|
||||
#define AA_MAY_READ (1 << 2)
|
||||
#define AA_MAY_APPEND (1 << 3)
|
||||
#define AA_MAY_CREATE (1 << 4)
|
||||
#define AA_MAY_DELETE (1 << 5)
|
||||
#define AA_MAY_OPEN (1 << 6)
|
||||
#define AA_MAY_RENAME (1 << 7)
|
||||
#define AA_MAY_SETATTR (1 << 8)
|
||||
#define AA_MAY_GETATTR (1 << 9)
|
||||
#define AA_MAY_SETCRED (1 << 10)
|
||||
#define AA_MAY_GETCRED (1 << 11)
|
||||
#define AA_MAY_CHMOD (1 << 12)
|
||||
#define AA_MAY_CHOWN (1 << 13)
|
||||
#define AA_MAY_LOCK 0x8000
|
||||
#define AA_EXEC_MMAP 0x10000
|
||||
#define AA_MAY_LINK 0x40000
|
||||
#define AA_MAY_ONEXEC 0x20000000
|
||||
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
||||
|
||||
/* Permission flags for the AA_CLASS_DBUS mediation class */
|
||||
#define AA_DBUS_SEND (1 << 1)
|
||||
#define AA_DBUS_RECEIVE (1 << 2)
|
||||
|
@ -58,6 +79,7 @@ extern int aa_change_onexec(const char *profile);
|
|||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||
extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
|
||||
|
||||
extern char *aa_splitcon(char *con, char **mode);
|
||||
/* Protypes for introspecting task confinement
|
||||
* Please see the aa_getcon(2) manpage for information
|
||||
*/
|
||||
|
@ -79,6 +101,17 @@ extern int aa_getpeercon(int fd, char **label, char **mode);
|
|||
|
||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||
int *audit);
|
||||
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
||||
size_t label_len, const char *path,
|
||||
size_t path_len, int *allowed, int *audited);
|
||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||
const char *path, int *allowed, int *audited);
|
||||
extern int aa_query_link_path_len(const char *label, size_t label_len,
|
||||
const char *target, size_t target_len,
|
||||
const char *link, size_t link_len,
|
||||
int *allowed, int *audited);
|
||||
extern int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);
|
||||
|
||||
#define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
|
||||
#define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
|
@ -105,52 +138,56 @@ extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
|||
(aa_change_hat_vargs)(T, __macroarg_counter(X), X)
|
||||
|
||||
typedef struct aa_features aa_features;
|
||||
int aa_features_new(aa_features **features, const char *path);
|
||||
int aa_features_new_from_string(aa_features **features,
|
||||
const char *string, size_t size);
|
||||
int aa_features_new_from_kernel(aa_features **features);
|
||||
aa_features *aa_features_ref(aa_features *features);
|
||||
void aa_features_unref(aa_features *features);
|
||||
extern int aa_features_new(aa_features **features, int dirfd, const char *path);
|
||||
extern int aa_features_new_from_string(aa_features **features,
|
||||
const char *string, size_t size);
|
||||
extern int aa_features_new_from_kernel(aa_features **features);
|
||||
extern aa_features *aa_features_ref(aa_features *features);
|
||||
extern void aa_features_unref(aa_features *features);
|
||||
|
||||
int aa_features_write_to_file(aa_features *features, const char *path);
|
||||
bool aa_features_is_equal(aa_features *features1, aa_features *features2);
|
||||
bool aa_features_supports(aa_features *features, const char *str);
|
||||
extern int aa_features_write_to_file(aa_features *features,
|
||||
int dirfd, const char *path);
|
||||
extern bool aa_features_is_equal(aa_features *features1,
|
||||
aa_features *features2);
|
||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
||||
|
||||
typedef struct aa_kernel_interface aa_kernel_interface;
|
||||
int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
aa_features *kernel_features,
|
||||
const char *apparmorfs);
|
||||
aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);
|
||||
void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);
|
||||
extern aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);
|
||||
extern void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);
|
||||
|
||||
int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
const char *path);
|
||||
int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
const char *path);
|
||||
int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *fqname);
|
||||
int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);
|
||||
extern int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
extern int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
int dirfd,
|
||||
const char *path);
|
||||
extern int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
extern int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
extern int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
int dirfd,
|
||||
const char *path);
|
||||
extern int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
extern int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *fqname);
|
||||
extern int aa_kernel_interface_write_policy(int fd, const char *buffer,
|
||||
size_t size);
|
||||
|
||||
typedef struct aa_policy_cache aa_policy_cache;
|
||||
int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features, const char *path,
|
||||
bool create);
|
||||
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache);
|
||||
extern int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path,
|
||||
uint16_t max_caches);
|
||||
extern aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
|
||||
extern void aa_policy_cache_unref(aa_policy_cache *policy_cache);
|
||||
|
||||
bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache);
|
||||
int aa_policy_cache_create(aa_policy_cache *policy_cache);
|
||||
int aa_policy_cache_remove(const char *path);
|
||||
int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
aa_kernel_interface *kernel_interface);
|
||||
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);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -17,13 +17,12 @@
|
|||
#ifndef _SYS_APPARMOR_PRIVATE_H
|
||||
#define _SYS_APPARMOR_PRIVATE_H 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int _aa_is_blacklisted(const char *name, const char *path);
|
||||
int _aa_is_blacklisted(const char *name);
|
||||
|
||||
void _aa_autofree(void *p);
|
||||
void _aa_autoclose(int *fd);
|
||||
|
@ -31,8 +30,8 @@ void _aa_autofclose(FILE **f);
|
|||
|
||||
int _aa_asprintf(char **strp, const char *fmt, ...);
|
||||
|
||||
int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
|
||||
int (* cb)(DIR *, const char *, struct stat *, void *));
|
||||
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -67,7 +67,11 @@ tst_aalogmisc_LDADD = .libs/libapparmor.a
|
|||
tst_features_SOURCES = tst_features.c
|
||||
tst_features_LDADD = .libs/libapparmor.a
|
||||
|
||||
check_PROGRAMS = tst_aalogmisc tst_features
|
||||
tst_kernel_SOURCES = tst_kernel.c
|
||||
tst_kernel_LDADD = .libs/libapparmor.a
|
||||
tst_kernel_LDFLAGS = -pthread
|
||||
|
||||
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc
|
||||
|
|
|
@ -80,7 +80,70 @@ static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
|
||||
/* load_features_file - opens and reads a file into @buffer and then NUL-terminates @buffer
|
||||
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
|
||||
* @path: name of the file
|
||||
* @buffer: the buffer to read the features file into (will be NUL-terminated on success)
|
||||
* @size: the size of @buffer
|
||||
*
|
||||
* Returns: The number of bytes copied into @buffer on success (not counting
|
||||
* the NUL-terminator), else -1 and errno is set. Note that @size must be
|
||||
* larger than the size of the file or -1 will be returned with errno set to
|
||||
* ENOBUFS indicating that @buffer was not large enough to contain all of the
|
||||
* file contents.
|
||||
*/
|
||||
static int load_features_file(int dirfd, const char *path,
|
||||
char *buffer, size_t size)
|
||||
{
|
||||
autoclose int file = -1;
|
||||
char *pos = buffer;
|
||||
ssize_t len;
|
||||
|
||||
file = openat(dirfd, path, O_RDONLY);
|
||||
if (file < 0) {
|
||||
PDEBUG("Could not open '%s'\n", path);
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("Opened features \"%s\"\n", path);
|
||||
|
||||
if (!size) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Save room for a NUL-terminator at the end of @buffer */
|
||||
size--;
|
||||
|
||||
do {
|
||||
len = read(file, pos, size);
|
||||
if (len > 0) {
|
||||
size -= len;
|
||||
pos += len;
|
||||
}
|
||||
} while (len > 0 && size);
|
||||
|
||||
/**
|
||||
* Possible error conditions:
|
||||
* - len == -1: read failed and errno is already set so return -1
|
||||
* - len > 0: read() never returned 0 (EOF) meaning that @buffer was
|
||||
* too small to contain all of the file contents so set
|
||||
* errno to ENOBUFS and return -1
|
||||
*/
|
||||
if (len) {
|
||||
if (len > 0)
|
||||
errno = ENOBUFS;
|
||||
|
||||
PDEBUG("Error reading features file '%s': %m\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NUL-terminate @buffer */
|
||||
*pos = 0;
|
||||
|
||||
return pos - buffer;
|
||||
}
|
||||
|
||||
static int features_dir_cb(int dirfd, const char *name, struct stat *st,
|
||||
void *data)
|
||||
{
|
||||
struct features_struct *fst = (struct features_struct *) data;
|
||||
|
@ -93,36 +156,16 @@ static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
|
|||
return -1;
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
autoclose int file = -1;
|
||||
int len;
|
||||
int remaining = fst->size - (fst->pos - fst->buffer);
|
||||
|
||||
file = openat(dirfd(dir), name, O_RDONLY);
|
||||
if (file == -1) {
|
||||
PDEBUG("Could not open '%s'", name);
|
||||
len = load_features_file(dirfd, name, fst->pos, remaining);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("Opened features \"%s\"\n", name);
|
||||
if (st->st_size > remaining) {
|
||||
PDEBUG("Feature buffer full.");
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
len = read(file, fst->pos, remaining);
|
||||
if (len > 0) {
|
||||
remaining -= len;
|
||||
fst->pos += len;
|
||||
*fst->pos = 0;
|
||||
}
|
||||
} while (len > 0);
|
||||
if (len < 0) {
|
||||
PDEBUG("Error reading feature file '%s'\n", name);
|
||||
return -1;
|
||||
}
|
||||
fst->pos += len;
|
||||
} else if (S_ISDIR(st->st_mode)) {
|
||||
if (_aa_dirat_for_each(dir, name, fst, features_dir_cb))
|
||||
if (_aa_dirat_for_each(dirfd, name, fst, features_dir_cb))
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -132,40 +175,19 @@ static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handle_features_dir(const char *filename, char *buffer, int size,
|
||||
char *pos)
|
||||
static int load_features_dir(int dirfd, const char *path,
|
||||
char *buffer, int size)
|
||||
{
|
||||
struct features_struct fst = { buffer, size, pos };
|
||||
struct features_struct fst = { buffer, size, buffer };
|
||||
|
||||
if (_aa_dirat_for_each(NULL, filename, &fst, features_dir_cb)) {
|
||||
PDEBUG("Failed evaluating %s\n", filename);
|
||||
if (_aa_dirat_for_each(dirfd, path, &fst, features_dir_cb)) {
|
||||
PDEBUG("Failed evaluating %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_features_file(const char *name, char *buffer, size_t size)
|
||||
{
|
||||
autofclose FILE *f = NULL;
|
||||
size_t end;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
errno = 0;
|
||||
end = fread(buffer, 1, size - 1, f);
|
||||
if (ferror(f)) {
|
||||
if (!errno)
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
buffer[end] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool islbrace(int c)
|
||||
{
|
||||
return c == '{';
|
||||
|
@ -334,15 +356,16 @@ static bool walk_one(const char **str, const struct component *component,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_new - create a new features based on a path
|
||||
* aa_features_new - create a new aa_features object based on a path
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to a features file or directory
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_features_new(aa_features **features, const char *path)
|
||||
int aa_features_new(aa_features **features, int dirfd, const char *path)
|
||||
{
|
||||
struct stat stat_file;
|
||||
aa_features *f;
|
||||
|
@ -350,7 +373,7 @@ int aa_features_new(aa_features **features, const char *path)
|
|||
|
||||
*features = NULL;
|
||||
|
||||
if (stat(path, &stat_file) == -1)
|
||||
if (fstatat(dirfd, path, &stat_file, 0) == -1)
|
||||
return -1;
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
|
@ -361,9 +384,9 @@ int aa_features_new(aa_features **features, const char *path)
|
|||
aa_features_ref(f);
|
||||
|
||||
retval = S_ISDIR(stat_file.st_mode) ?
|
||||
handle_features_dir(path, f->string, STRING_SIZE, f->string) :
|
||||
load_features_file(path, f->string, STRING_SIZE);
|
||||
if (retval) {
|
||||
load_features_dir(dirfd, path, f->string, STRING_SIZE) :
|
||||
load_features_file(dirfd, path, f->string, STRING_SIZE);
|
||||
if (retval == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_features_unref(f);
|
||||
|
@ -377,7 +400,7 @@ int aa_features_new(aa_features **features, const char *path)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_new_from_string - create a new features based on a string
|
||||
* aa_features_new_from_string - create a new aa_features object based on a string
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
* @string: a NUL-terminated string representation of features
|
||||
|
@ -412,7 +435,7 @@ int aa_features_new_from_string(aa_features **features,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_new_from_kernel - create a new features based on the current kernel
|
||||
* aa_features_new_from_kernel - create a new aa_features object based on the current kernel
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
*
|
||||
|
@ -421,11 +444,11 @@ int aa_features_new_from_string(aa_features **features,
|
|||
*/
|
||||
int aa_features_new_from_kernel(aa_features **features)
|
||||
{
|
||||
return aa_features_new(features, FEATURES_FILE);
|
||||
return aa_features_new(features, -1, FEATURES_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_ref - increments the ref count of a features
|
||||
* aa_features_ref - increments the ref count of an aa_features object
|
||||
* @features: the features
|
||||
*
|
||||
* Returns: the features
|
||||
|
@ -437,7 +460,7 @@ aa_features *aa_features_ref(aa_features *features)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_unref - decrements the ref count and frees the features when 0
|
||||
* aa_features_unref - decrements the ref count and frees the aa_features object when 0
|
||||
* @features: the features (can be NULL)
|
||||
*/
|
||||
void aa_features_unref(aa_features *features)
|
||||
|
@ -447,21 +470,24 @@ void aa_features_unref(aa_features *features)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_write_to_file - write a string representation to a file
|
||||
* aa_features_write_to_file - write a string representation of an aa_features object to a file
|
||||
* @features: the features
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: the path to write to
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_features_write_to_file(aa_features *features, const char *path)
|
||||
int aa_features_write_to_file(aa_features *features,
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
autoclose int fd = -1;
|
||||
size_t size;
|
||||
ssize_t retval;
|
||||
char *string;
|
||||
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
fd = openat(dirfd, path,
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -480,7 +506,7 @@ int aa_features_write_to_file(aa_features *features, const char *path)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_is_equal - equality test for two features
|
||||
* aa_features_is_equal - equality test for two aa_features objects
|
||||
* @features1: the first features (can be NULL)
|
||||
* @features2: the second features (can be NULL)
|
||||
*
|
||||
|
@ -493,7 +519,7 @@ bool aa_features_is_equal(aa_features *features1, aa_features *features2)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_features_supports - provides features support status
|
||||
* aa_features_supports - provides aa_features object support status
|
||||
* @features: the features
|
||||
* @str: the string representation of a feature to check
|
||||
*
|
||||
|
|
|
@ -169,6 +169,7 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||
%%
|
||||
|
||||
log_message: audit_type
|
||||
| dmesg_type
|
||||
| syslog_type
|
||||
| audit_dispatch
|
||||
;
|
||||
|
@ -199,6 +200,10 @@ other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
|
|||
}
|
||||
;
|
||||
|
||||
dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
;
|
||||
|
||||
syslog_type:
|
||||
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <pthread.h>
|
||||
|
||||
#include <sys/apparmor.h>
|
||||
#include "private.h"
|
||||
|
||||
/* some non-Linux systems do not define a static value */
|
||||
#ifndef PATH_MAX
|
||||
|
@ -43,6 +44,9 @@
|
|||
#define default_symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version)
|
||||
|
||||
#define UNCONFINED "unconfined"
|
||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||
|
||||
/**
|
||||
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
|
||||
* @mnt: returns buffer with the mountpoint string
|
||||
|
@ -152,30 +156,89 @@ static char *procattr_path(pid_t pid, const char *attr)
|
|||
}
|
||||
|
||||
/**
|
||||
* parse_confinement_mode - get the mode from the confinement context
|
||||
* parse_unconfined - check for the unconfined label
|
||||
* @con: the confinement context
|
||||
* @size: size of the confinement context
|
||||
* @size: size of the confinement context (not including the NUL terminator)
|
||||
*
|
||||
* Modifies con to NUL-terminate the label string and the mode string.
|
||||
*
|
||||
* Returns: a pointer to the NUL-terminated mode inside the confinement context
|
||||
* or NULL if the mode was not found
|
||||
* Returns: True if the con is the unconfined label or false otherwise
|
||||
*/
|
||||
static char *parse_confinement_mode(char *con, int size)
|
||||
static bool parse_unconfined(char *con, int size)
|
||||
{
|
||||
if (strcmp(con, "unconfined") != 0 &&
|
||||
size > 4 && con[size - 2] == ')') {
|
||||
int pos = size - 3;
|
||||
return size == UNCONFINED_SIZE &&
|
||||
strncmp(con, UNCONFINED, UNCONFINED_SIZE) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* splitcon - split the confinement context into a label and mode
|
||||
* @con: the confinement context
|
||||
* @size: size of the confinement context (not including the NUL terminator)
|
||||
* @strip_newline: true if a trailing newline character should be stripped
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @con
|
||||
* on success
|
||||
*
|
||||
* Modifies the @con string to split it into separate label and mode strings.
|
||||
* If @strip_newline is true and @con contains a single trailing newline, it
|
||||
* will be stripped on success (it will not be stripped on error). The @mode
|
||||
* argument is optional. If @mode is NULL, @con will still be split between the
|
||||
* label and mode (if present) but @mode will not be set.
|
||||
*
|
||||
* Returns: a pointer to the label string or NULL on error
|
||||
*/
|
||||
static char *splitcon(char *con, int size, bool strip_newline, char **mode)
|
||||
{
|
||||
char *label = NULL;
|
||||
char *mode_str = NULL;
|
||||
char *newline = NULL;
|
||||
|
||||
if (size == 0)
|
||||
goto out;
|
||||
|
||||
if (strip_newline && con[size - 1] == '\n') {
|
||||
newline = &con[size - 1];
|
||||
size--;
|
||||
}
|
||||
|
||||
if (parse_unconfined(con, size)) {
|
||||
label = con;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size > 3 && con[size - 1] == ')') {
|
||||
int pos = size - 2;
|
||||
|
||||
while (pos > 0 && !(con[pos] == ' ' && con[pos + 1] == '('))
|
||||
pos--;
|
||||
if (pos > 0) {
|
||||
con[pos] = 0; /* overwrite ' ' */
|
||||
con[size - 2] = 0; /* overwrite trailing ) */
|
||||
return &con[pos + 2]; /* skip '(' */
|
||||
con[size - 1] = 0; /* overwrite trailing ) */
|
||||
mode_str = &con[pos + 2]; /* skip '(' */
|
||||
label = con;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
out:
|
||||
if (label && strip_newline && newline)
|
||||
*newline = 0; /* overwrite '\n', if requested, on success */
|
||||
if (mode)
|
||||
*mode = mode_str;
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_splitcon - split the confinement context into a label and mode
|
||||
* @con: the confinement context
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @con
|
||||
* on success
|
||||
*
|
||||
* Modifies the @con string to split it into separate label and mode strings. A
|
||||
* single trailing newline character will be stripped from @con, if found. The
|
||||
* @mode argument is optional. If @mode is NULL, @con will still be split
|
||||
* between the label and mode (if present) but @mode will not be set.
|
||||
*
|
||||
* Returns: a pointer to the label string or NULL on error
|
||||
*/
|
||||
char *aa_splitcon(char *con, char **mode)
|
||||
{
|
||||
return splitcon(con, strlen(con), true, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,7 +257,6 @@ int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
|||
int rc = -1;
|
||||
int fd, ret;
|
||||
char *tmp = NULL;
|
||||
char *mode_str;
|
||||
int size = 0;
|
||||
|
||||
if (!buf || len <= 0) {
|
||||
|
@ -237,19 +299,20 @@ int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
|||
goto out;
|
||||
} else if (size > 0 && buf[size - 1] != 0) {
|
||||
/* check for null termination */
|
||||
if (buf[size - 1] == '\n') {
|
||||
buf[size - 1] = 0;
|
||||
} else if (len == 0) {
|
||||
errno = ERANGE;
|
||||
goto out2;
|
||||
} else {
|
||||
buf[size] = 0;
|
||||
size++;
|
||||
if (buf[size - 1] != '\n') {
|
||||
if (len == 0) {
|
||||
errno = ERANGE;
|
||||
goto out2;
|
||||
} else {
|
||||
buf[size] = 0;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
mode_str = parse_confinement_mode(buf, size);
|
||||
if (mode)
|
||||
*mode = mode_str;
|
||||
if (splitcon(buf, size, true, mode) != buf) {
|
||||
errno = EINVAL;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
rc = size;
|
||||
|
||||
|
@ -588,7 +651,6 @@ int aa_getcon(char **label, char **mode)
|
|||
int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode)
|
||||
{
|
||||
socklen_t optlen = *len;
|
||||
char *mode_str;
|
||||
int rc;
|
||||
|
||||
if (optlen <= 0 || buf == NULL) {
|
||||
|
@ -614,9 +676,11 @@ int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode)
|
|||
}
|
||||
}
|
||||
|
||||
mode_str = parse_confinement_mode(buf, optlen);
|
||||
if (mode)
|
||||
*mode = mode_str;
|
||||
if (splitcon(buf, optlen - 1, false, mode) != buf) {
|
||||
rc = -1;
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = optlen;
|
||||
out:
|
||||
|
@ -786,3 +850,133 @@ int query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
|||
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
|
||||
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
||||
|
||||
|
||||
/**
|
||||
* aa_query_file_path_len - query access permissions for a file @path
|
||||
* @mask: permission bits to query
|
||||
* @label: apparmor label
|
||||
* @label_len: length of @label (does not include any terminating nul byte)
|
||||
* @path: file path to query permissions for
|
||||
* @path_len: length of @path (does not include any terminating nul byte)
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_file_path_len(uint32_t mask, const char *label, size_t label_len,
|
||||
const char *path, size_t path_len, int *allowed,
|
||||
int *audited)
|
||||
{
|
||||
autofree char *query = NULL;
|
||||
|
||||
/* + 1 for null separator */
|
||||
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + path_len;
|
||||
query = malloc(size + 1);
|
||||
if (!query)
|
||||
return -1;
|
||||
memcpy(query + AA_QUERY_CMD_LABEL_SIZE, label, label_len);
|
||||
/* null separator */
|
||||
query[AA_QUERY_CMD_LABEL_SIZE + label_len] = 0;
|
||||
query[AA_QUERY_CMD_LABEL_SIZE + label_len + 1] = AA_CLASS_FILE;
|
||||
memcpy(query + AA_QUERY_CMD_LABEL_SIZE + label_len + 2, path, path_len);
|
||||
return aa_query_label(mask, query, size , allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_file_path - query access permissions for a file @path
|
||||
* @mask: permission bits to query
|
||||
* @label: apparmor label
|
||||
* @path: file path to query permissions for
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_file_path(uint32_t mask, const char *label, const char *path,
|
||||
int *allowed, int *audited)
|
||||
{
|
||||
return aa_query_file_path_len(mask, label, strlen(label), path,
|
||||
strlen(path), allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_link_path_len - query access permissions for a hard link @link
|
||||
* @label: apparmor label
|
||||
* @label_len: length of @label (does not include any terminating nul byte)
|
||||
* @target: file path that hard link will point to
|
||||
* @target_len: length of @target (does not include any terminating nul byte)
|
||||
* @link: file path of hard link
|
||||
* @link_len: length of @link (does not include any terminating nul byte)
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_link_path_len(const char *label, size_t label_len,
|
||||
const char *target, size_t target_len,
|
||||
const char *link, size_t link_len,
|
||||
int *allowed, int *audited)
|
||||
{
|
||||
autofree char *query = NULL;
|
||||
int rc;
|
||||
|
||||
/* + 1 for null separators */
|
||||
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + target_len +
|
||||
1 + link_len;
|
||||
size_t pos = AA_QUERY_CMD_LABEL_SIZE;
|
||||
|
||||
query = malloc(size);
|
||||
if (!query)
|
||||
return -1;
|
||||
memcpy(query + pos, label, label_len);
|
||||
/* null separator */
|
||||
pos += label_len;
|
||||
query[pos] = 0;
|
||||
query[++pos] = AA_CLASS_FILE;
|
||||
memcpy(query + pos + 1, link, link_len);
|
||||
/* The kernel does the query in two parts we could similate this
|
||||
* doing the following, however as long as policy is compiled
|
||||
* correctly this isn't requied, and it requires and extra round
|
||||
* trip to the kernel and adds a race on policy replacement between
|
||||
* the two queries.
|
||||
*
|
||||
rc = aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
|
||||
if (rc || !*allowed)
|
||||
return rc;
|
||||
*/
|
||||
pos += 1 + link_len;
|
||||
query[pos] = 0;
|
||||
memcpy(query + pos + 1, target, target_len);
|
||||
return aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_link_path - query access permissions for a hard link @link
|
||||
* @label: apparmor label
|
||||
* @target: file path that hard link will point to
|
||||
* @link: file path of hard link
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_link_path(const char *label, const char *target, const char *link,
|
||||
int *allowed, int *audited)
|
||||
{
|
||||
return aa_query_link_path_len(label, strlen(label), target,
|
||||
strlen(target), link, strlen(link),
|
||||
allowed, audited);
|
||||
}
|
||||
|
|
|
@ -183,11 +183,12 @@ static int write_policy_fd_to_iface(aa_kernel_interface *kernel_interface,
|
|||
}
|
||||
|
||||
static int write_policy_file_to_iface(aa_kernel_interface *kernel_interface,
|
||||
const char *iface_file, const char *path)
|
||||
const char *iface_file,
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
autoclose int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
fd = openat(dirfd, path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -195,10 +196,12 @@ static int write_policy_file_to_iface(aa_kernel_interface *kernel_interface,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_new - create a new kernel_interface from an optional path
|
||||
* aa_kernel_interface_new - create a new aa_kernel_interface object from an optional path
|
||||
* @kernel_interface: will point to the address of an allocated and initialized
|
||||
* aa_kernel_interface object upon success
|
||||
* @kernel_features: features representing the currently running kernel
|
||||
* @kernel_features: features representing the currently running kernel (can be
|
||||
* NULL and the features of the currently running kernel will
|
||||
* be used)
|
||||
* @apparmorfs: path to the apparmor directory of the mounted securityfs (can
|
||||
* be NULL and the path will be auto discovered)
|
||||
*
|
||||
|
@ -223,9 +226,17 @@ int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
|||
aa_kernel_interface_ref(ki);
|
||||
ki->dirfd = -1;
|
||||
|
||||
ki->supports_setload = kernel_features ?
|
||||
aa_features_supports(kernel_features, set_load) :
|
||||
false;
|
||||
if (kernel_features) {
|
||||
aa_features_ref(kernel_features);
|
||||
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_kernel_interface_unref(ki);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
ki->supports_setload = aa_features_supports(kernel_features, set_load);
|
||||
aa_features_unref(kernel_features);
|
||||
|
||||
if (!apparmorfs) {
|
||||
if (find_iface_dir(&alloced_apparmorfs) == -1) {
|
||||
|
@ -255,7 +266,7 @@ int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_ref - increments the ref count of a kernel_interface
|
||||
* aa_kernel_interface_ref - increments the ref count of an aa_kernel_interface object
|
||||
* @kernel_interface: the kernel_interface
|
||||
*
|
||||
* Returns: the kernel_interface
|
||||
|
@ -267,7 +278,7 @@ aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interfa
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_unref - decrements the ref count and frees the kernel_interface when 0
|
||||
* aa_kernel_interface_unref - decrements the ref count and frees the aa_kernel_interface object when 0
|
||||
* @kernel_interface: the kernel_interface (can be NULL)
|
||||
*/
|
||||
void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface)
|
||||
|
@ -280,7 +291,7 @@ void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_load_policy - load a policy into the kernel
|
||||
* aa_kernel_interface_load_policy - load a policy from a buffer into the kernel
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @buffer: a buffer containing a policy
|
||||
* @size: the size of the buffer
|
||||
|
@ -295,21 +306,21 @@ int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_load_policy_from_file - load a policy into the kernel
|
||||
* aa_kernel_interface_load_policy_from_file - load a policy from a file into the kernel
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @path: path to a policy binary
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
const char *path)
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
return write_policy_file_to_iface(kernel_interface, AA_IFACE_FILE_LOAD,
|
||||
path);
|
||||
dirfd, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_load_policy_from_fd - load a policy into the kernel
|
||||
* aa_kernel_interface_load_policy_from_fd - load a policy from a file descriptor into the kernel
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @fd: a pre-opened, readable file descriptor at the correct offset
|
||||
*
|
||||
|
@ -323,7 +334,7 @@ int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interfac
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_replace_policy - replace a policy in the kernel
|
||||
* aa_kernel_interface_replace_policy - replace a policy in the kernel with a policy from a buffer
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @buffer: a buffer containing a policy
|
||||
* @size: the size of the buffer
|
||||
|
@ -339,21 +350,21 @@ int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel
|
||||
* aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel with a policy from a file
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @path: path to a policy binary
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
const char *path)
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
return write_policy_file_to_iface(kernel_interface,
|
||||
AA_IFACE_FILE_REPLACE, path);
|
||||
AA_IFACE_FILE_REPLACE, dirfd, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel
|
||||
* aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel with a policy from a file descriptor
|
||||
* @kernel_interface: valid aa_kernel_interface
|
||||
* @fd: a pre-opened, readable file descriptor at the correct offset
|
||||
*
|
||||
|
|
|
@ -54,6 +54,10 @@ APPARMOR_2.9 {
|
|||
|
||||
APPARMOR_2.10 {
|
||||
global:
|
||||
aa_query_file_path;
|
||||
aa_query_file_path_len;
|
||||
aa_query_link_path;
|
||||
aa_query_link_path_len;
|
||||
aa_features_new;
|
||||
aa_features_new_from_string;
|
||||
aa_features_new_from_kernel;
|
||||
|
@ -76,10 +80,9 @@ APPARMOR_2.10 {
|
|||
aa_policy_cache_new;
|
||||
aa_policy_cache_ref;
|
||||
aa_policy_cache_unref;
|
||||
aa_policy_cache_is_valid;
|
||||
aa_policy_cache_create;
|
||||
aa_policy_cache_remove;
|
||||
aa_policy_cache_replace_all;
|
||||
aa_splitcon;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_2.9;
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
* Ltd.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -28,20 +28,21 @@
|
|||
|
||||
#include "private.h"
|
||||
|
||||
#define CACHE_FEATURES_FILE ".features"
|
||||
|
||||
struct aa_policy_cache {
|
||||
unsigned int ref_count;
|
||||
aa_features *features;
|
||||
aa_features *kernel_features;
|
||||
char *path;
|
||||
char *features_path;
|
||||
int dirfd;
|
||||
};
|
||||
|
||||
static int clear_cache_cb(DIR *dir, const char *path, struct stat *st,
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
/* remove regular files */
|
||||
if (S_ISREG(st->st_mode))
|
||||
return unlinkat(dirfd(dir), path, 0);
|
||||
return unlinkat(dirfd, path, 0);
|
||||
|
||||
/* do nothing with other file types */
|
||||
return 0;
|
||||
|
@ -49,52 +50,44 @@ static int clear_cache_cb(DIR *dir, const char *path, struct stat *st,
|
|||
|
||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||
{
|
||||
struct stat stat_file;
|
||||
autofclose FILE * f = NULL;
|
||||
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
|
||||
return -1;
|
||||
|
||||
if (aa_policy_cache_remove(policy_cache->path))
|
||||
goto error;
|
||||
|
||||
create_file:
|
||||
if (aa_features_write_to_file(features,
|
||||
policy_cache->features_path) == -1)
|
||||
goto error;
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE) == -1)
|
||||
return -1;
|
||||
|
||||
aa_features_unref(policy_cache->features);
|
||||
policy_cache->features = aa_features_ref(features);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
/* does the dir exist? */
|
||||
if (stat(policy_cache->path, &stat_file) == -1) {
|
||||
if (mkdir(policy_cache->path, 0700) == 0)
|
||||
goto create_file;
|
||||
PERROR("Can't create cache directory: %s\n",
|
||||
policy_cache->path);
|
||||
} else if (!S_ISDIR(stat_file.st_mode)) {
|
||||
PERROR("File in cache directory location: %s\n",
|
||||
policy_cache->path);
|
||||
} else {
|
||||
PERROR("Can't update cache directory: %s\n",
|
||||
policy_cache->path);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||
aa_features *kernel_features, bool create)
|
||||
{
|
||||
if (aa_features_new(&policy_cache->features,
|
||||
policy_cache->features_path)) {
|
||||
bool call_create_cache = false;
|
||||
|
||||
if (aa_features_new(&policy_cache->features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE)) {
|
||||
policy_cache->features = NULL;
|
||||
if (!create || errno != ENOENT)
|
||||
return -1;
|
||||
|
||||
return create_cache(policy_cache, kernel_features);
|
||||
/* The cache directory needs to be created */
|
||||
call_create_cache = true;
|
||||
} else if (!aa_features_is_equal(policy_cache->features,
|
||||
kernel_features)) {
|
||||
if (!create) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The cache directory needs to be refreshed */
|
||||
call_create_cache = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return call_create_cache ?
|
||||
create_cache(policy_cache, kernel_features) : 0;
|
||||
}
|
||||
|
||||
struct replace_all_cb_data {
|
||||
|
@ -102,45 +95,46 @@ struct replace_all_cb_data {
|
|||
aa_kernel_interface *kernel_interface;
|
||||
};
|
||||
|
||||
static int replace_all_cb(DIR *dir unused, const char *name, struct stat *st,
|
||||
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *cb_data)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name, NULL)) {
|
||||
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
|
||||
struct replace_all_cb_data *data;
|
||||
autofree char *path = NULL;
|
||||
|
||||
data = (struct replace_all_cb_data *) cb_data;
|
||||
if (asprintf(&path, "%s/%s",
|
||||
data->policy_cache->path, name) < 0) {
|
||||
path = NULL;
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
|
||||
path);
|
||||
data->policy_cache->dirfd,
|
||||
name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_new - create a new policy_cache from a path
|
||||
* aa_policy_cache_new - create a new aa_policy_cache object from a path
|
||||
* @policy_cache: will point to the address of an allocated and initialized
|
||||
* aa_policy_cache_new object upon success
|
||||
* @kernel_features: features representing the currently running kernel
|
||||
* @kernel_features: features representing a kernel (may be NULL if you want to
|
||||
* use the features of the currently running kernel)
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to the policy cache
|
||||
* @create: true if the cache should be created if it doesn't already exist
|
||||
* @max_caches: The maximum number of policy caches, one for each unique set of
|
||||
* kernel features, before older caches are auto-reaped. 0 means
|
||||
* that no new caches should be created (existing, valid caches
|
||||
* will be used) and auto-reaping is disabled. UINT16_MAX means
|
||||
* that a cache can be created and auto-reaping is disabled.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@policy_cache
|
||||
* pointing to NULL
|
||||
*/
|
||||
int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features, const char *path,
|
||||
bool create)
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path, uint16_t max_caches)
|
||||
{
|
||||
aa_policy_cache *pc;
|
||||
bool create = max_caches > 0;
|
||||
|
||||
*policy_cache = NULL;
|
||||
|
||||
|
@ -149,26 +143,51 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (max_caches > 1) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc = calloc(1, sizeof(*pc));
|
||||
if (!pc) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
pc->dirfd = -1;
|
||||
aa_policy_cache_ref(pc);
|
||||
|
||||
pc->path = strdup(path);
|
||||
if (!pc->path) {
|
||||
open:
|
||||
pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (pc->dirfd < 0) {
|
||||
int save;
|
||||
|
||||
/* does the dir exist? */
|
||||
if (create && errno == ENOENT) {
|
||||
if (mkdirat(dirfd, path, 0700) == 0)
|
||||
goto open;
|
||||
PERROR("Can't create cache directory '%s': %m\n", path);
|
||||
} else if (create) {
|
||||
PERROR("Can't update cache directory '%s': %m\n", path);
|
||||
} else {
|
||||
PDEBUG("Cache directory '%s' does not exist\n", path);
|
||||
}
|
||||
|
||||
save = errno;
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = ENOMEM;
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (asprintf(&pc->features_path, "%s/.features", pc->path) == -1) {
|
||||
pc->features_path = NULL;
|
||||
if (kernel_features) {
|
||||
aa_features_ref(kernel_features);
|
||||
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = ENOMEM;
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
pc->kernel_features = kernel_features;
|
||||
|
||||
if (init_cache_features(pc, kernel_features, create)) {
|
||||
int save = errno;
|
||||
|
@ -178,14 +197,13 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
|||
return -1;
|
||||
}
|
||||
|
||||
pc->kernel_features = aa_features_ref(kernel_features);
|
||||
*policy_cache = pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_ref - increments the ref count of a policy_cache
|
||||
* aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: the policy_cache
|
||||
|
@ -197,60 +215,38 @@ aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
|
|||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_unref - decrements the ref count and frees the policy_cache when 0
|
||||
* aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
|
||||
* @policy_cache: the policy_cache (can be NULL)
|
||||
*/
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
|
||||
aa_features_unref(policy_cache->kernel_features);
|
||||
aa_features_unref(policy_cache->features);
|
||||
free(policy_cache->features_path);
|
||||
free(policy_cache->path);
|
||||
aa_features_unref(policy_cache->kernel_features);
|
||||
if (policy_cache->dirfd != -1)
|
||||
close(policy_cache->dirfd);
|
||||
free(policy_cache);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_is_valid - checks if the policy_cache is valid for the currently running kernel
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: true if the policy_cache is valid for the currently running kernel,
|
||||
* false if not
|
||||
*/
|
||||
bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache)
|
||||
{
|
||||
return aa_features_is_equal(policy_cache->features,
|
||||
policy_cache->kernel_features);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_create - creates a valid policy_cache for the currently running kernel
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_policy_cache_create(aa_policy_cache *policy_cache)
|
||||
{
|
||||
return create_cache(policy_cache, policy_cache->kernel_features);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_remove - removes all policy cache files under a path
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: the path to a policy cache directory
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_policy_cache_remove(const char *path)
|
||||
int aa_policy_cache_remove(int dirfd, const char *path)
|
||||
{
|
||||
return _aa_dirat_for_each(NULL, path, NULL, clear_cache_cb);
|
||||
return _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
|
||||
* @policy_cache: the policy_cache
|
||||
* @kernel_interface: the kernel interface to use when doing the replacement
|
||||
* (may be NULL if the currently running kernel features
|
||||
* were used when calling aa_policy_cache_new())
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and features pointing to
|
||||
* NULL
|
||||
|
@ -272,7 +268,7 @@ int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
|||
|
||||
cb_data.policy_cache = policy_cache;
|
||||
cb_data.kernel_interface = kernel_interface;
|
||||
retval = _aa_dirat_for_each(NULL, policy_cache->path, &cb_data,
|
||||
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data,
|
||||
replace_all_cb);
|
||||
|
||||
aa_kernel_interface_unref(kernel_interface);
|
||||
|
|
|
@ -107,16 +107,15 @@ bool atomic_dec_and_test(unsigned int *v)
|
|||
return __sync_sub_and_fetch(v, 1) == 0;
|
||||
}
|
||||
|
||||
int _aa_is_blacklisted(const char *name, const char *path)
|
||||
int _aa_is_blacklisted(const char *name)
|
||||
{
|
||||
int name_len;
|
||||
size_t name_len = strlen(name);
|
||||
struct ignored_suffix_t *suffix;
|
||||
|
||||
/* skip dot files and files with no name */
|
||||
if (*name == '.' || !strlen(name))
|
||||
if (!name_len || *name == '.' || !strcmp(name, "README"))
|
||||
return 1;
|
||||
|
||||
name_len = strlen(name);
|
||||
/* skip blacklisted suffixes */
|
||||
for (suffix = ignored_suffixes; suffix->text; suffix++) {
|
||||
char *found;
|
||||
|
@ -170,25 +169,31 @@ int _aa_asprintf(char **strp, const char *fmt, ...)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int dot_or_dot_dot_filter(const struct dirent *ent)
|
||||
{
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* _aa_dirat_for_each: iterate over a directory calling cb for each entry
|
||||
* @dir: already opened directory (MAY BE NULL)
|
||||
* @name: name of the directory (MAY BE NULL)
|
||||
* @dirfd: already opened directory
|
||||
* @name: name of the directory (NOT NULL)
|
||||
* @data: data pointer to pass to the callback fn (MAY BE NULL)
|
||||
* @cb: the callback to pass entry too (NOT NULL)
|
||||
*
|
||||
* Iterate over the entries in a directory calling cb for each entry.
|
||||
* The directory to iterate is determined by a combination of @dir and
|
||||
* The directory to iterate is determined by a combination of @dirfd and
|
||||
* @name.
|
||||
*
|
||||
* IF @name is a relative path it is determine relative to at @dir if it
|
||||
* is specified, else it the lookup is done relative to the current
|
||||
* working directory.
|
||||
* See the openat section of the open(2) man page for details on valid @dirfd
|
||||
* and @name combinations. This function does accept AT_FDCWD as @dirfd if
|
||||
* @name should be considered relative to the current working directory.
|
||||
*
|
||||
* If @name is not specified then @dir is used as the directory to iterate
|
||||
* over.
|
||||
*
|
||||
* It is an error if both @name and @dir are null
|
||||
* Pass "." for @name if @dirfd is the directory to iterate over.
|
||||
*
|
||||
* The cb function is called with the DIR in use and the name of the
|
||||
* file in that directory. If the file is to be opened it should
|
||||
|
@ -196,88 +201,52 @@ int _aa_asprintf(char **strp, const char *fmt, ...)
|
|||
*
|
||||
* Returns: 0 on success, else -1 and errno is set to the error code
|
||||
*/
|
||||
int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
|
||||
int (* cb)(DIR *, const char *, struct stat *, void *))
|
||||
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *))
|
||||
{
|
||||
autofree struct dirent *dirent = NULL;
|
||||
DIR *d = NULL;
|
||||
int error;
|
||||
autofree struct dirent **namelist = NULL;
|
||||
autoclose int cb_dirfd = -1;
|
||||
int i, num_dirs, rc;
|
||||
|
||||
if (!cb || (!dir && !name)) {
|
||||
if (!cb || !name) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir && (!name || *name != '/')) {
|
||||
dirent = (struct dirent *)
|
||||
malloc(offsetof(struct dirent, d_name) +
|
||||
fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
|
||||
} else {
|
||||
dirent = (struct dirent *)
|
||||
malloc(offsetof(struct dirent, d_name) +
|
||||
pathconf(name, _PC_NAME_MAX) + 1);
|
||||
}
|
||||
if (!dirent) {
|
||||
errno = ENOMEM;
|
||||
PDEBUG("could not alloc dirent: %m\n");
|
||||
cb_dirfd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (cb_dirfd == -1) {
|
||||
PDEBUG("could not open directory '%s': %m\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
if (dir && *name != '/') {
|
||||
int fd = openat(dirfd(dir), name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
goto fail;
|
||||
d = fdopendir(fd);
|
||||
} else {
|
||||
d = opendir(name);
|
||||
}
|
||||
PDEBUG("Open dir '%s': %s\n", name, d ? "succeeded" : "failed");
|
||||
if (!(d))
|
||||
goto fail;
|
||||
} else { /* dir && !name */
|
||||
PDEBUG("Recieved cache directory\n");
|
||||
d = dir;
|
||||
num_dirs = scandirat(cb_dirfd, ".", &namelist,
|
||||
dot_or_dot_dot_filter, NULL);
|
||||
if (num_dirs == -1) {
|
||||
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
struct dirent *ent;
|
||||
for (rc = 0, i = 0; i < num_dirs; i++) {
|
||||
/* Must cycle through all dirs so that each one is autofreed */
|
||||
autofree struct dirent *dir = namelist[i];
|
||||
struct stat my_stat;
|
||||
|
||||
error = readdir_r(d, dirent, &ent);
|
||||
if (error) {
|
||||
errno = error; /* readdir_r directly returns an errno */
|
||||
PDEBUG("readdir_r failed: %m\n");
|
||||
goto fail;
|
||||
} else if (!ent) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", name);
|
||||
goto fail;
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb(d, ent->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed\n");
|
||||
goto fail;
|
||||
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (d != dir)
|
||||
closedir(d);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
error = errno;
|
||||
if (d && d != dir)
|
||||
closedir(d);
|
||||
errno = error;
|
||||
|
||||
return -1;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -355,6 +355,7 @@ yy_flex_debug = 0;
|
|||
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_TIME); }
|
||||
|
||||
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
|
||||
{dmesg_timestamp} { yylval->t_str = strdup(yytext); return(TOK_DMESG_STAMP); }
|
||||
|
||||
. { /* ignore any non-matched input */ BEGIN(unknown_message); yyless(0); }
|
||||
|
||||
|
|
228
libraries/libapparmor/src/tst_kernel.c
Normal file
228
libraries/libapparmor/src/tst_kernel.c
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2015
|
||||
* 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 Novell, Inc. or Canonical
|
||||
* Ltd.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "kernel.c"
|
||||
|
||||
static int nullcmp_and_strcmp(const void *s1, const void *s2)
|
||||
{
|
||||
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
|
||||
if (!s1 || !s2)
|
||||
return s1 != s2;
|
||||
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
static int do_test_splitcon(char *con, int size, bool strip_nl, char **mode,
|
||||
const char *expected_label,
|
||||
const char *expected_mode, const char *error)
|
||||
{
|
||||
char *label;
|
||||
int rc = 0;
|
||||
|
||||
label = splitcon(con, size, strip_nl, mode);
|
||||
|
||||
if (nullcmp_and_strcmp(label, expected_label)) {
|
||||
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
|
||||
error, label, expected_label);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
|
||||
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
|
||||
error, *mode, expected_mode);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int do_test_aa_splitcon(char *con, char **mode,
|
||||
const char *expected_label,
|
||||
const char *expected_mode, const char *error)
|
||||
{
|
||||
char *label;
|
||||
int rc = 0;
|
||||
|
||||
label = aa_splitcon(con, mode);
|
||||
|
||||
if (nullcmp_and_strcmp(label, expected_label)) {
|
||||
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
|
||||
error, label, expected_label);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
|
||||
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
|
||||
error, *mode, expected_mode);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define TEST_SPLITCON(con, size, strip_nl, expected_label, \
|
||||
expected_mode, error) \
|
||||
do { \
|
||||
char c1[] = con; \
|
||||
char c2[] = con; \
|
||||
size_t sz = size < 0 ? strlen(con) : size; \
|
||||
char *mode; \
|
||||
\
|
||||
if (do_test_splitcon(c1, sz, strip_nl, &mode, \
|
||||
expected_label, expected_mode, \
|
||||
"splitcon: " error)) { \
|
||||
rc = 1; \
|
||||
} else if (do_test_splitcon(c2, sz, strip_nl, NULL, \
|
||||
expected_label, NULL, \
|
||||
"splitcon: " error " (NULL mode)")) { \
|
||||
rc = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_AA_SPLITCON(con, expected_label, expected_mode, error) \
|
||||
do { \
|
||||
char c1[] = con; \
|
||||
char c2[] = con; \
|
||||
char c3[] = con "\n"; \
|
||||
char *mode; \
|
||||
\
|
||||
if (do_test_aa_splitcon(c1, &mode, expected_label, \
|
||||
expected_mode, "aa_splitcon: " error)) {\
|
||||
rc = 1; \
|
||||
} else if (do_test_aa_splitcon(c2, NULL, expected_label,\
|
||||
NULL, \
|
||||
"aa_splitcon: " error " (NULL mode)")) {\
|
||||
rc = 1; \
|
||||
} else if (do_test_aa_splitcon(c3, &mode, \
|
||||
expected_label, expected_mode, \
|
||||
"aa_splitcon: " error " (newline)")) { \
|
||||
rc = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int test_splitcon(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/**
|
||||
* NOTE: the TEST_SPLITCON() macro automatically generates
|
||||
* corresponding tests with a NULL mode pointer.
|
||||
*/
|
||||
|
||||
TEST_SPLITCON("", 0, true, NULL, NULL, "empty string test #1");
|
||||
TEST_SPLITCON("", 0, false, NULL, NULL, "empty string test #2");
|
||||
|
||||
TEST_SPLITCON("unconfined", -1, true, "unconfined", NULL,
|
||||
"unconfined #1");
|
||||
TEST_SPLITCON("unconfined", -1, false, "unconfined", NULL,
|
||||
"unconfined #2");
|
||||
TEST_SPLITCON("unconfined\n", -1, true, "unconfined", NULL,
|
||||
"unconfined #3");
|
||||
TEST_SPLITCON("unconfined\n", -1, false, NULL, NULL,
|
||||
"unconfined #4");
|
||||
|
||||
TEST_SPLITCON("label (mode)", -1, true, "label", "mode",
|
||||
"basic split #1");
|
||||
TEST_SPLITCON("label (mode)", -1, false, "label", "mode",
|
||||
"basic split #2");
|
||||
TEST_SPLITCON("label (mode)\n", -1, true, "label", "mode",
|
||||
"basic split #3");
|
||||
TEST_SPLITCON("label (mode)\n", -1, false, NULL, NULL,
|
||||
"basic split #4");
|
||||
|
||||
TEST_SPLITCON("/a/b/c (enforce)", -1, true, "/a/b/c", "enforce",
|
||||
"path enforce split #1");
|
||||
TEST_SPLITCON("/a/b/c (enforce)", -1, false, "/a/b/c", "enforce",
|
||||
"path enforce split #2");
|
||||
TEST_SPLITCON("/a/b/c (enforce)\n", -1, true, "/a/b/c", "enforce",
|
||||
"path enforce split #3");
|
||||
TEST_SPLITCON("/a/b/c (enforce)\n", -1, false, NULL, NULL,
|
||||
"path enforce split #4");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int test_aa_splitcon(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/**
|
||||
* NOTE: the TEST_AA_SPLITCON() macro automatically generates
|
||||
* corresponding tests with a NULL mode pointer and contexts with
|
||||
* trailing newline characters.
|
||||
*/
|
||||
|
||||
TEST_AA_SPLITCON("label (mode)", "label", "mode", "basic split");
|
||||
|
||||
TEST_AA_SPLITCON("/a/b/c (enforce)", "/a/b/c", "enforce",
|
||||
"path enforce split");
|
||||
|
||||
TEST_AA_SPLITCON("/a/b/c (complain)", "/a/b/c", "complain",
|
||||
"path complain split");
|
||||
|
||||
TEST_AA_SPLITCON("profile_name (enforce)", "profile_name", "enforce",
|
||||
"name enforce split");
|
||||
|
||||
TEST_AA_SPLITCON("profile_name (complain)", "profile_name", "complain",
|
||||
"name complain split");
|
||||
|
||||
TEST_AA_SPLITCON("unconfined", "unconfined", NULL, "unconfined");
|
||||
|
||||
TEST_AA_SPLITCON("(odd) (enforce)", "(odd)", "enforce",
|
||||
"parenthesized label #1");
|
||||
|
||||
TEST_AA_SPLITCON("(odd) (enforce) (enforce)", "(odd) (enforce)",
|
||||
"enforce", "parenthesized label #2");
|
||||
|
||||
TEST_AA_SPLITCON("/usr/bin/😺 (enforce)", "/usr/bin/😺", "enforce",
|
||||
"non-ASCII path");
|
||||
|
||||
TEST_AA_SPLITCON("👍 (enforce)", "👍", "enforce",
|
||||
"non-ASCII profile name");
|
||||
|
||||
/* Negative tests */
|
||||
|
||||
TEST_AA_SPLITCON("", NULL, NULL, "empty string test");
|
||||
|
||||
TEST_AA_SPLITCON("profile\t(enforce)", NULL, NULL,
|
||||
"invalid tab separator");
|
||||
|
||||
TEST_AA_SPLITCON("profile(enforce)", NULL, NULL,
|
||||
"invalid missing separator");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int retval, rc = 0;
|
||||
|
||||
retval = test_splitcon();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
retval = test_aa_splitcon();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -3,12 +3,30 @@
|
|||
%{
|
||||
#include <aalogparse.h>
|
||||
#include <sys/apparmor.h>
|
||||
#include <sys/apparmor_private.h>
|
||||
|
||||
%}
|
||||
|
||||
%include "typemaps.i"
|
||||
%include <aalogparse.h>
|
||||
|
||||
/**
|
||||
* swig doesn't like the macro magic we do in apparmor.h and apparmor_private.h
|
||||
* so the function prototypes must be manually inserted.
|
||||
*
|
||||
* Functions that return a negative int and set errno upon error use a special
|
||||
* %exception directive and must be listed after the %exception below. All
|
||||
* other functions go here.
|
||||
*/
|
||||
|
||||
/* apparmor.h */
|
||||
|
||||
extern char *aa_splitcon(char *con, char **mode);
|
||||
|
||||
/* apparmor_private.h */
|
||||
|
||||
extern int _aa_is_blacklisted(const char *name);
|
||||
|
||||
#ifdef SWIGPYTHON
|
||||
%exception {
|
||||
$action
|
||||
|
@ -19,9 +37,9 @@
|
|||
}
|
||||
#endif
|
||||
|
||||
/* swig doesn't like the macro magic we do in apparmor.h so the fn prototypes
|
||||
* are manually inserted here
|
||||
*/
|
||||
/* Functions that return a negative int and set errno upon error go here. */
|
||||
|
||||
/* apparmor.h */
|
||||
|
||||
extern int aa_is_enabled(void);
|
||||
extern int aa_find_mountpoint(char **mnt);
|
||||
|
@ -39,5 +57,16 @@ extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
|||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||
int *audit);
|
||||
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
||||
size_t label_len, const char *path,
|
||||
size_t path_len, int *allowed, int *audited);
|
||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||
const char *path, int *allowed, int *audited);
|
||||
extern int aa_query_link_path_len(const char *label, size_t label_len,
|
||||
const char *target, size_t target_len,
|
||||
const char *link, size_t link_len,
|
||||
int *allowed, int *audited);
|
||||
extern int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);
|
||||
|
||||
%exception;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Sep 9 12:51:36 ubuntu-desktop kernel: [ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"
|
|
@ -0,0 +1,11 @@
|
|||
START
|
||||
File: testcase_changeprofile_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1431116353.523:77
|
||||
Operation: change_profile
|
||||
Profile: /tests/regression/apparmor/changeprofile
|
||||
Command: changeprofile
|
||||
Name2: /tests/regression/apparmor/rename
|
||||
PID: 3459
|
||||
Epoch: 1431116353
|
||||
Audit subid: 77
|
|
@ -0,0 +1 @@
|
|||
[ 1612.746129] audit: type=1400 audit(1284061910.975:672): apparmor="DENIED" operation="capable" parent=2663 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority" pid=7292 comm="syscall_setprio" capability=23 capname="sys_nice"
|
|
@ -0,0 +1,12 @@
|
|||
START
|
||||
File: testcase_dmesg_capability.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284061910.975:672
|
||||
Operation: capable
|
||||
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority
|
||||
Name: sys_nice
|
||||
Command: syscall_setprio
|
||||
Parent: 2663
|
||||
PID: 7292
|
||||
Epoch: 1284061910
|
||||
Audit subid: 672
|
|
@ -0,0 +1 @@
|
|||
[ 1597.774866] audit: type=1400 audit(1284061896.005:28): apparmor="DENIED" operation="change_hat" info="unconfined" error=-1 pid=2698 comm="syscall_ptrace"
|
|
@ -0,0 +1,11 @@
|
|||
START
|
||||
File: testcase_dmesg_changehat_negative_error.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284061896.005:28
|
||||
Operation: change_hat
|
||||
Command: syscall_ptrace
|
||||
Info: unconfined
|
||||
ErrorCode: 1
|
||||
PID: 2698
|
||||
Epoch: 1284061896
|
||||
Audit subid: 28
|
|
@ -0,0 +1 @@
|
|||
[ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"
|
|
@ -0,0 +1,11 @@
|
|||
START
|
||||
File: testcase_dmesg_changeprofile_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1431116353.523:77
|
||||
Operation: change_profile
|
||||
Profile: /tests/regression/apparmor/changeprofile
|
||||
Command: changeprofile
|
||||
Name2: /tests/regression/apparmor/rename
|
||||
PID: 3459
|
||||
Epoch: 1431116353
|
||||
Audit subid: 77
|
|
@ -0,0 +1 @@
|
|||
[ 2010.738449] audit: type=1400 audit(1284062308.965:276251): apparmor="DENIED" operation="link" parent=19088 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/link" name="/tmp/sdtest.19088-12382-HWH57d/linkfile" pid=19142 comm="link" requested_mask="l" denied_mask="l" fsuid=0 ouid=0 target="/tmp/sdtest.19088-12382-HWH57d/target"
|
|
@ -0,0 +1,17 @@
|
|||
START
|
||||
File: testcase_dmesg_link_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284062308.965:276251
|
||||
Operation: link
|
||||
Mask: l
|
||||
Denied Mask: l
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/link
|
||||
Name: /tmp/sdtest.19088-12382-HWH57d/linkfile
|
||||
Command: link
|
||||
Name2: /tmp/sdtest.19088-12382-HWH57d/target
|
||||
Parent: 19088
|
||||
PID: 19142
|
||||
Epoch: 1284062308
|
||||
Audit subid: 276251
|
|
@ -0,0 +1 @@
|
|||
[45334.755142] audit: type=1503 audit(1282671283.411:2199): operation="mkdir" pid=4786 parent=4708 profile="/usr/sbin/sshd//ubuntu" requested_mask="c::" denied_mask="c::" fsuid=1000 ouid=1000 name="/tmp/ssh-gRozJw4786/"
|
|
@ -0,0 +1,15 @@
|
|||
START
|
||||
File: testcase_dmesg_mkdir.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1282671283.411:2199
|
||||
Operation: mkdir
|
||||
Mask: c::
|
||||
Denied Mask: c::
|
||||
fsuid: 1000
|
||||
ouid: 1000
|
||||
Profile: /usr/sbin/sshd//ubuntu
|
||||
Name: /tmp/ssh-gRozJw4786/
|
||||
Parent: 4708
|
||||
PID: 4786
|
||||
Epoch: 1282671283
|
||||
Audit subid: 2199
|
|
@ -0,0 +1 @@
|
|||
[ 878.663418] audit: type=1502 audit(1282626827.320:413): operation="rename_dest" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="wc::" denied_mask="wc::" fsuid=0 ouid=0 name="/var/run/motd"
|
|
@ -0,0 +1,15 @@
|
|||
START
|
||||
File: testcase_dmesg_rename_dest.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1282626827.320:413
|
||||
Operation: rename_dest
|
||||
Mask: wc::
|
||||
Denied Mask: wc::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /var/run/motd
|
||||
Parent: 650
|
||||
PID: 1881
|
||||
Epoch: 1282626827
|
||||
Audit subid: 413
|
|
@ -0,0 +1 @@
|
|||
[ 878.663410] audit: type=1502 audit(1282626827.320:412): operation="rename_src" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="r::" denied_mask="r::" fsuid=0 ouid=0 name="/var/run/motd.new"
|
|
@ -0,0 +1,15 @@
|
|||
START
|
||||
File: testcase_dmesg_rename_src.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1282626827.320:412
|
||||
Operation: rename_src
|
||||
Mask: r::
|
||||
Denied Mask: r::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /var/run/motd.new
|
||||
Parent: 650
|
||||
PID: 1881
|
||||
Epoch: 1282626827
|
||||
Audit subid: 412
|
|
@ -0,0 +1 @@
|
|||
[ 2143.902340] audit: type=1400 audit(1283989336.064:272335): apparmor="STATUS" info="failed to unpack profile" error=-71 pid=4958 comm="apparmor_parser" name="/home/jj/master/tests/regression/apparmor/net_raw" offset=159
|
|
@ -0,0 +1,11 @@
|
|||
START
|
||||
File: testcase_dmesg_status_offset.in
|
||||
Event type: AA_RECORD_STATUS
|
||||
Audit ID: 1283989336.064:272335
|
||||
Name: /home/jj/master/tests/regression/apparmor/net_raw
|
||||
Command: apparmor_parser
|
||||
Info: failed to unpack profile
|
||||
ErrorCode: 71
|
||||
PID: 4958
|
||||
Epoch: 1283989336
|
||||
Audit subid: 272335
|
|
@ -0,0 +1 @@
|
|||
[ 878.662172] audit: type=1503 audit(1282626827.320:411): operation="truncate" pid=1957 parent=1 profile="/etc/update-motd.d/91-release-upgrade" requested_mask="w::" denied_mask="w::" fsuid=0 ouid=0 name="/var/lib/update-notifier/release-upgrade-available"
|
|
@ -0,0 +1,15 @@
|
|||
START
|
||||
File: testcase_dmesg_truncate.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1282626827.320:411
|
||||
Operation: truncate
|
||||
Mask: w::
|
||||
Denied Mask: w::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /etc/update-motd.d/91-release-upgrade
|
||||
Name: /var/lib/update-notifier/release-upgrade-available
|
||||
Parent: 1
|
||||
PID: 1957
|
||||
Epoch: 1282626827
|
||||
Audit subid: 411
|
|
@ -50,7 +50,7 @@ CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
|
|||
endif
|
||||
endif #CFLAGS
|
||||
|
||||
EXTRA_CXXFLAGS = ${CFLAGS} ${CXX_WARNINGS} -std=gnu++0x -D_GNU_SOURCE
|
||||
EXTRA_CXXFLAGS = ${CFLAGS} ${CPPFLAGS} ${CXX_WARNINGS} -std=gnu++0x -D_GNU_SOURCE
|
||||
EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
|
||||
|
||||
#LEXLIB := -lfl
|
||||
|
@ -213,7 +213,7 @@ parser_include.o: parser_include.c parser.h parser_include.h
|
|||
parser_merge.o: parser_merge.c parser.h profile.h
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_regex.o: parser_regex.c parser.h profile.h libapparmor_re/apparmor_re.h $(APPARMOR_H)
|
||||
parser_regex.o: parser_regex.c parser.h profile.h libapparmor_re/apparmor_re.h libapparmor_re/aare_rules.h $(APPARMOR_H)
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_symtab.o: parser_symtab.c parser.h
|
||||
|
|
|
@ -44,19 +44,51 @@ to the policy; this behaviour is modelled after cpp(1).
|
|||
|
||||
=over 4
|
||||
|
||||
B<PROFILE FILE> = ( [ I<PREAMBLE> ] [ I<PROFILE> ] )*
|
||||
|
||||
B<PREAMBLE> = ( I<COMMENT> | I<VARIABLE ASSIGNMENT> | I<INCLUDE> )* (variable assignment must come before the profile)
|
||||
|
||||
B<INCLUDE> = '#include' ( I<ABS PATH> | I<MAGIC PATH> )
|
||||
|
||||
B<ABS PATH> = '"' path '"' (the path is passed to open(2))
|
||||
|
||||
B<MAGIC PATH> = 'E<lt>' relative path 'E<gt>' (the path is relative to F</etc/apparmor.d/>)
|
||||
|
||||
B<COMMENT> = '#' I<TEXT>
|
||||
B<COMMENT> = '#' I<TEXT> [ '\r' ] '\n'
|
||||
|
||||
B<TEXT> = any characters
|
||||
|
||||
B<PROFILE> = [ I<COMMENT> ... ] [ I<VARIABLE ASSIGNMENT> ... ] ( '"' I<PROGRAM> '"' | I<PROGRAM> ) [ 'flags=(complain)' ]'{' [ ( I<RESOURCE RULE> | I<COMMENT> | I<INCLUDE> | I<SUBPROFILE> | I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<DBUS RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE>) ... ] '}'
|
||||
B<PROFILE> = ( I<PROFILE HEAD> ) [ I<ATTACHMENT SPECIFICATION> ] [ I<PROFILE FLAG CONDS> ] '{' ( I<RULES> )* '}'
|
||||
|
||||
B<SUBPROFILE> = [ I<COMMENT> ... ] ( I<PROGRAMHAT> | 'profile ' I<PROGRAMCHILD> ) '{' [ ( I<FILE RULE> | I<COMMENT> | I<INCLUDE> ) ... ] '}'
|
||||
B<PROFILE HEAD> = [ 'profile' ] I<FILEGLOB> | 'profile' I<PROFILE NAME>
|
||||
|
||||
B<PROFILE NAME> ( I<UNQUOTED PROFILE NAME> | I<QUOTED PROFILE NAME> )
|
||||
|
||||
B<QUOTED PROFILE NAME> = '"' I<UNQUOTED PROFILE NAME> '"'
|
||||
|
||||
B<UNQUOTED PROFILE NAME> = (must start with alphanumeric character (after variable expansion), or '/' B<AARE> have special meanings; see below. May include I<VARIABLE>. Rules with embedded spaces or tabs must be quoted.)
|
||||
|
||||
B<ATTACHMENT SPECIFICATION> = I<FILEGLOB>
|
||||
|
||||
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
|
||||
|
||||
B<PROFILE FLAGS> = 'complain' | 'audit' | 'enforce' | 'mediate_deleted' | 'attach_disconnected' | 'chroot_relative'
|
||||
|
||||
B<RULES> = [ ( I<LINE RULES> | I<COMMA RULES> ',' | I<BLOCK RULES> )
|
||||
|
||||
B<LINE RULES> = ( I<COMMENT> | I<INCLUDE> ) [ '\r' ] '\n'
|
||||
|
||||
B<COMMA RULES> = ( I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE> | I<ALIAS RULE> | I<DBUS RULE> )
|
||||
|
||||
B<BLOCK RULES> = ( I<SUBPROFILE> | I<HAT> | I<QUALIFIER BLOCK> )
|
||||
|
||||
B<SUBPROFILE> = 'profile' I<PROFILE NAME> [ I<ATTACHMENT SPECIFICATION> ] [ I<PROFILE FLAG CONDS> ] '{' ( I<RULES> )* '}'
|
||||
|
||||
B<HAT> = ('hat' | '^') I<HATNAME> [ I<PROFILE FLAG CONDS> ] '{' ( I<RULES> )* '}'
|
||||
|
||||
B<HATNAME> = ( must start with alphanumeric character. see aa_change_hat(2) for a description of how this "hat" is used. IF '^' is used to start a hat then there is no space between the '^' and I<HATNAME>)
|
||||
|
||||
B<QUALIFIER BLOCK> = I<QUALIFIERS> I<BLOCK>
|
||||
|
||||
B<ACCESS TYPE> = ( 'allow' | 'deny' )
|
||||
|
||||
|
@ -69,7 +101,7 @@ B<CAPABILITY LIST> = ( I<CAPABILITY> )+
|
|||
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
|
||||
capabilities(7))
|
||||
|
||||
B<NETWORK RULE> = [ I<QUALIFIERS> 'network' [ [ I<DOMAIN> [ I<TYPE> | I<PROTOCOL> ] ] | [ I<PROTOCOL> ] ] ','
|
||||
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
||||
|
||||
B<DOMAIN> = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' | 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' ) ','
|
||||
|
||||
|
@ -77,15 +109,9 @@ B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
|||
|
||||
B<PROTOCOL> = ( 'tcp' | 'udp' | 'icmp' )
|
||||
|
||||
B<PROGRAM> = (non-whitespace characters except for '^', must start with '/'. Embedded spaces or tabs must be quoted.)
|
||||
|
||||
B<PROGRAMHAT> = '^' (non-whitespace characters; see aa_change_hat(2) for a description of how this "hat" is used.)
|
||||
|
||||
B<PROGRAMCHILD> = I<SUBPROFILE> name
|
||||
|
||||
B<MOUNT RULE> = ( I<MOUNT> | I<REMOUNT> | I<UMOUNT> )
|
||||
|
||||
B<MOUNT> = [ I<QUALIFIERS> ] 'mount' [ I<MOUNT CONDITIONS> ] [ I<SOURCE FILEGLOB> ] [ -E<gt> [ I<MOUNTPOINT FILEGLOB> ]
|
||||
B<MOUNT> = [ I<QUALIFIERS> ] 'mount' [ I<MOUNT CONDITIONS> ] [ I<SOURCE FILEGLOB> ] [ '-E<gt>' [ I<MOUNTPOINT FILEGLOB> ]
|
||||
|
||||
B<REMOUNT> = [ I<QUALIFIERS> ] 'remount' [ I<MOUNT CONDITIONS> ] I<MOUNTPOINT FILEGLOB>
|
||||
|
||||
|
@ -105,7 +131,7 @@ B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec'
|
|||
|
||||
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
||||
|
||||
B<PIVOT ROOT RULE> = [ I<QUALIFIERS> ] pivot_root [ oldroot=I<OLD PUT FILEGLOB> ] [ I<NEW ROOT FILEGLOB> ] [ -E<gt> I<PROGRAMCHILD> ]
|
||||
B<PIVOT ROOT RULE> = [ I<QUALIFIERS> ] pivot_root [ oldroot=I<OLD PUT FILEGLOB> ] [ I<NEW ROOT FILEGLOB> ] [ '-E<gt>' I<PROFILE NAME> ]
|
||||
|
||||
B<SOURCE FILEGLOB> = I<FILEGLOB>
|
||||
|
||||
|
@ -201,11 +227,11 @@ B<UNIX ATTR COND> 'attr' '=' ( I<AARE> | '(' '"' I<AARE> '"' | I<AARE> ')' )
|
|||
|
||||
B<UNIX OPT COND> 'opt' '=' ( I<AARE> | '(' '"' I<AARE> '"' | I<AARE> ')' )
|
||||
|
||||
B<RLIMIT RULE> = 'set' 'rlimit' [I<RLIMIT> 'E<lt>=' I<RLIMIT VALUE> ] ','
|
||||
B<RLIMIT RULE> = 'set' 'rlimit' [I<RLIMIT> 'E<lt>=' I<RLIMIT VALUE> ]
|
||||
|
||||
B<RLIMIT> = ( 'cpu' | 'fsize' | 'data' | 'stack' | 'core' | 'rss' | 'nofile' | 'ofile' | 'as' | 'nproc' | 'memlock' | 'locks' | 'sigpending' | 'msgqueue' | 'nice' | 'rtprio' | 'rttime' )
|
||||
|
||||
B<RLIMIT VALUE> = ( I<RLIMIT SIZE> | I<RLIMIT NUMBER> | I <RLIMIT NICE> )
|
||||
B<RLIMIT VALUE> = ( I<RLIMIT SIZE> | I<RLIMIT NUMBER> | I<RLIMIT NICE> )
|
||||
|
||||
B<RLIMIT SIZE> = I<NUMBER> ( 'K' | 'M' | 'G' ) Only applies to RLIMIT of 'fsize', 'data', 'stack', 'core', 'rss', 'as', 'memlock', 'msgqueue'.
|
||||
|
||||
|
@ -213,7 +239,7 @@ B<RLIMIT NUMBER> = number from 0 to max rlimit value. Only applies ot RLIMIT of
|
|||
|
||||
B<RLIMIT NICE> = a number between -20 and 19. Only applies to RLIMIT of 'nice'
|
||||
|
||||
B<FILE RULE> = [ I<QUALIFIERS> ] [ 'owner' ] ( 'file' | [ 'file' ] ( I<FILEGLOB> I<ACCESS> | I<ACCESS> I<FILEGLOB> ) [ -E<gt> <EXEC TARGET> ] ) ','
|
||||
B<FILE RULE> = [ I<QUALIFIERS> ] [ 'owner' ] ( 'file' | [ 'file' ] ( I<FILEGLOB> I<ACCESS> | I<ACCESS> I<FILEGLOB> ) [ '-E<gt>' I<EXEC TARGET> ] )
|
||||
|
||||
B<FILEGLOB> = ( I<QUOTED FILEGLOB> | I<UNQUOTED FILEGLOB> )
|
||||
|
||||
|
@ -227,19 +253,19 @@ B<EXEC TRANSITION> = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' |
|
|||
|
||||
B<EXEC TARGET> = name (requires I<EXEC TRANSITION> specified)
|
||||
|
||||
B<LINK RULE> = I<QUALIFIERS> [ 'owner' ] 'link' [ 'subset' ] <FILEGLOB> ( 'to' | '-E<gt>' ) <FILEGLOB> ','
|
||||
B<LINK RULE> = I<QUALIFIERS> [ 'owner' ] 'link' [ 'subset' ] I<FILEGLOB> ( 'to' | '-E<gt>' ) I<FILEGLOB>
|
||||
|
||||
B<VARIABLE> = '@{' I<ALPHA> [ ( I<ALPHANUMERIC> | '_' ) ... ] '}'
|
||||
|
||||
B<VARIABLE ASSIGNMENT> = I<VARIABLE> ('=' | '+=') (space separated values)
|
||||
|
||||
B<ALIAS RULE> = I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH> ','
|
||||
B<ALIAS RULE> = I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH>
|
||||
|
||||
B<ALPHA> = ('a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
|
||||
|
||||
B<ALPHANUMERIC> = ('0', '1', '2', ... '9', 'a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
|
||||
|
||||
B<CHANGE_PROFILE RULE> = 'change_profile' [ I<EXEC COND> ] [ -E<gt> I<PROGRAMCHILD> ]
|
||||
B<CHANGE_PROFILE RULE> = 'change_profile' [ I<EXEC COND> ] [ '-E<gt>' I<PROFILE NAME> ]
|
||||
|
||||
B<EXEC COND> = I<FILEGLOB>
|
||||
|
||||
|
@ -334,7 +360,7 @@ modes:
|
|||
|
||||
- transition to subprofile on execute with fallback to unconfined
|
||||
|
||||
=item B<Cux>
|
||||
=item B<CUx>
|
||||
|
||||
- transition to subprofile on execute with fallback to unconfined -- scrub the environment
|
||||
|
||||
|
@ -506,7 +532,7 @@ determine the profile to transition to from the executable name. It
|
|||
is however possible to specify the name of the profile that the transition
|
||||
should use.
|
||||
|
||||
The name of the profile to transition to is specified using the '->'
|
||||
The name of the profile to transition to is specified using the '-E<gt>'
|
||||
followed by the name of the profile to transition to. Eg.
|
||||
|
||||
/bin/** px -> profile,
|
||||
|
@ -546,8 +572,9 @@ or trailing the file glob. Eg.
|
|||
|
||||
/** rw, # trailing permissions
|
||||
|
||||
When a leading permissions is used further rule options and context
|
||||
When leading permissions are used further rule options and context
|
||||
may be allowed, Eg.
|
||||
|
||||
l /foo -> /bar, # lead 'l' link permission is equivalent to link rules
|
||||
|
||||
=back
|
||||
|
@ -567,25 +594,27 @@ Eg.
|
|||
/link* rw,
|
||||
link subset /link* -> /**,
|
||||
|
||||
The link rule allows linking of /link to both /file1 or /file2 by
|
||||
name however because the /link file has 'rw' permissions it is not
|
||||
allowed to link to /file1 because that would grant an access path
|
||||
to /file1 with more permissions than the 'r' permissions the profile
|
||||
specifies.
|
||||
The link rule allows linking of /link to both /file1 or /file2 by
|
||||
name however because the /link file has 'rw' permissions it is not
|
||||
allowed to link to /file1 because that would grant an access path
|
||||
to /file1 with more permissions than the 'r' permissions the profile
|
||||
specifies.
|
||||
|
||||
A link of /link to /file2 would be allowed because the 'rw' permissions
|
||||
of /link are a subset of the 'rwk' permissions for /file1.
|
||||
A link of /link to /file2 would be allowed because the 'rw' permissions
|
||||
of /link are a subset of the 'rwk' permissions for /file1.
|
||||
|
||||
The link rule is equivalent to specifying the 'l' link permission as
|
||||
a leading permission with no other file access permissions. When this
|
||||
is done the link rule options can be specified.
|
||||
|
||||
The following link rule is equivalent to the 'l' permission file rule
|
||||
|
||||
link /foo -> bar,
|
||||
l /foo -> /bar,
|
||||
|
||||
File rules that specify the 'l' permission and don't specify the extend
|
||||
link permissions map to link rules as follows.
|
||||
|
||||
/foo l,
|
||||
l /foo,
|
||||
link subset /foo -> /**,
|
||||
|
@ -1301,6 +1330,12 @@ Rule qualifiers can modify the rule and/or permissions within the rule.
|
|||
|
||||
=over 4
|
||||
|
||||
=item B<allow>
|
||||
|
||||
Specifies that permissions requests that match the rule are allowed. This
|
||||
is the default value for rules and does not need to be specified. Conflicts
|
||||
with the I<deny> qualifier.
|
||||
|
||||
=item B<audit>
|
||||
|
||||
Specifies that permissions requests that match the rule should be recorded
|
||||
|
@ -1309,7 +1344,8 @@ to the audit log.
|
|||
=item B<deny>
|
||||
|
||||
Specifies that permissions requests that match the rule should be denied
|
||||
without logging. Can be combined with 'audit' to enable logging.
|
||||
without logging. Can be combined with 'audit' to enable logging. Conflicts
|
||||
with the I<allow> qualifier.
|
||||
|
||||
=item B<owner>
|
||||
|
||||
|
@ -1318,6 +1354,16 @@ referenced by the permission check.
|
|||
|
||||
=back
|
||||
|
||||
=head3 Qualifier Blocks
|
||||
|
||||
Rule Qualifiers can be applied to multiple rules at a time by grouping the
|
||||
rules into a rule block.
|
||||
|
||||
audit {
|
||||
/foo r,
|
||||
network,
|
||||
}
|
||||
|
||||
=head2 #include mechanism
|
||||
|
||||
AppArmor provides an easy abstraction mechanism to group common file
|
||||
|
|
|
@ -183,6 +183,12 @@ defined as an absolute paths.
|
|||
Set the location of the apparmor security filesystem (default is
|
||||
"/sys/kernel/security/apparmor").
|
||||
|
||||
=item -M n, --features-file n
|
||||
|
||||
Use the features file located at path "n" (default is
|
||||
/etc/apparmor.d/cache/.features). If the --cache-loc option is present, the
|
||||
".features" file in the specified cache directory is used.
|
||||
|
||||
=item -m n, --match-string n
|
||||
|
||||
Only use match features "n".
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
#define AA_MAY_WRITE (1 << 1)
|
||||
#define AA_MAY_READ (1 << 2)
|
||||
#define AA_MAY_APPEND (1 << 3)
|
||||
#define AA_MAY_LINK (1 << 4)
|
||||
#define AA_MAY_LOCK (1 << 5)
|
||||
#define AA_EXEC_MMAP (1 << 6)
|
||||
#define AA_OLD_MAY_LINK (1 << 4)
|
||||
#define AA_OLD_MAY_LOCK (1 << 5)
|
||||
#define AA_OLD_EXEC_MMAP (1 << 6)
|
||||
#define AA_EXEC_PUX (1 << 7)
|
||||
#define AA_EXEC_UNSAFE (1 << 8)
|
||||
#define AA_EXEC_INHERIT (1 << 9)
|
||||
|
@ -42,8 +42,8 @@
|
|||
|
||||
#define AA_BASE_PERMS (AA_MAY_EXEC | AA_MAY_WRITE | \
|
||||
AA_MAY_READ | AA_MAY_APPEND | \
|
||||
AA_MAY_LINK | AA_MAY_LOCK | \
|
||||
AA_EXEC_PUX | AA_EXEC_MMAP | \
|
||||
AA_OLD_MAY_LINK | AA_OLD_MAY_LOCK | \
|
||||
AA_EXEC_PUX | AA_OLD_EXEC_MMAP | \
|
||||
AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
|
||||
AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
|
||||
AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
|
||||
|
@ -95,8 +95,8 @@
|
|||
#define ALL_USER_EXEC (AA_USER_EXEC | AA_USER_EXEC_TYPE)
|
||||
#define ALL_OTHER_EXEC (AA_OTHER_EXEC | AA_OTHER_EXEC_TYPE)
|
||||
|
||||
#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
|
||||
(AA_MAY_LINK << AA_OTHER_SHIFT))
|
||||
#define AA_LINK_BITS ((AA_OLD_MAY_LINK << AA_USER_SHIFT) | \
|
||||
(AA_OLD_MAY_LINK << AA_OTHER_SHIFT))
|
||||
|
||||
#define SHIFT_MODE(MODE, SHIFT) ((((MODE) & AA_BASE_PERMS) << (SHIFT))\
|
||||
| ((MODE) & ~AA_FILE_PERMS))
|
||||
|
@ -104,7 +104,7 @@
|
|||
| ((MODE) & ~AA_FILE_PERMS))
|
||||
|
||||
|
||||
#define AA_LINK_SUBSET_TEST (AA_MAY_LINK << 1)
|
||||
#define AA_LINK_SUBSET_TEST (AA_OLD_MAY_LINK << 1)
|
||||
#define LINK_SUBSET_BITS ((AA_LINK_SUBSET_TEST << AA_USER_SHIFT) | \
|
||||
(AA_LINK_SUBSET_TEST << AA_OTHER_SHIFT))
|
||||
#define LINK_TO_LINK_SUBSET(X) (((X) << 1) & AA_LINK_SUBSET_TEST)
|
||||
|
@ -137,9 +137,9 @@ enum pattern_t {
|
|||
#define HAS_MAY_WRITE(mode) ((mode) & AA_MAY_WRITE)
|
||||
#define HAS_MAY_APPEND(mode) ((mode) & AA_MAY_APPEND)
|
||||
#define HAS_MAY_EXEC(mode) ((mode) & AA_MAY_EXEC)
|
||||
#define HAS_MAY_LINK(mode) ((mode) & AA_MAY_LINK)
|
||||
#define HAS_MAY_LOCK(mode) ((mode) & AA_MAY_LOCK)
|
||||
#define HAS_EXEC_MMAP(mode) ((mode) & AA_EXEC_MMAP)
|
||||
#define HAS_MAY_LINK(mode) ((mode) & AA_OLD_MAY_LINK)
|
||||
#define HAS_MAY_LOCK(mode) ((mode) & AA_OLD_MAY_LOCK)
|
||||
#define HAS_EXEC_MMAP(mode) ((mode) & AA_OLD_EXEC_MMAP)
|
||||
|
||||
#define HAS_EXEC_UNSAFE(mode) ((mode) & AA_EXEC_UNSAFE)
|
||||
#define HAS_CHANGE_PROFILE(mode) ((mode) & AA_CHANGE_PROFILE)
|
||||
|
@ -161,3 +161,6 @@ static inline int is_merged_x_consistent(int a, int b)
|
|||
}
|
||||
|
||||
#endif /* ! _IMMUNIX_H */
|
||||
|
||||
/* LocalWords: MMAP
|
||||
*/
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* Ltd.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
@ -29,10 +28,10 @@
|
|||
#include "lib.h"
|
||||
#include "parser.h"
|
||||
|
||||
int dirat_for_each(DIR *dir, const char *name, void *data,
|
||||
int (* cb)(DIR *, const char *, struct stat *, void *))
|
||||
int dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *))
|
||||
{
|
||||
int retval = _aa_dirat_for_each(dir, name, data, cb);
|
||||
int retval = _aa_dirat_for_each(dirfd, name, data, cb);
|
||||
|
||||
if (retval)
|
||||
PDEBUG("dirat_for_each failed: %m\n");
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#define asprintf _aa_asprintf
|
||||
|
||||
int dirat_for_each(DIR *dir, const char *name, void *data,
|
||||
int (* cb)(DIR *, const char *, struct stat *, void *));
|
||||
int dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *));
|
||||
|
||||
int isodigit(char c);
|
||||
long strntol(const char *str, const char **endptr, int base, long maxval,
|
||||
|
|
|
@ -35,13 +35,13 @@
|
|||
#include "../immunix.h"
|
||||
|
||||
|
||||
|
||||
aare_rules::~aare_rules(void)
|
||||
{
|
||||
if (root)
|
||||
root->release();
|
||||
|
||||
aare_reset_matchflags();
|
||||
unique_perms.clear();
|
||||
expr_map.clear();
|
||||
}
|
||||
|
||||
bool aare_rules::add_rule(const char *rule, int deny, uint32_t perms,
|
||||
|
@ -50,40 +50,15 @@ bool aare_rules::add_rule(const char *rule, int deny, uint32_t perms,
|
|||
return add_rule_vec(deny, perms, audit, 1, &rule, flags);
|
||||
}
|
||||
|
||||
#define FLAGS_WIDTH 2
|
||||
#define MATCH_FLAGS_SIZE (sizeof(uint32_t) * 8 - 1)
|
||||
MatchFlag *match_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
|
||||
DenyMatchFlag *deny_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
|
||||
#define EXEC_MATCH_FLAGS_SIZE (AA_EXEC_COUNT *2 * 2 * 2) /* double for each of ix pux, unsafe x bits * u::o */
|
||||
MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix + pux * u::o */
|
||||
ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix + pux *u::o */
|
||||
|
||||
void aare_reset_matchflags(void)
|
||||
{
|
||||
uint32_t i, j;
|
||||
#define RESET_FLAGS(group, size) { \
|
||||
for (i = 0; i < FLAGS_WIDTH; i++) { \
|
||||
for (j = 0; j < size; j++) { \
|
||||
if ((group)[i][j]) delete (group)[i][j]; \
|
||||
(group)[i][j] = NULL; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
RESET_FLAGS(match_flags, MATCH_FLAGS_SIZE);
|
||||
RESET_FLAGS(deny_flags, MATCH_FLAGS_SIZE);
|
||||
RESET_FLAGS(exec_match_flags, EXEC_MATCH_FLAGS_SIZE);
|
||||
RESET_FLAGS(exact_match_flags, EXEC_MATCH_FLAGS_SIZE);
|
||||
#undef RESET_FLAGS
|
||||
}
|
||||
|
||||
void aare_rules::add_to_rules(Node *tree, Node *perms)
|
||||
{
|
||||
if (reverse)
|
||||
flip_tree(tree);
|
||||
if (root)
|
||||
root = new AltNode(root, new CatNode(tree, perms));
|
||||
Node *base = expr_map[perms];
|
||||
if (base)
|
||||
expr_map[perms] = new AltNode(base, tree);
|
||||
else
|
||||
root = new CatNode(tree, perms);
|
||||
expr_map[perms] = tree;
|
||||
}
|
||||
|
||||
static Node *cat_with_null_seperator(Node *l, Node *r)
|
||||
|
@ -91,84 +66,6 @@ static Node *cat_with_null_seperator(Node *l, Node *r)
|
|||
return new CatNode(new CatNode(l, new CharNode(0)), r);
|
||||
}
|
||||
|
||||
static Node *convert_file_perms(int deny, uint32_t perms, uint32_t audit,
|
||||
bool exact_match)
|
||||
{
|
||||
Node *accept;
|
||||
|
||||
assert(perms != 0);
|
||||
|
||||
/* 0x7f == 4 bits x mods + 1 bit unsafe mask + 1 bit ix, + 1 pux after shift */
|
||||
#define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 7)) & 0x7f)
|
||||
|
||||
|
||||
/* the permissions set is assumed to be non-empty if any audit
|
||||
* bits are specified */
|
||||
accept = NULL;
|
||||
for (unsigned int n = 0; perms && n < (sizeof(perms) * 8); n++) {
|
||||
uint32_t mask = 1 << n;
|
||||
|
||||
if (!(perms & mask))
|
||||
continue;
|
||||
|
||||
int ai = audit & mask ? 1 : 0;
|
||||
perms &= ~mask;
|
||||
|
||||
Node *flag;
|
||||
if (mask & ALL_AA_EXEC_TYPE)
|
||||
/* these cases are covered by EXEC_BITS */
|
||||
continue;
|
||||
if (deny) {
|
||||
if (deny_flags[ai][n]) {
|
||||
flag = deny_flags[ai][n];
|
||||
} else {
|
||||
//fprintf(stderr, "Adding deny ai %d mask 0x%x audit 0x%x\n", ai, mask, audit & mask);
|
||||
deny_flags[ai][n] = new DenyMatchFlag(mask, audit & mask);
|
||||
flag = deny_flags[ai][n];
|
||||
}
|
||||
} else if (mask & AA_EXEC_BITS) {
|
||||
uint32_t eperm = 0;
|
||||
uint32_t index = 0;
|
||||
if (mask & AA_USER_EXEC) {
|
||||
eperm = mask | (perms & AA_USER_EXEC_TYPE);
|
||||
index = EXTRACT_X_INDEX(eperm, AA_USER_SHIFT);
|
||||
} else {
|
||||
eperm = mask | (perms & AA_OTHER_EXEC_TYPE);
|
||||
index = EXTRACT_X_INDEX(eperm, AA_OTHER_SHIFT) + (AA_EXEC_COUNT << 2);
|
||||
}
|
||||
//fprintf(stderr, "index %d eperm 0x%x\n", index, eperm);
|
||||
if (exact_match) {
|
||||
if (exact_match_flags[ai][index]) {
|
||||
flag = exact_match_flags[ai][index];
|
||||
} else {
|
||||
exact_match_flags[ai][index] = new ExactMatchFlag(eperm, audit & mask);
|
||||
flag = exact_match_flags[ai][index];
|
||||
}
|
||||
} else {
|
||||
if (exec_match_flags[ai][index]) {
|
||||
flag = exec_match_flags[ai][index];
|
||||
} else {
|
||||
exec_match_flags[ai][index] = new MatchFlag(eperm, audit & mask);
|
||||
flag = exec_match_flags[ai][index];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (match_flags[ai][n]) {
|
||||
flag = match_flags[ai][n];
|
||||
} else {
|
||||
match_flags[ai][n] = new MatchFlag(mask, audit & mask);
|
||||
flag = match_flags[ai][n];
|
||||
}
|
||||
}
|
||||
if (accept)
|
||||
accept = new AltNode(accept, flag);
|
||||
else
|
||||
accept = flag;
|
||||
} /* for ... */
|
||||
|
||||
return accept;
|
||||
}
|
||||
|
||||
bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
||||
int count, const char **rulev, dfaflags_t flags)
|
||||
{
|
||||
|
@ -202,7 +99,7 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
|||
if (reverse)
|
||||
flip_tree(tree);
|
||||
|
||||
accept = convert_file_perms(deny, perms, audit, exact_match);
|
||||
accept = unique_perms.insert(deny, perms, audit, exact_match);
|
||||
|
||||
if (flags & DFA_DUMP_RULE_EXPR) {
|
||||
cerr << "rule: ";
|
||||
|
@ -235,6 +132,30 @@ void *aare_rules::create_dfa(size_t *size, dfaflags_t flags)
|
|||
{
|
||||
char *buffer = NULL;
|
||||
|
||||
/* finish constructing the expr tree from the different permission
|
||||
* set nodes */
|
||||
PermExprMap::iterator i = expr_map.begin();
|
||||
if (i != expr_map.end()) {
|
||||
if (flags & DFA_CONTROL_TREE_SIMPLE) {
|
||||
Node *tmp = simplify_tree(i->second, flags);
|
||||
root = new CatNode(tmp, i->first);
|
||||
} else
|
||||
root = new CatNode(i->second, i->first);
|
||||
for (i++; i != expr_map.end(); i++) {
|
||||
Node *tmp;
|
||||
if (flags & DFA_CONTROL_TREE_SIMPLE) {
|
||||
tmp = simplify_tree(i->second, flags);
|
||||
} else
|
||||
tmp = i->second;
|
||||
root = new AltNode(root, new CatNode(tmp, i->first));
|
||||
}
|
||||
}
|
||||
|
||||
/* dumping of the none simplified tree without -O no-expr-simplify
|
||||
* is broken because we need to build the tree above first, and
|
||||
* simplification is woven into the build. Reevaluate how to fix
|
||||
* this debug dump.
|
||||
*/
|
||||
label_nodes(root);
|
||||
if (flags & DFA_DUMP_TREE) {
|
||||
cerr << "\nDFA: Expression Tree\n";
|
||||
|
@ -243,7 +164,13 @@ void *aare_rules::create_dfa(size_t *size, dfaflags_t flags)
|
|||
}
|
||||
|
||||
if (flags & DFA_CONTROL_TREE_SIMPLE) {
|
||||
root = simplify_tree(root, flags);
|
||||
/* This is old total tree, simplification point
|
||||
* For now just do simplification up front. It gets most
|
||||
* of the benefit running on the smaller chains, and is
|
||||
* overall faster because there are less nodes. Reevaluate
|
||||
* once tree simplification is rewritten
|
||||
*/
|
||||
//root = simplify_tree(root, flags);
|
||||
|
||||
if (flags & DFA_DUMP_SIMPLE_TREE) {
|
||||
cerr << "\nDFA: Simplified Expression Tree\n";
|
||||
|
|
|
@ -26,14 +26,78 @@
|
|||
#include "apparmor_re.h"
|
||||
#include "expr-tree.h"
|
||||
|
||||
class UniquePerm {
|
||||
public:
|
||||
bool deny;
|
||||
bool exact_match;
|
||||
uint32_t perms;
|
||||
uint32_t audit;
|
||||
|
||||
bool operator<(UniquePerm const &rhs)const
|
||||
{
|
||||
if (deny == rhs.deny) {
|
||||
if (exact_match == rhs.exact_match) {
|
||||
if (perms == rhs.perms)
|
||||
return audit < rhs.audit;
|
||||
return perms < rhs.perms;
|
||||
}
|
||||
return exact_match;
|
||||
}
|
||||
return deny;
|
||||
}
|
||||
};
|
||||
|
||||
class UniquePermsCache {
|
||||
public:
|
||||
typedef map<UniquePerm, Node*> UniquePermMap;
|
||||
typedef UniquePermMap::iterator iterator;
|
||||
UniquePermMap nodes;
|
||||
|
||||
UniquePermsCache(void) { };
|
||||
~UniquePermsCache() { clear(); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (iterator i = nodes.begin(); i != nodes.end(); i++) {
|
||||
delete i->second;
|
||||
}
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
Node *insert(bool deny, uint32_t perms, uint32_t audit,
|
||||
bool exact_match)
|
||||
{
|
||||
UniquePerm tmp = { deny, exact_match, perms, audit };
|
||||
iterator res = nodes.find(tmp);
|
||||
if (res == nodes.end()) {
|
||||
Node *node;
|
||||
if (deny)
|
||||
node = new DenyMatchFlag(perms, audit);
|
||||
else if (exact_match)
|
||||
node = new ExactMatchFlag(perms, audit);
|
||||
else
|
||||
node = new MatchFlag(perms, audit);
|
||||
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
||||
if (val.second == false)
|
||||
return val.first->second;
|
||||
return node;
|
||||
}
|
||||
return res->second;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<Node *, Node *> PermExprMap;
|
||||
|
||||
class aare_rules {
|
||||
Node *root;
|
||||
void add_to_rules(Node *tree, Node *perms);
|
||||
public:
|
||||
UniquePermsCache unique_perms;
|
||||
PermExprMap expr_map;
|
||||
public:
|
||||
int reverse;
|
||||
int rule_count;
|
||||
aare_rules(): root(NULL), reverse(0), rule_count(0) { };
|
||||
aare_rules(int reverse): root(NULL), reverse(reverse), rule_count(0) { };
|
||||
aare_rules(void): root(NULL), unique_perms(), expr_map(), reverse(0), rule_count(0) { };
|
||||
aare_rules(int reverse): root(NULL), unique_perms(), expr_map(), reverse(reverse), rule_count(0) { };
|
||||
~aare_rules();
|
||||
|
||||
bool add_rule(const char *rule, int deny, uint32_t perms,
|
||||
|
@ -43,6 +107,4 @@ public:
|
|||
void *create_dfa(size_t *size, dfaflags_t flags);
|
||||
};
|
||||
|
||||
void aare_reset_matchflags(void);
|
||||
|
||||
#endif /* __LIBAA_RE_RULES_H */
|
||||
|
|
|
@ -100,7 +100,10 @@ struct cond_entry_list {
|
|||
struct cod_entry {
|
||||
char *ns;
|
||||
char *name;
|
||||
char *link_name;
|
||||
union {
|
||||
char *link_name;
|
||||
char *onexec;
|
||||
};
|
||||
char *nt_name;
|
||||
Profile *prof; /* Special profile defined
|
||||
* just for this executable */
|
||||
|
@ -333,7 +336,6 @@ extern int abort_on_error;
|
|||
extern int skip_bad_cache_rebuild;
|
||||
extern int mru_skip_cache;
|
||||
extern int debug_cache;
|
||||
extern struct timespec mru_tstamp;
|
||||
|
||||
/* provided by parser_lex.l (cannot be used in tst builds) */
|
||||
extern FILE *yyin;
|
||||
|
@ -359,8 +361,6 @@ extern int clear_and_convert_entry(std::string& buffer, char *entry);
|
|||
extern int process_regex(Profile *prof);
|
||||
extern int post_process_entry(struct cod_entry *entry);
|
||||
|
||||
extern void reset_regex(void);
|
||||
|
||||
extern int process_policydb(Profile *prof);
|
||||
|
||||
extern int process_policy_ents(Profile *prof);
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
@ -120,7 +119,7 @@ struct cb_struct {
|
|||
const char *filename;
|
||||
};
|
||||
|
||||
static int include_dir_cb(DIR *dir unused, const char *name, struct stat *st,
|
||||
static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *data)
|
||||
{
|
||||
struct cb_struct *d = (struct cb_struct *) data;
|
||||
|
@ -179,7 +178,7 @@ void include_filename(char *filename, int search)
|
|||
struct cb_struct data = { fullpath, filename };
|
||||
fclose(include_file);
|
||||
include_file = NULL;
|
||||
if (dirat_for_each(NULL, fullpath, &data, include_dir_cb)) {
|
||||
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
|
||||
yyerror(_("Could not process include directory"
|
||||
" '%s' in '%s'"), fullpath, filename);;
|
||||
}
|
||||
|
@ -443,7 +442,7 @@ LT_EQUAL <=
|
|||
|
||||
({IDS}|{QUOTED_ID}) {
|
||||
yylval.id = processid(yytext, yyleng);
|
||||
POP_AND_RETURN(TOK_ID);
|
||||
RETURN_TOKEN(TOK_ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,7 +611,7 @@ LT_EQUAL <=
|
|||
PUSH_AND_RETURN(state, token);
|
||||
}
|
||||
|
||||
<INITIAL,NETWORK_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE>{
|
||||
<INITIAL,NETWORK_MODE,RLIMIT_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE>{
|
||||
{END_OF_RULE} {
|
||||
if (YY_START != INITIAL)
|
||||
POP_NODUMP();
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
/* enable the following line to get voluminous debug info */
|
||||
/* #define DEBUG */
|
||||
|
@ -77,7 +76,7 @@ int abort_on_error = 0; /* stop processing profiles if error */
|
|||
int skip_bad_cache_rebuild = 0;
|
||||
int mru_skip_cache = 1;
|
||||
int debug_cache = 0;
|
||||
struct timespec mru_tstamp;
|
||||
struct timespec cache_tstamp, mru_policy_tstamp;
|
||||
|
||||
static char *apparmorfs = NULL;
|
||||
static char *cacheloc = NULL;
|
||||
|
@ -398,7 +397,7 @@ static int process_arg(int c, char *optarg)
|
|||
}
|
||||
break;
|
||||
case 'M':
|
||||
if (aa_features_new(&features, optarg)) {
|
||||
if (aa_features_new(&features, AT_FDCWD, optarg)) {
|
||||
fprintf(stderr,
|
||||
"Failed to load features from '%s': %m\n",
|
||||
optarg);
|
||||
|
@ -601,7 +600,7 @@ int process_binary(int option, aa_kernel_interface *kernel_interface,
|
|||
if (kernel_load) {
|
||||
if (option == OPTION_ADD) {
|
||||
retval = profilename ?
|
||||
aa_kernel_interface_load_policy_from_file(kernel_interface, profilename) :
|
||||
aa_kernel_interface_load_policy_from_file(kernel_interface, AT_FDCWD, profilename) :
|
||||
aa_kernel_interface_load_policy_from_fd(kernel_interface, 0);
|
||||
if (retval == -1) {
|
||||
retval = errno;
|
||||
|
@ -611,7 +610,7 @@ int process_binary(int option, aa_kernel_interface *kernel_interface,
|
|||
}
|
||||
} else if (option == OPTION_REPLACE) {
|
||||
retval = profilename ?
|
||||
aa_kernel_interface_replace_policy_from_file(kernel_interface, profilename) :
|
||||
aa_kernel_interface_replace_policy_from_file(kernel_interface, AT_FDCWD, profilename) :
|
||||
aa_kernel_interface_replace_policy_from_fd(kernel_interface, 0);
|
||||
if (retval == -1) {
|
||||
retval = errno;
|
||||
|
@ -646,12 +645,12 @@ int process_binary(int option, aa_kernel_interface *kernel_interface,
|
|||
|
||||
void reset_parser(const char *filename)
|
||||
{
|
||||
memset(&mru_tstamp, 0, sizeof(mru_tstamp));
|
||||
memset(&mru_policy_tstamp, 0, sizeof(mru_policy_tstamp));
|
||||
memset(&cache_tstamp, 0, sizeof(cache_tstamp));
|
||||
mru_skip_cache = 1;
|
||||
free_aliases();
|
||||
free_symtabs();
|
||||
free_policies();
|
||||
reset_regex();
|
||||
reset_include_stack(filename);
|
||||
}
|
||||
|
||||
|
@ -811,7 +810,7 @@ struct dir_cb_data {
|
|||
};
|
||||
|
||||
/* data - pointer to a dir_cb_data */
|
||||
static int profile_dir_cb(DIR *dir unused, const char *name, struct stat *st,
|
||||
static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -828,7 +827,7 @@ static int profile_dir_cb(DIR *dir unused, const char *name, struct stat *st,
|
|||
}
|
||||
|
||||
/* data - pointer to a dir_cb_data */
|
||||
static int binary_dir_cb(DIR *dir unused, const char *name, struct stat *st,
|
||||
static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -898,13 +897,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
if ((!skip_cache && (write_cache || !skip_read_cache)) ||
|
||||
force_clear_cache) {
|
||||
uint16_t max_caches = write_cache && cond_clear_cache ? 1 : 0;
|
||||
|
||||
if (!cacheloc && asprintf(&cacheloc, "%s/cache", basedir) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (force_clear_cache) {
|
||||
if (aa_policy_cache_remove(cacheloc)) {
|
||||
if (aa_policy_cache_remove(AT_FDCWD, cacheloc)) {
|
||||
PERROR(_("Failed to clear cache files (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
|
@ -916,31 +917,25 @@ int main(int argc, char *argv[])
|
|||
if (create_cache_dir)
|
||||
pwarn(_("The --create-cache-dir option is deprecated. Please use --write-cache.\n"));
|
||||
|
||||
retval = aa_policy_cache_new(&policy_cache, features, cacheloc,
|
||||
write_cache);
|
||||
retval = aa_policy_cache_new(&policy_cache, features,
|
||||
AT_FDCWD, cacheloc, max_caches);
|
||||
if (retval) {
|
||||
if (errno != ENOENT) {
|
||||
if (errno != ENOENT && errno != EEXIST) {
|
||||
PERROR(_("Failed setting up policy cache (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
write_cache = 0;
|
||||
skip_read_cache = 0;
|
||||
} else if (!aa_policy_cache_is_valid(policy_cache)) {
|
||||
if (write_cache && cond_clear_cache &&
|
||||
aa_policy_cache_create(policy_cache)) {
|
||||
if (show_cache)
|
||||
if (show_cache) {
|
||||
if (max_caches > 0)
|
||||
PERROR("Cache write disabled: Cannot create cache '%s': %m\n",
|
||||
cacheloc);
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
} else if (!write_cache || !cond_clear_cache) {
|
||||
if (show_cache)
|
||||
else
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid\n");
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
}
|
||||
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,14 +960,14 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (profilename && S_ISDIR(stat_file.st_mode)) {
|
||||
int (*cb)(DIR *dir, const char *name, struct stat *st,
|
||||
int (*cb)(int dirfd, const char *name, struct stat *st,
|
||||
void *data);
|
||||
struct dir_cb_data cb_data;
|
||||
|
||||
cb_data.dirname = profilename;
|
||||
cb_data.cachedir = cacheloc;
|
||||
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
||||
if ((retval = dirat_for_each(NULL, profilename,
|
||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||
&cb_data, cb))) {
|
||||
PDEBUG("Failed loading profiles from %s\n",
|
||||
profilename);
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
int is_blacklisted(const char *name, const char *path)
|
||||
{
|
||||
int retval = _aa_is_blacklisted(name, path);
|
||||
int retval = _aa_is_blacklisted(name);
|
||||
|
||||
if (retval == -1)
|
||||
PERROR("Ignoring: '%s'\n", path ? path : name);
|
||||
|
@ -332,7 +332,7 @@ reeval:
|
|||
case COD_READ_CHAR:
|
||||
if (read_implies_exec) {
|
||||
PDEBUG("Parsing mode: found %s READ imply X\n", mode_desc);
|
||||
mode |= AA_MAY_READ | AA_EXEC_MMAP;
|
||||
mode |= AA_MAY_READ | AA_OLD_EXEC_MMAP;
|
||||
} else {
|
||||
PDEBUG("Parsing mode: found %s READ\n", mode_desc);
|
||||
mode |= AA_MAY_READ;
|
||||
|
@ -355,12 +355,12 @@ reeval:
|
|||
|
||||
case COD_LINK_CHAR:
|
||||
PDEBUG("Parsing mode: found %s LINK\n", mode_desc);
|
||||
mode |= AA_MAY_LINK;
|
||||
mode |= AA_OLD_MAY_LINK;
|
||||
break;
|
||||
|
||||
case COD_LOCK_CHAR:
|
||||
PDEBUG("Parsing mode: found %s LOCK\n", mode_desc);
|
||||
mode |= AA_MAY_LOCK;
|
||||
mode |= AA_OLD_MAY_LOCK;
|
||||
break;
|
||||
|
||||
case COD_INHERIT_CHAR:
|
||||
|
@ -439,7 +439,7 @@ reeval:
|
|||
|
||||
case COD_MMAP_CHAR:
|
||||
PDEBUG("Parsing mode: found %s MMAP\n", mode_desc);
|
||||
mode |= AA_EXEC_MMAP;
|
||||
mode |= AA_OLD_EXEC_MMAP;
|
||||
break;
|
||||
|
||||
case COD_EXEC_CHAR:
|
||||
|
|
|
@ -492,6 +492,8 @@ static int process_profile_name_xmatch(Profile *prof)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int warn_change_profile = 1;
|
||||
|
||||
static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
||||
{
|
||||
std::string tbuf;
|
||||
|
@ -514,9 +516,9 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
* dfa states like it does for pcre
|
||||
*/
|
||||
if ((entry->mode >> AA_OTHER_SHIFT) & AA_EXEC_INHERIT)
|
||||
entry->mode |= AA_EXEC_MMAP << AA_OTHER_SHIFT;
|
||||
entry->mode |= AA_OLD_EXEC_MMAP << AA_OTHER_SHIFT;
|
||||
if ((entry->mode >> AA_USER_SHIFT) & AA_EXEC_INHERIT)
|
||||
entry->mode |= AA_EXEC_MMAP << AA_USER_SHIFT;
|
||||
entry->mode |= AA_OLD_EXEC_MMAP << AA_USER_SHIFT;
|
||||
|
||||
/* the link bit on the first pair entry should not get masked
|
||||
* out by a deny rule, as both pieces of the link pair must
|
||||
|
@ -530,8 +532,9 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
if (entry->deny) {
|
||||
if ((entry->mode & ~(AA_LINK_BITS | AA_CHANGE_PROFILE)) &&
|
||||
!dfarules->add_rule(tbuf.c_str(), entry->deny,
|
||||
entry->mode & ~AA_LINK_BITS,
|
||||
entry->audit & ~AA_LINK_BITS, dfaflags))
|
||||
entry->mode & ~(AA_LINK_BITS | AA_CHANGE_PROFILE),
|
||||
entry->audit & ~(AA_LINK_BITS | AA_CHANGE_PROFILE),
|
||||
dfaflags))
|
||||
return FALSE;
|
||||
} else if (entry->mode & ~AA_CHANGE_PROFILE) {
|
||||
if (!dfarules->add_rule(tbuf.c_str(), entry->deny, entry->mode,
|
||||
|
@ -562,11 +565,25 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
}
|
||||
if (entry->mode & AA_CHANGE_PROFILE) {
|
||||
const char *vec[3];
|
||||
std::string lbuf;
|
||||
std::string lbuf, xbuf;
|
||||
int index = 1;
|
||||
|
||||
/* allow change_profile for all execs */
|
||||
vec[0] = "/[^\\x00]*";
|
||||
if ((warnflags & WARN_RULE_DOWNGRADED) && entry->audit && warn_change_profile) {
|
||||
/* don't have profile name here, so until this code
|
||||
* gets refactored just throw out a generic warning
|
||||
*/
|
||||
fprintf(stderr, "Warning kernel does not support audit modifier for change_profile rule.\n");
|
||||
warn_change_profile = 0;
|
||||
}
|
||||
|
||||
if (entry->onexec) {
|
||||
ptype = convert_aaregex_to_pcre(entry->onexec, 0, glob_default, xbuf, &pos);
|
||||
if (ptype == ePatternInvalid)
|
||||
return FALSE;
|
||||
vec[0] = xbuf.c_str();
|
||||
} else
|
||||
/* allow change_profile for all execs */
|
||||
vec[0] = "/[^/\\x00][^\\x00]*";
|
||||
|
||||
if (entry->ns) {
|
||||
int pos;
|
||||
|
@ -576,12 +593,12 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
vec[index++] = tbuf.c_str();
|
||||
|
||||
/* regular change_profile rule */
|
||||
if (!dfarules->add_rule_vec(0, AA_CHANGE_PROFILE | AA_ONEXEC, 0, index - 1, &vec[1], dfaflags))
|
||||
if (!dfarules->add_rule_vec(entry->deny, AA_CHANGE_PROFILE | AA_ONEXEC, 0, index - 1, &vec[1], dfaflags))
|
||||
return FALSE;
|
||||
/* onexec rules - both rules are needed for onexec */
|
||||
if (!dfarules->add_rule_vec(0, AA_ONEXEC, 0, 1, vec, dfaflags))
|
||||
if (!dfarules->add_rule_vec(entry->deny, AA_ONEXEC, 0, 1, vec, dfaflags))
|
||||
return FALSE;
|
||||
if (!dfarules->add_rule_vec(0, AA_ONEXEC, 0, index, vec, dfaflags))
|
||||
if (!dfarules->add_rule_vec(entry->deny, AA_ONEXEC, 0, index, vec, dfaflags))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -762,8 +779,6 @@ int process_profile_policydb(Profile *prof)
|
|||
prof->policy.rules = NULL;
|
||||
}
|
||||
|
||||
aare_reset_matchflags();
|
||||
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
|
@ -773,11 +788,6 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
void reset_regex(void)
|
||||
{
|
||||
aare_reset_matchflags();
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
|
||||
#include "unit_test.h"
|
||||
|
|
|
@ -254,6 +254,11 @@ static int process_variables_in_entries(struct cod_entry *entry_list)
|
|||
error = expand_entry_variables(&entry->name);
|
||||
if (error)
|
||||
return error;
|
||||
if (entry->link_name) {
|
||||
error = expand_entry_variables(&entry->link_name);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -244,6 +244,7 @@ void add_local_entry(Profile *prof);
|
|||
%type <flags> flagval
|
||||
%type <cap> caps
|
||||
%type <cap> capability
|
||||
%type <id> change_profile_head
|
||||
%type <user_entry> change_profile
|
||||
%type <set_var> TOK_SET_VAR
|
||||
%type <bool_var> TOK_BOOL_VAR
|
||||
|
@ -258,6 +259,7 @@ void add_local_entry(Profile *prof);
|
|||
%type <boolean> opt_flags
|
||||
%type <boolean> opt_perm_mode
|
||||
%type <id> opt_ns
|
||||
%type <id> ns_id
|
||||
%type <id> opt_id
|
||||
%type <prefix> opt_prefix
|
||||
%type <fmode> dbus_perm
|
||||
|
@ -297,8 +299,10 @@ opt_profile_flag: { /* nothing */ $$ = 0; }
|
|||
| TOK_PROFILE { $$ = 1; }
|
||||
| hat_start { $$ = 2; }
|
||||
|
||||
ns_id: TOK_COLON id_or_var TOK_COLON { $$ = $2; }
|
||||
|
||||
opt_ns: { /* nothing */ $$ = NULL; }
|
||||
| TOK_COLON TOK_ID TOK_COLON { $$ = $2; }
|
||||
| ns_id { $$ = $1; }
|
||||
|
||||
opt_id: { /* nothing */ $$ = NULL; }
|
||||
| TOK_ID { $$ = $1; }
|
||||
|
@ -785,13 +789,23 @@ rules: rules opt_prefix unix_rule
|
|||
$$ = $1;
|
||||
}
|
||||
|
||||
rules: rules change_profile
|
||||
rules: rules opt_prefix change_profile
|
||||
{
|
||||
PDEBUG("matched: rules change_profile\n");
|
||||
PDEBUG("rules change_profile: (%s)\n", $2->name);
|
||||
if (!$2)
|
||||
PDEBUG("rules change_profile: (%s)\n", $3->name);
|
||||
if (!$3)
|
||||
yyerror(_("Assert: `change_profile' returned NULL."));
|
||||
add_entry_to_policy($1, $2);
|
||||
if ($2.owner)
|
||||
yyerror(_("owner prefix not allowed on unix rules"));
|
||||
if ($2.deny && $2.audit) {
|
||||
$3->deny = 1;
|
||||
} else if ($2.deny) {
|
||||
$3->deny = 1;
|
||||
$3->audit = $3->mode;
|
||||
} else if ($2.audit) {
|
||||
$3->audit = $3->mode;
|
||||
}
|
||||
add_entry_to_policy($1, $3);
|
||||
$$ = $1;
|
||||
};
|
||||
|
||||
|
@ -1043,11 +1057,11 @@ opt_named_transition:
|
|||
$$.ns = NULL;
|
||||
$$.name = $2;
|
||||
}
|
||||
| TOK_ARROW TOK_COLON id_or_var TOK_COLON id_or_var
|
||||
| TOK_ARROW ns_id id_or_var
|
||||
{
|
||||
$$.present = 1;
|
||||
$$.ns = $3;
|
||||
$$.name = $5;
|
||||
$$.ns = $2;
|
||||
$$.name = $3;
|
||||
};
|
||||
|
||||
rule: file_rule { $$ = $1; }
|
||||
|
@ -1120,7 +1134,7 @@ file_rule_tail: opt_unsafe id_or_var file_mode id_or_var
|
|||
yyerror(_("missing an end of line character? (entry: %s)"), $2);
|
||||
};
|
||||
|
||||
link_rule: TOK_LINK opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
|
||||
link_rule: TOK_LINK opt_subset_flag id_or_var TOK_ARROW id_or_var TOK_END_OF_RULE
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
|
||||
|
@ -1481,29 +1495,38 @@ file_mode: TOK_MODE
|
|||
free($1);
|
||||
}
|
||||
|
||||
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_ID TOK_END_OF_RULE
|
||||
change_profile_head: TOK_CHANGE_PROFILE opt_id
|
||||
{
|
||||
if ($2 && !($2[0] == '/' || strncmp($2, "@{", 2) == 0))
|
||||
yyerror(_("Exec condition must begin with '/'."));
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
change_profile: change_profile_head TOK_END_OF_RULE
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
PDEBUG("Matched change_profile: tok_id (%s)\n", $3);
|
||||
entry = new_entry(NULL, $3, AA_CHANGE_PROFILE, NULL);
|
||||
char *rule = strdup("**");
|
||||
if (!rule)
|
||||
yyerror(_("Memory allocation error."));
|
||||
PDEBUG("Matched change_profile,\n");
|
||||
entry = new_entry(NULL, rule, AA_CHANGE_PROFILE, $1);
|
||||
if (!entry)
|
||||
yyerror(_("Memory allocation error."));
|
||||
PDEBUG("change_profile,\n");
|
||||
$$ = entry;
|
||||
};
|
||||
|
||||
change_profile: change_profile_head TOK_ARROW opt_ns TOK_ID TOK_END_OF_RULE
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
PDEBUG("Matched change_profile: tok_id (:%s://%s)\n", $3 ? $3 : "", $4);
|
||||
entry = new_entry($3, $4, AA_CHANGE_PROFILE, $1);
|
||||
if (!entry)
|
||||
yyerror(_("Memory allocation error."));
|
||||
PDEBUG("change_profile.entry: (%s)\n", entry->name);
|
||||
$$ = entry;
|
||||
};
|
||||
|
||||
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $4, $6);
|
||||
entry = new_entry($4, $6, AA_CHANGE_PROFILE, NULL);
|
||||
if (!entry)
|
||||
yyerror(_("Memory allocation error."));
|
||||
PDEBUG("change_profile.entry: (%s)\n", entry->name);
|
||||
$$ = entry;
|
||||
};
|
||||
|
||||
|
||||
capability: TOK_CAPABILITY caps TOK_END_OF_RULE
|
||||
{
|
||||
if ($2 == 0) {
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "parser.h"
|
||||
|
@ -70,22 +72,27 @@ bool valid_cached_file_version(const char *cachename)
|
|||
}
|
||||
|
||||
|
||||
void set_mru_tstamp(struct timespec t)
|
||||
void set_cache_tstamp(struct timespec t)
|
||||
{
|
||||
mru_skip_cache = 0;
|
||||
mru_tstamp = t;
|
||||
cache_tstamp = t;
|
||||
}
|
||||
|
||||
void update_mru_tstamp(FILE *file, const char *name)
|
||||
{
|
||||
struct stat stat_file;
|
||||
if (fstat(fileno(file), &stat_file) || (mru_tstamp.tv_sec == 0 && mru_tstamp.tv_nsec == 0))
|
||||
if (fstat(fileno(file), &stat_file))
|
||||
return;
|
||||
if (mru_t_cmp(stat_file.st_mtim)) {
|
||||
if (tstamp_cmp(mru_policy_tstamp, stat_file.st_mtim) < 0)
|
||||
/* keep track of the most recent policy tstamp */
|
||||
mru_policy_tstamp = stat_file.st_mtim;
|
||||
if (tstamp_is_null(cache_tstamp))
|
||||
return;
|
||||
if (tstamp_cmp(stat_file.st_mtim, cache_tstamp) > 0) {
|
||||
if (debug_cache)
|
||||
pwarn("%s: file '%s' is newer than cache file\n", progname, name);
|
||||
mru_skip_cache = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *cache_filename(const char *cachedir, const char *basename)
|
||||
|
@ -109,7 +116,7 @@ void valid_read_cache(const char *cachename)
|
|||
if (stat(cachename, &stat_bin) == 0 &&
|
||||
stat_bin.st_size > 0) {
|
||||
if (valid_cached_file_version(cachename))
|
||||
set_mru_tstamp(stat_bin.st_ctim);
|
||||
set_cache_tstamp(stat_bin.st_mtim);
|
||||
else if (!cond_clear_cache)
|
||||
write_cache = 0;
|
||||
} else {
|
||||
|
@ -159,6 +166,12 @@ void install_cache(const char *cachetmpname, const char *cachename)
|
|||
/* Only install the generate cache file if it parsed correctly
|
||||
and did not have write/close errors */
|
||||
if (cachetmpname) {
|
||||
struct timeval t;
|
||||
/* set the mtime of the cache file to the most newest mtime
|
||||
* of policy files used to generate it
|
||||
*/
|
||||
TIMESPEC_TO_TIMEVAL(&t, &mru_policy_tstamp);
|
||||
utimes(cachetmpname, &t);
|
||||
if (rename(cachetmpname, cachename) < 0) {
|
||||
pwarn("Warning failed to write cache: %s\n", cachename);
|
||||
unlink(cachetmpname);
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
#ifndef __AA_POLICY_CACHE_H
|
||||
#define __AA_POLICY_CACHE_H
|
||||
|
||||
extern struct timespec mru_tstamp;
|
||||
extern struct timespec cache_tstamp, mru_policy_tstamp;
|
||||
|
||||
/* returns true if time is more recent than mru_tstamp */
|
||||
#define mru_t_cmp(a) \
|
||||
(((a).tv_sec == (mru_tstamp).tv_sec) ? \
|
||||
(a).tv_nsec > (mru_tstamp).tv_nsec : (a).tv_sec > (mru_tstamp).tv_sec)
|
||||
#define tstamp_cmp(a, b) \
|
||||
(((a).tv_sec == (b).tv_sec) ? \
|
||||
((a).tv_nsec - (b).tv_nsec) : \
|
||||
((a).tv_sec - (b).tv_sec))
|
||||
#define tstamp_is_null(a) ((a).tv_sec == 0 && (a).tv_nsec == 0)
|
||||
|
||||
extern int show_cache;
|
||||
extern int skip_cache;
|
||||
|
@ -36,7 +38,7 @@ extern int create_cache_dir; /* create the cache dir if missing? */
|
|||
extern int mru_skip_cache;
|
||||
extern int debug_cache;
|
||||
|
||||
void set_mru_tstamp(struct timespec t);
|
||||
void set_cache_tstamp(struct timespec t);
|
||||
void update_mru_tstamp(FILE *file, const char *path);
|
||||
bool valid_cached_file_version(const char *cachename);
|
||||
char *cache_filename(const char *cachedir, const char *basename);
|
||||
|
|
|
@ -458,6 +458,12 @@ verify_binary_equality "Deny of ungranted perm" \
|
|||
"/t { /foo/[abc] r, }"
|
||||
|
||||
|
||||
verify_binary_equality "change_profile == change_profile -> **" \
|
||||
"/t { change_profile, }" \
|
||||
"/t { change_profile -> **, }" \
|
||||
"/t { change_profile /**, }" \
|
||||
"/t { change_profile /** -> **, }"
|
||||
|
||||
if [ $fails -ne 0 -o $errors -ne 0 ]
|
||||
then
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||
|
|
7
parser/tst/simple_tests/change_profile/a_bare_ok_1.sd
Normal file
7
parser/tst/simple_tests/change_profile/a_bare_ok_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile,
|
||||
}
|
7
parser/tst/simple_tests/change_profile/a_ok_1.sd
Normal file
7
parser/tst/simple_tests/change_profile/a_ok_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> /bin/foo,
|
||||
}
|
7
parser/tst/simple_tests/change_profile/a_ok_2.sd
Normal file
7
parser/tst/simple_tests/change_profile/a_ok_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile to a hat
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> /bin/foo//bar,
|
||||
}
|
7
parser/tst/simple_tests/change_profile/a_ok_3.sd
Normal file
7
parser/tst/simple_tests/change_profile/a_ok_3.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with name space
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> :foo:/bin/foo,
|
||||
}
|
10
parser/tst/simple_tests/change_profile/a_ok_4.sd
Normal file
10
parser/tst/simple_tests/change_profile/a_ok_4.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with a variable (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> @{LIBVIRT}-foo,
|
||||
}
|
10
parser/tst/simple_tests/change_profile/a_ok_5.sd
Normal file
10
parser/tst/simple_tests/change_profile/a_ok_5.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with variable+regex (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> @{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
11
parser/tst/simple_tests/change_profile/a_ok_6.sd
Normal file
11
parser/tst/simple_tests/change_profile/a_ok_6.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> "/bin/foo",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> "/bin/ foo",
|
||||
}
|
11
parser/tst/simple_tests/change_profile/a_ok_7.sd
Normal file
11
parser/tst/simple_tests/change_profile/a_ok_7.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile to a hat with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> "/bin/foo//bar",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> "/bin/foo// bar",
|
||||
}
|
11
parser/tst/simple_tests/change_profile/a_ok_8.sd
Normal file
11
parser/tst/simple_tests/change_profile/a_ok_8.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with name space with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> ":foo:/bin/foo",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> ":foo:/bin/ foo",
|
||||
}
|
24
parser/tst/simple_tests/change_profile/a_re_ok_1.sd
Normal file
24
parser/tst/simple_tests/change_profile/a_re_ok_1.sd
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> /bin/*,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> /bin/**,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> /bin/?,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> /bin/[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> /bin/[^ab],
|
||||
}
|
||||
|
69
parser/tst/simple_tests/change_profile/a_re_ok_2.sd
Normal file
69
parser/tst/simple_tests/change_profile/a_re_ok_2.sd
Normal file
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile to a hat
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> /bin/foo//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> /bin/foo//ba*,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> /bin/foo//ba**,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> /bin/foo//ba?,
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> /bin/foo//ba[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> /bin/foo//ba[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> /bin/fo*//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> /bin/fo**//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit change_profile -> /bin/fo?//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> /bin/fo[ab]//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> /bin/fo[^ab]//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit change_profile -> /bin/fo*//ba*,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit change_profile -> /bin/fo**//ba**,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit change_profile -> /bin/fo?//ba?,
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit change_profile -> /bin/fo[ab]//ba[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo16 {
|
||||
audit change_profile -> /bin/fo[^ab]//ba[^ab],
|
||||
}
|
||||
|
||||
|
67
parser/tst/simple_tests/change_profile/a_re_ok_3.sd
Normal file
67
parser/tst/simple_tests/change_profile/a_re_ok_3.sd
Normal file
|
@ -0,0 +1,67 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with name space
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> :foo:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> :foo:/bin/fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> :foo:/bin/fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> :foo:/bin/fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> :foo:/bin/fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> :foo:/bin/fo[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> :fo*:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> :fo**:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit change_profile -> :fo?:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> :fo[ab]:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> :fo[^ab]:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit change_profile -> :fo*:/bin/fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit change_profile -> :fo**:/bin/fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit change_profile -> :fo?:/bin/fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit change_profile -> :fo[ab]:/bin/fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo16 {
|
||||
audit change_profile -> :fo[^ab]:/bin/fo[^ab],
|
||||
}
|
51
parser/tst/simple_tests/change_profile/a_re_ok_4.sd
Normal file
51
parser/tst/simple_tests/change_profile/a_re_ok_4.sd
Normal file
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with a variable (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
@{LIBVIRT_RE}="libvirt*"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> @{LIBVIRT}-fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> @{LIBVIRT}-fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> @{LIBVIRT}-fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> @{LIBVIRT}-fo[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> @{LIBVIRT}-fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> @{LIBVIRT_RE}-fo[^ab],
|
||||
}
|
25
parser/tst/simple_tests/change_profile/a_re_ok_5.sd
Normal file
25
parser/tst/simple_tests/change_profile/a_re_ok_5.sd
Normal file
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with just res
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> *,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> **,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> ?,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> [ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> [^ab],
|
||||
}
|
||||
|
65
parser/tst/simple_tests/change_profile/a_re_ok_6.sd
Normal file
65
parser/tst/simple_tests/change_profile/a_re_ok_6.sd
Normal file
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with just res, child profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> *//ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> **//ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> ?//ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> [ab]//ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> [^ab]//ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> ab//*,
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> ab//**,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> ab//?,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit change_profile -> ab//[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> ab//[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> *//*,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit change_profile -> **//*,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit change_profile -> ?//*,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit change_profile -> [ab]//*,
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit change_profile -> [^ab]//*,
|
||||
}
|
||||
|
65
parser/tst/simple_tests/change_profile/a_re_ok_7.sd
Normal file
65
parser/tst/simple_tests/change_profile/a_re_ok_7.sd
Normal file
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile with just re, namespace
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
|
||||
/usr/bin/foo {
|
||||
audit change_profile -> :ab:*,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit change_profile -> :ab:**,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit change_profile -> :ab:?,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit change_profile -> :ab:[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> :ab:[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> :*:ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> :**:ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> :?:ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit change_profile -> :[ab]:ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> :[^ab]:ab,
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> :*:*,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit change_profile -> :**:**,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit change_profile -> :?:?,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit change_profile -> :[ab]:[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit change_profile -> :[^ab]:[^ab],
|
||||
}
|
45
parser/tst/simple_tests/change_profile/a_re_ok_8.sd
Normal file
45
parser/tst/simple_tests/change_profile/a_re_ok_8.sd
Normal file
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
#=DESCRIPTION audit change_profile re with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit change_profile -> "/bin/*",
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit change_profile -> "/bin/**",
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit change_profile -> "/bin/[ab]",
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit change_profile -> "/bin/[^ab]",
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit change_profile -> "/bin/?ab",
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit change_profile -> "/bin/ *",
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit change_profile -> "/bin/ **",
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit change_profile -> "/bin/ [ab]",
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit change_profile -> "/bin/ [^ab]",
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit change_profile -> "/bin/ ?ab",
|
||||
}
|
||||
|
7
parser/tst/simple_tests/change_profile/aa_ok_1.sd
Normal file
7
parser/tst/simple_tests/change_profile/aa_ok_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> /bin/foo,
|
||||
}
|
7
parser/tst/simple_tests/change_profile/aa_ok_2.sd
Normal file
7
parser/tst/simple_tests/change_profile/aa_ok_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile to a hat
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> /bin/foo//bar,
|
||||
}
|
7
parser/tst/simple_tests/change_profile/aa_ok_3.sd
Normal file
7
parser/tst/simple_tests/change_profile/aa_ok_3.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with name space
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> :foo:/bin/foo,
|
||||
}
|
10
parser/tst/simple_tests/change_profile/aa_ok_4.sd
Normal file
10
parser/tst/simple_tests/change_profile/aa_ok_4.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with a variable (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> @{LIBVIRT}-foo,
|
||||
}
|
10
parser/tst/simple_tests/change_profile/aa_ok_5.sd
Normal file
10
parser/tst/simple_tests/change_profile/aa_ok_5.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with variable+regex (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> @{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
11
parser/tst/simple_tests/change_profile/aa_ok_6.sd
Normal file
11
parser/tst/simple_tests/change_profile/aa_ok_6.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> "/bin/foo",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> "/bin/ foo",
|
||||
}
|
11
parser/tst/simple_tests/change_profile/aa_ok_7.sd
Normal file
11
parser/tst/simple_tests/change_profile/aa_ok_7.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile to a hat with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> "/bin/foo//bar",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> "/bin/foo// bar",
|
||||
}
|
11
parser/tst/simple_tests/change_profile/aa_ok_8.sd
Normal file
11
parser/tst/simple_tests/change_profile/aa_ok_8.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with name space with quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> ":foo:/bin/foo",
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> ":foo:/bin/ foo",
|
||||
}
|
24
parser/tst/simple_tests/change_profile/aa_re_ok_1.sd
Normal file
24
parser/tst/simple_tests/change_profile/aa_re_ok_1.sd
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> /bin/*,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> /bin/**,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit allow change_profile -> /bin/?,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit allow change_profile -> /bin/[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit allow change_profile -> /bin/[^ab],
|
||||
}
|
||||
|
69
parser/tst/simple_tests/change_profile/aa_re_ok_2.sd
Normal file
69
parser/tst/simple_tests/change_profile/aa_re_ok_2.sd
Normal file
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile to a hat
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> /bin/foo//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> /bin/foo//ba*,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit allow change_profile -> /bin/foo//ba**,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit allow change_profile -> /bin/foo//ba?,
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit allow change_profile -> /bin/foo//ba[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit allow change_profile -> /bin/foo//ba[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit allow change_profile -> /bin/fo*//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit allow change_profile -> /bin/fo**//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit allow change_profile -> /bin/fo?//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit allow change_profile -> /bin/fo[ab]//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit allow change_profile -> /bin/fo[^ab]//bar,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit allow change_profile -> /bin/fo*//ba*,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit allow change_profile -> /bin/fo**//ba**,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit allow change_profile -> /bin/fo?//ba?,
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit allow change_profile -> /bin/fo[ab]//ba[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo16 {
|
||||
audit allow change_profile -> /bin/fo[^ab]//ba[^ab],
|
||||
}
|
||||
|
||||
|
67
parser/tst/simple_tests/change_profile/aa_re_ok_3.sd
Normal file
67
parser/tst/simple_tests/change_profile/aa_re_ok_3.sd
Normal file
|
@ -0,0 +1,67 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with name space
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> :foo:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> :foo:/bin/fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit allow change_profile -> :foo:/bin/fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit allow change_profile -> :foo:/bin/fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit allow change_profile -> :foo:/bin/fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit allow change_profile -> :foo:/bin/fo[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit allow change_profile -> :fo*:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit allow change_profile -> :fo**:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit allow change_profile -> :fo?:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit allow change_profile -> :fo[ab]:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit allow change_profile -> :fo[^ab]:/bin/foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo12 {
|
||||
audit allow change_profile -> :fo*:/bin/fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo13 {
|
||||
audit allow change_profile -> :fo**:/bin/fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo14 {
|
||||
audit allow change_profile -> :fo?:/bin/fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo15 {
|
||||
audit allow change_profile -> :fo[ab]:/bin/fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo16 {
|
||||
audit allow change_profile -> :fo[^ab]:/bin/fo[^ab],
|
||||
}
|
51
parser/tst/simple_tests/change_profile/aa_re_ok_4.sd
Normal file
51
parser/tst/simple_tests/change_profile/aa_re_ok_4.sd
Normal file
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with a variable (LP: #390810)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{LIBVIRT}="libvirt"
|
||||
@{LIBVIRT_RE}="libvirt*"
|
||||
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> @{LIBVIRT}-fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> @{LIBVIRT}-fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit allow change_profile -> @{LIBVIRT}-fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit allow change_profile -> @{LIBVIRT}-fo[^ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit allow change_profile -> @{LIBVIRT}-fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo6 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-foo,
|
||||
}
|
||||
|
||||
/usr/bin/foo7 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-fo*,
|
||||
}
|
||||
|
||||
/usr/bin/foo8 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-fo**,
|
||||
}
|
||||
|
||||
/usr/bin/foo9 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-fo?,
|
||||
}
|
||||
|
||||
/usr/bin/foo10 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-fo[ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo11 {
|
||||
audit allow change_profile -> @{LIBVIRT_RE}-fo[^ab],
|
||||
}
|
25
parser/tst/simple_tests/change_profile/aa_re_ok_5.sd
Normal file
25
parser/tst/simple_tests/change_profile/aa_re_ok_5.sd
Normal file
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
#=DESCRIPTION audit allow change_profile with just res
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
/usr/bin/foo {
|
||||
audit allow change_profile -> *,
|
||||
}
|
||||
|
||||
/usr/bin/foo2 {
|
||||
audit allow change_profile -> **,
|
||||
}
|
||||
|
||||
/usr/bin/foo3 {
|
||||
audit allow change_profile -> ?,
|
||||
}
|
||||
|
||||
/usr/bin/foo4 {
|
||||
audit allow change_profile -> [ab],
|
||||
}
|
||||
|
||||
/usr/bin/foo5 {
|
||||
audit allow change_profile -> [^ab],
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue