aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-06-03 07:36:43 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:33:41 -0400
commitc8c57e842720d8cc92ac8607f2d1c16d92314573 (patch)
treedc921366b931ba5817ad530433f3b1ee178bc56a
parent9b244373da3eab671da6c5125482121528a9ebf3 (diff)
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>
-rw-r--r--security/tomoyo/common.h48
-rw-r--r--security/tomoyo/domain.c72
-rw-r--r--security/tomoyo/file.c136
-rw-r--r--security/tomoyo/memory.c1
-rw-r--r--security/tomoyo/mount.c55
-rw-r--r--security/tomoyo/realpath.c214
6 files changed, 208 insertions, 318 deletions
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 6270a530c4d8..f4a8aa244af5 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -33,14 +33,7 @@ struct linux_binprm;
33#define TOMOYO_HASH_BITS 8 33#define TOMOYO_HASH_BITS 8
34#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) 34#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
35 35
36/* 36#define TOMOYO_EXEC_TMPSIZE 4096
37 * This is the max length of a token.
38 *
39 * A token consists of only ASCII printable characters.
40 * Non printable characters in a token is represented in \ooo style
41 * octal string. Thus, \ itself is represented as \\.
42 */
43#define TOMOYO_MAX_PATHNAME_LEN 4000
44 37
45/* Profile number is an integer between 0 and 255. */ 38/* Profile number is an integer between 0 and 255. */
46#define TOMOYO_MAX_PROFILES 256 39#define TOMOYO_MAX_PROFILES 256
@@ -168,17 +161,6 @@ enum tomoyo_securityfs_interface_index {
168/********** Structure definitions. **********/ 161/********** Structure definitions. **********/
169 162
170/* 163/*
171 * tomoyo_page_buffer is a structure which is used for holding a pathname
172 * obtained from "struct dentry" and "struct vfsmount" pair.
173 * As of now, it is 4096 bytes. If users complain that 4096 bytes is too small
174 * (because TOMOYO escapes non ASCII printable characters using \ooo format),
175 * we will make the buffer larger.
176 */
177struct tomoyo_page_buffer {
178 char buffer[4096];
179};
180
181/*
182 * tomoyo_request_info is a structure which is used for holding 164 * tomoyo_request_info is a structure which is used for holding
183 * 165 *
184 * (1) Domain information of current process. 166 * (1) Domain information of current process.
@@ -231,28 +213,6 @@ struct tomoyo_name_entry {
231 struct tomoyo_path_info entry; 213 struct tomoyo_path_info entry;
232}; 214};
233 215
234/*
235 * tomoyo_path_info_with_data is a structure which is used for holding a
236 * pathname obtained from "struct dentry" and "struct vfsmount" pair.
237 *
238 * "struct tomoyo_path_info_with_data" consists of "struct tomoyo_path_info"
239 * and buffer for the pathname, while "struct tomoyo_page_buffer" consists of
240 * buffer for the pathname only.
241 *
242 * "struct tomoyo_path_info_with_data" is intended to allow TOMOYO to release
243 * both "struct tomoyo_path_info" and buffer for the pathname by single kfree()
244 * so that we don't need to return two pointers to the caller. If the caller
245 * puts "struct tomoyo_path_info" on stack memory, we will be able to remove
246 * "struct tomoyo_path_info_with_data".
247 */
248struct tomoyo_path_info_with_data {
249 /* Keep "head" first, for this pointer is passed to kfree(). */
250 struct tomoyo_path_info head;
251 char barrier1[16]; /* Safeguard for overrun. */
252 char body[TOMOYO_MAX_PATHNAME_LEN];
253 char barrier2[16]; /* Safeguard for overrun. */
254};
255
256struct tomoyo_name_union { 216struct tomoyo_name_union {
257 const struct tomoyo_path_info *filename; 217 const struct tomoyo_path_info *filename;
258 struct tomoyo_path_group *group; 218 struct tomoyo_path_group *group;
@@ -827,11 +787,7 @@ void tomoyo_load_policy(const char *filename);
827void tomoyo_put_number_union(struct tomoyo_number_union *ptr); 787void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
828 788
829/* Convert binary string to ascii string. */ 789/* Convert binary string to ascii string. */
830int tomoyo_encode(char *buffer, int buflen, const char *str); 790char *tomoyo_encode(const char *str);
831
832/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
833int tomoyo_realpath_from_path2(struct path *path, char *newname,
834 int newname_len);
835 791
836/* 792/*
837 * Returns realpath(3) of the given pathname but ignores chroot'ed root. 793 * Returns realpath(3) of the given pathname but ignores chroot'ed root.
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 08428bc082df..7b8693e29a13 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -676,47 +676,43 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
676int tomoyo_find_next_domain(struct linux_binprm *bprm) 676int tomoyo_find_next_domain(struct linux_binprm *bprm)
677{ 677{
678 struct tomoyo_request_info r; 678 struct tomoyo_request_info r;
679 /* 679 char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
680 * This function assumes that the size of buffer returned by
681 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
682 */
683 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
684 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 680 struct tomoyo_domain_info *old_domain = tomoyo_domain();
685 struct tomoyo_domain_info *domain = NULL; 681 struct tomoyo_domain_info *domain = NULL;
686 const char *old_domain_name = old_domain->domainname->name; 682 const char *old_domain_name = old_domain->domainname->name;
687 const char *original_name = bprm->filename; 683 const char *original_name = bprm->filename;
688 char *new_domain_name = NULL;
689 char *real_program_name = NULL;
690 char *symlink_program_name = NULL;
691 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 684 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
692 const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); 685 const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
693 int retval = -ENOMEM; 686 int retval = -ENOMEM;
694 struct tomoyo_path_info rn; /* real name */ 687 bool need_kfree = false;
695 struct tomoyo_path_info sn; /* symlink name */ 688 struct tomoyo_path_info rn = { }; /* real name */
689 struct tomoyo_path_info sn = { }; /* symlink name */
696 struct tomoyo_path_info ln; /* last name */ 690 struct tomoyo_path_info ln; /* last name */
697 691
692 ln.name = tomoyo_get_last_name(old_domain);
693 tomoyo_fill_path_info(&ln);
698 tomoyo_init_request_info(&r, NULL); 694 tomoyo_init_request_info(&r, NULL);
699 if (!tmp) 695 if (!tmp)
700 goto out; 696 goto out;
701 697
702 retry: 698 retry:
699 if (need_kfree) {
700 kfree(rn.name);
701 need_kfree = false;
702 }
703 /* Get tomoyo_realpath of program. */ 703 /* Get tomoyo_realpath of program. */
704 retval = -ENOENT; 704 retval = -ENOENT;
705 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 705 rn.name = tomoyo_realpath(original_name);
706 real_program_name = tomoyo_realpath(original_name); 706 if (!rn.name)
707 if (!real_program_name)
708 goto out; 707 goto out;
708 tomoyo_fill_path_info(&rn);
709 need_kfree = true;
710
709 /* Get tomoyo_realpath of symbolic link. */ 711 /* Get tomoyo_realpath of symbolic link. */
710 symlink_program_name = tomoyo_realpath_nofollow(original_name); 712 sn.name = tomoyo_realpath_nofollow(original_name);
711 if (!symlink_program_name) 713 if (!sn.name)
712 goto out; 714 goto out;
713
714 rn.name = real_program_name;
715 tomoyo_fill_path_info(&rn);
716 sn.name = symlink_program_name;
717 tomoyo_fill_path_info(&sn); 715 tomoyo_fill_path_info(&sn);
718 ln.name = tomoyo_get_last_name(old_domain);
719 tomoyo_fill_path_info(&ln);
720 716
721 /* Check 'alias' directive. */ 717 /* Check 'alias' directive. */
722 if (tomoyo_pathcmp(&rn, &sn)) { 718 if (tomoyo_pathcmp(&rn, &sn)) {
@@ -727,10 +723,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
727 tomoyo_pathcmp(&rn, ptr->original_name) || 723 tomoyo_pathcmp(&rn, ptr->original_name) ||
728 tomoyo_pathcmp(&sn, ptr->aliased_name)) 724 tomoyo_pathcmp(&sn, ptr->aliased_name))
729 continue; 725 continue;
730 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 726 kfree(rn.name);
731 strncpy(real_program_name, ptr->aliased_name->name, 727 need_kfree = false;
732 TOMOYO_MAX_PATHNAME_LEN - 1); 728 /* This is OK because it is read only. */
733 tomoyo_fill_path_info(&rn); 729 rn = *ptr->aliased_name;
734 break; 730 break;
735 } 731 }
736 } 732 }
@@ -742,11 +738,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
742 if (retval < 0) 738 if (retval < 0)
743 goto out; 739 goto out;
744 740
745 new_domain_name = tmp->buffer;
746 if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) { 741 if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
747 /* Transit to the child of tomoyo_kernel_domain domain. */ 742 /* Transit to the child of tomoyo_kernel_domain domain. */
748 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 743 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
749 TOMOYO_ROOT_NAME " " "%s", real_program_name); 744 TOMOYO_ROOT_NAME " " "%s", rn.name);
750 } else if (old_domain == &tomoyo_kernel_domain && 745 } else if (old_domain == &tomoyo_kernel_domain &&
751 !tomoyo_policy_loaded) { 746 !tomoyo_policy_loaded) {
752 /* 747 /*
@@ -760,29 +755,27 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
760 domain = old_domain; 755 domain = old_domain;
761 } else { 756 } else {
762 /* Normal domain transition. */ 757 /* Normal domain transition. */
763 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 758 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
764 "%s %s", old_domain_name, real_program_name); 759 "%s %s", old_domain_name, rn.name);
765 } 760 }
766 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 761 if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
767 goto done; 762 goto done;
768 domain = tomoyo_find_domain(new_domain_name); 763 domain = tomoyo_find_domain(tmp);
769 if (domain) 764 if (domain)
770 goto done; 765 goto done;
771 if (is_enforce) { 766 if (is_enforce) {
772 int error = tomoyo_supervisor(&r, "# wants to create domain\n" 767 int error = tomoyo_supervisor(&r, "# wants to create domain\n"
773 "%s\n", new_domain_name); 768 "%s\n", tmp);
774 if (error == TOMOYO_RETRY_REQUEST) 769 if (error == TOMOYO_RETRY_REQUEST)
775 goto retry; 770 goto retry;
776 if (error < 0) 771 if (error < 0)
777 goto done; 772 goto done;
778 } 773 }
779 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 774 domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile);
780 old_domain->profile);
781 done: 775 done:
782 if (domain) 776 if (domain)
783 goto out; 777 goto out;
784 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 778 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
785 new_domain_name);
786 if (is_enforce) 779 if (is_enforce)
787 retval = -EPERM; 780 retval = -EPERM;
788 else 781 else
@@ -793,8 +786,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
793 /* Update reference count on "struct tomoyo_domain_info". */ 786 /* Update reference count on "struct tomoyo_domain_info". */
794 atomic_inc(&domain->users); 787 atomic_inc(&domain->users);
795 bprm->cred->security = domain; 788 bprm->cred->security = domain;
796 kfree(real_program_name); 789 if (need_kfree)
797 kfree(symlink_program_name); 790 kfree(rn.name);
791 kfree(sn.name);
798 kfree(tmp); 792 kfree(tmp);
799 return retval; 793 return retval;
800} 794}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index c13806937dc6..cef685415df1 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -148,6 +148,17 @@ const char *tomoyo_path_number2keyword(const u8 operation)
148 ? tomoyo_path_number_keyword[operation] : NULL; 148 ? tomoyo_path_number_keyword[operation] : NULL;
149} 149}
150 150
151static void tomoyo_add_slash(struct tomoyo_path_info *buf)
152{
153 if (buf->is_dir)
154 return;
155 /*
156 * This is OK because tomoyo_encode() reserves space for appending "/".
157 */
158 strcat((char *) buf->name, "/");
159 tomoyo_fill_path_info(buf);
160}
161
151/** 162/**
152 * tomoyo_strendswith - Check whether the token ends with the given token. 163 * tomoyo_strendswith - Check whether the token ends with the given token.
153 * 164 *
@@ -167,30 +178,21 @@ static bool tomoyo_strendswith(const char *name, const char *tail)
167} 178}
168 179
169/** 180/**
170 * tomoyo_get_path - Get realpath. 181 * tomoyo_get_realpath - Get realpath.
171 * 182 *
183 * @buf: Pointer to "struct tomoyo_path_info".
172 * @path: Pointer to "struct path". 184 * @path: Pointer to "struct path".
173 * 185 *
174 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 186 * Returns true on success, false otherwise.
175 */ 187 */
176static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 188static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
177{ 189{
178 int error; 190 buf->name = tomoyo_realpath_from_path(path);
179 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), 191 if (buf->name) {
180 GFP_NOFS); 192 tomoyo_fill_path_info(buf);
181 193 return true;
182 if (!buf)
183 return NULL;
184 /* Reserve one byte for appending "/". */
185 error = tomoyo_realpath_from_path2(path, buf->body,
186 sizeof(buf->body) - 2);
187 if (!error) {
188 buf->head.name = buf->body;
189 tomoyo_fill_path_info(&buf->head);
190 return &buf->head;
191 } 194 }
192 kfree(buf); 195 return false;
193 return NULL;
194} 196}
195 197
196static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 198static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
@@ -1259,26 +1261,20 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
1259{ 1261{
1260 struct tomoyo_request_info r; 1262 struct tomoyo_request_info r;
1261 int error = -ENOMEM; 1263 int error = -ENOMEM;
1262 struct tomoyo_path_info *buf; 1264 struct tomoyo_path_info buf;
1263 int idx; 1265 int idx;
1264 1266
1265 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || 1267 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
1266 !path->mnt || !path->dentry) 1268 !path->mnt || !path->dentry)
1267 return 0; 1269 return 0;
1268 idx = tomoyo_read_lock(); 1270 idx = tomoyo_read_lock();
1269 buf = tomoyo_get_path(path); 1271 if (!tomoyo_get_realpath(&buf, path))
1270 if (!buf)
1271 goto out; 1272 goto out;
1272 if (type == TOMOYO_TYPE_MKDIR && !buf->is_dir) { 1273 if (type == TOMOYO_TYPE_MKDIR)
1273 /* 1274 tomoyo_add_slash(&buf);
1274 * tomoyo_get_path() reserves space for appending "/." 1275 error = tomoyo_path_number_perm2(&r, type, &buf, number);
1275 */
1276 strcat((char *) buf->name, "/");
1277 tomoyo_fill_path_info(buf);
1278 }
1279 error = tomoyo_path_number_perm2(&r, type, buf, number);
1280 out: 1276 out:
1281 kfree(buf); 1277 kfree(buf.name);
1282 tomoyo_read_unlock(idx); 1278 tomoyo_read_unlock(idx);
1283 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1279 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1284 error = 0; 1280 error = 0;
@@ -1319,7 +1315,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1319{ 1315{
1320 const u8 acc_mode = ACC_MODE(flag); 1316 const u8 acc_mode = ACC_MODE(flag);
1321 int error = -ENOMEM; 1317 int error = -ENOMEM;
1322 struct tomoyo_path_info *buf; 1318 struct tomoyo_path_info buf;
1323 struct tomoyo_request_info r; 1319 struct tomoyo_request_info r;
1324 int idx; 1320 int idx;
1325 1321
@@ -1335,8 +1331,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1335 */ 1331 */
1336 return 0; 1332 return 0;
1337 idx = tomoyo_read_lock(); 1333 idx = tomoyo_read_lock();
1338 buf = tomoyo_get_path(path); 1334 if (!tomoyo_get_realpath(&buf, path))
1339 if (!buf)
1340 goto out; 1335 goto out;
1341 error = 0; 1336 error = 0;
1342 /* 1337 /*
@@ -1346,15 +1341,15 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1346 */ 1341 */
1347 if ((acc_mode & MAY_WRITE) && 1342 if ((acc_mode & MAY_WRITE) &&
1348 ((flag & O_TRUNC) || !(flag & O_APPEND)) && 1343 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1349 (tomoyo_is_no_rewrite_file(buf))) { 1344 (tomoyo_is_no_rewrite_file(&buf))) {
1350 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, buf); 1345 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf);
1351 } 1346 }
1352 if (!error) 1347 if (!error)
1353 error = tomoyo_file_perm(&r, buf, acc_mode); 1348 error = tomoyo_file_perm(&r, &buf, acc_mode);
1354 if (!error && (flag & O_TRUNC)) 1349 if (!error && (flag & O_TRUNC))
1355 error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, buf); 1350 error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, &buf);
1356 out: 1351 out:
1357 kfree(buf); 1352 kfree(buf.name);
1358 tomoyo_read_unlock(idx); 1353 tomoyo_read_unlock(idx);
1359 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1354 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1360 error = 0; 1355 error = 0;
@@ -1372,7 +1367,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1372int tomoyo_path_perm(const u8 operation, struct path *path) 1367int tomoyo_path_perm(const u8 operation, struct path *path)
1373{ 1368{
1374 int error = -ENOMEM; 1369 int error = -ENOMEM;
1375 struct tomoyo_path_info *buf; 1370 struct tomoyo_path_info buf;
1376 struct tomoyo_request_info r; 1371 struct tomoyo_request_info r;
1377 int idx; 1372 int idx;
1378 1373
@@ -1380,29 +1375,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
1380 !path->mnt) 1375 !path->mnt)
1381 return 0; 1376 return 0;
1382 idx = tomoyo_read_lock(); 1377 idx = tomoyo_read_lock();
1383 buf = tomoyo_get_path(path); 1378 if (!tomoyo_get_realpath(&buf, path))
1384 if (!buf)
1385 goto out; 1379 goto out;
1386 switch (operation) { 1380 switch (operation) {
1387 case TOMOYO_TYPE_REWRITE: 1381 case TOMOYO_TYPE_REWRITE:
1388 if (!tomoyo_is_no_rewrite_file(buf)) { 1382 if (!tomoyo_is_no_rewrite_file(&buf)) {
1389 error = 0; 1383 error = 0;
1390 goto out; 1384 goto out;
1391 } 1385 }
1392 break; 1386 break;
1393 case TOMOYO_TYPE_RMDIR: 1387 case TOMOYO_TYPE_RMDIR:
1394 case TOMOYO_TYPE_CHROOT: 1388 case TOMOYO_TYPE_CHROOT:
1395 if (!buf->is_dir) { 1389 tomoyo_add_slash(&buf);
1396 /* 1390 break;
1397 * tomoyo_get_path() reserves space for appending "/."
1398 */
1399 strcat((char *) buf->name, "/");
1400 tomoyo_fill_path_info(buf);
1401 }
1402 } 1391 }
1403 error = tomoyo_path_permission(&r, operation, buf); 1392 error = tomoyo_path_permission(&r, operation, &buf);
1404 out: 1393 out:
1405 kfree(buf); 1394 kfree(buf.name);
1406 tomoyo_read_unlock(idx); 1395 tomoyo_read_unlock(idx);
1407 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1396 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1408 error = 0; 1397 error = 0;
@@ -1465,7 +1454,7 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path,
1465{ 1454{
1466 struct tomoyo_request_info r; 1455 struct tomoyo_request_info r;
1467 int error = -ENOMEM; 1456 int error = -ENOMEM;
1468 struct tomoyo_path_info *buf; 1457 struct tomoyo_path_info buf;
1469 int idx; 1458 int idx;
1470 1459
1471 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || 1460 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
@@ -1473,11 +1462,10 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path,
1473 return 0; 1462 return 0;
1474 idx = tomoyo_read_lock(); 1463 idx = tomoyo_read_lock();
1475 error = -ENOMEM; 1464 error = -ENOMEM;
1476 buf = tomoyo_get_path(path); 1465 if (tomoyo_get_realpath(&buf, path)) {
1477 if (buf) { 1466 error = tomoyo_path_number3_perm2(&r, operation, &buf, mode,
1478 error = tomoyo_path_number3_perm2(&r, operation, buf, mode,
1479 new_decode_dev(dev)); 1467 new_decode_dev(dev));
1480 kfree(buf); 1468 kfree(buf.name);
1481 } 1469 }
1482 tomoyo_read_unlock(idx); 1470 tomoyo_read_unlock(idx);
1483 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1471 if (r.mode != TOMOYO_CONFIG_ENFORCING)
@@ -1499,48 +1487,40 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1499{ 1487{
1500 int error = -ENOMEM; 1488 int error = -ENOMEM;
1501 const char *msg; 1489 const char *msg;
1502 struct tomoyo_path_info *buf1; 1490 struct tomoyo_path_info buf1;
1503 struct tomoyo_path_info *buf2; 1491 struct tomoyo_path_info buf2;
1504 struct tomoyo_request_info r; 1492 struct tomoyo_request_info r;
1505 int idx; 1493 int idx;
1506 1494
1507 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || 1495 if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED ||
1508 !path1->mnt || !path2->mnt) 1496 !path1->mnt || !path2->mnt)
1509 return 0; 1497 return 0;
1498 buf1.name = NULL;
1499 buf2.name = NULL;
1510 idx = tomoyo_read_lock(); 1500 idx = tomoyo_read_lock();
1511 buf1 = tomoyo_get_path(path1); 1501 if (!tomoyo_get_realpath(&buf1, path1) ||
1512 buf2 = tomoyo_get_path(path2); 1502 !tomoyo_get_realpath(&buf2, path2))
1513 if (!buf1 || !buf2)
1514 goto out; 1503 goto out;
1515 { 1504 {
1516 struct dentry *dentry = path1->dentry; 1505 struct dentry *dentry = path1->dentry;
1517 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { 1506 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1518 /* 1507 tomoyo_add_slash(&buf1);
1519 * tomoyo_get_path() reserves space for appending "/." 1508 tomoyo_add_slash(&buf2);
1520 */
1521 if (!buf1->is_dir) {
1522 strcat((char *) buf1->name, "/");
1523 tomoyo_fill_path_info(buf1);
1524 }
1525 if (!buf2->is_dir) {
1526 strcat((char *) buf2->name, "/");
1527 tomoyo_fill_path_info(buf2);
1528 }
1529 } 1509 }
1530 } 1510 }
1531 do { 1511 do {
1532 error = tomoyo_path2_acl(&r, operation, buf1, buf2); 1512 error = tomoyo_path2_acl(&r, operation, &buf1, &buf2);
1533 if (!error) 1513 if (!error)
1534 break; 1514 break;
1535 msg = tomoyo_path22keyword(operation); 1515 msg = tomoyo_path22keyword(operation);
1536 tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name); 1516 tomoyo_warn_log(&r, "%s %s %s", msg, buf1.name, buf2.name);
1537 error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg, 1517 error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
1538 tomoyo_file_pattern(buf1), 1518 tomoyo_file_pattern(&buf1),
1539 tomoyo_file_pattern(buf2)); 1519 tomoyo_file_pattern(&buf2));
1540 } while (error == TOMOYO_RETRY_REQUEST); 1520 } while (error == TOMOYO_RETRY_REQUEST);
1541 out: 1521 out:
1542 kfree(buf1); 1522 kfree(buf1.name);
1543 kfree(buf2); 1523 kfree(buf2.name);
1544 tomoyo_read_unlock(idx); 1524 tomoyo_read_unlock(idx);
1545 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1525 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1546 error = 0; 1526 error = 0;
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 8fb73ff5cb63..4809febc1acb 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -153,7 +153,6 @@ void __init tomoyo_mm_init(void)
153{ 153{
154 int idx; 154 int idx;
155 155
156 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
157 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) 156 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
158 INIT_LIST_HEAD(&tomoyo_name_list[idx]); 157 INIT_LIST_HEAD(&tomoyo_name_list[idx]);
159 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 158 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index aeac619f787d..7c1c7fdd3681 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -25,57 +25,6 @@
25#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared" 25#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
26 26
27/** 27/**
28 * tomoyo_encode2: Encode binary string to ascii string.
29 *
30 * @str: String in binary format.
31 *
32 * Returns pointer to @str in ascii format on success, NULL otherwise.
33 *
34 * This function uses kzalloc(), so caller must kfree() if this function
35 * didn't return NULL.
36 */
37static char *tomoyo_encode2(const char *str)
38{
39 int len = 0;
40 const char *p = str;
41 char *cp;
42 char *cp0;
43 if (!p)
44 return NULL;
45 while (*p) {
46 const unsigned char c = *p++;
47 if (c == '\\')
48 len += 2;
49 else if (c > ' ' && c < 127)
50 len++;
51 else
52 len += 4;
53 }
54 len++;
55 /* Reserve space for appending "/". */
56 cp = kzalloc(len + 10, GFP_NOFS);
57 if (!cp)
58 return NULL;
59 cp0 = cp;
60 p = str;
61 while (*p) {
62 const unsigned char c = *p++;
63 if (c == '\\') {
64 *cp++ = '\\';
65 *cp++ = '\\';
66 } else if (c > ' ' && c < 127) {
67 *cp++ = c;
68 } else {
69 *cp++ = '\\';
70 *cp++ = (c >> 6) + '0';
71 *cp++ = ((c >> 3) & 7) + '0';
72 *cp++ = (c & 7) + '0';
73 }
74 }
75 return cp0;
76}
77
78/**
79 * tomoyo_mount_acl2 - Check permission for mount() operation. 28 * tomoyo_mount_acl2 - Check permission for mount() operation.
80 * 29 *
81 * @r: Pointer to "struct tomoyo_request_info". 30 * @r: Pointer to "struct tomoyo_request_info".
@@ -104,7 +53,7 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
104 int error = -ENOMEM; 53 int error = -ENOMEM;
105 54
106 /* Get fstype. */ 55 /* Get fstype. */
107 requested_type = tomoyo_encode2(type); 56 requested_type = tomoyo_encode(type);
108 if (!requested_type) 57 if (!requested_type)
109 goto out; 58 goto out;
110 rtype.name = requested_type; 59 rtype.name = requested_type;
@@ -155,7 +104,7 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
155 /* Map dev_name to "<NULL>" if no dev_name given. */ 104 /* Map dev_name to "<NULL>" if no dev_name given. */
156 if (!dev_name) 105 if (!dev_name)
157 dev_name = "<NULL>"; 106 dev_name = "<NULL>";
158 requested_dev_name = tomoyo_encode2(dev_name); 107 requested_dev_name = tomoyo_encode(dev_name);
159 if (!requested_dev_name) { 108 if (!requested_dev_name) {
160 error = -ENOMEM; 109 error = -ENOMEM;
161 goto out; 110 goto out;
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 1fd685a94ad1..153fa23a05cc 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -12,141 +12,153 @@
12#include <linux/fs_struct.h> 12#include <linux/fs_struct.h>
13#include <linux/magic.h> 13#include <linux/magic.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <net/sock.h>
15#include "common.h" 16#include "common.h"
16 17
17/** 18/**
18 * tomoyo_encode: Convert binary string to ascii string. 19 * tomoyo_encode: Convert binary string to ascii string.
19 * 20 *
20 * @buffer: Buffer for ASCII string. 21 * @str: String in binary format.
21 * @buflen: Size of @buffer.
22 * @str: Binary string.
23 * 22 *
24 * Returns 0 on success, -ENOMEM otherwise. 23 * Returns pointer to @str in ascii format on success, NULL otherwise.
24 *
25 * This function uses kzalloc(), so caller must kfree() if this function
26 * didn't return NULL.
25 */ 27 */
26int tomoyo_encode(char *buffer, int buflen, const char *str) 28char *tomoyo_encode(const char *str)
27{ 29{
28 while (1) { 30 int len = 0;
29 const unsigned char c = *(unsigned char *) str++; 31 const char *p = str;
32 char *cp;
33 char *cp0;
30 34
31 if (tomoyo_is_valid(c)) { 35 if (!p)
32 if (--buflen <= 0) 36 return NULL;
33 break; 37 while (*p) {
34 *buffer++ = (char) c; 38 const unsigned char c = *p++;
35 if (c != '\\') 39 if (c == '\\')
36 continue; 40 len += 2;
37 if (--buflen <= 0) 41 else if (c > ' ' && c < 127)
38 break; 42 len++;
39 *buffer++ = (char) c; 43 else
40 continue; 44 len += 4;
41 } 45 }
42 if (!c) { 46 len++;
43 if (--buflen <= 0) 47 /* Reserve space for appending "/". */
44 break; 48 cp = kzalloc(len + 10, GFP_NOFS);
45 *buffer = '\0'; 49 if (!cp)
46 return 0; 50 return NULL;
51 cp0 = cp;
52 p = str;
53 while (*p) {
54 const unsigned char c = *p++;
55
56 if (c == '\\') {
57 *cp++ = '\\';
58 *cp++ = '\\';
59 } else if (c > ' ' && c < 127) {
60 *cp++ = c;
61 } else {
62 *cp++ = '\\';
63 *cp++ = (c >> 6) + '0';
64 *cp++ = ((c >> 3) & 7) + '0';
65 *cp++ = (c & 7) + '0';
47 } 66 }
48 buflen -= 4;
49 if (buflen <= 0)
50 break;
51 *buffer++ = '\\';
52 *buffer++ = (c >> 6) + '0';
53 *buffer++ = ((c >> 3) & 7) + '0';
54 *buffer++ = (c & 7) + '0';
55 } 67 }
56 return -ENOMEM; 68 return cp0;
57} 69}
58 70
59/** 71/**
60 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root. 72 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
61 * 73 *
62 * @path: Pointer to "struct path". 74 * @path: Pointer to "struct path".
63 * @newname: Pointer to buffer to return value in.
64 * @newname_len: Size of @newname.
65 * 75 *
66 * Returns 0 on success, negative value otherwise. 76 * Returns the realpath of the given @path on success, NULL otherwise.
67 * 77 *
68 * If dentry is a directory, trailing '/' is appended. 78 * If dentry is a directory, trailing '/' is appended.
69 * Characters out of 0x20 < c < 0x7F range are converted to 79 * Characters out of 0x20 < c < 0x7F range are converted to
70 * \ooo style octal string. 80 * \ooo style octal string.
71 * Character \ is converted to \\ string. 81 * Character \ is converted to \\ string.
82 *
83 * These functions use kzalloc(), so the caller must call kfree()
84 * if these functions didn't return NULL.
72 */ 85 */
73int tomoyo_realpath_from_path2(struct path *path, char *newname, 86char *tomoyo_realpath_from_path(struct path *path)
74 int newname_len)
75{ 87{
76 int error = -ENOMEM; 88 char *buf = NULL;
89 char *name = NULL;
90 unsigned int buf_len = PAGE_SIZE / 2;
77 struct dentry *dentry = path->dentry; 91 struct dentry *dentry = path->dentry;
78 char *sp; 92 bool is_dir;
79 93 if (!dentry)
80 if (!dentry || !path->mnt || !newname || newname_len <= 2048) 94 return NULL;
81 return -EINVAL; 95 is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode);
82 if (dentry->d_op && dentry->d_op->d_dname) { 96 while (1) {
97 struct path ns_root = { .mnt = NULL, .dentry = NULL };
98 char *pos;
99 buf_len <<= 1;
100 kfree(buf);
101 buf = kmalloc(buf_len, GFP_NOFS);
102 if (!buf)
103 break;
104 /* Get better name for socket. */
105 if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) {
106 struct inode *inode = dentry->d_inode;
107 struct socket *sock = inode ? SOCKET_I(inode) : NULL;
108 struct sock *sk = sock ? sock->sk : NULL;
109 if (sk) {
110 snprintf(buf, buf_len - 1, "socket:[family=%u:"
111 "type=%u:protocol=%u]", sk->sk_family,
112 sk->sk_type, sk->sk_protocol);
113 } else {
114 snprintf(buf, buf_len - 1, "socket:[unknown]");
115 }
116 name = tomoyo_encode(buf);
117 break;
118 }
83 /* For "socket:[\$]" and "pipe:[\$]". */ 119 /* For "socket:[\$]" and "pipe:[\$]". */
84 static const int offset = 1536; 120 if (dentry->d_op && dentry->d_op->d_dname) {
85 sp = dentry->d_op->d_dname(dentry, newname + offset, 121 pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
86 newname_len - offset); 122 if (IS_ERR(pos))
87 } else { 123 continue;
88 struct path ns_root = {.mnt = NULL, .dentry = NULL}; 124 name = tomoyo_encode(pos);
89 125 break;
126 }
127 /* If we don't have a vfsmount, we can't calculate. */
128 if (!path->mnt)
129 break;
90 spin_lock(&dcache_lock); 130 spin_lock(&dcache_lock);
91 /* go to whatever namespace root we are under */ 131 /* go to whatever namespace root we are under */
92 sp = __d_path(path, &ns_root, newname, newname_len); 132 pos = __d_path(path, &ns_root, buf, buf_len);
93 spin_unlock(&dcache_lock); 133 spin_unlock(&dcache_lock);
94 /* Prepend "/proc" prefix if using internal proc vfs mount. */ 134 /* Prepend "/proc" prefix if using internal proc vfs mount. */
95 if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) && 135 if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
96 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { 136 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
97 sp -= 5; 137 pos -= 5;
98 if (sp >= newname) 138 if (pos >= buf)
99 memcpy(sp, "/proc", 5); 139 memcpy(pos, "/proc", 5);
100 else 140 else
101 sp = ERR_PTR(-ENOMEM); 141 pos = ERR_PTR(-ENOMEM);
102 }
103 }
104 if (IS_ERR(sp))
105 error = PTR_ERR(sp);
106 else
107 error = tomoyo_encode(newname, sp - newname, sp);
108 /* Append trailing '/' if dentry is a directory. */
109 if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
110 && *newname) {
111 sp = newname + strlen(newname);
112 if (*(sp - 1) != '/') {
113 if (sp < newname + newname_len - 4) {
114 *sp++ = '/';
115 *sp = '\0';
116 } else {
117 error = -ENOMEM;
118 }
119 } 142 }
143 if (IS_ERR(pos))
144 continue;
145 name = tomoyo_encode(pos);
146 break;
120 } 147 }
121 if (error)
122 tomoyo_warn_oom(__func__);
123 return error;
124}
125
126/**
127 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
128 *
129 * @path: Pointer to "struct path".
130 *
131 * Returns the realpath of the given @path on success, NULL otherwise.
132 *
133 * These functions use kzalloc(), so the caller must call kfree()
134 * if these functions didn't return NULL.
135 */
136char *tomoyo_realpath_from_path(struct path *path)
137{
138 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
139
140 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
141 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
142 <= TOMOYO_MAX_PATHNAME_LEN - 1);
143 if (!buf)
144 return NULL;
145 if (tomoyo_realpath_from_path2(path, buf,
146 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
147 return buf;
148 kfree(buf); 148 kfree(buf);
149 return NULL; 149 if (!name)
150 tomoyo_warn_oom(__func__);
151 else if (is_dir && *name) {
152 /* Append trailing '/' if dentry is a directory. */
153 char *pos = name + strlen(name) - 1;
154 if (*pos != '/')
155 /*
156 * This is OK because tomoyo_encode() reserves space
157 * for appending "/".
158 */
159 *++pos = '/';
160 }
161 return name;
150} 162}
151 163
152/** 164/**