mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 23:05:11 +00:00
parser: add support for attach_disconnected.ipc flag
The attach_disconnected.ipc flag allows the use of disconnected paths on posix mqueues. This flag is a subset of attach_disconnected, and it does not allow disconnected paths for all files. Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
@@ -115,6 +115,7 @@ B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of
|
||||
|
||||
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
|
||||
| 'attach_disconnected' | 'attach_disconneced.path='I<ABS PATH> | 'chroot_relative'
|
||||
| 'attach_disconnected.ipc' | 'attach_disconnected.ipc='I<ABS PATH>
|
||||
| 'debug' | 'interruptible' | 'kill.signal='I<SIGNAL> | 'error='I<ERROR CODE>
|
||||
|
||||
B<ERROR CODE> = (case insensitive error code name starting with 'E'; see errno(3))
|
||||
@@ -560,6 +561,14 @@ allowed. Its intent is a debug and policy development tool.
|
||||
attach disconnected objects to the supplied path instead of the root of
|
||||
the namespace.
|
||||
|
||||
=item B<attach_disconnected.ipc> A subset of attach_disconnected, but specific
|
||||
for IPC namespaces. It allows attaching disconnected IPC paths without having
|
||||
to allow attaching all types of files.
|
||||
|
||||
=item B<attach_disconnected.ipc>=I<ABS PATH> Like attach_disconnected.ipc, but
|
||||
attach disconnected posix mqueue to the supplied path instead of the root of
|
||||
the namespace.
|
||||
|
||||
=item B<chroot_relative> This forces file names to be relative to a
|
||||
chroot and behave as if the chroot is a mount namespace.
|
||||
|
||||
|
@@ -189,7 +189,7 @@ extern int preprocess_only;
|
||||
#define PATH_DELEGATE_DELETED 0x20
|
||||
#define PATH_ATTACH 0x40
|
||||
#define PATH_NO_ATTACH 0x80
|
||||
|
||||
#define PATH_IPC_ATTACH 0x100
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -334,6 +334,7 @@ extern int features_supports_io_uring;
|
||||
extern int features_supports_flag_interruptible;
|
||||
extern int features_supports_flag_signal;
|
||||
extern int features_supports_flag_error;
|
||||
extern int features_supports_flag_disconnected_ipc;
|
||||
extern int kernel_supports_oob;
|
||||
extern int kernel_supports_promptdev;
|
||||
extern int kernel_supports_permstable32;
|
||||
|
@@ -86,6 +86,7 @@ int features_supports_io_uring = 0; /* kernel supports io_uring rules */
|
||||
int features_supports_flag_interruptible = 0;
|
||||
int features_supports_flag_signal = 0;
|
||||
int features_supports_flag_error = 0;
|
||||
int features_supports_flag_disconnected_ipc = 0; /* kernel supports disconnected paths for ipc ns */
|
||||
int kernel_supports_oob = 0; /* out of band transitions */
|
||||
int kernel_supports_promptdev = 0; /* prompt via audit perms */
|
||||
int kernel_supports_permstable32 = 0; /* extended permissions */
|
||||
|
@@ -474,6 +474,11 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
|
||||
"disconnected");
|
||||
}
|
||||
|
||||
if (profile->flags.disconnected_ipc && features_supports_flag_disconnected_ipc) {
|
||||
sd_write_string(buf, profile->flags.disconnected_ipc,
|
||||
"disconnected_ipc");
|
||||
}
|
||||
|
||||
if (profile->flags.signal && features_supports_flag_signal) {
|
||||
sd_write_name(buf, "kill");
|
||||
sd_write_uint32(buf, profile->flags.signal);
|
||||
@@ -500,6 +505,8 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
|
||||
flags |= 0x4;
|
||||
if (profile->flags.path & PATH_CHROOT_NSATTACH)
|
||||
flags |= 0x10;
|
||||
if (profile->flags.path & PATH_IPC_ATTACH)
|
||||
flags |= 0x20;
|
||||
|
||||
sd_write_name(buf, "path_flags");
|
||||
sd_write_uint32(buf, flags);
|
||||
|
@@ -991,6 +991,9 @@ void set_supported_features()
|
||||
features_supports_flag_error = features_intersect(kernel_features,
|
||||
policy_features,
|
||||
"policy/profile/error");
|
||||
features_supports_flag_disconnected_ipc = features_intersect(kernel_features,
|
||||
policy_features,
|
||||
"domain/disconnected.ipc");
|
||||
}
|
||||
|
||||
static bool do_print_cache_dir(aa_features *features, int dirfd, const char *path)
|
||||
|
@@ -272,6 +272,23 @@ static int process_variables_in_rules(Profile &prof)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int process_variable_in_attach_disconnected(char **disconnected)
|
||||
{
|
||||
int error = expand_entry_variables(disconnected);
|
||||
if (error)
|
||||
return error;
|
||||
filter_slashes(*disconnected);
|
||||
// TODO: semantic check should go somewhere else
|
||||
if ((*disconnected)[0] != '/')
|
||||
yyerror(_("attach_disconnected path must begin with a /"));
|
||||
int n = strlen(*disconnected);
|
||||
// removing trailing / */
|
||||
while (n && (*disconnected)[n-1] == '/')
|
||||
(*disconnected)[--n] = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int process_variables_in_name(Profile &prof)
|
||||
{
|
||||
/* this needs to be done before alias expansion, ie. altnames are
|
||||
@@ -280,20 +297,10 @@ static int process_variables_in_name(Profile &prof)
|
||||
int error = expand_entry_variables(&prof.name);
|
||||
if (!error && 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;
|
||||
|
||||
}
|
||||
if (!error && prof.flags.disconnected_path)
|
||||
error = process_variable_in_attach_disconnected(&prof.flags.disconnected_path);
|
||||
if (!error && prof.flags.disconnected_ipc)
|
||||
error = process_variable_in_attach_disconnected(&prof.flags.disconnected_ipc);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@@ -97,6 +97,8 @@ Profile::~Profile()
|
||||
free(attachment);
|
||||
if (flags.disconnected_path)
|
||||
free(flags.disconnected_path);
|
||||
if (flags.disconnected_ipc)
|
||||
free(flags.disconnected_ipc);
|
||||
if (ns)
|
||||
free(ns);
|
||||
for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++)
|
||||
|
@@ -159,6 +159,7 @@ public:
|
||||
int audit;
|
||||
int path;
|
||||
char *disconnected_path;
|
||||
char *disconnected_ipc;
|
||||
int signal;
|
||||
int error;
|
||||
|
||||
@@ -170,6 +171,7 @@ public:
|
||||
audit = 0;
|
||||
path = 0;
|
||||
disconnected_path = NULL;
|
||||
disconnected_ipc = NULL;
|
||||
signal = 0;
|
||||
error = 0;
|
||||
}
|
||||
@@ -216,6 +218,12 @@ public:
|
||||
yyerror("unknown error code specified for error=\'%s\'\n", str + 6);
|
||||
} else if (strcmp(str, "interruptible") == 0) {
|
||||
flags |= FLAG_INTERRUPTIBLE;
|
||||
} else if (strcmp(str, "attach_disconnected.ipc") == 0) {
|
||||
path |= PATH_IPC_ATTACH;
|
||||
} else if (strncmp(str, "attach_disconnected.ipc=", 24) == 0) {
|
||||
/* TODO: make this a proper parse */
|
||||
path |= PATH_IPC_ATTACH;
|
||||
disconnected_ipc = strdup(str + 24);
|
||||
} else {
|
||||
yyerror(_("Invalid profile flag: %s."), str);
|
||||
}
|
||||
@@ -237,6 +245,8 @@ public:
|
||||
os << ", kill.signal=" << signal;
|
||||
if (error)
|
||||
os << ", error=" << find_error_name_mapping(error);
|
||||
if (disconnected_ipc)
|
||||
os << ", attach_disconnected.ipc=" << disconnected_ipc;
|
||||
|
||||
if (flags & FLAG_PROMPT_COMPAT)
|
||||
os << ", prompt_dev";
|
||||
@@ -277,6 +287,9 @@ public:
|
||||
if ((path & (PATH_ATTACH | PATH_NO_ATTACH)) ==
|
||||
(PATH_ATTACH | PATH_NO_ATTACH))
|
||||
yyerror(_("Profile flag attach_disconnected conflicts with no_attach_disconnected"));
|
||||
if ((path & (PATH_IPC_ATTACH | PATH_NO_ATTACH)) ==
|
||||
(PATH_IPC_ATTACH | PATH_NO_ATTACH))
|
||||
yyerror(_("Profile flag attach_disconnected.ipc conflicts with no_attach_disconnected"));
|
||||
if ((path & (PATH_CHROOT_NSATTACH | PATH_CHROOT_NO_ATTACH)) ==
|
||||
(PATH_CHROOT_NSATTACH | PATH_CHROOT_NO_ATTACH))
|
||||
yyerror(_("Profile flag chroot_attach conflicts with chroot_no_attach"));
|
||||
@@ -291,6 +304,16 @@ public:
|
||||
disconnected_path = rhs.disconnected_path;
|
||||
}
|
||||
}
|
||||
if (rhs.disconnected_ipc) {
|
||||
if (disconnected_ipc) {
|
||||
if (strcmp(disconnected_ipc, rhs.disconnected_ipc) != 0) {
|
||||
yyerror(_("Profile flag attach_disconnected set to conflicting values: '%s' and '%s'"), disconnected_ipc, rhs.disconnected_ipc);
|
||||
}
|
||||
// same so do nothing
|
||||
} else {
|
||||
disconnected_ipc = rhs.disconnected_ipc;
|
||||
}
|
||||
}
|
||||
if (rhs.signal) {
|
||||
if (signal) {
|
||||
if (signal != rhs.signal) {
|
||||
|
Reference in New Issue
Block a user