* [PATCH] TOMOYO: Add recursive directory matching operator support.
@ 2009-11-24 13:00 Tetsuo Handa
2009-11-24 23:37 ` John Johansen
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Tetsuo Handa @ 2009-11-24 13:00 UTC (permalink / raw)
To: linux-security-module; +Cc: linux-kernel
TOMOYO 1.7.1 has recursive directory matching operator support.
I want to add it to TOMOYO for Linux 2.6.33 .
----------
[PATCH] TOMOYO: Add recursive directory matching operator support.
This patch introduces new operator /\{dir\}/ which matches
'/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ /dir/dir/dir/ ).
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
security/tomoyo/common.c | 200 ++++++++++++++++++++++++++++-------------------
security/tomoyo/common.h | 4
2 files changed, 121 insertions(+), 83 deletions(-)
--- security-testing-2.6.orig/security/tomoyo/common.c
+++ security-testing-2.6/security/tomoyo/common.c
@@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *
const s8 pattern_type, const s8 end_type,
const char *function)
{
+ const char *const start = filename;
+ bool in_repetition = false;
bool contains_pattern = false;
unsigned char c;
unsigned char d;
@@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *
if (c == '/')
goto out;
}
- while ((c = *filename++) != '\0') {
+ while (1) {
+ c = *filename++;
+ if (!c)
+ break;
if (c == '\\') {
- switch ((c = *filename++)) {
+ c = *filename++;
+ switch (c) {
case '\\': /* "\\" */
continue;
case '$': /* "\$" */
@@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *
break; /* Must not contain pattern */
contains_pattern = true;
continue;
+ case '{': /* "/\{" */
+ if (filename - 3 < start ||
+ *(filename - 3) != '/')
+ break;
+ if (pattern_type == -1)
+ break; /* Must not contain pattern */
+ contains_pattern = true;
+ in_repetition = true;
+ continue;
+ case '}': /* "\}/" */
+ if (*filename != '/')
+ break;
+ if (!in_repetition)
+ break;
+ in_repetition = false;
+ continue;
case '0': /* "\ooo" */
case '1':
case '2':
@@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *
continue; /* pattern is not \000 */
}
goto out;
+ } else if (in_repetition && c == '/') {
+ goto out;
} else if (tomoyo_is_invalid(c)) {
goto out;
}
@@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *
if (!contains_pattern)
goto out;
}
+ if (in_repetition)
+ goto out;
return true;
out:
printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
@@ -360,33 +386,6 @@ struct tomoyo_domain_info *tomoyo_find_d
}
/**
- * tomoyo_path_depth - Evaluate the number of '/' in a string.
- *
- * @pathname: The string to evaluate.
- *
- * Returns path depth of the string.
- *
- * I score 2 for each of the '/' in the @pathname
- * and score 1 if the @pathname ends with '/'.
- */
-static int tomoyo_path_depth(const char *pathname)
-{
- int i = 0;
-
- if (pathname) {
- const char *ep = pathname + strlen(pathname);
- if (pathname < ep--) {
- if (*ep != '/')
- i++;
- while (pathname <= ep)
- if (*ep-- == '/')
- i += 2;
- }
- }
- return i;
-}
-
-/**
* tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
*
* @filename: The string to evaluate.
@@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo
ptr->is_dir = len && (name[len - 1] == '/');
ptr->is_patterned = (ptr->const_len < len);
ptr->hash = full_name_hash(name, len);
- ptr->depth = tomoyo_path_depth(name);
}
/**
- * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
+ * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
* and "\-" pattern.
*
* @filename: The start of string to check.
@@ -458,10 +456,10 @@ void tomoyo_fill_path_info(struct tomoyo
*
* Returns true if @filename matches @pattern, false otherwise.
*/
-static bool tomoyo_file_matches_to_pattern2(const char *filename,
- const char *filename_end,
- const char *pattern,
- const char *pattern_end)
+static bool tomoyo_file_matches_pattern2(const char *filename,
+ const char *filename_end,
+ const char *pattern,
+ const char *pattern_end)
{
while (filename < filename_end && pattern < pattern_end) {
char c;
@@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_patte
case '*':
case '@':
for (i = 0; i <= filename_end - filename; i++) {
- if (tomoyo_file_matches_to_pattern2(
+ if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
@@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_patte
j++;
}
for (i = 1; i <= j; i++) {
- if (tomoyo_file_matches_to_pattern2(
+ if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
@@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_patte
}
/**
- * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
+ * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
*
* @filename: The start of string to check.
* @filename_end: The end of string to check.
@@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_patte
*
* Returns true if @filename matches @pattern, false otherwise.
*/
-static bool tomoyo_file_matches_to_pattern(const char *filename,
+static bool tomoyo_file_matches_pattern(const char *filename,
const char *filename_end,
const char *pattern,
const char *pattern_end)
@@ -589,10 +587,10 @@ static bool tomoyo_file_matches_to_patte
/* Split at "\-" pattern. */
if (*pattern++ != '\\' || *pattern++ != '-')
continue;
- result = tomoyo_file_matches_to_pattern2(filename,
- filename_end,
- pattern_start,
- pattern - 2);
+ result = tomoyo_file_matches_pattern2(filename,
+ filename_end,
+ pattern_start,
+ pattern - 2);
if (first)
result = !result;
if (result)
@@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_patte
first = false;
pattern_start = pattern;
}
- result = tomoyo_file_matches_to_pattern2(filename, filename_end,
- pattern_start, pattern_end);
+ result = tomoyo_file_matches_pattern2(filename, filename_end,
+ pattern_start, pattern_end);
return first ? result : !result;
}
/**
+ * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
+ *
+ * @f: The start of string to check.
+ * @p: The start of pattern to compare.
+ *
+ * Returns true if @f matches @p, false otherwise.
+ */
+static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
+{
+ const char *f_delimiter;
+ const char *p_delimiter;
+
+ while (*f && *p) {
+ f_delimiter = strchr(f, '/');
+ if (!f_delimiter)
+ f_delimiter = f + strlen(f);
+ p_delimiter = strchr(p, '/');
+ if (!p_delimiter)
+ p_delimiter = p + strlen(p);
+ if (*p == '\\' && *(p + 1) == '{')
+ goto recursive;
+ if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
+ p_delimiter))
+ return false;
+ f = f_delimiter;
+ if (*f)
+ f++;
+ p = p_delimiter;
+ if (*p)
+ p++;
+ }
+ /* Ignore trailing "\*" and "\@" in @pattern. */
+ while (*p == '\\' &&
+ (*(p + 1) == '*' || *(p + 1) == '@'))
+ p += 2;
+ return !*f && !*p;
+ recursive:
+ /*
+ * The "\{" pattern is permitted only after '/' character.
+ * This guarantees that below "*(p - 1)" is safe.
+ * Also, the "\}" pattern is permitted only before '/' character
+ * so that "\{" + "\}" pair will not break the "\-" operator.
+ */
+ if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
+ *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
+ return false; /* Bad pattern. */
+ do {
+ /* Compare current component with pattern. */
+ if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
+ p_delimiter - 2))
+ break;
+ /* Proceed to next component. */
+ f = f_delimiter;
+ if (!*f)
+ break;
+ f++;
+ /* Continue comparison. */
+ if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
+ return true;
+ f_delimiter = strchr(f, '/');
+ } while (f_delimiter);
+ return false; /* Not matched. */
+}
+
+/**
* tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
+ *
* @filename: The filename to check.
* @pattern: The pattern to compare.
*
@@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_patte
* The following patterns are available.
* \\ \ itself.
* \ooo Octal representation of a byte.
- * \* More than or equals to 0 character other than '/'.
- * \@ More than or equals to 0 character other than '/' or '.'.
+ * \* Zero or more repetitions of characters other than '/'.
+ * \@ Zero or more repetitions of characters other than '/' or '.'.
* \? 1 byte character other than '/'.
- * \$ More than or equals to 1 decimal digit.
+ * \$ One or more repetitions of decimal digits.
* \+ 1 decimal digit.
- * \X More than or equals to 1 hexadecimal digit.
+ * \X One or more repetitions of hexadecimal digits.
* \x 1 hexadecimal digit.
- * \A More than or equals to 1 alphabet character.
+ * \A One or more repetitions of alphabet characters.
* \a 1 alphabet character.
+ *
* \- Subtraction operator.
+ *
+ * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
+ * /dir/dir/dir/ ).
*/
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
const struct tomoyo_path_info *pattern)
{
- /*
- if (!filename || !pattern)
- return false;
- */
const char *f = filename->name;
const char *p = pattern->name;
const int len = pattern->const_len;
@@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const s
/* If @pattern doesn't contain pattern, I can use strcmp(). */
if (!pattern->is_patterned)
return !tomoyo_pathcmp(filename, pattern);
- /* Dont compare if the number of '/' differs. */
- if (filename->depth != pattern->depth)
+ /* Don't compare directory and non-directory. */
+ if (filename->is_dir != pattern->is_dir)
return false;
/* Compare the initial length without patterns. */
if (strncmp(f, p, len))
return false;
f += len;
p += len;
- /* Main loop. Compare each directory component. */
- while (*f && *p) {
- const char *f_delimiter = strchr(f, '/');
- const char *p_delimiter = strchr(p, '/');
- if (!f_delimiter)
- f_delimiter = f + strlen(f);
- if (!p_delimiter)
- p_delimiter = p + strlen(p);
- if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
- p, p_delimiter))
- return false;
- f = f_delimiter;
- if (*f)
- f++;
- p = p_delimiter;
- if (*p)
- p++;
- }
- /* Ignore trailing "\*" and "\@" in @pattern. */
- while (*p == '\\' &&
- (*(p + 1) == '*' || *(p + 1) == '@'))
- p += 2;
- return !*f && !*p;
+ return tomoyo_path_matches_pattern2(f, p);
}
/**
--- security-testing-2.6.orig/security/tomoyo/common.h
+++ security-testing-2.6/security/tomoyo/common.h
@@ -56,9 +56,6 @@ struct tomoyo_page_buffer {
* (5) "is_patterned" is a bool which is true if "name" contains wildcard
* characters, false otherwise. This allows TOMOYO to use "hash" and
* strcmp() for string comparison if "is_patterned" is false.
- * (6) "depth" is calculated using the number of "/" characters in "name".
- * This allows TOMOYO to avoid comparing two pathnames which never match
- * (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").
*/
struct tomoyo_path_info {
const char *name;
@@ -66,7 +63,6 @@ struct tomoyo_path_info {
u16 const_len; /* = tomoyo_const_part_length(name) */
bool is_dir; /* = tomoyo_strendswith(name, "/") */
bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
- u16 depth; /* = tomoyo_path_depth(name) */
};
/*
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] TOMOYO: Add recursive directory matching operator support.
2009-11-24 13:00 [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
@ 2009-11-24 23:37 ` John Johansen
2009-11-25 7:52 ` James Morris
2009-11-25 14:00 ` Serge E. Hallyn
2 siblings, 0 replies; 7+ messages in thread
From: John Johansen @ 2009-11-24 23:37 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: linux-security-module, linux-kernel
Tetsuo Handa wrote:
> TOMOYO 1.7.1 has recursive directory matching operator support.
> I want to add it to TOMOYO for Linux 2.6.33 .
> ----------
> [PATCH] TOMOYO: Add recursive directory matching operator support.
>
> This patch introduces new operator /\{dir\}/ which matches
> '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ /dir/dir/dir/ ).
>
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
I gave this a pass through and didn't see any problems with it
Acked-by: John Johansen <john.johansen@canonical.com>
> ---
> security/tomoyo/common.c | 200 ++++++++++++++++++++++++++++-------------------
> security/tomoyo/common.h | 4
> 2 files changed, 121 insertions(+), 83 deletions(-)
>
> --- security-testing-2.6.orig/security/tomoyo/common.c
> +++ security-testing-2.6/security/tomoyo/common.c
> @@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *
> const s8 pattern_type, const s8 end_type,
> const char *function)
> {
> + const char *const start = filename;
> + bool in_repetition = false;
> bool contains_pattern = false;
> unsigned char c;
> unsigned char d;
> @@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *
> if (c == '/')
> goto out;
> }
> - while ((c = *filename++) != '\0') {
> + while (1) {
> + c = *filename++;
> + if (!c)
> + break;
> if (c == '\\') {
> - switch ((c = *filename++)) {
> + c = *filename++;
> + switch (c) {
> case '\\': /* "\\" */
> continue;
> case '$': /* "\$" */
> @@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *
> break; /* Must not contain pattern */
> contains_pattern = true;
> continue;
> + case '{': /* "/\{" */
> + if (filename - 3 < start ||
> + *(filename - 3) != '/')
> + break;
> + if (pattern_type == -1)
> + break; /* Must not contain pattern */
> + contains_pattern = true;
> + in_repetition = true;
> + continue;
> + case '}': /* "\}/" */
> + if (*filename != '/')
> + break;
> + if (!in_repetition)
> + break;
> + in_repetition = false;
> + continue;
> case '0': /* "\ooo" */
> case '1':
> case '2':
> @@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *
> continue; /* pattern is not \000 */
> }
> goto out;
> + } else if (in_repetition && c == '/') {
> + goto out;
> } else if (tomoyo_is_invalid(c)) {
> goto out;
> }
> @@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *
> if (!contains_pattern)
> goto out;
> }
> + if (in_repetition)
> + goto out;
> return true;
> out:
> printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
> @@ -360,33 +386,6 @@ struct tomoyo_domain_info *tomoyo_find_d
> }
>
> /**
> - * tomoyo_path_depth - Evaluate the number of '/' in a string.
> - *
> - * @pathname: The string to evaluate.
> - *
> - * Returns path depth of the string.
> - *
> - * I score 2 for each of the '/' in the @pathname
> - * and score 1 if the @pathname ends with '/'.
> - */
> -static int tomoyo_path_depth(const char *pathname)
> -{
> - int i = 0;
> -
> - if (pathname) {
> - const char *ep = pathname + strlen(pathname);
> - if (pathname < ep--) {
> - if (*ep != '/')
> - i++;
> - while (pathname <= ep)
> - if (*ep-- == '/')
> - i += 2;
> - }
> - }
> - return i;
> -}
> -
> -/**
> * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
> *
> * @filename: The string to evaluate.
> @@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo
> ptr->is_dir = len && (name[len - 1] == '/');
> ptr->is_patterned = (ptr->const_len < len);
> ptr->hash = full_name_hash(name, len);
> - ptr->depth = tomoyo_path_depth(name);
> }
>
> /**
> - * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
> + * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
> * and "\-" pattern.
> *
> * @filename: The start of string to check.
> @@ -458,10 +456,10 @@ void tomoyo_fill_path_info(struct tomoyo
> *
> * Returns true if @filename matches @pattern, false otherwise.
> */
> -static bool tomoyo_file_matches_to_pattern2(const char *filename,
> - const char *filename_end,
> - const char *pattern,
> - const char *pattern_end)
> +static bool tomoyo_file_matches_pattern2(const char *filename,
> + const char *filename_end,
> + const char *pattern,
> + const char *pattern_end)
> {
> while (filename < filename_end && pattern < pattern_end) {
> char c;
> @@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_patte
> case '*':
> case '@':
> for (i = 0; i <= filename_end - filename; i++) {
> - if (tomoyo_file_matches_to_pattern2(
> + if (tomoyo_file_matches_pattern2(
> filename + i, filename_end,
> pattern + 1, pattern_end))
> return true;
> @@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_patte
> j++;
> }
> for (i = 1; i <= j; i++) {
> - if (tomoyo_file_matches_to_pattern2(
> + if (tomoyo_file_matches_pattern2(
> filename + i, filename_end,
> pattern + 1, pattern_end))
> return true;
> @@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_patte
> }
>
> /**
> - * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
> + * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
> *
> * @filename: The start of string to check.
> * @filename_end: The end of string to check.
> @@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_patte
> *
> * Returns true if @filename matches @pattern, false otherwise.
> */
> -static bool tomoyo_file_matches_to_pattern(const char *filename,
> +static bool tomoyo_file_matches_pattern(const char *filename,
> const char *filename_end,
> const char *pattern,
> const char *pattern_end)
> @@ -589,10 +587,10 @@ static bool tomoyo_file_matches_to_patte
> /* Split at "\-" pattern. */
> if (*pattern++ != '\\' || *pattern++ != '-')
> continue;
> - result = tomoyo_file_matches_to_pattern2(filename,
> - filename_end,
> - pattern_start,
> - pattern - 2);
> + result = tomoyo_file_matches_pattern2(filename,
> + filename_end,
> + pattern_start,
> + pattern - 2);
> if (first)
> result = !result;
> if (result)
> @@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_patte
> first = false;
> pattern_start = pattern;
> }
> - result = tomoyo_file_matches_to_pattern2(filename, filename_end,
> - pattern_start, pattern_end);
> + result = tomoyo_file_matches_pattern2(filename, filename_end,
> + pattern_start, pattern_end);
> return first ? result : !result;
> }
>
> /**
> + * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
> + *
> + * @f: The start of string to check.
> + * @p: The start of pattern to compare.
> + *
> + * Returns true if @f matches @p, false otherwise.
> + */
> +static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
> +{
> + const char *f_delimiter;
> + const char *p_delimiter;
> +
> + while (*f && *p) {
> + f_delimiter = strchr(f, '/');
> + if (!f_delimiter)
> + f_delimiter = f + strlen(f);
> + p_delimiter = strchr(p, '/');
> + if (!p_delimiter)
> + p_delimiter = p + strlen(p);
> + if (*p == '\\' && *(p + 1) == '{')
> + goto recursive;
> + if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
> + p_delimiter))
> + return false;
> + f = f_delimiter;
> + if (*f)
> + f++;
> + p = p_delimiter;
> + if (*p)
> + p++;
> + }
> + /* Ignore trailing "\*" and "\@" in @pattern. */
> + while (*p == '\\' &&
> + (*(p + 1) == '*' || *(p + 1) == '@'))
> + p += 2;
> + return !*f && !*p;
> + recursive:
> + /*
> + * The "\{" pattern is permitted only after '/' character.
> + * This guarantees that below "*(p - 1)" is safe.
> + * Also, the "\}" pattern is permitted only before '/' character
> + * so that "\{" + "\}" pair will not break the "\-" operator.
> + */
> + if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
> + *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
> + return false; /* Bad pattern. */
> + do {
> + /* Compare current component with pattern. */
> + if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
> + p_delimiter - 2))
> + break;
> + /* Proceed to next component. */
> + f = f_delimiter;
> + if (!*f)
> + break;
> + f++;
> + /* Continue comparison. */
> + if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
> + return true;
> + f_delimiter = strchr(f, '/');
> + } while (f_delimiter);
> + return false; /* Not matched. */
> +}
> +
> +/**
> * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
> + *
> * @filename: The filename to check.
> * @pattern: The pattern to compare.
> *
> @@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_patte
> * The following patterns are available.
> * \\ \ itself.
> * \ooo Octal representation of a byte.
> - * \* More than or equals to 0 character other than '/'.
> - * \@ More than or equals to 0 character other than '/' or '.'.
> + * \* Zero or more repetitions of characters other than '/'.
> + * \@ Zero or more repetitions of characters other than '/' or '.'.
> * \? 1 byte character other than '/'.
> - * \$ More than or equals to 1 decimal digit.
> + * \$ One or more repetitions of decimal digits.
> * \+ 1 decimal digit.
> - * \X More than or equals to 1 hexadecimal digit.
> + * \X One or more repetitions of hexadecimal digits.
> * \x 1 hexadecimal digit.
> - * \A More than or equals to 1 alphabet character.
> + * \A One or more repetitions of alphabet characters.
> * \a 1 alphabet character.
> + *
> * \- Subtraction operator.
> + *
> + * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
> + * /dir/dir/dir/ ).
> */
> bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
> const struct tomoyo_path_info *pattern)
> {
> - /*
> - if (!filename || !pattern)
> - return false;
> - */
> const char *f = filename->name;
> const char *p = pattern->name;
> const int len = pattern->const_len;
> @@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const s
> /* If @pattern doesn't contain pattern, I can use strcmp(). */
> if (!pattern->is_patterned)
> return !tomoyo_pathcmp(filename, pattern);
> - /* Dont compare if the number of '/' differs. */
> - if (filename->depth != pattern->depth)
> + /* Don't compare directory and non-directory. */
> + if (filename->is_dir != pattern->is_dir)
> return false;
> /* Compare the initial length without patterns. */
> if (strncmp(f, p, len))
> return false;
> f += len;
> p += len;
> - /* Main loop. Compare each directory component. */
> - while (*f && *p) {
> - const char *f_delimiter = strchr(f, '/');
> - const char *p_delimiter = strchr(p, '/');
> - if (!f_delimiter)
> - f_delimiter = f + strlen(f);
> - if (!p_delimiter)
> - p_delimiter = p + strlen(p);
> - if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
> - p, p_delimiter))
> - return false;
> - f = f_delimiter;
> - if (*f)
> - f++;
> - p = p_delimiter;
> - if (*p)
> - p++;
> - }
> - /* Ignore trailing "\*" and "\@" in @pattern. */
> - while (*p == '\\' &&
> - (*(p + 1) == '*' || *(p + 1) == '@'))
> - p += 2;
> - return !*f && !*p;
> + return tomoyo_path_matches_pattern2(f, p);
> }
>
> /**
> --- security-testing-2.6.orig/security/tomoyo/common.h
> +++ security-testing-2.6/security/tomoyo/common.h
> @@ -56,9 +56,6 @@ struct tomoyo_page_buffer {
> * (5) "is_patterned" is a bool which is true if "name" contains wildcard
> * characters, false otherwise. This allows TOMOYO to use "hash" and
> * strcmp() for string comparison if "is_patterned" is false.
> - * (6) "depth" is calculated using the number of "/" characters in "name".
> - * This allows TOMOYO to avoid comparing two pathnames which never match
> - * (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").
> */
> struct tomoyo_path_info {
> const char *name;
> @@ -66,7 +63,6 @@ struct tomoyo_path_info {
> u16 const_len; /* = tomoyo_const_part_length(name) */
> bool is_dir; /* = tomoyo_strendswith(name, "/") */
> bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
> - u16 depth; /* = tomoyo_path_depth(name) */
> };
>
> /*
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] TOMOYO: Add recursive directory matching operator support.
2009-11-24 13:00 [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
2009-11-24 23:37 ` John Johansen
@ 2009-11-25 7:52 ` James Morris
2009-11-25 14:00 ` Serge E. Hallyn
2 siblings, 0 replies; 7+ messages in thread
From: James Morris @ 2009-11-25 7:52 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: linux-security-module, linux-kernel
On Tue, 24 Nov 2009, Tetsuo Handa wrote:
> TOMOYO 1.7.1 has recursive directory matching operator support.
> I want to add it to TOMOYO for Linux 2.6.33 .
> ----------
> [PATCH] TOMOYO: Add recursive directory matching operator support.
>
> This patch introduces new operator /\{dir\}/ which matches
> '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ /dir/dir/dir/ ).
>
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Applied to
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next
--
James Morris
<jmorris@namei.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] TOMOYO: Add recursive directory matching operator support.
2009-11-24 13:00 [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
2009-11-24 23:37 ` John Johansen
2009-11-25 7:52 ` James Morris
@ 2009-11-25 14:00 ` Serge E. Hallyn
2009-11-25 14:59 ` [PATCH] TOMOYO: Add recursive directory matching operatorsupport Tetsuo Handa
2 siblings, 1 reply; 7+ messages in thread
From: Serge E. Hallyn @ 2009-11-25 14:00 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: linux-security-module, linux-kernel
Quoting Tetsuo Handa (penguin-kernel@I-love.SAKURA.ne.jp):
> TOMOYO 1.7.1 has recursive directory matching operator support.
> I want to add it to TOMOYO for Linux 2.6.33 .
> ----------
> [PATCH] TOMOYO: Add recursive directory matching operator support.
>
> This patch introduces new operator /\{dir\}/ which matches
> '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ /dir/dir/dir/ ).
As a unix admin, I expect something like
/{bin,sbin}/init
(or more likely /{s,}bin/init )
to mean match both /bin/init and /sbin/init. Are you sure you want to use
this syntax for 'in_repeating'?
-serge
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] TOMOYO: Add recursive directory matching operatorsupport.
2009-11-25 14:00 ` Serge E. Hallyn
@ 2009-11-25 14:59 ` Tetsuo Handa
2009-11-25 15:27 ` Serge E. Hallyn
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2009-11-25 14:59 UTC (permalink / raw)
To: serue; +Cc: linux-security-module, linux-kernel
Hello.
Serge E. Hallyn wrote:
> Are you sure you want to use this syntax for 'in_repeating'?
Yes.
I don't have a plan to implement conventional regular expressions.
There are many variants for regular expressions (e.g. shell, perl, sed) and
users likely use characters with special meaning without knowing.
TOMOYO treats a character as literal unless prefixed by '\' character so that
users who didn't know the meaning of a character don't get unwanted results.
> As a unix admin, I expect something like
>
> /{bin,sbin}/init
> (or more likely /{s,}bin/init )
>
> to mean match both /bin/init and /sbin/init.
You will be able to use
path_group ALL_INIT /bin/init
path_group ALL_INIT /sbin/init
+
allow_execute @ALL_INIT
in the future (hopefully in Linux 2.6.34).
^ permalink raw reply [flat|nested] 7+ messages in thread
* [TOMOYO #16 00/25] Starting TOMOYO 2.3
@ 2009-10-04 12:49 Tetsuo Handa
2009-10-04 12:49 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown() Tetsuo Handa
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2009-10-04 12:49 UTC (permalink / raw)
To: linux-security-module; +Cc: linux-kernel
Hello.
This is the beginning of TOMOYO 2.3. TOMOYO 2.2 (which is in kernel 2.6.30 and
later) is terribly lacking in functionality (e.g. no audit logs, no network).
I hope TOMOYO 2.3 can provide practically sufficient functionality.
This patchset provides almost all functionality in TOMOYO 1.7.0 except
(1) DAC before MAC checks for directory modification operations.
(2) Incoming UDP/RAW packet filtering.
(3) Signal transmission restriction.
(4) Many of non-posix capabilities support.
Since this patchset is not yet accepted, I haven't written documentation for
TOMOYO 2.3. You can see http://tomoyo.sourceforge.jp/1.7/policy-reference.html
instead.
Conventionally, patches should be submitted in the form of diff file.
But this time, I submit in the form of entire file due to amount of changes.
# diff -u security/tomoyo.2.2/realpath.c security/tomoyo/new-realpath.c | diffstat -f0
new-realpath.c | 609 186 + 423 - 0 !
1 file changed, 186 insertions(+), 423 deletions(-)
# wc -l security/tomoyo/new-realpath.c
251 security/tomoyo/new-realpath.c
# diff -u security/tomoyo.2.2/file.c security/tomoyo/new-file.c | diffstat -f0
new-file.c | 2472 1693 + 779 - 0 !
1 file changed, 1693 insertions(+), 779 deletions(-)
# wc -l security/tomoyo/new-file.c
2249 security/tomoyo/new-file.c
# diff -u security/tomoyo.2.2/domain.c security/tomoyo/new-domain.c | diffstat -f0
new-domain.c | 1322 877 + 445 - 0 !
1 file changed, 877 insertions(+), 445 deletions(-)
# wc -l security/tomoyo/new-domain.c
1354 security/tomoyo/new-domain.c
# diff -u security/tomoyo.2.2/tomoyo.c security/tomoyo/lsm.c | diffstat -f0
lsm.c | 492 350 + 142 - 0 !
1 file changed, 350 insertions(+), 142 deletions(-)
# wc -l security/tomoyo/lsm.c
523 security/tomoyo/lsm.c
# diff -Nur security/tomoyo.2.2/ security/tomoyo/ | diffstat -f0
Kconfig | 67 67 + 0 - 0 !
Makefile | 2 1 + 1 - 0 !
address_group.c | 270 270 + 0 - 0 !
audit.c | 561 561 + 0 - 0 !
capability.c | 141 141 + 0 - 0 !
common.c | 2276 0 + 2276 - 0 !
common.h | 461 0 + 461 - 0 !
condition.c | 1332 1332 + 0 - 0 !
domain.c | 922 0 + 922 - 0 !
environ.c | 232 232 + 0 - 0 !
file.c | 1335 0 + 1335 - 0 !
gc.c | 606 606 + 0 - 0 !
internal.h | 1317 1317 + 0 - 0 !
load_policy.c | 97 97 + 0 - 0 !
lsm.c | 523 523 + 0 - 0 !
memory.c | 391 391 + 0 - 0 !
mount.c | 366 366 + 0 - 0 !
network.c | 757 757 + 0 - 0 !
new-domain.c | 1354 1354 + 0 - 0 !
new-file.c | 2249 2249 + 0 - 0 !
new-realpath.c | 251 251 + 0 - 0 !
number_group.c | 212 212 + 0 - 0 !
path_group.c | 210 210 + 0 - 0 !
policy_io.c | 2734 2734 + 0 - 0 !
realpath.c | 488 0 + 488 - 0 !
realpath.h | 66 0 + 66 - 0 !
securityfs_if.c | 148 148 + 0 - 0 !
tomoyo.c | 315 0 + 315 - 0 !
tomoyo.h | 96 0 + 96 - 0 !
util.c | 1144 1144 + 0 - 0 !
30 files changed, 14963 insertions(+), 5960 deletions(-)
Regards.
--
^ permalink raw reply [flat|nested] 7+ messages in thread
* [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown().
2009-10-04 12:49 [TOMOYO #16 00/25] Starting TOMOYO 2.3 Tetsuo Handa
@ 2009-10-04 12:49 ` Tetsuo Handa
2009-10-08 17:10 ` John Johansen
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2009-10-04 12:49 UTC (permalink / raw)
To: linux-security-module; +Cc: linux-kernel, Tetsuo Handa
[-- Attachment #1: lsm-add-chmod-chown-hooks.patch --]
[-- Type: text/plain, Size: 7056 bytes --]
This patch allows pathname based LSM modules to check chmod()/chown()
operations. Since notify_change() does not receive "struct vfsmount *",
we add security_path_chmod() and security_path_chown() to the caller of
notify_change().
These hooks are used by TOMOYO.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
fs/open.c | 24 ++++++++++++++++++++----
include/linux/security.h | 30 ++++++++++++++++++++++++++++++
security/capability.c | 13 +++++++++++++
security/security.c | 15 +++++++++++++++
4 files changed, 78 insertions(+), 4 deletions(-)
--- security-testing-2.6.orig/fs/open.c
+++ security-testing-2.6/fs/open.c
@@ -616,6 +616,9 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
err = mnt_want_write_file(file);
if (err)
goto out_putf;
+ err = security_path_chmod(dentry, file->f_vfsmnt, mode);
+ if (err)
+ goto out_drop_write;
mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1)
mode = inode->i_mode;
@@ -623,6 +626,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
+out_drop_write:
mnt_drop_write(file->f_path.mnt);
out_putf:
fput(file);
@@ -645,6 +649,9 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
error = mnt_want_write(path.mnt);
if (error)
goto dput_and_out;
+ error = security_path_chmod(path.dentry, path.mnt, mode);
+ if (error)
+ goto out_drop_write;
mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1)
mode = inode->i_mode;
@@ -652,6 +659,7 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(path.dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
+out_drop_write:
mnt_drop_write(path.mnt);
dput_and_out:
path_put(&path);
@@ -700,7 +708,9 @@ SYSCALL_DEFINE3(chown, const char __user
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
- error = chown_common(path.dentry, user, group);
+ error = security_path_chown(&path, user, group);
+ if (!error)
+ error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
@@ -725,7 +735,9 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
- error = chown_common(path.dentry, user, group);
+ error = security_path_chown(&path, user, group);
+ if (!error)
+ error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
@@ -744,7 +756,9 @@ SYSCALL_DEFINE3(lchown, const char __use
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
- error = chown_common(path.dentry, user, group);
+ error = security_path_chown(&path, user, group);
+ if (!error)
+ error = chown_common(path.dentry, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
@@ -767,7 +781,9 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
goto out_fput;
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, user, group);
+ error = security_path_chown(&file->f_path, user, group);
+ if (!error)
+ error = chown_common(dentry, user, group);
mnt_drop_write(file->f_path.mnt);
out_fput:
fput(file);
--- security-testing-2.6.orig/include/linux/security.h
+++ security-testing-2.6/include/linux/security.h
@@ -447,6 +447,18 @@ static inline void security_free_mnt_opt
* @new_dir contains the path structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link.
* Return 0 if permission is granted.
+ * @path_chmod:
+ * Check for permission to change DAC's permission of a file or directory.
+ * @dentry contains the dentry structure.
+ * @mnt contains the vfsmnt structure.
+ * @mode contains DAC's mode.
+ * Return 0 if permission is granted.
+ * @path_chown:
+ * Check for permission to change owner/group of a file or directory.
+ * @path contains the path structure.
+ * @uid contains new owner's ID.
+ * @gid contains new group's ID.
+ * Return 0 if permission is granted.
* @inode_readlink:
* Check the permission to read the symbolic link.
* @dentry contains the dentry structure for the file link.
@@ -1488,6 +1500,9 @@ struct security_operations {
struct dentry *new_dentry);
int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry);
+ int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt,
+ mode_t mode);
+ int (*path_chown) (struct path *path, uid_t uid, gid_t gid);
#endif
int (*inode_alloc_security) (struct inode *inode);
@@ -2952,6 +2967,9 @@ int security_path_link(struct dentry *ol
struct dentry *new_dentry);
int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry);
+int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+ mode_t mode);
+int security_path_chown(struct path *path, uid_t uid, gid_t gid);
#else /* CONFIG_SECURITY_PATH */
static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
{
@@ -3001,6 +3019,18 @@ static inline int security_path_rename(s
{
return 0;
}
+
+static inline int security_path_chmod(struct dentry *dentry,
+ struct vfsmount *mnt,
+ mode_t mode)
+{
+ return 0;
+}
+
+static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY_PATH */
#ifdef CONFIG_KEYS
--- security-testing-2.6.orig/security/capability.c
+++ security-testing-2.6/security/capability.c
@@ -308,6 +308,17 @@ static int cap_path_truncate(struct path
{
return 0;
}
+
+static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+ mode_t mode)
+{
+ return 0;
+}
+
+static int cap_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+ return 0;
+}
#endif
static int cap_file_permission(struct file *file, int mask)
@@ -977,6 +988,8 @@ void security_fixup_ops(struct security_
set_to_cap_if_null(ops, path_link);
set_to_cap_if_null(ops, path_rename);
set_to_cap_if_null(ops, path_truncate);
+ set_to_cap_if_null(ops, path_chmod);
+ set_to_cap_if_null(ops, path_chown);
#endif
set_to_cap_if_null(ops, file_permission);
set_to_cap_if_null(ops, file_alloc_security);
--- security-testing-2.6.orig/security/security.c
+++ security-testing-2.6/security/security.c
@@ -434,6 +434,21 @@ int security_path_truncate(struct path *
return 0;
return security_ops->path_truncate(path, length, time_attrs);
}
+
+int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+ mode_t mode)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->path_chmod(dentry, mnt, mode);
+}
+
+int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+ return 0;
+ return security_ops->path_chown(path, uid, gid);
+}
#endif
int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
--
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown().
2009-10-04 12:49 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown() Tetsuo Handa
@ 2009-10-08 17:10 ` John Johansen
2009-10-12 1:04 ` James Morris
0 siblings, 1 reply; 7+ messages in thread
From: John Johansen @ 2009-10-08 17:10 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: linux-security-module, linux-kernel
Tetsuo Handa wrote:
> This patch allows pathname based LSM modules to check chmod()/chown()
> operations. Since notify_change() does not receive "struct vfsmount *",
> we add security_path_chmod() and security_path_chown() to the caller of
> notify_change().
>
> These hooks are used by TOMOYO.
This hooks would be useful for AppArmor as well.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown().
2009-10-08 17:10 ` John Johansen
@ 2009-10-12 1:04 ` James Morris
2009-10-13 11:34 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() andsecurity_path_chown() Tetsuo Handa
0 siblings, 1 reply; 7+ messages in thread
From: James Morris @ 2009-10-12 1:04 UTC (permalink / raw)
To: John Johansen; +Cc: Tetsuo Handa, linux-security-module, linux-kernel
On Thu, 8 Oct 2009, John Johansen wrote:
> Tetsuo Handa wrote:
> > This patch allows pathname based LSM modules to check chmod()/chown()
> > operations. Since notify_change() does not receive "struct vfsmount *",
> > we add security_path_chmod() and security_path_chown() to the caller of
> > notify_change().
> >
> > These hooks are used by TOMOYO.
>
> This hooks would be useful for AppArmor as well.
I've applied the first three patches to
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next
It would be good to see some more evidence of review for the remaining
patches.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [TOMOYO #16 01/25] LSM: Add security_path_chmod() andsecurity_path_chown().
2009-10-12 1:04 ` James Morris
@ 2009-10-13 11:34 ` Tetsuo Handa
2009-10-13 11:37 ` [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2009-10-13 11:34 UTC (permalink / raw)
To: jmorris; +Cc: linux-security-module, linux-kernel
James Morris wrote:
> On Thu, 8 Oct 2009, John Johansen wrote:
>
> > Tetsuo Handa wrote:
> > > This patch allows pathname based LSM modules to check chmod()/chown()
> > > operations. Since notify_change() does not receive "struct vfsmount *",
> > > we add security_path_chmod() and security_path_chown() to the caller of
> > > notify_change().
> > >
> > > These hooks are used by TOMOYO.
> >
> > This hooks would be useful for AppArmor as well.
>
>
> I've applied the first three patches to
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next
>
Thank you.
> It would be good to see some more evidence of review for the remaining
> patches.
Yes. I'm ready to submit first three patches.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] TOMOYO: Add recursive directory matching operator support.
2009-10-13 11:34 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() andsecurity_path_chown() Tetsuo Handa
@ 2009-10-13 11:37 ` Tetsuo Handa
0 siblings, 0 replies; 7+ messages in thread
From: Tetsuo Handa @ 2009-10-13 11:37 UTC (permalink / raw)
To: linux-security-module; +Cc: linux-kernel
[PATCH] TOMOYO: Add recursive directory matching operator support.
This patch introduces new operator /\{dir\}/ which matches
'/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ /dir/dir/dir/ ).
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
security/tomoyo/common.c | 200 ++++++++++++++++++++++++++++-------------------
security/tomoyo/common.h | 4
2 files changed, 121 insertions(+), 83 deletions(-)
--- security-testing-2.6.orig/security/tomoyo/common.c
+++ security-testing-2.6/security/tomoyo/common.c
@@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *
const s8 pattern_type, const s8 end_type,
const char *function)
{
+ const char *const start = filename;
+ bool in_repetition = false;
bool contains_pattern = false;
unsigned char c;
unsigned char d;
@@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *
if (c == '/')
goto out;
}
- while ((c = *filename++) != '\0') {
+ while (1) {
+ c = *filename++;
+ if (!c)
+ break;
if (c == '\\') {
- switch ((c = *filename++)) {
+ c = *filename++;
+ switch (c) {
case '\\': /* "\\" */
continue;
case '$': /* "\$" */
@@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *
break; /* Must not contain pattern */
contains_pattern = true;
continue;
+ case '{': /* "/\{" */
+ if (filename - 3 < start ||
+ *(filename - 3) != '/')
+ break;
+ if (pattern_type == -1)
+ break; /* Must not contain pattern */
+ contains_pattern = true;
+ in_repetition = true;
+ continue;
+ case '}': /* "\}/" */
+ if (*filename != '/')
+ break;
+ if (!in_repetition)
+ break;
+ in_repetition = false;
+ continue;
case '0': /* "\ooo" */
case '1':
case '2':
@@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *
continue; /* pattern is not \000 */
}
goto out;
+ } else if (in_repetition && c == '/') {
+ goto out;
} else if (tomoyo_is_invalid(c)) {
goto out;
}
@@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *
if (!contains_pattern)
goto out;
}
+ if (in_repetition)
+ goto out;
return true;
out:
printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
@@ -360,33 +386,6 @@ struct tomoyo_domain_info *tomoyo_find_d
}
/**
- * tomoyo_path_depth - Evaluate the number of '/' in a string.
- *
- * @pathname: The string to evaluate.
- *
- * Returns path depth of the string.
- *
- * I score 2 for each of the '/' in the @pathname
- * and score 1 if the @pathname ends with '/'.
- */
-static int tomoyo_path_depth(const char *pathname)
-{
- int i = 0;
-
- if (pathname) {
- const char *ep = pathname + strlen(pathname);
- if (pathname < ep--) {
- if (*ep != '/')
- i++;
- while (pathname <= ep)
- if (*ep-- == '/')
- i += 2;
- }
- }
- return i;
-}
-
-/**
* tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
*
* @filename: The string to evaluate.
@@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo
ptr->is_dir = len && (name[len - 1] == '/');
ptr->is_patterned = (ptr->const_len < len);
ptr->hash = full_name_hash(name, len);
- ptr->depth = tomoyo_path_depth(name);
}
/**
- * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
+ * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
* and "\-" pattern.
*
* @filename: The start of string to check.
@@ -458,10 +456,10 @@ void tomoyo_fill_path_info(struct tomoyo
*
* Returns true if @filename matches @pattern, false otherwise.
*/
-static bool tomoyo_file_matches_to_pattern2(const char *filename,
- const char *filename_end,
- const char *pattern,
- const char *pattern_end)
+static bool tomoyo_file_matches_pattern2(const char *filename,
+ const char *filename_end,
+ const char *pattern,
+ const char *pattern_end)
{
while (filename < filename_end && pattern < pattern_end) {
char c;
@@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_patte
case '*':
case '@':
for (i = 0; i <= filename_end - filename; i++) {
- if (tomoyo_file_matches_to_pattern2(
+ if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
@@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_patte
j++;
}
for (i = 1; i <= j; i++) {
- if (tomoyo_file_matches_to_pattern2(
+ if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
@@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_patte
}
/**
- * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
+ * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
*
* @filename: The start of string to check.
* @filename_end: The end of string to check.
@@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_patte
*
* Returns true if @filename matches @pattern, false otherwise.
*/
-static bool tomoyo_file_matches_to_pattern(const char *filename,
+static bool tomoyo_file_matches_pattern(const char *filename,
const char *filename_end,
const char *pattern,
const char *pattern_end)
@@ -589,10 +587,10 @@ static bool tomoyo_file_matches_to_patte
/* Split at "\-" pattern. */
if (*pattern++ != '\\' || *pattern++ != '-')
continue;
- result = tomoyo_file_matches_to_pattern2(filename,
- filename_end,
- pattern_start,
- pattern - 2);
+ result = tomoyo_file_matches_pattern2(filename,
+ filename_end,
+ pattern_start,
+ pattern - 2);
if (first)
result = !result;
if (result)
@@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_patte
first = false;
pattern_start = pattern;
}
- result = tomoyo_file_matches_to_pattern2(filename, filename_end,
- pattern_start, pattern_end);
+ result = tomoyo_file_matches_pattern2(filename, filename_end,
+ pattern_start, pattern_end);
return first ? result : !result;
}
/**
+ * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
+ *
+ * @f: The start of string to check.
+ * @p: The start of pattern to compare.
+ *
+ * Returns true if @f matches @p, false otherwise.
+ */
+static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
+{
+ const char *f_delimiter;
+ const char *p_delimiter;
+
+ while (*f && *p) {
+ f_delimiter = strchr(f, '/');
+ if (!f_delimiter)
+ f_delimiter = f + strlen(f);
+ p_delimiter = strchr(p, '/');
+ if (!p_delimiter)
+ p_delimiter = p + strlen(p);
+ if (*p == '\\' && *(p + 1) == '{')
+ goto recursive;
+ if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
+ p_delimiter))
+ return false;
+ f = f_delimiter;
+ if (*f)
+ f++;
+ p = p_delimiter;
+ if (*p)
+ p++;
+ }
+ /* Ignore trailing "\*" and "\@" in @pattern. */
+ while (*p == '\\' &&
+ (*(p + 1) == '*' || *(p + 1) == '@'))
+ p += 2;
+ return !*f && !*p;
+ recursive:
+ /*
+ * The "\{" pattern is permitted only after '/' character.
+ * This guarantees that below "*(p - 1)" is safe.
+ * Also, the "\}" pattern is permitted only before '/' character
+ * so that "\{" + "\}" pair will not break the "\-" operator.
+ */
+ if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
+ *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
+ return false; /* Bad pattern. */
+ do {
+ /* Compare current component with pattern. */
+ if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
+ p_delimiter - 2))
+ break;
+ /* Proceed to next component. */
+ f = f_delimiter;
+ if (!*f)
+ break;
+ f++;
+ /* Continue comparison. */
+ if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
+ return true;
+ f_delimiter = strchr(f, '/');
+ } while (f_delimiter);
+ return false; /* Not matched. */
+}
+
+/**
* tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
+ *
* @filename: The filename to check.
* @pattern: The pattern to compare.
*
@@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_patte
* The following patterns are available.
* \\ \ itself.
* \ooo Octal representation of a byte.
- * \* More than or equals to 0 character other than '/'.
- * \@ More than or equals to 0 character other than '/' or '.'.
+ * \* Zero or more repetitions of characters other than '/'.
+ * \@ Zero or more repetitions of characters other than '/' or '.'.
* \? 1 byte character other than '/'.
- * \$ More than or equals to 1 decimal digit.
+ * \$ One or more repetitions of decimal digits.
* \+ 1 decimal digit.
- * \X More than or equals to 1 hexadecimal digit.
+ * \X One or more repetitions of hexadecimal digits.
* \x 1 hexadecimal digit.
- * \A More than or equals to 1 alphabet character.
+ * \A One or more repetitions of alphabet characters.
* \a 1 alphabet character.
+ *
* \- Subtraction operator.
+ *
+ * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
+ * /dir/dir/dir/ ).
*/
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
const struct tomoyo_path_info *pattern)
{
- /*
- if (!filename || !pattern)
- return false;
- */
const char *f = filename->name;
const char *p = pattern->name;
const int len = pattern->const_len;
@@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const s
/* If @pattern doesn't contain pattern, I can use strcmp(). */
if (!pattern->is_patterned)
return !tomoyo_pathcmp(filename, pattern);
- /* Dont compare if the number of '/' differs. */
- if (filename->depth != pattern->depth)
+ /* Don't compare directory and non-directory. */
+ if (filename->is_dir != pattern->is_dir)
return false;
/* Compare the initial length without patterns. */
if (strncmp(f, p, len))
return false;
f += len;
p += len;
- /* Main loop. Compare each directory component. */
- while (*f && *p) {
- const char *f_delimiter = strchr(f, '/');
- const char *p_delimiter = strchr(p, '/');
- if (!f_delimiter)
- f_delimiter = f + strlen(f);
- if (!p_delimiter)
- p_delimiter = p + strlen(p);
- if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
- p, p_delimiter))
- return false;
- f = f_delimiter;
- if (*f)
- f++;
- p = p_delimiter;
- if (*p)
- p++;
- }
- /* Ignore trailing "\*" and "\@" in @pattern. */
- while (*p == '\\' &&
- (*(p + 1) == '*' || *(p + 1) == '@'))
- p += 2;
- return !*f && !*p;
+ return tomoyo_path_matches_pattern2(f, p);
}
/**
--- security-testing-2.6.orig/security/tomoyo/common.h
+++ security-testing-2.6/security/tomoyo/common.h
@@ -56,9 +56,6 @@ struct tomoyo_page_buffer {
* (5) "is_patterned" is a bool which is true if "name" contains wildcard
* characters, false otherwise. This allows TOMOYO to use "hash" and
* strcmp() for string comparison if "is_patterned" is false.
- * (6) "depth" is calculated using the number of "/" characters in "name".
- * This allows TOMOYO to avoid comparing two pathnames which never match
- * (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").
*/
struct tomoyo_path_info {
const char *name;
@@ -66,7 +63,6 @@ struct tomoyo_path_info {
u16 const_len; /* = tomoyo_const_part_length(name) */
bool is_dir; /* = tomoyo_strendswith(name, "/") */
bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
- u16 depth; /* = tomoyo_path_depth(name) */
};
/*
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-11-25 15:28 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-24 13:00 [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
2009-11-24 23:37 ` John Johansen
2009-11-25 7:52 ` James Morris
2009-11-25 14:00 ` Serge E. Hallyn
2009-11-25 14:59 ` [PATCH] TOMOYO: Add recursive directory matching operatorsupport Tetsuo Handa
2009-11-25 15:27 ` Serge E. Hallyn
-- strict thread matches above, loose matches on Subject: below --
2009-10-04 12:49 [TOMOYO #16 00/25] Starting TOMOYO 2.3 Tetsuo Handa
2009-10-04 12:49 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() and security_path_chown() Tetsuo Handa
2009-10-08 17:10 ` John Johansen
2009-10-12 1:04 ` James Morris
2009-10-13 11:34 ` [TOMOYO #16 01/25] LSM: Add security_path_chmod() andsecurity_path_chown() Tetsuo Handa
2009-10-13 11:37 ` [PATCH] TOMOYO: Add recursive directory matching operator support Tetsuo Handa
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.