2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-30 05:47:59 +00:00

parser: add support for attach_disconnected.path

Add support for specifying the path prefix used when attach disconnected
is specified. The kernel supports prepending a different value than
/ when a path is disconnected. Expose through a profile flag.

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2020-10-20 03:53:06 -07:00
parent 65de34f462
commit b46b2662ff
20 changed files with 232 additions and 4 deletions

View File

@ -113,7 +113,9 @@ B<XATTR VALUE FILEGLOB> = I<FILEGLOB>
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')' B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted' | 'attach_disconnected' | 'chroot_relative' | 'debug' B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
| 'attach_disconnected' | 'attach_disconneced.path' |'chroot_relative'
| 'debug'
B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'unconfined' | 'prompt' B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'unconfined' | 'prompt'
@ -491,6 +493,10 @@ though they are part of the namespace. WARNING this mode is unsafe and
can result in aliasing and access to objects that should not be can result in aliasing and access to objects that should not be
allowed. Its intent is a debug and policy development tool. allowed. Its intent is a debug and policy development tool.
=item B<attach_disconnected.path> If attach_disconnected is in use
attach disconnected object to the supplied path instead of the root of
the namespace.
=item B<chroot_relative> This forces file names to be relative to a =item B<chroot_relative> This forces file names to be relative to a
chroot and behave as if the chroot is a mount namespace. chroot and behave as if the chroot is a mount namespace.

View File

@ -420,6 +420,12 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
} }
} }
/* added in 4.13, unfortunately there is no features flag */
if (profile->flags.disconnected_path) {
sd_write_string(buf, profile->flags.disconnected_path,
"disconnected");
}
sd_write_struct(buf, "flags"); sd_write_struct(buf, "flags");
/* used to be flags.debug, but that's no longer supported */ /* used to be flags.debug, but that's no longer supported */
sd_write_uint32(buf, profile->flags.flags); sd_write_uint32(buf, profile->flags.flags);

View File

@ -285,7 +285,20 @@ static int process_variables_in_name(Profile &prof)
int error = expand_entry_variables(&prof.name); int error = expand_entry_variables(&prof.name);
if (!error && prof.attachment) if (!error && prof.attachment)
error = expand_entry_variables(&prof.attachment); error = expand_entry_variables(&prof.attachment);
if (!error && prof.flags.disconnected_path) {
error = expand_entry_variables(&prof.flags.disconnected_path);
if (error)
return error;
filter_slashes(prof.flags.disconnected_path);
// TODO: semantic check should go somewhere else
if (prof.flags.disconnected_path[0] != '/')
yyerror(_("attach_disconnected_path value must begin with a /"));
int n = strlen(prof.flags.disconnected_path);
// removing trailing / */
while (n && prof.flags.disconnected_path[n-1] == '/')
prof.flags.disconnected_path[--n] = 0;
}
return error; return error;
} }

View File

@ -575,7 +575,7 @@ valuelist: valuelist TOK_VALUE
} }
flags: { /* nothing */ flags: { /* nothing */
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0 }; flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
$$ = fv; $$ = fv;
}; };
@ -627,7 +627,7 @@ flagvals: flagval
flagval: TOK_VALUE flagval: TOK_VALUE
{ {
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0 }; flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
enum profile_mode mode; enum profile_mode mode;
if (strcmp($1, "debug") == 0) { if (strcmp($1, "debug") == 0) {
@ -653,6 +653,9 @@ flagval: TOK_VALUE
fv.path |= PATH_CHROOT_NSATTACH; fv.path |= PATH_CHROOT_NSATTACH;
} else if (strcmp($1, "chroot_no_attach") == 0) { } else if (strcmp($1, "chroot_no_attach") == 0) {
fv.path |= PATH_CHROOT_NO_ATTACH; fv.path |= PATH_CHROOT_NO_ATTACH;
} else if (strncmp($1, "attach_disconnected.path=", 25) == 0) {
/* TODO: make this a proper parse */
fv.disconnected_path = strdup($1 + 25);
} else { } else {
yyerror(_("Invalid profile flag: %s."), $1); yyerror(_("Invalid profile flag: %s."), $1);
} }

View File

@ -107,6 +107,8 @@ Profile::~Profile()
free(name); free(name);
if (attachment) if (attachment)
free(attachment); free(attachment);
if (flags.disconnected_path)
free(flags.disconnected_path);
if (ns) if (ns)
free(ns); free(ns);
for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++) for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++)

View File

@ -121,6 +121,7 @@ public:
enum profile_mode mode; enum profile_mode mode;
int audit; int audit;
int path; int path;
char *disconnected_path;
ostream &dump(ostream &os) ostream &dump(ostream &os)
{ {
@ -132,6 +133,8 @@ public:
if (flags & FLAG_HAT) if (flags & FLAG_HAT)
os << ", Hat"; os << ", Hat";
if (disconnected_path)
os << ", attach_disconnected.path=" << disconnected_path;
os << "\n"; os << "\n";
return os; return os;
@ -222,7 +225,7 @@ public:
parent = NULL; parent = NULL;
flags = { 0, MODE_UNSPECIFIED, 0, 0 }; flags = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
rlimits = {0, {}}; rlimits = {0, {}};
std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL); std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL);

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=foo/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar/
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar/
/does/not/exist flags=(attach_disconnected.path=@{var}/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo//) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo/bar) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=/foo/@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=/foo/@{var}/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=@{var}/foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@ -164,6 +164,11 @@ exception_not_raised = (
'profile/flags/flags_bad54.sd', 'profile/flags/flags_bad54.sd',
'profile/flags/flags_bad55.sd', 'profile/flags/flags_bad55.sd',
'profile/flags/flags_bad56.sd', 'profile/flags/flags_bad56.sd',
'profile/flags/flags_bad_disconnected_path1.sd',
'profile/flags/flags_bad_disconnected_path2.sd',
'profile/flags/flags_bad_disconnected_path3.sd',
'profile/flags/flags_bad_disconnected_path4.sd',
'profile/flags/flags_bad_disconnected_path5.sd',
'profile/profile_ns_bad8.sd', # 'profile :ns/t' without terminating ':' 'profile/profile_ns_bad8.sd', # 'profile :ns/t' without terminating ':'
'ptrace/bad_05.sd', # actually contains a capability rule with invalid (ptrace-related) keyword 'ptrace/bad_05.sd', # actually contains a capability rule with invalid (ptrace-related) keyword
'ptrace/bad_06.sd', # actually contains a capability rule with invalid (ptrace-related) keyword 'ptrace/bad_06.sd', # actually contains a capability rule with invalid (ptrace-related) keyword