aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/util.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2020-09-09 20:05:58 +0900
committerTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2020-09-09 20:05:58 +0900
commit5384d92e4e02661d2b08e9e20c7b2cd3b0b82db6 (patch)
tree400f0328ef79bf6647b195d117fa20f82fbb4c0d /security/tomoyo/util.c
parentLinux 5.9-rc4 (diff)
downloadlinux-dev-5384d92e4e02661d2b08e9e20c7b2cd3b0b82db6.tar.xz
linux-dev-5384d92e4e02661d2b08e9e20c7b2cd3b0b82db6.zip
tomoyo: Loosen pathname/domainname validation.
Since commit e2dc9bf3f5275ca3 ("umd: Transform fork_usermode_blob into fork_usermode_driver") started calling execve() on a program written in a local mount which is not connected to mount tree, tomoyo_realpath_from_path() started returning a pathname in "$fsname:/$pathname" format which violates TOMOYO's domainname rule that it must start with "<$namespace>" followed by zero or more repetitions of pathnames which start with '/'. Since $fsname must not contain '.' since commit 79c0b2df79eb56fc ("add filesystem subtype support"), tomoyo_correct_path() can recognize a token which appears '/' before '.' appears (e.g. proc:/self/exe ) as a pathname while rejecting a token which appears '.' before '/' appears (e.g. exec.realpath="/bin/bash" ) as a condition parameter. Therefore, accept domainnames which contain pathnames which do not start with '/' but contain '/' before '.' (e.g. <kernel> tmpfs:/bpfilter_umh ). Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Diffstat (limited to '')
-rw-r--r--security/tomoyo/util.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index eba0b3395851..a40abb0b91ee 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -143,6 +143,8 @@ char *tomoyo_read_token(struct tomoyo_acl_param *param)
return pos;
}
+static bool tomoyo_correct_path2(const char *filename, const size_t len);
+
/**
* tomoyo_get_domainname - Read a domainname from a line.
*
@@ -157,10 +159,10 @@ const struct tomoyo_path_info *tomoyo_get_domainname
char *pos = start;
while (*pos) {
- if (*pos++ != ' ' || *pos++ == '/')
+ if (*pos++ != ' ' ||
+ tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos))
continue;
- pos -= 2;
- *pos++ = '\0';
+ *(pos - 1) = '\0';
break;
}
param->data = pos;
@@ -514,6 +516,22 @@ bool tomoyo_correct_word(const char *string)
}
/**
+ * tomoyo_correct_path2 - Check whether the given pathname follows the naming rules.
+ *
+ * @filename: The pathname to check.
+ * @len: Length of @filename.
+ *
+ * Returns true if @filename follows the naming rules, false otherwise.
+ */
+static bool tomoyo_correct_path2(const char *filename, const size_t len)
+{
+ const char *cp1 = memchr(filename, '/', len);
+ const char *cp2 = memchr(filename, '.', len);
+
+ return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len);
+}
+
+/**
* tomoyo_correct_path - Validate a pathname.
*
* @filename: The pathname to check.
@@ -523,7 +541,7 @@ bool tomoyo_correct_word(const char *string)
*/
bool tomoyo_correct_path(const char *filename)
{
- return *filename == '/' && tomoyo_correct_word(filename);
+ return tomoyo_correct_path2(filename, strlen(filename));
}
/**
@@ -545,8 +563,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname)
if (!cp)
break;
- if (*domainname != '/' ||
- !tomoyo_correct_word2(domainname, cp - domainname))
+ if (!tomoyo_correct_path2(domainname, cp - domainname))
return false;
domainname = cp + 1;
}