diff options
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 136 |
1 files changed, 58 insertions, 78 deletions
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 | ||
151 | static 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 | */ |
176 | static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | 188 | static 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 | ||
196 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | 198 | static 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, | |||
1372 | int tomoyo_path_perm(const u8 operation, struct path *path) | 1367 | int 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; |