TOMOYO: Simplify profile structure.
Remove global preference from profile structure in order to make code simpler. Due to this structure change, printk() warnings upon policy violation are temporarily disabled. They will be replaced by /sys/kernel/security/tomoyo/audit by next patch. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
0d2171d711
commit
d5ca1725ac
|
@ -11,16 +11,6 @@
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
static struct tomoyo_profile tomoyo_default_profile = {
|
|
||||||
.learning = &tomoyo_default_profile.preference,
|
|
||||||
.permissive = &tomoyo_default_profile.preference,
|
|
||||||
.enforcing = &tomoyo_default_profile.preference,
|
|
||||||
.preference.enforcing_verbose = true,
|
|
||||||
.preference.learning_max_entry = 2048,
|
|
||||||
.preference.learning_verbose = false,
|
|
||||||
.preference.permissive_verbose = true
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Profile version. Currently only 20090903 is defined. */
|
/* Profile version. Currently only 20090903 is defined. */
|
||||||
static unsigned int tomoyo_profile_version;
|
static unsigned int tomoyo_profile_version;
|
||||||
|
|
||||||
|
@ -61,6 +51,11 @@ static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
|
||||||
[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
|
[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* String table for PREFERENCE keyword. */
|
||||||
|
static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = {
|
||||||
|
[TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
|
||||||
|
};
|
||||||
|
|
||||||
/* Permit policy management by non-root user? */
|
/* Permit policy management by non-root user? */
|
||||||
static bool tomoyo_manage_by_non_root;
|
static bool tomoyo_manage_by_non_root;
|
||||||
|
|
||||||
|
@ -71,11 +66,22 @@ static bool tomoyo_manage_by_non_root;
|
||||||
*
|
*
|
||||||
* @value: Bool value.
|
* @value: Bool value.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
static const char *tomoyo_yesno(const unsigned int value)
|
static const char *tomoyo_yesno(const unsigned int value)
|
||||||
{
|
{
|
||||||
return value ? "yes" : "no";
|
return value ? "yes" : "no";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tomoyo_addprintf - strncat()-like-snprintf().
|
||||||
|
*
|
||||||
|
* @buffer: Buffer to write to. Must be '\0'-terminated.
|
||||||
|
* @len: Size of @buffer.
|
||||||
|
* @fmt: The printf()'s format string, followed by parameters.
|
||||||
|
*
|
||||||
|
* Returns nothing.
|
||||||
|
*/
|
||||||
static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
|
static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
@ -294,12 +300,10 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
|
||||||
ptr = tomoyo_profile_ptr[profile];
|
ptr = tomoyo_profile_ptr[profile];
|
||||||
if (!ptr && tomoyo_memory_ok(entry)) {
|
if (!ptr && tomoyo_memory_ok(entry)) {
|
||||||
ptr = entry;
|
ptr = entry;
|
||||||
ptr->learning = &tomoyo_default_profile.preference;
|
|
||||||
ptr->permissive = &tomoyo_default_profile.preference;
|
|
||||||
ptr->enforcing = &tomoyo_default_profile.preference;
|
|
||||||
ptr->default_config = TOMOYO_CONFIG_DISABLED;
|
ptr->default_config = TOMOYO_CONFIG_DISABLED;
|
||||||
memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
|
memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
|
||||||
sizeof(ptr->config));
|
sizeof(ptr->config));
|
||||||
|
ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048;
|
||||||
mb(); /* Avoid out-of-order execution. */
|
mb(); /* Avoid out-of-order execution. */
|
||||||
tomoyo_profile_ptr[profile] = ptr;
|
tomoyo_profile_ptr[profile] = ptr;
|
||||||
entry = NULL;
|
entry = NULL;
|
||||||
|
@ -319,13 +323,22 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
|
||||||
*/
|
*/
|
||||||
struct tomoyo_profile *tomoyo_profile(const u8 profile)
|
struct tomoyo_profile *tomoyo_profile(const u8 profile)
|
||||||
{
|
{
|
||||||
|
static struct tomoyo_profile tomoyo_null_profile;
|
||||||
struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
|
struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
|
||||||
if (!tomoyo_policy_loaded)
|
if (!ptr)
|
||||||
return &tomoyo_default_profile;
|
ptr = &tomoyo_null_profile;
|
||||||
BUG_ON(!ptr);
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tomoyo_find_yesno - Find values for specified keyword.
|
||||||
|
*
|
||||||
|
* @string: String to check.
|
||||||
|
* @find: Name of keyword.
|
||||||
|
*
|
||||||
|
* Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
static s8 tomoyo_find_yesno(const char *string, const char *find)
|
static s8 tomoyo_find_yesno(const char *string, const char *find)
|
||||||
{
|
{
|
||||||
const char *cp = strstr(string, find);
|
const char *cp = strstr(string, find);
|
||||||
|
@ -338,19 +351,17 @@ static s8 tomoyo_find_yesno(const char *string, const char *find)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static void tomoyo_set_bool(bool *b, const char *string, const char *find)
|
/**
|
||||||
{
|
* tomoyo_set_uint - Set value for specified preference.
|
||||||
switch (tomoyo_find_yesno(string, find)) {
|
*
|
||||||
case 1:
|
* @i: Pointer to "unsigned int".
|
||||||
*b = true;
|
* @string: String to check.
|
||||||
break;
|
* @find: Name of keyword.
|
||||||
case 0:
|
*
|
||||||
*b = false;
|
* Returns nothing.
|
||||||
break;
|
*/
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tomoyo_set_uint(unsigned int *i, const char *string,
|
static void tomoyo_set_uint(unsigned int *i, const char *string,
|
||||||
const char *find)
|
const char *find)
|
||||||
{
|
{
|
||||||
|
@ -359,51 +370,16 @@ static void tomoyo_set_uint(unsigned int *i, const char *string,
|
||||||
sscanf(cp + strlen(find), "=%u", i);
|
sscanf(cp + strlen(find), "=%u", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tomoyo_set_pref(const char *name, const char *value,
|
/**
|
||||||
const bool use_default,
|
* tomoyo_set_mode - Set mode for specified profile.
|
||||||
struct tomoyo_profile *profile)
|
*
|
||||||
{
|
* @name: Name of functionality.
|
||||||
struct tomoyo_preference **pref;
|
* @value: Mode for @name.
|
||||||
bool *verbose;
|
* @profile: Pointer to "struct tomoyo_profile".
|
||||||
if (!strcmp(name, "enforcing")) {
|
*
|
||||||
if (use_default) {
|
* Returns 0 on success, negative value otherwise.
|
||||||
pref = &profile->enforcing;
|
*/
|
||||||
goto set_default;
|
|
||||||
}
|
|
||||||
profile->enforcing = &profile->preference;
|
|
||||||
verbose = &profile->preference.enforcing_verbose;
|
|
||||||
goto set_verbose;
|
|
||||||
}
|
|
||||||
if (!strcmp(name, "permissive")) {
|
|
||||||
if (use_default) {
|
|
||||||
pref = &profile->permissive;
|
|
||||||
goto set_default;
|
|
||||||
}
|
|
||||||
profile->permissive = &profile->preference;
|
|
||||||
verbose = &profile->preference.permissive_verbose;
|
|
||||||
goto set_verbose;
|
|
||||||
}
|
|
||||||
if (!strcmp(name, "learning")) {
|
|
||||||
if (use_default) {
|
|
||||||
pref = &profile->learning;
|
|
||||||
goto set_default;
|
|
||||||
}
|
|
||||||
profile->learning = &profile->preference;
|
|
||||||
tomoyo_set_uint(&profile->preference.learning_max_entry, value,
|
|
||||||
"max_entry");
|
|
||||||
verbose = &profile->preference.learning_verbose;
|
|
||||||
goto set_verbose;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
set_default:
|
|
||||||
*pref = &tomoyo_default_profile.preference;
|
|
||||||
return;
|
|
||||||
set_verbose:
|
|
||||||
tomoyo_set_bool(verbose, value, "verbose");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tomoyo_set_mode(char *name, const char *value,
|
static int tomoyo_set_mode(char *name, const char *value,
|
||||||
const bool use_default,
|
|
||||||
struct tomoyo_profile *profile)
|
struct tomoyo_profile *profile)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
|
@ -425,7 +401,7 @@ static int tomoyo_set_mode(char *name, const char *value,
|
||||||
} else {
|
} else {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (use_default) {
|
if (strstr(value, "use_default")) {
|
||||||
config = TOMOYO_CONFIG_USE_DEFAULT;
|
config = TOMOYO_CONFIG_USE_DEFAULT;
|
||||||
} else {
|
} else {
|
||||||
u8 mode;
|
u8 mode;
|
||||||
|
@ -455,34 +431,21 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
|
||||||
{
|
{
|
||||||
char *data = head->write_buf;
|
char *data = head->write_buf;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool use_default = false;
|
|
||||||
char *cp;
|
char *cp;
|
||||||
struct tomoyo_profile *profile;
|
struct tomoyo_profile *profile;
|
||||||
if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
|
if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
|
||||||
return 0;
|
return 0;
|
||||||
i = simple_strtoul(data, &cp, 10);
|
i = simple_strtoul(data, &cp, 10);
|
||||||
if (data == cp) {
|
|
||||||
profile = &tomoyo_default_profile;
|
|
||||||
} else {
|
|
||||||
if (*cp != '-')
|
if (*cp != '-')
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
data = cp + 1;
|
data = cp + 1;
|
||||||
profile = tomoyo_assign_profile(i);
|
profile = tomoyo_assign_profile(i);
|
||||||
if (!profile)
|
if (!profile)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
cp = strchr(data, '=');
|
cp = strchr(data, '=');
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*cp++ = '\0';
|
*cp++ = '\0';
|
||||||
if (profile != &tomoyo_default_profile)
|
|
||||||
use_default = strstr(cp, "use_default") != NULL;
|
|
||||||
if (tomoyo_str_starts(&data, "PREFERENCE::")) {
|
|
||||||
tomoyo_set_pref(data, cp, use_default, profile);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (profile == &tomoyo_default_profile)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!strcmp(data, "COMMENT")) {
|
if (!strcmp(data, "COMMENT")) {
|
||||||
static DEFINE_SPINLOCK(lock);
|
static DEFINE_SPINLOCK(lock);
|
||||||
const struct tomoyo_path_info *new_comment
|
const struct tomoyo_path_info *new_comment
|
||||||
|
@ -497,48 +460,13 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
|
||||||
tomoyo_put_name(old_comment);
|
tomoyo_put_name(old_comment);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return tomoyo_set_mode(data, cp, use_default, profile);
|
if (!strcmp(data, "PREFERENCE")) {
|
||||||
}
|
for (i = 0; i < TOMOYO_MAX_PREF; i++)
|
||||||
|
tomoyo_set_uint(&profile->pref[i], cp,
|
||||||
static void tomoyo_print_preference(struct tomoyo_io_buffer *head,
|
tomoyo_pref_keywords[i]);
|
||||||
const int idx)
|
return 0;
|
||||||
{
|
|
||||||
struct tomoyo_preference *pref = &tomoyo_default_profile.preference;
|
|
||||||
const struct tomoyo_profile *profile = idx >= 0 ?
|
|
||||||
tomoyo_profile_ptr[idx] : NULL;
|
|
||||||
char buffer[16] = "";
|
|
||||||
if (profile) {
|
|
||||||
buffer[sizeof(buffer) - 1] = '\0';
|
|
||||||
snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
|
|
||||||
}
|
}
|
||||||
if (profile) {
|
return tomoyo_set_mode(data, cp, profile);
|
||||||
pref = profile->learning;
|
|
||||||
if (pref == &tomoyo_default_profile.preference)
|
|
||||||
goto skip1;
|
|
||||||
}
|
|
||||||
tomoyo_io_printf(head, "%sPREFERENCE::%s={ "
|
|
||||||
"verbose=%s max_entry=%u }\n",
|
|
||||||
buffer, "learning",
|
|
||||||
tomoyo_yesno(pref->learning_verbose),
|
|
||||||
pref->learning_max_entry);
|
|
||||||
skip1:
|
|
||||||
if (profile) {
|
|
||||||
pref = profile->permissive;
|
|
||||||
if (pref == &tomoyo_default_profile.preference)
|
|
||||||
goto skip2;
|
|
||||||
}
|
|
||||||
tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
|
|
||||||
buffer, "permissive",
|
|
||||||
tomoyo_yesno(pref->permissive_verbose));
|
|
||||||
skip2:
|
|
||||||
if (profile) {
|
|
||||||
pref = profile->enforcing;
|
|
||||||
if (pref == &tomoyo_default_profile.preference)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
|
|
||||||
buffer, "enforcing",
|
|
||||||
tomoyo_yesno(pref->enforcing_verbose));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
|
static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
|
||||||
|
@ -561,7 +489,6 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
|
||||||
switch (head->r.step) {
|
switch (head->r.step) {
|
||||||
case 0:
|
case 0:
|
||||||
tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
|
tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
|
||||||
tomoyo_print_preference(head, -1);
|
|
||||||
head->r.step++;
|
head->r.step++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -575,11 +502,18 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
|
u8 i;
|
||||||
const struct tomoyo_path_info *comment =
|
const struct tomoyo_path_info *comment =
|
||||||
profile->comment;
|
profile->comment;
|
||||||
tomoyo_io_printf(head, "%u-COMMENT=", index);
|
tomoyo_io_printf(head, "%u-COMMENT=", index);
|
||||||
tomoyo_set_string(head, comment ? comment->name : "");
|
tomoyo_set_string(head, comment ? comment->name : "");
|
||||||
tomoyo_set_lf(head);
|
tomoyo_set_lf(head);
|
||||||
|
tomoyo_io_printf(head, "%u-PREFERENCE={ ", index);
|
||||||
|
for (i = 0; i < TOMOYO_MAX_PREF; i++)
|
||||||
|
tomoyo_io_printf(head, "%s=%u ",
|
||||||
|
tomoyo_pref_keywords[i],
|
||||||
|
profile->pref[i]);
|
||||||
|
tomoyo_set_string(head, "}\n");
|
||||||
head->r.step++;
|
head->r.step++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -606,7 +540,6 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
|
||||||
}
|
}
|
||||||
if (head->r.bit == TOMOYO_MAX_MAC_INDEX
|
if (head->r.bit == TOMOYO_MAX_MAC_INDEX
|
||||||
+ TOMOYO_MAX_MAC_CATEGORY_INDEX) {
|
+ TOMOYO_MAX_MAC_CATEGORY_INDEX) {
|
||||||
tomoyo_print_preference(head, index);
|
|
||||||
head->r.index++;
|
head->r.index++;
|
||||||
head->r.step = 1;
|
head->r.step = 1;
|
||||||
}
|
}
|
||||||
|
@ -1777,7 +1710,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
|
||||||
static void tomoyo_read_version(struct tomoyo_io_buffer *head)
|
static void tomoyo_read_version(struct tomoyo_io_buffer *head)
|
||||||
{
|
{
|
||||||
if (!head->r.eof) {
|
if (!head->r.eof) {
|
||||||
tomoyo_io_printf(head, "2.3.0");
|
tomoyo_io_printf(head, "2.4.0");
|
||||||
head->r.eof = true;
|
head->r.eof = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,12 @@ enum tomoyo_mac_category_index {
|
||||||
*/
|
*/
|
||||||
#define TOMOYO_RETRY_REQUEST 1
|
#define TOMOYO_RETRY_REQUEST 1
|
||||||
|
|
||||||
|
/* Index numbers for profile's PREFERENCE values. */
|
||||||
|
enum tomoyo_pref_index {
|
||||||
|
TOMOYO_PREF_MAX_LEARNING_ENTRY,
|
||||||
|
TOMOYO_MAX_PREF
|
||||||
|
};
|
||||||
|
|
||||||
/********** Structure definitions. **********/
|
/********** Structure definitions. **********/
|
||||||
|
|
||||||
/* Common header for holding ACL entries. */
|
/* Common header for holding ACL entries. */
|
||||||
|
@ -497,6 +503,7 @@ struct tomoyo_profile {
|
||||||
struct tomoyo_preference preference;
|
struct tomoyo_preference preference;
|
||||||
u8 default_config;
|
u8 default_config;
|
||||||
u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX];
|
u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX];
|
||||||
|
unsigned int pref[TOMOYO_MAX_PREF];
|
||||||
};
|
};
|
||||||
|
|
||||||
/********** Function prototypes. **********/
|
/********** Function prototypes. **********/
|
||||||
|
|
|
@ -899,35 +899,10 @@ const char *tomoyo_last_word(const char *name)
|
||||||
*/
|
*/
|
||||||
void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
|
void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
/*
|
||||||
char *buffer;
|
* Temporarily disabled.
|
||||||
const struct tomoyo_domain_info * const domain = r->domain;
|
* Will be replaced with /sys/kernel/security/tomoyo/audit interface.
|
||||||
const struct tomoyo_profile *profile = tomoyo_profile(domain->profile);
|
*/
|
||||||
switch (r->mode) {
|
|
||||||
case TOMOYO_CONFIG_ENFORCING:
|
|
||||||
if (!profile->enforcing->enforcing_verbose)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
case TOMOYO_CONFIG_PERMISSIVE:
|
|
||||||
if (!profile->permissive->permissive_verbose)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
case TOMOYO_CONFIG_LEARNING:
|
|
||||||
if (!profile->learning->learning_verbose)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buffer = kmalloc(4096, GFP_NOFS);
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(buffer, 4095, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
buffer[4095] = '\0';
|
|
||||||
printk(KERN_WARNING "%s: Access %s denied for %s\n",
|
|
||||||
r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer,
|
|
||||||
tomoyo_last_word(domain->domainname->name));
|
|
||||||
kfree(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -978,13 +953,13 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
|
||||||
if (perm & (1 << i))
|
if (perm & (1 << i))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count < tomoyo_profile(domain->profile)->learning->
|
if (count < tomoyo_profile(domain->profile)->
|
||||||
learning_max_entry)
|
pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
|
||||||
return true;
|
return true;
|
||||||
if (!domain->quota_warned) {
|
if (!domain->quota_warned) {
|
||||||
domain->quota_warned = true;
|
domain->quota_warned = true;
|
||||||
printk(KERN_WARNING "TOMOYO-WARNING: "
|
printk(KERN_WARNING "TOMOYO-WARNING: "
|
||||||
"Domain '%s' has so many ACLs to hold. "
|
"Domain '%s' has too many ACLs to hold. "
|
||||||
"Stopped learning mode.\n", domain->domainname->name);
|
"Stopped learning mode.\n", domain->domainname->name);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue