TOMOYO: Support longer pathname.
Allow pathnames longer than 4000 bytes.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index c138069..cef6854 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -148,6 +148,17 @@
? tomoyo_path_number_keyword[operation] : NULL;
}
+static void tomoyo_add_slash(struct tomoyo_path_info *buf)
+{
+ if (buf->is_dir)
+ return;
+ /*
+ * This is OK because tomoyo_encode() reserves space for appending "/".
+ */
+ strcat((char *) buf->name, "/");
+ tomoyo_fill_path_info(buf);
+}
+
/**
* tomoyo_strendswith - Check whether the token ends with the given token.
*
@@ -167,30 +178,21 @@
}
/**
- * tomoyo_get_path - Get realpath.
+ * tomoyo_get_realpath - Get realpath.
*
+ * @buf: Pointer to "struct tomoyo_path_info".
* @path: Pointer to "struct path".
*
- * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
+ * Returns true on success, false otherwise.
*/
-static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
+static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
{
- int error;
- struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf),
- GFP_NOFS);
-
- if (!buf)
- return NULL;
- /* Reserve one byte for appending "/". */
- error = tomoyo_realpath_from_path2(path, buf->body,
- sizeof(buf->body) - 2);
- if (!error) {
- buf->head.name = buf->body;
- tomoyo_fill_path_info(&buf->head);
- return &buf->head;
+ buf->name = tomoyo_realpath_from_path(path);
+ if (buf->name) {
+ tomoyo_fill_path_info(buf);
+ return true;
}
- kfree(buf);
- return NULL;
+ return false;
}
static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
@@ -1259,26 +1261,20 @@
{
struct tomoyo_request_info r;
int error = -ENOMEM;
- struct tomoyo_path_info *buf;
+ struct tomoyo_path_info buf;
int idx;
if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
!path->mnt || !path->dentry)
return 0;
idx = tomoyo_read_lock();
- buf = tomoyo_get_path(path);
- if (!buf)
+ if (!tomoyo_get_realpath(&buf, path))
goto out;
- if (type == TOMOYO_TYPE_MKDIR && !buf->is_dir) {
- /*
- * tomoyo_get_path() reserves space for appending "/."
- */
- strcat((char *) buf->name, "/");
- tomoyo_fill_path_info(buf);
- }
- error = tomoyo_path_number_perm2(&r, type, buf, number);
+ if (type == TOMOYO_TYPE_MKDIR)
+ tomoyo_add_slash(&buf);
+ error = tomoyo_path_number_perm2(&r, type, &buf, number);
out:
- kfree(buf);
+ kfree(buf.name);
tomoyo_read_unlock(idx);
if (r.mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
@@ -1319,7 +1315,7 @@
{
const u8 acc_mode = ACC_MODE(flag);
int error = -ENOMEM;
- struct tomoyo_path_info *buf;
+ struct tomoyo_path_info buf;
struct tomoyo_request_info r;
int idx;
@@ -1335,8 +1331,7 @@
*/
return 0;
idx = tomoyo_read_lock();
- buf = tomoyo_get_path(path);
- if (!buf)
+ if (!tomoyo_get_realpath(&buf, path))
goto out;
error = 0;
/*
@@ -1346,15 +1341,15 @@
*/
if ((acc_mode & MAY_WRITE) &&
((flag & O_TRUNC) || !(flag & O_APPEND)) &&
- (tomoyo_is_no_rewrite_file(buf))) {
- error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, buf);
+ (tomoyo_is_no_rewrite_file(&buf))) {
+ error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf);
}
if (!error)
- error = tomoyo_file_perm(&r, buf, acc_mode);
+ error = tomoyo_file_perm(&r, &buf, acc_mode);
if (!error && (flag & O_TRUNC))
- error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, buf);
+ error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, &buf);
out:
- kfree(buf);
+ kfree(buf.name);
tomoyo_read_unlock(idx);
if (r.mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
@@ -1372,7 +1367,7 @@
int tomoyo_path_perm(const u8 operation, struct path *path)
{
int error = -ENOMEM;
- struct tomoyo_path_info *buf;
+ struct tomoyo_path_info buf;
struct tomoyo_request_info r;
int idx;
@@ -1380,29 +1375,23 @@
!path->mnt)
return 0;
idx = tomoyo_read_lock();
- buf = tomoyo_get_path(path);
- if (!buf)
+ if (!tomoyo_get_realpath(&buf, path))
goto out;
switch (operation) {
case TOMOYO_TYPE_REWRITE:
- if (!tomoyo_is_no_rewrite_file(buf)) {
+ if (!tomoyo_is_no_rewrite_file(&buf)) {
error = 0;
goto out;
}
break;
case TOMOYO_TYPE_RMDIR:
case TOMOYO_TYPE_CHROOT:
- if (!buf->is_dir) {
- /*
- * tomoyo_get_path() reserves space for appending "/."
- */
- strcat((char *) buf->name, "/");
- tomoyo_fill_path_info(buf);
- }
+ tomoyo_add_slash(&buf);
+ break;
}
- error = tomoyo_path_permission(&r, operation, buf);
+ error = tomoyo_path_permission(&r, operation, &buf);
out:
- kfree(buf);
+ kfree(buf.name);
tomoyo_read_unlock(idx);
if (r.mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
@@ -1465,7 +1454,7 @@
{
struct tomoyo_request_info r;
int error = -ENOMEM;
- struct tomoyo_path_info *buf;
+ struct tomoyo_path_info buf;
int idx;
if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
@@ -1473,11 +1462,10 @@
return 0;
idx = tomoyo_read_lock();
error = -ENOMEM;
- buf = tomoyo_get_path(path);
- if (buf) {
- error = tomoyo_path_number3_perm2(&r, operation, buf, mode,
+ if (tomoyo_get_realpath(&buf, path)) {
+ error = tomoyo_path_number3_perm2(&r, operation, &buf, mode,
new_decode_dev(dev));
- kfree(buf);
+ kfree(buf.name);
}
tomoyo_read_unlock(idx);
if (r.mode != TOMOYO_CONFIG_ENFORCING)
@@ -1499,48 +1487,40 @@
{
int error = -ENOMEM;
const char *msg;
- struct tomoyo_path_info *buf1;
- struct tomoyo_path_info *buf2;
+ struct tomoyo_path_info buf1;
+ struct tomoyo_path_info buf2;
struct tomoyo_request_info r;
int idx;
if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
!path1->mnt || !path2->mnt)
return 0;
+ buf1.name = NULL;
+ buf2.name = NULL;
idx = tomoyo_read_lock();
- buf1 = tomoyo_get_path(path1);
- buf2 = tomoyo_get_path(path2);
- if (!buf1 || !buf2)
+ if (!tomoyo_get_realpath(&buf1, path1) ||
+ !tomoyo_get_realpath(&buf2, path2))
goto out;
{
struct dentry *dentry = path1->dentry;
if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
- /*
- * tomoyo_get_path() reserves space for appending "/."
- */
- if (!buf1->is_dir) {
- strcat((char *) buf1->name, "/");
- tomoyo_fill_path_info(buf1);
- }
- if (!buf2->is_dir) {
- strcat((char *) buf2->name, "/");
- tomoyo_fill_path_info(buf2);
- }
+ tomoyo_add_slash(&buf1);
+ tomoyo_add_slash(&buf2);
}
}
do {
- error = tomoyo_path2_acl(&r, operation, buf1, buf2);
+ error = tomoyo_path2_acl(&r, operation, &buf1, &buf2);
if (!error)
break;
msg = tomoyo_path22keyword(operation);
- tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name);
+ tomoyo_warn_log(&r, "%s %s %s", msg, buf1.name, buf2.name);
error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
- tomoyo_file_pattern(buf1),
- tomoyo_file_pattern(buf2));
+ tomoyo_file_pattern(&buf1),
+ tomoyo_file_pattern(&buf2));
} while (error == TOMOYO_RETRY_REQUEST);
out:
- kfree(buf1);
- kfree(buf2);
+ kfree(buf1.name);
+ kfree(buf2.name);
tomoyo_read_unlock(idx);
if (r.mode != TOMOYO_CONFIG_ENFORCING)
error = 0;